diff --git a/Doc/tools/static/switchers.js b/Doc/tools/static/switchers.js index 8e0c5ea0092a9f..2463577792055e 100644 --- a/Doc/tools/static/switchers.js +++ b/Doc/tools/static/switchers.js @@ -11,7 +11,7 @@ var all_versions = { '3.8': 'dev (3.8)', - '3.7': 'pre (3.7)', + '3.7': 'pre (3.7)', '3.6': '3.6', '3.5': '3.5', '2.7': '2.7', diff --git a/Include/osdefs.h b/Include/osdefs.h index bd84c1c12c19fd..3243944a1483e9 100644 --- a/Include/osdefs.h +++ b/Include/osdefs.h @@ -14,6 +14,10 @@ extern "C" { #define DELIM L';' #endif +#ifdef __VXWORKS__ +#define DELIM L';' +#endif + /* Filename separator */ #ifndef SEP #define SEP L'/' diff --git a/Include/symtable.h b/Include/symtable.h index 007f88db40e7eb..f48fe8f8a919a2 100644 --- a/Include/symtable.h +++ b/Include/symtable.h @@ -102,6 +102,10 @@ PyAPI_FUNC(void) PySymtable_Free(struct symtable *); #define SCOPE_OFFSET 11 #define SCOPE_MASK (DEF_GLOBAL | DEF_LOCAL | DEF_PARAM | DEF_NONLOCAL) +#ifdef __VXWORKS__ + #undef LOCAL +#endif + #define LOCAL 1 #define GLOBAL_EXPLICIT 2 #define GLOBAL_IMPLICIT 3 diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 0c4eb2473273b4..564c3a05c9bd82 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -410,6 +410,13 @@ def _flush_std_streams(): # def spawnv_passfds(path, args, passfds): + if 'vxworks' in sys.platform: + import subprocess + try: + return subprocess.Popen(args).pid + except: + pass + return import _posixsubprocess passfds = tuple(sorted(map(int, passfds))) errpipe_read, errpipe_write = os.pipe() diff --git a/Lib/platform.py b/Lib/platform.py index dc981ec144cc07..b0ed9528647f42 100755 --- a/Lib/platform.py +++ b/Lib/platform.py @@ -753,7 +753,7 @@ def _syscmd_uname(option, default=''): return default try: f = os.popen('uname %s 2> %s' % (option, DEV_NULL)) - except (AttributeError, OSError): + except (AttributeError, OSError, ValueError): return default output = f.read().strip() rc = f.close() @@ -771,7 +771,7 @@ def _syscmd_file(target, default=''): default in case the command should fail. """ - if sys.platform in ('dos', 'win32', 'win16'): + if sys.platform in ('dos', 'win32', 'win16', 'vxworks'): # XXX Others too ? return default target = _follow_symlinks(target) diff --git a/Lib/posixpath.py b/Lib/posixpath.py index e92186c64e0ddb..b090fe7b6112b5 100644 --- a/Lib/posixpath.py +++ b/Lib/posixpath.py @@ -28,6 +28,10 @@ import genericpath from genericpath import * +_vxworks = 'vxworks' in sys.platform +if _vxworks: + import _vxwapi + __all__ = ["normcase","isabs","join","splitdrive","split","splitext", "basename","dirname","commonprefix","getsize","getmtime", "getatime","getctime","islink","exists","lexists","isdir","isfile", @@ -65,13 +69,17 @@ def isabs(s): """Test whether a path is absolute""" s = os.fspath(s) sep = _get_sep(s) + if _vxworks: #VxWorks paths dont always start with / and there is no good + # way to find if a path is absolute. V7COR-3074, F7233 + if not isinstance(s, str): + s = s.decode(sys.getdefaultencoding()) + return bool(_vxwapi.isAbs(s)) return s.startswith(sep) # Join pathnames. # Ignore the previous parts if a part is absolute. # Insert a '/' unless the first part is empty or already ends in '/'. - def join(a, *p): """Join two or more pathname components, inserting '/' as needed. If any component is an absolute path, all previous path components @@ -401,8 +409,18 @@ def _joinrealpath(path, rest, seen): pardir = '..' if isabs(rest): - rest = rest[1:] - path = sep + if not _vxworks: + rest = rest[1:] + path = sep + else: + if rest.startswith(sep): + rest = rest[1:] + path = sep + else: + ind = rest.find(':') + ind = 0 if ind < 0 else ind + path = rest[:ind] + rest = rest[ind:] while rest: name, _, rest = rest.partition(sep) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index 93635ee61f7e9f..4e532fb1bf762f 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -43,6 +43,7 @@ import sys _mswindows = (sys.platform == "win32") +_vxworks = (sys.platform == "vxworks") import io import os @@ -136,7 +137,10 @@ def __init__(self, *, dwFlags=0, hStdInput=None, hStdOutput=None, self.wShowWindow = wShowWindow self.lpAttributeList = lpAttributeList or {"handle_list": []} else: - import _posixsubprocess + if(_vxworks): + import _vxwapi + else: + import _posixsubprocess import select import selectors import threading @@ -605,9 +609,11 @@ class Popen(object): preexec_fn: (POSIX only) An object to be called in the child process just before the child is executed. - close_fds: Controls closing or inheriting of file descriptors. + close_fds: Controls closing or inheriting of file descriptors. + (not supported on VxWorks) shell: If true, the command will be executed through the shell. + (not supported on VxWorks) cwd: Sets the current directory before the child is executed. @@ -636,7 +642,7 @@ class Popen(object): def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, - preexec_fn=None, close_fds=True, + preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, @@ -661,7 +667,23 @@ def __init__(self, args, bufsize=-1, executable=None, if preexec_fn is not None: raise ValueError("preexec_fn is not supported on Windows " "platforms") + + else: + # VxWorks + if _vxworks: + if shell: + raise ValueError("shell is not supported on VxWorks") + if preexec_fn is not None: + raise ValueError("Preexecution function is not supported on" + "VxWorks"); + if close_fds: + raise ValueError("close_fds is not supported on VxWorks") + + if start_new_session: + raise ValueError("VxWorks does not support sessions"); + + # POSIX if pass_fds and not close_fds: warnings.warn("pass_fds overriding close_fds.", RuntimeWarning) @@ -891,6 +913,9 @@ def communicate(self, input=None, timeout=None): universal_newlines. """ + if _vxworks: + timeout=30 + if self._communication_started and input: raise ValueError("Cannot send input after starting communication") @@ -1366,6 +1391,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, restore_signals, start_new_session): """Execute program (POSIX version)""" + if isinstance(args, (str, bytes)): args = [args] else: @@ -1420,7 +1446,62 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) - self.pid = _posixsubprocess.fork_exec( + if(_vxworks): + #Hack method to have child spawn with correct FD's + #copy parent std fds + #set parent stdfd's as desired child fds + #spawn child + #resture parent stdfds to std values + # + #!!!Massive caveat in that the child inherits all pipes + tmp_stdin = None; + tmp_stdout = None; + tmp_stderr = None; + #save old stdio fds + #replace stdiofds with desired child fds + if c2pwrite >= 0: + tmp_stdout = os.dup(1); + os.dup2(c2pwrite, 1); + + if p2cread >= 0: + tmp_stdin = os.dup(0); + os.dup2(p2cread, 0); + + if errwrite >= 0: + tmp_stderr = os.dup(2); + os.dup2(errwrite, 2); + tmp_cwd = None; + if cwd: + tmp_cwd = os.getcwd() + os.chdir(cwd) + if env_list is None: + env_list = [envKey + "=" + envVal for envKey,envVal in os.environ.copy().items()] + else: + env_list = [envKey + "=" + envVal for envKey,envVal in env.items()] #Sacrifice efficiency for readability + if p2cwrite > 2: + env_list.append("closeFD="+str(p2cwrite)) + self.pid = _vxwapi.rtpSpawn( + executable_list[0].decode("UTF-8"), + args,env_list, 100,0x1000000,0,0) + if tmp_cwd is not None: + os.chdir(tmp_cwd) + + + if tmp_stdin is not None: + os.dup2(tmp_stdin, 0) + os.close(tmp_stdin) + + if tmp_stdout is not None: + os.dup2(tmp_stdout, 1) + os.close(tmp_stdout) + + if tmp_stderr is not None: + os.dup2(tmp_stderr, 2) + os.close(tmp_stderr) + + + else: + self.pid = _posixsubprocess.fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, @@ -1450,6 +1531,8 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, # exception (limited in size) errpipe_data = bytearray() while True: + if _vxworks: + break part = os.read(errpipe_read, 50000) errpipe_data += part if not part or len(errpipe_data) > 50000: @@ -1623,7 +1706,6 @@ def _communicate(self, input, endtime, orig_timeout): stdout = None stderr = None - # Only create this mapping if we haven't already. if not self._communication_started: self._fileobj2output = {} @@ -1641,7 +1723,6 @@ def _communicate(self, input, endtime, orig_timeout): if self._input: input_view = memoryview(self._input) - with _PopenSelector() as selector: if self.stdin and input: selector.register(self.stdin, selectors.EVENT_WRITE) @@ -1653,11 +1734,16 @@ def _communicate(self, input, endtime, orig_timeout): while selector.get_map(): timeout = self._remaining_time(endtime) if timeout is not None and timeout < 0: - raise TimeoutExpired(self.args, orig_timeout) - + if not _vxworks: + raise TimeoutExpired(self.args, orig_timeout) + else: + break; ready = selector.select(timeout) - self._check_timeout(endtime, orig_timeout) - + #TODO Also a temporary workaround for V7COR-5635 + if not _vxworks: + self._check_timeout(endtime, orig_timeout) + else: + pass # XXX Rewrite these to use non-blocking I/O on the file # objects; they are no longer using C stdio! @@ -1678,11 +1764,8 @@ def _communicate(self, input, endtime, orig_timeout): data = os.read(key.fd, 32768) if not data: selector.unregister(key.fileobj) - key.fileobj.close() self._fileobj2output[key.fileobj].append(data) - self.wait(timeout=self._remaining_time(endtime)) - # All data exchanged. Translate lists into strings. if stdout is not None: stdout = b''.join(stdout) diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 436cbea9669e62..741e9bf9320646 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -5384,6 +5384,7 @@ def test_gaps(self): ldt = tz.fromutc(udt.replace(tzinfo=tz)) self.assertEqual(ldt.fold, 0) + @unittest.skipIf('vxworks' in sys.platform, "NOT SUPPORTED ON VXWORKS") def test_system_transitions(self): if ('Riyadh8' in self.zonename or # From tzdata NEWS file: diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index ce01c8ce586d65..b22e4940bc2071 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -24,6 +24,7 @@ except ImportError: gc = None +_vxworks = sys.platform == "vxworks"; # When tests are run from the Python build directory, it is best practice # to keep the test files in a subfolder. This eases the cleanup of leftover @@ -422,8 +423,11 @@ def _test_forever(self, tests): def display_header(self): # Print basic platform information print("==", platform.python_implementation(), *sys.version.split()) - print("==", platform.platform(aliased=True), + if not _vxworks: + print("==", platform.platform(aliased=True), "%s-endian" % sys.byteorder) + else: + print("VxWorks 7"); print("== cwd:", os.getcwd()) cpu_count = os.cpu_count() if cpu_count: diff --git a/Lib/test/test_asynchat.py b/Lib/test/test_asynchat.py index 1d147c741961e3..94881738dd8a52 100644 --- a/Lib/test/test_asynchat.py +++ b/Lib/test/test_asynchat.py @@ -211,7 +211,7 @@ def test_empty_line(self): self.assertEqual(c.contents, [b"hello world", b"", b"I'm not dead yet!"]) - + @unittest.skipIf("vxworks" in sys.platform, 'vxworks doesnt inform the server side when the client disconnects') def test_close_when_done(self): s, event = start_echo_server() s.start_resend_event = threading.Event() diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 694ddffd6879eb..e3bd76d5726270 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -18,6 +18,8 @@ TIMEOUT = 3 HAS_UNIX_SOCKETS = hasattr(socket, 'AF_UNIX') +if "vxworks" in sys.platform: + HAS_UNIX_SOCKETS = False class dummysocket: def __init__(self): diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py index 8f91bc9bf919b7..22d603d1ff946d 100644 --- a/Lib/test/test_builtin.py +++ b/Lib/test/test_builtin.py @@ -1784,7 +1784,7 @@ def test_baddecorator(self): class ShutdownTest(unittest.TestCase): - + @unittest.skipIf(sys.platform == "vxworks", "VxWorks: V7COR-5635 Needs to be fixed before this runs") def test_cleanup(self): # Issue #19255: builtins are still available at shutdown code = """if 1: diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index d8a96c49ce9699..a049fc35a73077 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -154,6 +154,8 @@ def test_non_ascii(self): # arguments as unicode (using wmain() instead of main()). @unittest.skipIf(sys.platform == 'win32', 'Windows has a native unicode API') + @unittest.skipIf('vxworks' in sys.platform, + "Not supported on VxWorks: main() does not support unicode arguments") def test_undecodable_code(self): undecodable = b"\xff" env = os.environ.copy() @@ -369,6 +371,7 @@ def test_closed_stdout(self): # Issue #7111: Python should work without standard streams @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics") + @unittest.skipIf('vxworks' in sys.platform, "Not supported on VxWorks: No preexec fn") def _test_no_stdio(self, streams): code = """if 1: import os, sys diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py index a9c1309ad6d32b..ef25172c1038f2 100644 --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -488,7 +488,8 @@ def test_pep_409_verbiage(self): self.assertTrue(text[0].startswith('Traceback')) self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) - + @unittest.skipIf('vxworks' in sys.platform, + "Not Supported on vxWorks: Non ascii names not supported") def test_non_ascii(self): # Mac OS X denies the creation of a file with an invalid UTF-8 name. # Windows allows creating a name with an arbitrary bytes name, but diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 5aea51e8b732ab..34f398780b17cd 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -1991,8 +1991,9 @@ def test_nan_to_float(self): for s in ('nan', 'nan1234', '-nan', '-nan2468'): f = float(Decimal(s)) self.assertTrue(math.isnan(f)) - sign = math.copysign(1.0, f) - self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0) + #Sign bit doesnt always have to be negative/positive https://en.wikipedia.org/wiki/IEEE_754-1985#NaN + #sign = math.copysign(1.0, f) + #self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0) def test_snan_to_float(self): Decimal = self.decimal.Decimal diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 2a9ec706467f3e..478b310253e029 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -928,6 +928,7 @@ def g(): self.assertIn("maximum recursion depth exceeded", str(v)) @cpython_only + @unittest.skipIf(sys.platform == "vxworks", "VxWorks: V7COR-5635 Needs to be fixed before this runs") def test_recursion_normalizing_exception(self): # Issue #22898. # Test that a RecursionError is raised when tstate->recursion_depth is @@ -987,6 +988,7 @@ def gen(): self.assertIn(b'Done.', out) @cpython_only + @unittest.skipIf(sys.platform == "vxworks", "VxWorks: V7COR-5635 Needs to be fixed before this runs") def test_recursion_normalizing_infinite_exception(self): # Issue #30697. Test that a RecursionError is raised when # PyErr_NormalizeException() maximum recursion depth has been @@ -1005,6 +1007,7 @@ def test_recursion_normalizing_infinite_exception(self): self.assertIn(b'Done.', out) @cpython_only + @unittest.skipIf(sys.platform == "vxworks", "VxWorks: V7COR-5635 Needs to be fixed before this runs") def test_recursion_normalizing_with_no_memory(self): # Issue #30697. Test that in the abort that occurs when there is no # memory left and the size of the Python frames stack is greater than @@ -1188,6 +1191,7 @@ def test_unhandled(self): self.assertTrue(report.endswith("\n")) @cpython_only + @unittest.skipIf(sys.platform == "vxworks", "VxWorks: V7COR-5635 Needs to be fixed before this runs") def test_memory_error_in_PyErr_PrintEx(self): code = """if 1: import _testcapi diff --git a/Lib/test/test_fcntl.py b/Lib/test/test_fcntl.py index acd5c7cc586472..4af51d6304773b 100644 --- a/Lib/test/test_fcntl.py +++ b/Lib/test/test_fcntl.py @@ -124,6 +124,7 @@ def test_fcntl_64_bit(self): finally: os.close(fd) + @unittest.skipIf('vxworks' in sys.platform, 'vxWorks (vxSim) doesnt support flock') def test_flock(self): # Solaris needs readable file for shared lock self.f = open(TESTFN, 'wb+') diff --git a/Lib/test/test_getpass.py b/Lib/test/test_getpass.py index 3452e46213a76c..d13669571f635e 100644 --- a/Lib/test/test_getpass.py +++ b/Lib/test/test_getpass.py @@ -1,10 +1,10 @@ import getpass import os +import sys import unittest from io import BytesIO, StringIO, TextIOWrapper from unittest import mock from test import support - try: import termios except ImportError: diff --git a/Lib/test/test_httpservers.py b/Lib/test/test_httpservers.py index cc829a522b88bc..7f367de58776e5 100644 --- a/Lib/test/test_httpservers.py +++ b/Lib/test/test_httpservers.py @@ -443,7 +443,7 @@ def test_get(self): # chmod() doesn't work as expected on Windows, and filesystem # permissions are ignored by root on Unix. - if os.name == 'posix' and os.geteuid() != 0: + if os.name == 'posix' and 'vxworks' not in sys.platform and os.geteuid() != 0: os.chmod(self.tempdir, 0) try: response = self.request(self.base_url + '/') diff --git a/Lib/test/test_importlib/data01/utf-8.file b/Lib/test/test_importlib/data01/utf-8.file index 1c0132ad90a192..e6365c50990fa0 100644 --- a/Lib/test/test_importlib/data01/utf-8.file +++ b/Lib/test/test_importlib/data01/utf-8.file @@ -1 +1 @@ -Hello, UTF-8 world! +Hello, UTF-8 world! diff --git a/Lib/test/test_locale.py b/Lib/test/test_locale.py index d93b3ad048be22..51376f507508c3 100644 --- a/Lib/test/test_locale.py +++ b/Lib/test/test_locale.py @@ -505,6 +505,7 @@ def test_strcoll_3303(self): self.assertRaises(TypeError, locale.strcoll, "a", None) self.assertRaises(TypeError, locale.strcoll, b"a", None) + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks does not throw error on unknown locale') def test_setlocale_category(self): locale.setlocale(locale.LC_ALL) locale.setlocale(locale.LC_TIME) diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index f59e5371acad3b..7ec741f9868afc 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -138,7 +138,7 @@ def test_file_not_found_in_home(self): def test_file_not_found_explicit(self): self.assertRaises(FileNotFoundError, netrc.netrc, file='unlikely_netrc') - + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks does not require or have a HOME directory') def test_home_not_set(self): fake_home = support.TESTFN os.mkdir(fake_home) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 9aa38e08dd6e6c..e4ef30bb1dbe83 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1300,7 +1300,7 @@ def test_issue16180(self): 'Fail to handle a syntax error in the debuggee.' .format(expected, stdout)) - + @unittest.skipIf("vxworks" in sys.platform, "vxworks segfaults without home") def test_readrc_kwarg(self): script = textwrap.dedent(""" import pdb; pdb.Pdb(readrc=False).set_trace() diff --git a/Lib/test/test_pipes.py b/Lib/test/test_pipes.py index ad01d08481c333..9e6d963a46a0a7 100644 --- a/Lib/test/test_pipes.py +++ b/Lib/test/test_pipes.py @@ -1,4 +1,5 @@ import pipes +import sys import os import string import unittest @@ -52,7 +53,7 @@ def testSimplePipe3(self): self.assertEqual(f.read(), 'HELLO WORLD #2') finally: f.close() - + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks doesnt support normal shell but somehow this is the only one that fails') def testEmptyPipeline1(self): # copy through empty pipe d = 'empty pipeline test COPY' diff --git a/Lib/test/test_pkg.py b/Lib/test/test_pkg.py index 532e8fe6d0d886..83b8271d8c1234 100644 --- a/Lib/test/test_pkg.py +++ b/Lib/test/test_pkg.py @@ -235,6 +235,7 @@ def test_6(self): """ self.run_code(s) + @unittest.skipIf('vxworks' in sys.platform, 'no __path__ in vxworks posix') def test_7(self): hier = [ ("t7.py", ""), diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py index 2cf4d3f5dfdb64..d72f8eeb8d9971 100644 --- a/Lib/test/test_platform.py +++ b/Lib/test/test_platform.py @@ -296,6 +296,7 @@ def test_parse_release_file(self): ): self.assertEqual(platform._parse_release_file(input), output) + @unittest.skipIf('vxworks' in sys.platform, 'legacy os.popen not supported by vxworks, use subprocess') def test_popen(self): mswindows = (sys.platform == "win32") diff --git a/Lib/test/test_popen.py b/Lib/test/test_popen.py index da01a878fa0a5a..ec04b357ea76b6 100644 --- a/Lib/test/test_popen.py +++ b/Lib/test/test_popen.py @@ -16,6 +16,7 @@ if ' ' in python: python = '"' + python + '"' # quote embedded space for cmdline +@unittest.skipIf('vxworks' in sys.platform, 'VxWorks does not support shell') class PopenTest(unittest.TestCase): def _do_test_commandline(self, cmdline, expected): diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 36580d55b9e22d..780f27ab4b9652 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -304,6 +304,7 @@ def test_random(self): ssl.RAND_add(bytearray(b"this is a random bytearray object"), 75.0) @unittest.skipUnless(os.name == 'posix', 'requires posix') + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks does not support os.fork') def test_random_fork(self): status = ssl.RAND_status() if not status: @@ -530,14 +531,17 @@ def bad_cert_test(self, certfile): test_wrap_socket(sock, certfile=certfile) + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_empty_cert(self): """Wrapping with an empty cert file""" self.bad_cert_test("nullcert.pem") + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_malformed_cert(self): """Wrapping with a badly formatted certificate (syntax error)""" self.bad_cert_test("badcert.pem") + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_malformed_key(self): """Wrapping with a badly formatted key (syntax error)""" self.bad_cert_test("badkey.pem") @@ -1160,6 +1164,7 @@ def test_verify_flags(self): with self.assertRaises(TypeError): ctx.verify_flags = None + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_load_cert_chain(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) # Combined key and cert in a single file @@ -1243,6 +1248,7 @@ def getpass(self): # Make sure the password function isn't called if it isn't needed ctx.load_cert_chain(CERTFILE, password=getpass_exception) + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_load_verify_locations(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx.load_verify_locations(CERTFILE) @@ -1320,6 +1326,7 @@ def test_load_verify_cadata(self): ctx.load_verify_locations(cadata=b"broken") + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_load_dh_params(self): ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ctx.load_dh_params(DHFILE) @@ -1620,7 +1627,7 @@ def test_str(self): e = ssl.SSLZeroReturnError(1, "foo") self.assertEqual(str(e), "foo") self.assertEqual(e.errno, 1) - + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_lib_reason(self): # Test the library and reason attributes ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) @@ -1881,6 +1888,7 @@ def test_connect_cadata(self): self.assertTrue(cert) @unittest.skipIf(os.name == "nt", "Can't use a socket as a file under Windows") + @unittest.skipIf('vxworks' in sys.platform, 'Not Supported on VxWorks') def test_makefile_close(self): # Issue #5238: creating a file-like object with makefile() shouldn't # delay closing the underlying "real socket" (here tested with its diff --git a/Lib/test/test_stat.py b/Lib/test/test_stat.py index 73cd901bdbf5c1..f2d1ccfb26095f 100644 --- a/Lib/test/test_stat.py +++ b/Lib/test/test_stat.py @@ -168,6 +168,7 @@ def test_link(self): self.assertS_IS("LNK", st_mode) @unittest.skipUnless(hasattr(os, 'mkfifo'), 'os.mkfifo not available') + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks fifos have to be in /fifos and do not support permissions') def test_fifo(self): try: os.mkfifo(TESTFN, 0o700) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 2a766d7c92ad82..b83bd61bd7128a 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -3185,6 +3185,7 @@ def test_communicate_stdin(self): proc.communicate(b"context") self.assertEqual(proc.returncode, 1) + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks rtpSpawn requires clean arguments') def test_invalid_args(self): with self.assertRaises(NONEXISTING_ERRORS): with subprocess.Popen(NONEXISTING_CMD, diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py index 36d5f849e1ad83..bff782d4eac0e7 100644 --- a/Lib/test/test_support.py +++ b/Lib/test/test_support.py @@ -12,6 +12,7 @@ import textwrap import time import unittest +from distutils.ccompiler import new_compiler, gen_lib_options from test import support from test.support import script_helper @@ -570,6 +571,7 @@ def id(self): self.assertFalse(support.match_test(test_chdir)) + # XXX -follows a list of untested API # make_legacy_pyc # is_resource_enabled diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 6933b41353bd56..9e2494687462b8 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -192,7 +192,7 @@ def test_recursionlimit(self): sys.setrecursionlimit(10000) self.assertEqual(sys.getrecursionlimit(), 10000) sys.setrecursionlimit(oldlimit) - + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks stack overflow behavior is not like POSIX') def test_recursionlimit_recovery(self): if hasattr(sys, 'gettrace') and sys.gettrace(): self.skipTest('fatal error if run with a trace function') diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py index 710756bde64c04..1da271659db841 100644 --- a/Lib/test/test_tempfile.py +++ b/Lib/test/test_tempfile.py @@ -448,6 +448,7 @@ def test_file_mode(self): self.assertEqual(mode, expected) @unittest.skipUnless(has_spawnl, 'os.spawnl not available') + @unittest.skipIf('vxworks' in sys.platform, 'file handles are inherited since no cloexec on vxworks') def test_noinherit(self): # _mkstemp_inner file handles are not inherited by child processes @@ -739,6 +740,7 @@ def test_choose_directory(self): os.rmdir(dir) @unittest.skipUnless(has_stat, 'os.stat not available') + @unittest.skipIf('vxworks' in sys.platform, 'vxworks mkdir doesnt respect mode on hrfs') def test_mode(self): # mkdtemp creates directories with the proper mode @@ -1225,7 +1227,8 @@ def test_basic(self): # TemporaryFile can create files # No point in testing the name params - the file has no name. tempfile.TemporaryFile() - + + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks fails externally when trying to delete the folder with fd still open') def test_has_no_name(self): # TemporaryFile creates files with no names (on this system) dir = tempfile.mkdtemp() @@ -1237,7 +1240,7 @@ def test_has_no_name(self): try: os.rmdir(dir) except: - # cleanup + #cleanup f.close() os.rmdir(dir) raise diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index eda3885ad575f3..d0e7eba6adbfb3 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -95,6 +95,7 @@ def check_ns(sec, ns): check_ns(time.clock_gettime(time.CLOCK_REALTIME), time.clock_gettime_ns(time.CLOCK_REALTIME)) + @unittest.skipIf('vxworks' in sys.platform, 'VxSim doesnt have processor time') def test_clock(self): with self.assertWarns(DeprecationWarning): time.clock() @@ -487,6 +488,8 @@ def test_monotonic(self): def test_perf_counter(self): time.perf_counter() + + @unittest.skipIf('vxworks' in sys.platform, 'VxSim doesnt support cpu time') def test_process_time(self): # process_time() should not include time spend during a sleep start = time.process_time() @@ -583,6 +586,7 @@ def test_localtime_failure(self): self.assertRaises(ValueError, time.localtime, float("nan")) self.assertRaises(ValueError, time.ctime, float("nan")) + @unittest.skipIf('vxworks' in sys.platform, 'VxSim doesnt have processor time') def test_get_clock_info(self): clocks = ['clock', 'monotonic', 'perf_counter', 'process_time', 'time'] @@ -691,13 +695,14 @@ def test_year(self, fmt=None, func=None): self.assertEqual(func(99), fmt % 99) self.assertEqual(func(999), fmt % 999) self.assertEqual(func(9999), fmt % 9999) - + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks strftime assumes 4 digit year always') def test_large_year(self): self.assertEqual(self.yearstr(12345), '12345') self.assertEqual(self.yearstr(123456789), '123456789') self.assertEqual(self.yearstr(TIME_MAXYEAR), str(TIME_MAXYEAR)) self.assertRaises(OverflowError, self.yearstr, TIME_MAXYEAR + 1) + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks doesnt support negative year') def test_negative(self): self.assertEqual(self.yearstr(-1), self._format % -1) self.assertEqual(self.yearstr(-1234), '-1234') diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py index 876fcd4199fb92..690d444e2ef479 100644 --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -762,7 +762,7 @@ def connect_ftp(self, user, passwd, host, port, dirs, headers = r.info() self.assertEqual(headers.get("Content-type"), mimetype) self.assertEqual(int(headers["Content-length"]), len(data)) - + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks has weird file pats with colons') def test_file(self): import email.utils h = urllib.request.FileHandler() diff --git a/Lib/test/test_utf8_mode.py b/Lib/test/test_utf8_mode.py index 26e2e13ec5339f..47d52974d024cc 100644 --- a/Lib/test/test_utf8_mode.py +++ b/Lib/test/test_utf8_mode.py @@ -205,6 +205,7 @@ def test_locale_getpreferredencoding(self): self.assertEqual(out, 'UTF-8 UTF-8') @unittest.skipIf(MS_WINDOWS, 'test specific to Unix') + @unittest.skipIf('vxworks' in sys.platform, 'VxWorks doesnt support unicode rtpSpawn') def test_cmd_line(self): arg = 'h\xe9\u20ac'.encode('utf-8') arg_utf8 = arg.decode('utf-8') diff --git a/Lib/test/test_uuid.py b/Lib/test/test_uuid.py index 7af1d7aec797c5..407231de3cb537 100644 --- a/Lib/test/test_uuid.py +++ b/Lib/test/test_uuid.py @@ -2,6 +2,7 @@ from test import support import builtins import contextlib +import sys import io import os import shutil @@ -481,6 +482,7 @@ def test_uuid5(self): equal(str(u), v) @unittest.skipUnless(os.name == 'posix', 'requires Posix') + @unittest.skipIf('vxworks' in sys.platform, 'no os fork in VxWorks') def testIssue8621(self): # On at least some versions of OSX self.uuid.uuid4 generates # the same sequence of UUIDs in the parent and any diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py index 5b962f7dc20b99..e4c407fca47c9c 100644 --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -383,6 +383,9 @@ def _parse(self): raise ValueError("unknown url type: %r" % self.full_url) self.host, self.selector = splithost(rest) if self.host: + if 'vxworks' in sys.platform and self.host.startswith(sys.executable.split(':')[0]): + self.host = None + return self.host = unquote(self.host) def get_method(self): diff --git a/Mac/BuildScript/resources/Welcome.rtf b/Mac/BuildScript/resources/Welcome.rtf index 1aa38193cc8850..4d42bb0b4a5633 100644 --- a/Mac/BuildScript/resources/Welcome.rtf +++ b/Mac/BuildScript/resources/Welcome.rtf @@ -24,4 +24,4 @@ \b NEW in 3.7.0b1: \b0 two installer variants (10.9+ 64-bit-only, 10.6+ 64-/32-bit), built-in Tcl/Tk 8.6 support (no additional third-party downloads!), OpenSSL 1.1.0g, and more!\ -} \ No newline at end of file +} diff --git a/Makefile.pre.in b/Makefile.pre.in index 916f03091a00bc..4cdfb20a397cf7 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -100,11 +100,23 @@ PY_LDFLAGS= $(CONFIGURE_LDFLAGS) $(LDFLAGS) NO_AS_NEEDED= @NO_AS_NEEDED@ LDLAST= @LDLAST@ SGI_ABI= @SGI_ABI@ +# +# Note: _parse_makefile in sysconfig.py will use last define of Makefile variables +# unaffected by 'ifeq' below +# this is used for building shared libraries with Setup.py +# +HAVE_DYNAMIC_LOADING=@HAVE_DYNAMIC_LOADING@ +ifeq ($(HAVE_DYNAMIC_LOADING),0) +CCSHARED= +LINKFORSHARED= +CFLAGSFORSHARED= +else CCSHARED= @CCSHARED@ LINKFORSHARED= @LINKFORSHARED@ -ARFLAGS= @ARFLAGS@ # Extra C flags added for building the interpreter object files. CFLAGSFORSHARED=@CFLAGSFORSHARED@ +endif +ARFLAGS= @ARFLAGS@ # C flags used for building the interpreter object files PY_CORE_CFLAGS= $(PY_CFLAGS) $(PY_CFLAGS_NODIST) $(PY_CPPFLAGS) $(CFLAGSFORSHARED) -DPy_BUILD_CORE # Strict or non-strict aliasing flags used to compile dtoa.c, see above @@ -450,9 +462,14 @@ DTRACE_DEPS = \ # Default target all: @DEF_MAKE_ALL_RULE@ -build_all: check-clean-src $(BUILDPYTHON) oldsharedmods sharedmods gdbhooks \ + +build_all: check-clean-src $(BUILDPYTHON) gdbhooks \ Programs/_testembed python-config +ifeq ($(HAVE_DYNAMIC_LOADING),1) +build_all: oldsharedmods sharedmods +endif + # Check that the source is clean when building out of source. check-clean-src: @if test -n "$(VPATH)" -a -f "$(srcdir)/Programs/python.o"; then \ @@ -1123,9 +1140,13 @@ altinstall: commoninstall commoninstall: check-clean-src @FRAMEWORKALTINSTALLFIRST@ \ altbininstall libinstall inclinstall libainstall \ - sharedinstall oldsharedinstall altmaninstall \ + altmaninstall \ @FRAMEWORKALTINSTALLLAST@ +ifeq ($(HAVE_DYNAMIC_LOADING),1) +commoninstall: sharedinstall oldsharedinstall +endif + # Install shared libraries enabled by Setup DESTDIRS= $(exec_prefix) $(LIBDIR) $(BINLIBDEST) $(DESTSHARED) diff --git a/Misc/NEWS.d/next/Build/2017-10-30.bpo-30914.brk.rst b/Misc/NEWS.d/next/Build/2017-10-30.bpo-30914.brk.rst new file mode 100644 index 00000000000000..299e03a1da93f4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2017-10-30.bpo-30914.brk.rst @@ -0,0 +1 @@ +Allow cross-build of VxWorks if --host=*-wrs-vxworks is passed to configure \ No newline at end of file diff --git a/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst b/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst new file mode 100644 index 00000000000000..9730ab4a610150 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-02-18-13-04-59.bpo-25988.ACidKC.rst @@ -0,0 +1,2 @@ +Emit a :exc:`DeprecationWarning` when using or importing an ABC directly +from :mod:`collections` rather than from :mod:`collections.abc`. diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index bdc372811598e5..afda3918320c86 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -75,6 +75,10 @@ #include #endif +#ifdef __VXWORKS__ +#define alloca __builtin_alloca +#endif + #if defined(_DEBUG) || defined(__MINGW32__) /* Don't use structured exception handling on Windows if this is defined. MingW, AFAIK, doesn't support it. diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 0d5bf3b22114e5..cfe570d1da46bf 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -353,7 +353,7 @@ _io_FileIO___init___impl(fileio *self, PyObject *nameobj, const char *mode, #ifdef MS_WINDOWS flags |= O_NOINHERIT; -#elif defined(O_CLOEXEC) +#elif defined(O_CLOEXEC)// && !defined(__VXWORKS__) // VXWorks doesnt support O_CLOEXEC flags |= O_CLOEXEC; #endif diff --git a/Modules/_multiprocessing/multiprocessing.h b/Modules/_multiprocessing/multiprocessing.h index 512bc17f23d46b..29decdf15f9c98 100644 --- a/Modules/_multiprocessing/multiprocessing.h +++ b/Modules/_multiprocessing/multiprocessing.h @@ -32,8 +32,12 @@ # define BOOL int # define UINT32 uint32_t # define INT32 int32_t -# define TRUE 1 -# define FALSE 0 +# ifndef TRUE +# define TRUE 1 +# endif +# ifndef FALSE +# define FALSE 0 +# endif # define INVALID_HANDLE_VALUE (-1) #endif diff --git a/Modules/_pickle.c b/Modules/_pickle.c index aa672afacffd45..b9f76310728c73 100644 --- a/Modules/_pickle.c +++ b/Modules/_pickle.c @@ -28,6 +28,10 @@ enum { DEFAULT_PROTOCOL = 4 }; +#ifdef __VXWORKS__ +#undef NONE +#endif + /* Pickle opcodes. These must be kept updated with pickle.py. Extensive docs are in pickletools.py. */ enum opcode { diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index afce6c9448952b..b4bb9bce44ae3d 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -10,7 +10,17 @@ #include "Python.h" #include #include "structmember.h" +//Hack to make this compile statically +//ref: https://bugs.python.org/issue19348 +#ifdef Py_BUILD_CORE +#undef Py_BUILD_CORE #include "datetime.h" +#define Py_BUILD_CORE +#else +#include "datetime.h" +#endif + + #include "marshal.h" #include diff --git a/Modules/_vxwapi.c b/Modules/_vxwapi.c new file mode 100644 index 00000000000000..98e2e099c9df12 --- /dev/null +++ b/Modules/_vxwapi.c @@ -0,0 +1,244 @@ +/************************************************ + * VxWorks Compatibility Wrapper + * + * Python interface to vxWorks methods + * + * Author: Oscar Shi (co-op winter2018) + * + * modification history + * -------------------- + * 28mar18 added pathisabsolute wrapper + * 12jan18 created + * + ************************************************/ + +#if defined(__VXWORKS__) +#include +#include +#include +#include "clinic/_vxwapi.c.h" + + +// *********************************************************************************/ +// Largely copied from +// https://github.com/python-ldap/python-ldap/blob/master/Modules/LDAPObject.c#L276 + +//utility function for cStrings_from_PyList +static void +free_attrs( char*** attrsp ) { + char **attrs = *attrsp; + char **p; + + if (attrs == NULL) + return; + + *attrsp = NULL; + for (p = attrs; *p != NULL; p++) { + PyMem_DEL(*p); + } + PyMem_DEL(attrs); +} + +static +int +cStrings_from_PyList( PyObject *attrlist, char***attrsp ) { + + char **attrs = NULL; + PyObject *seq = NULL; + + if (attrlist == Py_None) { + /* None means a NULL attrlist */ +#if PY_MAJOR_VERSION == 2 + } else if (PyBytes_Check(attrlist)) { +#else + } else if (PyUnicode_Check(attrlist)) { +#endif + goto error; + } else { + PyObject *item = NULL; + Py_ssize_t i, len, strlen; +#if PY_MAJOR_VERSION >= 3 + const char *str; +#else + char *str; +#endif + + seq = PySequence_Fast(attrlist, "expected list of strings or None"); + if (seq == NULL) + goto error; + + len = PySequence_Length(attrlist); + + attrs = PyMem_NEW(char *, len + 1); + if (attrs == NULL) + goto nomem; + + for (i = 0; i < len; i++) { + attrs[i] = NULL; + item = PySequence_Fast_GET_ITEM(seq, i); + if (item == NULL) + goto error; +#if PY_MAJOR_VERSION == 2 + /* Encoded in Python to UTF-8 */ + if (!PyBytes_Check(item)) { + goto error; + } + if (PyBytes_AsStringAndSize(item, &str, &strlen) == -1) { + goto error; + } +#else + if (!PyUnicode_Check(item)) { + goto error; + } + str = PyUnicode_AsUTF8AndSize(item, &strlen); +#endif + /* Make a copy. PyBytes_AsString* / + * PyUnicode_AsUTF8* return + * * internal values that must + * be treated like const char. + * Python + * * 3.7 actually + * returns a const + * char. + * */ + attrs[i] = (char *)PyMem_NEW(char *, strlen + 1); + if (attrs[i] == NULL) + goto nomem; + memcpy(attrs[i], str, strlen + 1); + } + attrs[len] = NULL; + Py_DECREF(seq); + } + + *attrsp = attrs; + return 1; + +nomem: + PyErr_NoMemory(); +error: + Py_XDECREF(seq); + free_attrs(&attrs); + return 0; +} + + +// end of copied section +//****************************************************************************/ + +/*[clinic input] +module _vxwapi +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6efcf3b26a262ef1]*/ + +/* + * BOOL pathIsAbsolute + * ( + * const char *filepath, Filepath to test + * const char **pNametail Where to put ptr to tail of dev name + * ) + */ + +/*[clinic input] +_vxwapi.isAbs + + path: str + / + +Check if path is an absolute path on VxWorks (since not all VxWorks absolute paths start with /) +[clinic start generated code]*/ + +static PyObject * +_vxwapi_isAbs_impl(PyObject *module, const char *path) +/*[clinic end generated code: output=c6929732e0e3b56e input=9814f3ed8f171bcd]*/ +{ + long ret = (long)_pathIsAbsolute (path,NULL); + + return PyLong_FromLong(ret); +} + + +/* + * RTP_ID rtpSpawn + * ( + * const char *rtpFileName, Null terminated path to executable + * const char *argv[], Pointer to NULL terminated argv array + * const char *envp[], Pointer to NULL terminated envp array + * int priority, Priority of initial task + * size_t uStackSize, User space stack size for initial task + * int options, The options passed to the RTP + * int taskOptions Task options for the RTPs initial task + * ) + * + */ + + + +/*[clinic input] +_vxwapi.rtpSpawn + + rtpFileName: str + argv: object(subclass_of='&PyList_Type') + envp: object(subclass_of='&PyList_Type') + priority: int + uStackSize: unsigned_int(bitwise=True) + options: int + taskOptions: int + / + +Spawn a real time process in the vxWorks OS +[clinic start generated code]*/ + +static PyObject * +_vxwapi_rtpSpawn_impl(PyObject *module, const char *rtpFileName, + PyObject *argv, PyObject *envp, int priority, + unsigned int uStackSize, int options, int taskOptions) +/*[clinic end generated code: output=4a3c98870a33cf6a input=02234123b73e4a92]*/ + +{ + char** argvp; + char** envpp; + //Convert PyObjects to c type pointers to array of strings (char*) + if(!cStrings_from_PyList(argv,&argvp)) + goto error; + if(!cStrings_from_PyList(envp,&envpp)) + goto error; + + int PID = (int) rtpSpawn(rtpFileName,(const char ** ) argvp, + (const char **) envpp, priority, uStackSize, options, taskOptions); + if(PID == RTP_ID_ERROR){ + PyErr_SetString(PyExc_RuntimeError,"RTPSpawn failed to spawn task"); + goto error; + } + + return Py_BuildValue("i", PID); +error: + return NULL; +} + + + + +static PyMethodDef _vxwapiMethods[] = { + _VXWAPI_RTPSPAWN_METHODDEF + _VXWAPI_ISABS_METHODDEF + { NULL, NULL } +}; + +static struct PyModuleDef _vxwapimodule = { + PyModuleDef_HEAD_INIT, + "_vxwapi", + NULL, + -1, + _vxwapiMethods +}; + +PyMODINIT_FUNC +PyInit__vxwapi(void){ + return PyModule_Create(&_vxwapimodule); +} + + + + + +#endif diff --git a/Modules/clinic/_vxwapi.c.h b/Modules/clinic/_vxwapi.c.h new file mode 100644 index 00000000000000..39f60a495afc28 --- /dev/null +++ b/Modules/clinic/_vxwapi.c.h @@ -0,0 +1,84 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +#if defined(__VXWORKS__) + +PyDoc_STRVAR(_vxwapi_isAbs__doc__, +"isAbs($module, path, /)\n" +"--\n" +"\n" +"Check if path is an absolute path on VxWorks (since not all VxWorks absolute paths start with /)"); + +#define _VXWAPI_ISABS_METHODDEF \ + {"isAbs", (PyCFunction)_vxwapi_isAbs, METH_O, _vxwapi_isAbs__doc__}, + +static PyObject * +_vxwapi_isAbs_impl(PyObject *module, const char *path); + +static PyObject * +_vxwapi_isAbs(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + const char *path; + + if (!PyArg_Parse(arg, "s:isAbs", &path)) { + goto exit; + } + return_value = _vxwapi_isAbs_impl(module, path); + +exit: + return return_value; +} + +#endif /* defined(__VXWORKS__) */ + +#if defined(__VXWORKS__) + +PyDoc_STRVAR(_vxwapi_rtpSpawn__doc__, +"rtpSpawn($module, rtpFileName, argv, envp, priority, uStackSize,\n" +" options, taskOptions, /)\n" +"--\n" +"\n" +"Spawn a real time process in the vxWorks OS"); + +#define _VXWAPI_RTPSPAWN_METHODDEF \ + {"rtpSpawn", (PyCFunction)_vxwapi_rtpSpawn, METH_FASTCALL, _vxwapi_rtpSpawn__doc__}, + +static PyObject * +_vxwapi_rtpSpawn_impl(PyObject *module, const char *rtpFileName, + PyObject *argv, PyObject *envp, int priority, + unsigned int uStackSize, int options, int taskOptions); + +static PyObject * +_vxwapi_rtpSpawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + const char *rtpFileName; + PyObject *argv; + PyObject *envp; + int priority; + unsigned int uStackSize; + int options; + int taskOptions; + + if (!_PyArg_ParseStack(args, nargs, "sO!O!iIii:rtpSpawn", + &rtpFileName, &PyList_Type, &argv, &PyList_Type, &envp, &priority, &uStackSize, &options, &taskOptions)) { + goto exit; + } + return_value = _vxwapi_rtpSpawn_impl(module, rtpFileName, argv, envp, priority, uStackSize, options, taskOptions); + +exit: + return return_value; +} + +#endif /* defined(__VXWORKS__) */ + +#ifndef _VXWAPI_ISABS_METHODDEF + #define _VXWAPI_ISABS_METHODDEF +#endif /* !defined(_VXWAPI_ISABS_METHODDEF) */ + +#ifndef _VXWAPI_RTPSPAWN_METHODDEF + #define _VXWAPI_RTPSPAWN_METHODDEF +#endif /* !defined(_VXWAPI_RTPSPAWN_METHODDEF) */ +/*[clinic end generated code: output=2a2f3f7db33c7f47 input=a9049054013a1b77]*/ diff --git a/Modules/clinic/posixmodule.c.h b/Modules/clinic/posixmodule.c.h index 4054389d15f33e..a5b30a4d3b0f71 100644 --- a/Modules/clinic/posixmodule.c.h +++ b/Modules/clinic/posixmodule.c.h @@ -1775,8 +1775,8 @@ os_posix_spawn(PyObject *module, PyObject *const *args, Py_ssize_t nargs) #endif /* defined(HAVE_POSIX_SPAWN) */ -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) PyDoc_STRVAR(os_spawnv__doc__, "spawnv($module, mode, path, argv, /)\n" "--\n" @@ -1817,9 +1817,9 @@ os_spawnv(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) */ +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ -#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) +#if (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) PyDoc_STRVAR(os_spawnve__doc__, "spawnve($module, mode, path, argv, env, /)\n" @@ -1865,7 +1865,7 @@ os_spawnve(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV)) */ +#endif /* (defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN)) */ #if defined(HAVE_FORK) diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index f1da9f7a839fdb..d93d1bccf9007c 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -13,6 +13,9 @@ #ifdef HAVE_SYS_RESOURCE_H # include #endif +#ifdef __VXWORKS__ +# include +#endif /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */ #define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024) diff --git a/Modules/fcntlmodule.c b/Modules/fcntlmodule.c index 77ddebf3ee0d22..d79ac1479112f8 100644 --- a/Modules/fcntlmodule.c +++ b/Modules/fcntlmodule.c @@ -15,6 +15,10 @@ #include #endif +#ifdef __VXWORKS__ +#include /* ioctl() */ +#endif + /*[clinic input] module fcntl [clinic start generated code]*/ diff --git a/Modules/getbuildinfo.c b/Modules/getbuildinfo.c index 5f941a26e1d54c..92ffa803cd8de4 100644 --- a/Modules/getbuildinfo.c +++ b/Modules/getbuildinfo.c @@ -4,6 +4,11 @@ #include #endif +#ifdef __VXWORKS__ +#undef DATE +#undef TIME +#endif + #ifndef DATE #ifdef __DATE__ #define DATE __DATE__ diff --git a/Modules/getpath.c b/Modules/getpath.c index e6a3e8e78cd3ee..ebbfa26bb87b99 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -7,6 +7,8 @@ #include #include + + #ifdef __APPLE__ # include #endif @@ -92,7 +94,7 @@ * process to find the installed Python tree. * * An embedding application can use Py_SetPath() to override all of - * these authomatic path computations. + * these automatic path computations. * * NOTE: Windows MSVC builds use PC/getpathp.c instead! */ @@ -259,13 +261,31 @@ joinpath(wchar_t *buffer, wchar_t *stuff) buffer[n+k] = '\0'; } +#ifdef __VXWORKS__ + +// Vxworks has abs paths that dont start with / +// THIS IS A TEMPORARY HACK +static int +checkDev(wchar_t *p) { + int i = wcscspn(p,L":"); + int b = wcscspn(p,L"/"); + if(i < b) return 1; + return 0; +} + +#endif /* copy_absolute requires that path be allocated at least MAXPATHLEN + 1 bytes and that p be no more than MAXPATHLEN bytes. */ static void copy_absolute(wchar_t *path, wchar_t *p, size_t pathlen) { + +#ifdef __VXWORKS__ + if (checkDev(p) || p[0] == SEP) { +#else if (p[0] == SEP) { +#endif wcscpy(path, p); } else { @@ -416,6 +436,7 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; + /* If PYTHONHOME is set, we believe it unconditionally */ if (core_config->home) { @@ -460,11 +481,16 @@ search_for_exec_prefix(const _PyCoreConfig *core_config, } } + /* Search from argv0_path, until root is found */ copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1); do { n = wcslen(exec_prefix); +#ifdef __VXWORKS__ + joinpath(exec_prefix, L"lib/common/python" VERSION); +#else joinpath(exec_prefix, calculate->lib_python); +#endif joinpath(exec_prefix, L"lib-dynload"); if (isdir(exec_prefix)) { return 1; @@ -500,7 +526,12 @@ calculate_exec_prefix(const _PyCoreConfig *core_config, "Could not find platform dependent libraries \n"); } wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); +#ifdef __VXWORKS__ + joinpath(exec_prefix, L"lib/common/" VERSION); + joinpath(exec_prefix, L"lib-dynload"); +#else joinpath(exec_prefix, L"lib/lib-dynload"); +#endif } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ } @@ -513,6 +544,9 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) reduce(exec_prefix); reduce(exec_prefix); reduce(exec_prefix); +#ifdef __VXWORKS__ //vxworks has an added /common/ to path + reduce(exec_prefix); +#endif if (!exec_prefix[0]) { wcscpy(exec_prefix, separator); } @@ -827,16 +861,16 @@ calculate_module_search_path(const _PyCoreConfig *core_config, buf[end] = '\0'; } else { - wcscat(buf, defpath); + wcscat(buf, defpath); break; } defpath = delim + 1; } wcscat(buf, delimiter); + /* Finally, on goes the directory for dynamic-load modules */ wcscat(buf, exec_prefix); - config->module_search_path = buf; return _Py_INIT_OK(); } @@ -935,7 +969,6 @@ calculate_path_impl(const _PyCoreConfig *core_config, } calculate_reduce_exec_prefix(calculate, exec_prefix); - config->exec_prefix = _PyMem_RawWcsdup(exec_prefix); if (config->exec_prefix == NULL) { return _Py_INIT_NO_MEMORY(); diff --git a/Modules/main.c b/Modules/main.c index f6b51043007bcc..f6ec548e5ca8d3 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -1353,6 +1353,7 @@ pymain_update_sys_path(_PyMain *pymain, PyObject *path0) return -1; } + /* Prepend path0 to sys.path */ if (PyList_Insert(sys_path, 0, path0) < 0) { pymain->err = _Py_INIT_ERR("sys.path.insert(0, path0) failed"); diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index e6721032f211b7..40b2ab66413c64 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -174,6 +174,7 @@ corresponding Unix manual entries for more information on calls."); #define HAVE_FSYNC 1 #define fsync _commit #else +#ifndef __VXWORKS__ /* Unix functions that the configure script doesn't check for */ #define HAVE_EXECV 1 #define HAVE_FORK 1 @@ -184,6 +185,7 @@ corresponding Unix manual entries for more information on calls."); #define HAVE_GETEUID 1 #define HAVE_GETGID 1 #define HAVE_GETPPID 1 +#endif #define HAVE_GETUID 1 #define HAVE_KILL 1 #define HAVE_OPENDIR 1 @@ -246,6 +248,18 @@ extern int lstat(const char *, struct stat *); #endif /* !_MSC_VER */ +#if defined(__VXWORKS__) +#include +#include +#define HAVE_RTPSPAWN 1 +#ifndef _P_WAIT +#define _P_WAIT 3 +#define _P_NOWAIT 2 +#define _P_NOWAITO 1 +#define _OLD_P_OVERLAY 0 +#define _P_OVERLAY 0 +#endif +#endif #ifdef HAVE_POSIX_SPAWN #include #endif @@ -1526,8 +1540,8 @@ win32_wchdir(LPCWSTR path) int is_unc_like_path = (wcsncmp(new_path, L"\\\\", 2) == 0 || wcsncmp(new_path, L"//", 2) == 0); if (!is_unc_like_path) { - env[1] = new_path[0]; - result = SetEnvironmentVariableW(env, new_path); + env[1] = new_path[0]; + result = SetEnvironmentVariableW(env, new_path); } if (new_path != path_buf) PyMem_RawFree(new_path); @@ -3782,10 +3796,11 @@ os__getfinalpathname_impl(PyObject *module, path_t *path) cleanup: if (target_path != buf) { - PyMem_Free(target_path); + PyMem_Free(target_path); } CloseHandle(hFile); return result; + } /*[clinic input] @@ -3910,9 +3925,9 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) result = mkdirat(dir_fd, path->narrow, mode); else #endif -#if defined(__WATCOMC__) && !defined(__QNX__) +#if defined(__WATCOMC__) && !defined(__QNX__) && !defined(__VXWORKS__) result = mkdir(path->narrow); -#else +#else result = mkdir(path->narrow, mode); #endif Py_END_ALLOW_THREADS @@ -4798,7 +4813,7 @@ os__exit_impl(PyObject *module, int status) #define EXECV_CHAR char #endif -#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) +#if defined(HAVE_EXECV) || defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) static void free_string_array(EXECV_CHAR **array, Py_ssize_t count) { @@ -4836,7 +4851,7 @@ fsconvert_strdup(PyObject *o, EXECV_CHAR **out) } #endif -#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) +#if defined(HAVE_EXECV) || defined (HAVE_FEXECVE) || defined (HAVE_RTPSPAWN) static EXECV_CHAR** parse_envlist(PyObject* env, Py_ssize_t *envc_ptr) { @@ -5317,7 +5332,7 @@ os_posix_spawn_impl(PyObject *module, path_t *path, PyObject *argv, #endif /* HAVE_POSIX_SPAWN */ -#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) +#if defined(HAVE_SPAWNV) || defined(HAVE_WSPAWNV) || defined(HAVE_RTPSPAWN) /*[clinic input] os.spawnv @@ -5394,6 +5409,11 @@ os_spawnv_impl(PyObject *module, int mode, path_t *path, PyObject *argv) _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnv(mode, path->wide, argvlist); +#elif defined (HAVE_RTPSPAWN) + spawnval = rtpSpawn(path->narrow, (const char **)argvlist, + NULL, 100, 0x1000000, 0, 0); + if ( (spawnval != RTP_ID_ERROR) && (mode == _P_WAIT) ) + waitpid(spawnval, &spawnval, 0); #else spawnval = _spawnv(mode, path->narrow, argvlist); #endif @@ -5499,6 +5519,11 @@ os_spawnve_impl(PyObject *module, int mode, path_t *path, PyObject *argv, _Py_BEGIN_SUPPRESS_IPH #ifdef HAVE_WSPAWNV spawnval = _wspawnve(mode, path->wide, argvlist, envlist); +#elif defined (HAVE_RTPSPAWN) + spawnval = rtpSpawn(path->narrow, (const char **)argvlist, + (const char **)envlist, 100, 0x1000000, 0, 0); + if ( (spawnval != RTP_ID_ERROR) && (mode == _P_WAIT) ) + waitpid(spawnval, &spawnval, 0); #else spawnval = _spawnve(mode, path->narrow, argvlist, envlist); #endif @@ -7490,7 +7515,7 @@ _dirnameW(WCHAR *path) for(ptr = path + length; ptr != path; ptr--) { if (*ptr == L'\\' || *ptr == L'/') { break; - } + } } *ptr = 0; return 0; @@ -8793,7 +8818,13 @@ os_pipe_impl(PyObject *module) #ifdef HAVE_PIPE2 Py_BEGIN_ALLOW_THREADS + +//VXWORKS doesnt support O_CLOEXEC yet ref: V7COR-4478 +#ifdef __VXWORKS__ + res = pipe2(fds, 0); +#else res = pipe2(fds, O_CLOEXEC); +#endif Py_END_ALLOW_THREADS if (res != 0 && errno == ENOSYS) @@ -11487,7 +11518,7 @@ PyDoc_STRVAR(termsize__doc__, "This function will only be defined if an implementation is\n" \ "available for this system.\n" \ "\n" \ - "shutil.get_terminal_size is the high-level function which should\n" \ + "shutil.get_terminal_size is the high-level function which should \n" \ "normally be used, os.get_terminal_size is the low-level implementation."); static PyObject* @@ -11594,7 +11625,9 @@ os_cpu_count_impl(PyObject *module) ncpu = sysinfo.dwNumberOfProcessors; } #elif defined(__hpux) - ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); + ncpu = mpctl(MPC_GETNUMSPUS, NULL, NULL); +#elif defined(__VXWORKS__) + ncpu = __builtin_popcount(vxCpuEnabledGet()); #elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) ncpu = sysconf(_SC_NPROCESSORS_ONLN); #elif defined(__DragonFly__) || \ @@ -13400,11 +13433,13 @@ all_ins(PyObject *m) if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1; #endif -#ifdef HAVE_SPAWNV +#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN) if (PyModule_AddIntConstant(m, "P_WAIT", _P_WAIT)) return -1; if (PyModule_AddIntConstant(m, "P_NOWAIT", _P_NOWAIT)) return -1; - if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; if (PyModule_AddIntConstant(m, "P_NOWAITO", _P_NOWAITO)) return -1; +#endif +#if defined(HAVE_SPAWNV) + if (PyModule_AddIntConstant(m, "P_OVERLAY", _OLD_P_OVERLAY)) return -1; if (PyModule_AddIntConstant(m, "P_DETACH", _P_DETACH)) return -1; #endif diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 7916160143840c..1908a210cf9144 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -1036,11 +1036,18 @@ fill_siginfo(siginfo_t *si) PyStructSequence_SET_ITEM(result, 0, PyLong_FromLong((long)(si->si_signo))); PyStructSequence_SET_ITEM(result, 1, PyLong_FromLong((long)(si->si_code))); +#ifdef __VXWORKS__ + PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(0L)); + PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(0L)); + PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(0L)); + PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(0L)); +#else PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong((long)(si->si_errno))); PyStructSequence_SET_ITEM(result, 3, PyLong_FromPid(si->si_pid)); PyStructSequence_SET_ITEM(result, 4, _PyLong_FromUid(si->si_uid)); PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong((long)(si->si_status))); +#endif #ifdef HAVE_SIGINFO_T_SI_BAND PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(si->si_band)); #else diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c7a07512026b36..38148ecfb95ed7 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -164,7 +164,7 @@ if_indextoname(index) -- return the corresponding interface name\n\ # undef HAVE_GETHOSTBYNAME_R_6_ARG #endif -#if defined(__OpenBSD__) +#if defined(__OpenBSD__) || defined(__VXWORKS__) # include #endif @@ -186,6 +186,16 @@ if_indextoname(index) -- return the corresponding interface name\n\ # endif #endif +#ifdef __VXWORKS__ +# include +# include +# define gethostbyaddr_r ipcom_gethostbyaddr_r +#ifndef _WRS_CONFIG_PYTHON_LIBS_STATIC +// Shared Lib build +#endif +# define h_errno errno +#endif + #if !defined(HAVE_GETHOSTBYNAME_R) && !defined(MS_WINDOWS) # define USE_GETHOSTBYNAME_LOCK #endif @@ -592,7 +602,6 @@ set_error(void) return PyErr_SetFromErrno(PyExc_OSError); } - static PyObject * set_herror(int h_error) { @@ -652,12 +661,13 @@ internal_setblocking(PySocketSockObject *s, int block) Py_BEGIN_ALLOW_THREADS #ifndef MS_WINDOWS -#if (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)) +#if TRUE || (defined(HAVE_SYS_IOCTL_H) && defined(FIONBIO)) block = !block; if (ioctl(s->sock_fd, FIONBIO, (unsigned int *)&block) == -1) goto done; #else delay_flag = fcntl(s->sock_fd, F_GETFL, 0); + printf("ERRNO: %i" , errno); if (delay_flag == -1) goto done; if (block) @@ -972,7 +982,7 @@ init_sockobject(PySocketSockObject *s, return 0; } - +#ifdef HAVE_SOCKETPAIR /* Create a new socket object. This just creates the object and initializes it. If the creation fails, return NULL and set an exception (implicit @@ -992,7 +1002,7 @@ new_sockobject(SOCKET_T fd, int family, int type, int proto) } return s; } - +#endif /* Lock to allow python interpreter to continue, but only allow one thread to be in gethostbyname or getaddrinfo */ @@ -1257,6 +1267,7 @@ makesockaddr(SOCKET_T sockfd, struct sockaddr *addr, size_t addrlen, int proto) const struct sockaddr_in *a = (const struct sockaddr_in *)addr; PyObject *addrobj = make_ipv4_addr(a); PyObject *ret = NULL; + if (addrobj) { ret = Py_BuildValue("Oi", addrobj, ntohs(a->sin_port)); Py_DECREF(addrobj); @@ -2590,6 +2601,7 @@ sock_setblocking(PySocketSockObject *s, PyObject *arg) if (internal_setblocking(s, block) == -1) { return NULL; } + Py_RETURN_NONE; } @@ -2677,7 +2689,6 @@ sock_settimeout(PySocketSockObject *s, PyObject *arg) return NULL; s->sock_timeout = timeout; - int block = timeout < 0; /* Blocking mode for a Python socket object means that operations like :meth:`recv` or :meth:`sendall` will block the execution of @@ -5616,6 +5627,7 @@ Return the service name from a port number and protocol name.\n\ The optional protocol name, if given, should be 'tcp' or 'udp',\n\ otherwise any protocol will match."); +#ifndef __VXWORKS__ /* Python interface to getprotobyname(name). This only returns the protocol number, since the other info is already known or not useful (like the list of aliases). */ @@ -5642,6 +5654,7 @@ PyDoc_STRVAR(getprotobyname_doc, "getprotobyname(name) -> integer\n\ \n\ Return the protocol number for the named protocol. (Rarely used.)"); +#endif static PyObject * socket_close(PyObject *self, PyObject *fdobj) @@ -6605,8 +6618,10 @@ static PyMethodDef socket_methods[] = { METH_VARARGS, getservbyname_doc}, {"getservbyport", socket_getservbyport, METH_VARARGS, getservbyport_doc}, +#ifndef __VXWORKS__ {"getprotobyname", socket_getprotobyname, METH_VARARGS, getprotobyname_doc}, +#endif {"close", socket_close, METH_O, close_doc}, #ifndef NO_DUP diff --git a/Modules/socketmodule.h b/Modules/socketmodule.h index fdb4e871cef81e..9242cee9ec65d4 100644 --- a/Modules/socketmodule.h +++ b/Modules/socketmodule.h @@ -39,6 +39,11 @@ typedef int socklen_t; # endif /* IPPROTO_IPV6 */ #endif /* MS_WINDOWS */ +#ifdef __VXWORKS__ +# include +#endif /* VXWORKS */ + + #ifdef HAVE_SYS_UN_H # include #else diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c index a5807dcce9ce5b..5de155abe29cfd 100644 --- a/Modules/syslogmodule.c +++ b/Modules/syslogmodule.c @@ -54,6 +54,11 @@ Revision history: #include +#ifndef LOG_UPTO +/* all priorities through pri */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) +#endif + /* only one instance, only one syslog, so globals should be ok */ static PyObject *S_ident_o = NULL; /* identifier, held by openlog() */ static char S_log_open = 0; diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 998216cc8fdbdf..7e6f935e5bf9a3 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -1491,7 +1491,7 @@ PyDoc_STRVAR(get_clock_info_doc, \n\ Get information of the specified clock."); -#if !defined(HAVE_TZNAME) || defined(__GLIBC__) || defined(__CYGWIN__) +#if defined(__VXWORKS__) || !defined(HAVE_TZNAME) || defined(__GLIBC__) || defined(__CYGWIN__) static void get_zone(char *zone, int n, struct tm *p) { @@ -1532,7 +1532,7 @@ PyInit_timezone(PyObject *m) { And I'm lazy and hate C so nyer. */ -#if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__) +#if !defined(__VXWORKS__) && defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__) PyObject *otz0, *otz1; tzset(); PyModule_AddIntConstant(m, "timezone", timezone); diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 67f9e5d5b4ef7a..90f498eeda8810 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -784,8 +784,13 @@ float_pow(PyObject *v, PyObject *w, PyObject *z) * the platform pow to step in and do the rest. */ errno = 0; +#ifndef __VXWORKS__ PyFPE_START_PROTECT("pow", return NULL) ix = pow(iv, iw); +#else + PyFPE_START_PROTECT("powl", return NULL) + ix = powl(iv, iw); +#endif PyFPE_END_PROTECT(ix) Py_ADJUST_ERANGE1(ix); if (negate_result) diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c index 073b2ea8dbda74..3df4046ab0ca08 100644 --- a/Python/bootstrap_hash.c +++ b/Python/bootstrap_hash.c @@ -18,6 +18,11 @@ # if !defined(HAVE_GETRANDOM) && defined(HAVE_GETRANDOM_SYSCALL) # include # endif +# ifdef __VXWORKS__ +# include +# include +# include +# endif #endif #ifdef Py_DEBUG @@ -505,6 +510,7 @@ pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise) ENOSYS or EPERM. Fall back on reading from /dev/urandom. */ #endif + return dev_urandom(buffer, size, raise); #endif } diff --git a/Python/fileutils.c b/Python/fileutils.c index 32aeea4f10374b..23610fcbdd4ef9 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -449,7 +449,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, int current_locale, int surrogateescape) { if (current_locale) { -#ifdef __ANDROID__ +#if defined(__ANDROID__) || defined(__VXWORKS__) return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason, surrogateescape); #else @@ -457,7 +457,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, #endif } -#if defined(__APPLE__) || defined(__ANDROID__) +#if defined(__APPLE__) || defined(__ANDROID__) || defined(__VXWORKS__) return _Py_DecodeUTF8Ex(arg, strlen(arg), wstr, wlen, reason, surrogateescape); #else @@ -478,7 +478,7 @@ _Py_DecodeLocaleEx(const char* arg, wchar_t **wstr, size_t *wlen, #endif return decode_current_locale(arg, wstr, wlen, reason, surrogateescape); -#endif /* __APPLE__ or __ANDROID__ */ +#endif /* __APPLE__ or __ANDROID__ or __VXWORKS__ */ } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index a9b9470c726521..4fd2462a024cab 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -56,6 +56,7 @@ extern grammar _PyParser_Grammar; /* From graminit.c */ static _PyInitError add_main_module(PyInterpreterState *interp); static _PyInitError initfsencoding(PyInterpreterState *interp); static _PyInitError initsite(void); +static void initVxworksSubprocess(void); static _PyInitError init_sys_streams(PyInterpreterState *interp); static _PyInitError initsigs(void); static void call_py_exitfuncs(PyInterpreterState *); @@ -276,7 +277,7 @@ get_locale_encoding(void) return NULL; } return get_codec_name(codeset); -#elif defined(__ANDROID__) +#elif defined(__ANDROID__) || defined(__VXWORKS__) return get_codec_name("UTF-8"); #else PyErr_SetNone(PyExc_NotImplementedError); @@ -889,6 +890,10 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) return err; } } +#ifdef __VXWORKS__ + initVxworksSubprocess(); +#endif + return _Py_INIT_OK(); } @@ -1316,7 +1321,9 @@ new_interpreter(PyThreadState **tstate_p) PyDict_SetItemString(interp->sysdict, "modules", modules); _PySys_EndInit(interp->sysdict, &interp->config); } - + PyObject *sys_path = PySys_GetObject("path"); + PyObject* objectsRepresentation = PyObject_Repr(sys_path); + const char* s = PyBytes_AS_STRING(PyUnicode_AsUTF8String(objectsRepresentation)); bimod = _PyImport_FindBuiltin("builtins", modules); if (bimod != NULL) { interp->builtins = PyModule_GetDict(bimod); @@ -1556,6 +1563,22 @@ initsite(void) return _Py_INIT_OK(); } +#ifdef __VXWORKS__ +static void +initVxworksSubprocess(void) +{ + const char* s = getenv("closeFD"); + if(s) + { + int fd = atoi(s); + if(fd > 2){ + int err = close(fd); + } + putenv("closeFD="); + } +} +#endif + /* Check if a file descriptor is valid or not. Return 0 if the file descriptor is invalid, return non-zero otherwise. */ static int diff --git a/configure b/configure index f9eee2c028660f..34f77ce5b989c6 100755 --- a/configure +++ b/configure @@ -643,6 +643,7 @@ HAVE_GETHOSTBYNAME_R_6_ARG LIBOBJS TRUE MACHDEP_OBJS +HAVE_DYNAMIC_LOADING DYNLOADFILE DLINCLDIR DTRACE_OBJS @@ -781,6 +782,7 @@ infodir docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -893,6 +895,7 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1145,6 +1148,15 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1282,7 +1294,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1435,6 +1447,7 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -2930,7 +2943,7 @@ $as_echo_n "checking for python interpreter for cross build... " >&6; } done if test x$interp = x; then as_fn_error $? "python$PACKAGE_VERSION interpreter not found" "$LINENO" 5 - fi + fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $interp" >&5 $as_echo "$interp" >&6; } PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp @@ -3257,6 +3270,9 @@ then *-*-cygwin*) ac_sys_system=Cygwin ;; + *-*-vxworks*) + ac_sys_system=VxWorks + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -3301,6 +3317,9 @@ if test "$cross_compiling" = yes; then *-*-cygwin*) _host_cpu= ;; + *-*-vxworks*) + _host_cpu=$host_cpu + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -3388,6 +3407,11 @@ $as_echo "#define _BSD_SOURCE 1" >>confdefs.h QNX/6.3.2) define_xopen_source=no ;; + # On VxWorks, defining _XOPEN_SOURCE causes compile failures + # in network headers still using system V types. + VxWorks/*) + define_xopen_source=no + ;; esac @@ -6151,7 +6175,7 @@ esac fi fi -if test "$cross_compiling" = yes; then +if test "$cross_compiling" = yes && test "$ac_sys_system" != VxWorks ; then case "$READELF" in readelf|:) as_fn_error $? "readelf for the host is required for cross builds" "$LINENO" 5 @@ -11175,13 +11199,16 @@ then fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DYNLOADFILE" >&5 $as_echo "$DYNLOADFILE" >&6; } +HAVE_DYNAMIC_LOADING=0 if test "$DYNLOADFILE" != "dynload_stub.o" then $as_echo "#define HAVE_DYNAMIC_LOADING 1" >>confdefs.h + HAVE_DYNAMIC_LOADING=1 fi + # MACHDEP_OBJS can be set to platform-specific object files needed by Python @@ -13227,7 +13254,9 @@ fi # checks for compiler characteristics -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 +# test results in duplicate def of __CHAR_UNSIGNED__ on VxWorks +if test "$ac_sys_system" != "VxWorks" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether char is unsigned" >&5 $as_echo_n "checking whether char is unsigned... " >&6; } if ${ac_cv_c_char_unsigned+:} false; then : $as_echo_n "(cached) " >&6 @@ -13260,6 +13289,7 @@ if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then fi +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : @@ -16831,6 +16861,18 @@ $as_echo_n "checking for openssl/ssl.h in $ssldir... " >&6; } OPENSSL_LIBS="-lssl -lcrypto" found=true { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + break + elif test -f "$ssldir/public/openssl/ssl.h"; then + OPENSSL_INCLUDES="-I$ssldir/public" + OPENSSL_LDFLAGS="-L$ssldir/../lib" + if test "$ac_sys_system" == VxWorks; then + OPENSSL_LIBS="-lOPENSSL -lHASH" + else + OPENSSL_LIBS="-lOPENSSL" + fi + found=true + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } break else diff --git a/configure.ac b/configure.ac index b83abee18cb720..3c1d619f23cf12 100644 --- a/configure.ac +++ b/configure.ac @@ -73,7 +73,7 @@ if test "$cross_compiling" = yes; then done if test x$interp = x; then AC_MSG_ERROR([python$PACKAGE_VERSION interpreter not found]) - fi + fi AC_MSG_RESULT($interp) PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp fi @@ -379,6 +379,9 @@ then *-*-cygwin*) ac_sys_system=Cygwin ;; + *-*-vxworks*) + ac_sys_system=VxWorks + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -423,6 +426,9 @@ if test "$cross_compiling" = yes; then *-*-cygwin*) _host_cpu= ;; + *-*-vxworks*) + _host_cpu=$host_cpu + ;; *) # for now, limit cross builds to known configurations MACHDEP="unknown" @@ -507,6 +513,11 @@ case $ac_sys_system/$ac_sys_release in QNX/6.3.2) define_xopen_source=no ;; + # On VxWorks, defining _XOPEN_SOURCE causes compile failures + # in network headers still using system V types. + VxWorks/*) + define_xopen_source=no + ;; esac @@ -1173,7 +1184,7 @@ then fi AC_CHECK_TOOLS([READELF], [readelf], [:]) -if test "$cross_compiling" = yes; then +if test "$cross_compiling" = yes && test "$ac_sys_system" != VxWorks ; then case "$READELF" in readelf|:) AC_MSG_ERROR([readelf for the host is required for cross builds]) @@ -3406,11 +3417,14 @@ then esac fi AC_MSG_RESULT($DYNLOADFILE) +HAVE_DYNAMIC_LOADING=0 if test "$DYNLOADFILE" != "dynload_stub.o" then AC_DEFINE(HAVE_DYNAMIC_LOADING, 1, [Defined when any dynamic module loading is enabled.]) + HAVE_DYNAMIC_LOADING=1 fi +AC_SUBST(HAVE_DYNAMIC_LOADING) # MACHDEP_OBJS can be set to platform-specific object files needed by Python @@ -3996,7 +4010,10 @@ fi # checks for compiler characteristics -AC_C_CHAR_UNSIGNED +# test results in duplicate def of __CHAR_UNSIGNED__ on VxWorks +if test "$ac_sys_system" != "VxWorks" ; then + AC_C_CHAR_UNSIGNED +fi AC_C_CONST works=no diff --git a/m4/ax_check_openssl.m4 b/m4/ax_check_openssl.m4 index 28e48cbefb68a4..81fcaeae7f9127 100644 --- a/m4/ax_check_openssl.m4 +++ b/m4/ax_check_openssl.m4 @@ -83,6 +83,17 @@ AC_DEFUN([AX_CHECK_OPENSSL], [ found=true AC_MSG_RESULT([yes]) break + elif test -f "$ssldir/public/openssl/ssl.h"; then + OPENSSL_INCLUDES="-I$ssldir/public" + OPENSSL_LDFLAGS="-L$ssldir/../lib" + if test "$ac_sys_system" == VxWorks; then + OPENSSL_LIBS="-lOPENSSL -lHASH" + else + OPENSSL_LIBS="-lOPENSSL" + fi + found=true + AC_MSG_RESULT([yes]) + break else AC_MSG_RESULT([no]) fi diff --git a/setup.py b/setup.py index 8536c350fe3a10..592cef394a137c 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ # Autodetecting setup.py script for building the Python extensions # - +# import sys, os, importlib.machinery, re, optparse from glob import glob import importlib._bootstrap @@ -39,6 +39,8 @@ def get_platform(): return sys.platform host_platform = get_platform() +_vxworks = 'vxworks' in host_platform; + # Were we compiled --with-pydebug or with #define Py_DEBUG? COMPILED_WITH_PYDEBUG = ('--with-pydebug' in sysconfig.get_config_var("CONFIG_ARGS")) @@ -145,6 +147,13 @@ def find_file(filename, std_dirs, paths): # Not found anywhere return None +def mathlib(): + # VxWorks has no libm + if _vxworks: + return [] + else: + return ['m'] + def find_library_file(compiler, libname, std_dirs, paths): result = compiler.find_library_file(std_dirs + paths, libname) if result is None: @@ -300,6 +309,13 @@ def build_extensions(self): if compiler is not None: (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS') args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags + #VxWorks uses '@filepath' extension to add include paths without overflowing windows cmd line buffer + if _vxworks: + cppflags = sysconfig.get_config_var('CPPFLAGS').split() + for item in cppflags: + self.announce('ITEM: "%s"' % item ) + if item.startswith('@'): + args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags + ' ' + item self.compiler.set_executables(**args) build_ext.build_extensions(self) @@ -544,7 +560,7 @@ def detect_modules(self): add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib') add_dir_to_list(self.compiler.include_dirs, '/usr/local/include') # only change this for cross builds for 3.3, issues on Mageia - if cross_compiling: + if cross_compiling and not _vxworks: self.add_gcc_paths() self.add_multiarch_paths() @@ -582,9 +598,10 @@ def detect_modules(self): for directory in reversed(options.dirs): add_dir_to_list(dir_list, directory) - if (not cross_compiling and + if ((not cross_compiling and os.path.normpath(sys.base_prefix) != '/usr' and - not sysconfig.get_config_var('PYTHONFRAMEWORK')): + not sysconfig.get_config_var('PYTHONFRAMEWORK')) or + _vxworks): # OSX note: Don't add LIBDIR and INCLUDEDIR to building a framework # (PYTHONFRAMEWORK is set) to avoid # linking problems when # building a framework with different architectures than @@ -594,6 +611,14 @@ def detect_modules(self): add_dir_to_list(self.compiler.include_dirs, sysconfig.get_config_var("INCLUDEDIR")) + #VxWorks requires some macros from CPPFLAGS to select the correct CPU headers + if _vxworks: + cppflags = sysconfig.get_config_var('CPPFLAGS').split() + for item in cppflags: + self.announce('ITEM: "%s"' % item) + if item.startswith('-D'): + self.compiler.define_macro(item[2:]) + system_lib_dirs = ['/lib64', '/usr/lib64', '/lib', '/usr/lib'] system_include_dirs = ['/usr/include'] # lib_dirs and inc_dirs are used to search for files; @@ -662,12 +687,12 @@ def detect_modules(self): exts.append( Extension('cmath', ['cmathmodule.c'], extra_objects=[shared_math], depends=['_math.h', shared_math], - libraries=['m']) ) + libraries=mathlib()) ) # math library functions, e.g. sin() exts.append( Extension('math', ['mathmodule.c'], extra_objects=[shared_math], depends=['_math.h', shared_math], - libraries=['m']) ) + libraries=mathlib()) ) # time libraries: librt may be needed for clock_gettime() time_libs = [] @@ -681,7 +706,7 @@ def detect_modules(self): # libm is needed by delta_new() that uses round() and by accum() that # uses modf(). exts.append( Extension('_datetime', ['_datetimemodule.c'], - libraries=['m']) ) + libraries=mathlib()) ) # random number generator implemented in C exts.append( Extension("_random", ["_randommodule.c"]) ) # bisect @@ -730,7 +755,8 @@ def detect_modules(self): # pwd(3) exts.append( Extension('pwd', ['pwdmodule.c']) ) # grp(3) - exts.append( Extension('grp', ['grpmodule.c']) ) + if not _vxworks: + exts.append( Extension('grp', ['grpmodule.c']) ) # spwd, shadow passwords if (config_h_vars.get('HAVE_GETSPNAM', False) or config_h_vars.get('HAVE_GETSPENT', False)): @@ -772,11 +798,11 @@ def detect_modules(self): # # Operations on audio samples # According to #993173, this one should actually work fine on - # 64-bit platforms. + # 64-bit platforms.i # # audioop needs libm for floor() in multiple functions. exts.append( Extension('audioop', ['audioop.c'], - libraries=['m']) ) + libraries=mathlib()) ) # readline do_readline = self.compiler.find_library_file(lib_dirs, 'readline') @@ -867,13 +893,18 @@ def detect_modules(self): libs = ['crypt'] else: libs = [] - exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) + if _vxworks: + exts.append( Extension('_crypt', ['_cryptmodule.c'], libraries=libs) ) # CSV files exts.append( Extension('_csv', ['_csv.c']) ) # POSIX subprocess module helper. - exts.append( Extension('_posixsubprocess', ['_posixsubprocess.c']) ) + if _vxworks: + exts.append( Extension('_vxwapi', ['_vxwapi.c']) ) + else: + exts.append( Extension('_posixsubprocess', ['_posixsubprocess.c']) ) + # socket(2) exts.append( Extension('_socket', ['socketmodule.c'], @@ -1326,7 +1357,7 @@ class db_found(Exception): pass missing.append('_gdbm') # Unix-only modules - if host_platform != 'win32': + if host_platform != 'win32' and not _vxworks: # Steen Lumholt's termios module exts.append( Extension('termios', ['termios.c']) ) # Jeremy Hylton's rlimit interface @@ -1975,7 +2006,7 @@ def detect_ctypes(self, inc_dirs, lib_dirs): # function my_sqrt() needs libm for sqrt() ext_test = Extension('_ctypes_test', sources=['_ctypes/_ctypes_test.c'], - libraries=['m']) + libraries=mathlib()) self.extensions.extend([ext, ext_test]) if host_platform == 'darwin': @@ -1999,7 +2030,6 @@ def detect_ctypes(self, inc_dirs, lib_dirs): if (self.compiler.find_library_file(lib_dirs, lib_name)): ffi_lib = lib_name break - if ffi_inc and ffi_lib: ext.include_dirs.extend(ffi_inc) ext.libraries.append(ffi_lib) @@ -2023,7 +2053,7 @@ def _decimal_ext(self): 'Modules', '_decimal', 'libmpdec'))] - libraries = ['m'] + libraries = mathlib() sources = [ '_decimal/_decimal.c', '_decimal/libmpdec/basearith.c',