diff options
Diffstat (limited to '.venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py')
-rw-r--r-- | .venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py b/.venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py new file mode 100644 index 00000000..f4e28984 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py @@ -0,0 +1,350 @@ +"""Tests for distutils.unixccompiler.""" + +import os +import sys +import unittest.mock as mock +from distutils import sysconfig +from distutils.compat import consolidate_linker_args +from distutils.errors import DistutilsPlatformError +from distutils.tests import support +from distutils.tests.compat.py39 import EnvironmentVarGuard +from distutils.util import _clear_cached_macosx_ver + +import pytest + +from .. import unix + + +@pytest.fixture(autouse=True) +def save_values(monkeypatch): + monkeypatch.setattr(sys, 'platform', sys.platform) + monkeypatch.setattr(sysconfig, 'get_config_var', sysconfig.get_config_var) + monkeypatch.setattr(sysconfig, 'get_config_vars', sysconfig.get_config_vars) + + +@pytest.fixture(autouse=True) +def compiler_wrapper(request): + class CompilerWrapper(unix.Compiler): + def rpath_foo(self): + return self.runtime_library_dir_option('/foo') + + request.instance.cc = CompilerWrapper() + + +class TestUnixCCompiler(support.TempdirManager): + @pytest.mark.skipif('platform.system == "Windows"') + def test_runtime_libdir_option(self): # noqa: C901 + # Issue #5900; GitHub Issue #37 + # + # Ensure RUNPATH is added to extension modules with RPATH if + # GNU ld is used + + # darwin + sys.platform = 'darwin' + darwin_ver_var = 'MACOSX_DEPLOYMENT_TARGET' + darwin_rpath_flag = '-Wl,-rpath,/foo' + darwin_lib_flag = '-L/foo' + + # (macOS version from syscfg, macOS version from env var) -> flag + # Version value of None generates two tests: as None and as empty string + # Expected flag value of None means an mismatch exception is expected + darwin_test_cases = [ + ((None, None), darwin_lib_flag), + ((None, '11'), darwin_rpath_flag), + (('10', None), darwin_lib_flag), + (('10.3', None), darwin_lib_flag), + (('10.3.1', None), darwin_lib_flag), + (('10.5', None), darwin_rpath_flag), + (('10.5.1', None), darwin_rpath_flag), + (('10.3', '10.3'), darwin_lib_flag), + (('10.3', '10.5'), darwin_rpath_flag), + (('10.5', '10.3'), darwin_lib_flag), + (('10.5', '11'), darwin_rpath_flag), + (('10.4', '10'), None), + ] + + def make_darwin_gcv(syscfg_macosx_ver): + def gcv(var): + if var == darwin_ver_var: + return syscfg_macosx_ver + return "xxx" + + return gcv + + def do_darwin_test(syscfg_macosx_ver, env_macosx_ver, expected_flag): + env = os.environ + msg = f"macOS version = (sysconfig={syscfg_macosx_ver!r}, env={env_macosx_ver!r})" + + # Save + old_gcv = sysconfig.get_config_var + old_env_macosx_ver = env.get(darwin_ver_var) + + # Setup environment + _clear_cached_macosx_ver() + sysconfig.get_config_var = make_darwin_gcv(syscfg_macosx_ver) + if env_macosx_ver is not None: + env[darwin_ver_var] = env_macosx_ver + elif darwin_ver_var in env: + env.pop(darwin_ver_var) + + # Run the test + if expected_flag is not None: + assert self.cc.rpath_foo() == expected_flag, msg + else: + with pytest.raises( + DistutilsPlatformError, match=darwin_ver_var + r' mismatch' + ): + self.cc.rpath_foo() + + # Restore + if old_env_macosx_ver is not None: + env[darwin_ver_var] = old_env_macosx_ver + elif darwin_ver_var in env: + env.pop(darwin_ver_var) + sysconfig.get_config_var = old_gcv + _clear_cached_macosx_ver() + + for macosx_vers, expected_flag in darwin_test_cases: + syscfg_macosx_ver, env_macosx_ver = macosx_vers + do_darwin_test(syscfg_macosx_ver, env_macosx_ver, expected_flag) + # Bonus test cases with None interpreted as empty string + if syscfg_macosx_ver is None: + do_darwin_test("", env_macosx_ver, expected_flag) + if env_macosx_ver is None: + do_darwin_test(syscfg_macosx_ver, "", expected_flag) + if syscfg_macosx_ver is None and env_macosx_ver is None: + do_darwin_test("", "", expected_flag) + + old_gcv = sysconfig.get_config_var + + # hp-ux + sys.platform = 'hp-ux' + + def gcv(v): + return 'xxx' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == ['+s', '-L/foo'] + + def gcv(v): + return 'gcc' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == ['-Wl,+s', '-L/foo'] + + def gcv(v): + return 'g++' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == ['-Wl,+s', '-L/foo'] + + sysconfig.get_config_var = old_gcv + + # GCC GNULD + sys.platform = 'bar' + + def gcv(v): + if v == 'CC': + return 'gcc' + elif v == 'GNULD': + return 'yes' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == consolidate_linker_args([ + '-Wl,--enable-new-dtags', + '-Wl,-rpath,/foo', + ]) + + def gcv(v): + if v == 'CC': + return 'gcc -pthread -B /bar' + elif v == 'GNULD': + return 'yes' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == consolidate_linker_args([ + '-Wl,--enable-new-dtags', + '-Wl,-rpath,/foo', + ]) + + # GCC non-GNULD + sys.platform = 'bar' + + def gcv(v): + if v == 'CC': + return 'gcc' + elif v == 'GNULD': + return 'no' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == '-Wl,-R/foo' + + # GCC GNULD with fully qualified configuration prefix + # see #7617 + sys.platform = 'bar' + + def gcv(v): + if v == 'CC': + return 'x86_64-pc-linux-gnu-gcc-4.4.2' + elif v == 'GNULD': + return 'yes' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == consolidate_linker_args([ + '-Wl,--enable-new-dtags', + '-Wl,-rpath,/foo', + ]) + + # non-GCC GNULD + sys.platform = 'bar' + + def gcv(v): + if v == 'CC': + return 'cc' + elif v == 'GNULD': + return 'yes' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == consolidate_linker_args([ + '-Wl,--enable-new-dtags', + '-Wl,-rpath,/foo', + ]) + + # non-GCC non-GNULD + sys.platform = 'bar' + + def gcv(v): + if v == 'CC': + return 'cc' + elif v == 'GNULD': + return 'no' + + sysconfig.get_config_var = gcv + assert self.cc.rpath_foo() == '-Wl,-R/foo' + + @pytest.mark.skipif('platform.system == "Windows"') + def test_cc_overrides_ldshared(self): + # Issue #18080: + # ensure that setting CC env variable also changes default linker + def gcv(v): + if v == 'LDSHARED': + return 'gcc-4.2 -bundle -undefined dynamic_lookup ' + return 'gcc-4.2' + + def gcvs(*args, _orig=sysconfig.get_config_vars): + if args: + return list(map(sysconfig.get_config_var, args)) + return _orig() + + sysconfig.get_config_var = gcv + sysconfig.get_config_vars = gcvs + with EnvironmentVarGuard() as env: + env['CC'] = 'my_cc' + del env['LDSHARED'] + sysconfig.customize_compiler(self.cc) + assert self.cc.linker_so[0] == 'my_cc' + + @pytest.mark.skipif('platform.system == "Windows"') + @pytest.mark.usefixtures('disable_macos_customization') + def test_cc_overrides_ldshared_for_cxx_correctly(self): + """ + Ensure that setting CC env variable also changes default linker + correctly when building C++ extensions. + + pypa/distutils#126 + """ + + def gcv(v): + if v == 'LDSHARED': + return 'gcc-4.2 -bundle -undefined dynamic_lookup ' + elif v == 'LDCXXSHARED': + return 'g++-4.2 -bundle -undefined dynamic_lookup ' + elif v == 'CXX': + return 'g++-4.2' + elif v == 'CC': + return 'gcc-4.2' + return '' + + def gcvs(*args, _orig=sysconfig.get_config_vars): + if args: + return list(map(sysconfig.get_config_var, args)) + return _orig() + + sysconfig.get_config_var = gcv + sysconfig.get_config_vars = gcvs + with ( + mock.patch.object(self.cc, 'spawn', return_value=None) as mock_spawn, + mock.patch.object(self.cc, '_need_link', return_value=True), + mock.patch.object(self.cc, 'mkpath', return_value=None), + EnvironmentVarGuard() as env, + ): + env['CC'] = 'ccache my_cc' + env['CXX'] = 'my_cxx' + del env['LDSHARED'] + sysconfig.customize_compiler(self.cc) + assert self.cc.linker_so[0:2] == ['ccache', 'my_cc'] + self.cc.link(None, [], 'a.out', target_lang='c++') + call_args = mock_spawn.call_args[0][0] + expected = ['my_cxx', '-bundle', '-undefined', 'dynamic_lookup'] + assert call_args[:4] == expected + + @pytest.mark.skipif('platform.system == "Windows"') + def test_explicit_ldshared(self): + # Issue #18080: + # ensure that setting CC env variable does not change + # explicit LDSHARED setting for linker + def gcv(v): + if v == 'LDSHARED': + return 'gcc-4.2 -bundle -undefined dynamic_lookup ' + return 'gcc-4.2' + + def gcvs(*args, _orig=sysconfig.get_config_vars): + if args: + return list(map(sysconfig.get_config_var, args)) + return _orig() + + sysconfig.get_config_var = gcv + sysconfig.get_config_vars = gcvs + with EnvironmentVarGuard() as env: + env['CC'] = 'my_cc' + env['LDSHARED'] = 'my_ld -bundle -dynamic' + sysconfig.customize_compiler(self.cc) + assert self.cc.linker_so[0] == 'my_ld' + + def test_has_function(self): + # Issue https://github.com/pypa/distutils/issues/64: + # ensure that setting output_dir does not raise + # FileNotFoundError: [Errno 2] No such file or directory: 'a.out' + self.cc.output_dir = 'scratch' + os.chdir(self.mkdtemp()) + self.cc.has_function('abort') + + def test_find_library_file(self, monkeypatch): + compiler = unix.Compiler() + compiler._library_root = lambda dir: dir + monkeypatch.setattr(os.path, 'exists', lambda d: 'existing' in d) + + libname = 'libabc.dylib' if sys.platform != 'cygwin' else 'cygabc.dll' + dirs = ('/foo/bar/missing', '/foo/bar/existing') + assert ( + compiler.find_library_file(dirs, 'abc').replace('\\', '/') + == f'/foo/bar/existing/{libname}' + ) + assert ( + compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/') + == f'/foo/bar/existing/{libname}' + ) + + monkeypatch.setattr( + os.path, + 'exists', + lambda d: 'existing' in d and '.a' in d and '.dll.a' not in d, + ) + assert ( + compiler.find_library_file(dirs, 'abc').replace('\\', '/') + == '/foo/bar/existing/libabc.a' + ) + assert ( + compiler.find_library_file(reversed(dirs), 'abc').replace('\\', '/') + == '/foo/bar/existing/libabc.a' + ) |