Skip to content

test_record_extensions failing on Windows #166

@jaraco

Description

@jaraco

I recently learned that no extension modules were being tested since this code was adopted from CPython. I corrected that issue in 3f16eed.

Now, the test in test_install.InstallTestCase.test_record_extensions is failing (instead of being skipped).

Details
___________________ InstallTestCase.test_record_extensions ____________________

self = <distutils._msvccompiler.MSVCCompiler object at 0x000001A599E82A08>
target_desc = 'shared_object'
objects = ['build\\temp.win32-cpython-37\\Release\\xxmodule.obj']
output_filename = 'build\\lib.win32-cpython-37\\xx.cp37-win_amd64.pyd'
output_dir = 'C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmpb5c38b31\\foo\\build\\lib.win32-cpython-37'
libraries = []
library_dirs = ['D:\\a\\distutils\\distutils\\.tox\\python\\libs', 'C:\\hostedtoolcache\\windows\\Python\\3.7.9\\x64\\libs', 'C:\\hos...lib\\x86', 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\lib\\x86', ...]
runtime_library_dirs = [], export_symbols = ['PyInit_xx'], debug = False
extra_preargs = None, extra_postargs = []
build_temp = 'build\\temp.win32-cpython-37\\Release', target_lang = 'c'

    def link(
        self,
        target_desc,
        objects,
        output_filename,
        output_dir=None,
        libraries=None,
        library_dirs=None,
        runtime_library_dirs=None,
        export_symbols=None,
        debug=0,
        extra_preargs=None,
        extra_postargs=None,
        build_temp=None,
        target_lang=None,
    ):
    
        if not self.initialized:
            self.initialize()
        objects, output_dir = self._fix_object_args(objects, output_dir)
        fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
        libraries, library_dirs, runtime_library_dirs = fixed_args
    
        if runtime_library_dirs:
            self.warn(
                "I don't know what to do with 'runtime_library_dirs': "
                + str(runtime_library_dirs)
            )
    
        lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
        if output_dir is not None:
            output_filename = os.path.join(output_dir, output_filename)
    
        if self._need_link(objects, output_filename):
            ldflags = self._ldflags[target_desc, debug]
    
            export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
    
            ld_args = (
                ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
            )
    
            # The MSVC linker generates .lib and .exp files, which cannot be
            # suppressed by any linker switches. The .lib files may even be
            # needed! Make sure they are generated in the temporary build
            # directory. Since they have different names for debug and release
            # builds, they can go into the same directory.
            build_temp = os.path.dirname(objects[0])
            if export_symbols is not None:
                (dll_name, dll_ext) = os.path.splitext(
                    os.path.basename(output_filename)
                )
                implib_file = os.path.join(build_temp, self.library_filename(dll_name))
                ld_args.append('/IMPLIB:' + implib_file)
    
            if extra_preargs:
                ld_args[:0] = extra_preargs
            if extra_postargs:
                ld_args.extend(extra_postargs)
    
            output_dir = os.path.dirname(os.path.abspath(output_filename))
            self.mkpath(output_dir)
            try:
                log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
>               self.spawn([self.linker] + ld_args)

D:\a\distutils\distutils\distutils\_msvccompiler.py:529: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <distutils._msvccompiler.MSVCCompiler object at 0x000001A599E82A08>
cmd = ['C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x86\\link.exe', '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DLL', '/MANIFEST:EMBED,ID=2', ...]

    def spawn(self, cmd):
        env = dict(os.environ, PATH=self._paths)
        with self._fallback_spawn(cmd, env) as fallback:
>           return super().spawn(cmd, env=env)

D:\a\distutils\distutils\distutils\_msvccompiler.py:538: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <distutils._msvccompiler.MSVCCompiler object at 0x000001A599E82A08>
cmd = ['C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x86\\link.exe', '/nologo', '/INCREMENTAL:NO', '/LTCG', '/DLL', '/MANIFEST:EMBED,ID=2', ...]
kwargs = {'env': {'APPDATA': 'C:\\Users\\runneradmin\\AppData\\Roaming', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'NUMBER_O...:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Common7\\IDE\\VC\\Linux\\bin\\ConnectionManagerExe', ...}}

    def spawn(self, cmd, **kwargs):
>       spawn(cmd, dry_run=self.dry_run, **kwargs)

D:\a\distutils\distutils\distutils\ccompiler.py:987: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

cmd = 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x86\\link.exe'
search_path = 1, verbose = 0, dry_run = 0
env = {'APPDATA': 'C:\\Users\\runneradmin\\AppData\\Roaming', 'COMSPEC': 'C:\\Windows\\system32\\cmd.exe', 'NUMBER_OF_PROCES...C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\Common7\\IDE\\VC\\Linux\\bin\\ConnectionManagerExe', ...}

    def spawn(cmd, search_path=1, verbose=0, dry_run=0, env=None):  # noqa: C901
        """Run another program, specified as a command list 'cmd', in a new process.
    
        'cmd' is just the argument list for the new process, ie.
        cmd[0] is the program to run and cmd[1:] are the rest of its arguments.
        There is no way to run a program with a name different from that of its
        executable.
    
        If 'search_path' is true (the default), the system's executable
        search path will be used to find the program; otherwise, cmd[0]
        must be the exact path to the executable.  If 'dry_run' is true,
        the command will not actually be run.
    
        Raise DistutilsExecError if running the program fails in any way; just
        return on success.
        """
        # cmd is documented as a list, but just in case some code passes a tuple
        # in, protect our %-formatting code against horrible death
        cmd = list(cmd)
    
        log.info(subprocess.list2cmdline(cmd))
        if dry_run:
            return
    
        if search_path:
            executable = find_executable(cmd[0])
            if executable is not None:
                cmd[0] = executable
    
        env = env if env is not None else dict(os.environ)
    
        if sys.platform == 'darwin':
            from distutils.util import MACOSX_VERSION_VAR, get_macosx_target_ver
    
            macosx_target_ver = get_macosx_target_ver()
            if macosx_target_ver:
                env[MACOSX_VERSION_VAR] = macosx_target_ver
    
        try:
            proc = subprocess.Popen(cmd, env=env)
            proc.wait()
            exitcode = proc.returncode
        except OSError as exc:
            if not DEBUG:
                cmd = cmd[0]
            raise DistutilsExecError(
                "command {!r} failed: {}".format(cmd, exc.args[-1])
            ) from exc
    
        if exitcode:
            if not DEBUG:
                cmd = cmd[0]
            raise DistutilsExecError(
>               "command {!r} failed with exit code {}".format(cmd, exitcode)
            )
E           distutils.errors.DistutilsExecError: command 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x86\\link.exe' failed with exit code 1120

D:\a\distutils\distutils\distutils\spawn.py:71: DistutilsExecError

During handling of the above exception, another exception occurred:

self = <distutils.tests.test_install.InstallTestCase testMethod=test_record_extensions>

    def test_record_extensions(self):
        cmd = test_support.missing_compiler_executable()
        if cmd is not None:
            self.skipTest('The %r command is not found' % cmd)
        install_dir = self.mkdtemp()
        project_dir, dist = self.create_dist(
            ext_modules=[Extension('xx', ['xxmodule.c'])]
        )
        os.chdir(project_dir)
        support.copy_xxmodule_c(project_dir)
    
        buildextcmd = build_ext(dist)
        support.fixup_build_ext(buildextcmd)
        buildextcmd.ensure_finalized()
    
        cmd = install(dist)
        dist.command_obj['install'] = cmd
        dist.command_obj['build_ext'] = buildextcmd
        cmd.root = install_dir
        cmd.record = os.path.join(project_dir, 'filelist')
        cmd.ensure_finalized()
>       cmd.run()

D:\a\distutils\distutils\distutils\tests\test_install.py:253: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
D:\a\distutils\distutils\distutils\command\install.py:698: in run
    self.run_command('build')
D:\a\distutils\distutils\distutils\cmd.py:319: in run_command
    self.distribution.run_command(command)
D:\a\distutils\distutils\distutils\dist.py:992: in run_command
    cmd_obj.run()
D:\a\distutils\distutils\distutils\command\build.py:132: in run
    self.run_command(cmd_name)
D:\a\distutils\distutils\distutils\cmd.py:319: in run_command
    self.distribution.run_command(command)
D:\a\distutils\distutils\distutils\dist.py:992: in run_command
    cmd_obj.run()
D:\a\distutils\distutils\distutils\command\build_ext.py:346: in run
    self.build_extensions()
D:\a\distutils\distutils\distutils\command\build_ext.py:466: in build_extensions
    self._build_extensions_serial()
D:\a\distutils\distutils\distutils\command\build_ext.py:492: in _build_extensions_serial
    self.build_extension(ext)
D:\a\distutils\distutils\distutils\command\build_ext.py:581: in build_extension
    target_lang=language,
D:\a\distutils\distutils\distutils\ccompiler.py:764: in link_shared_object
    target_lang,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <distutils._msvccompiler.MSVCCompiler object at 0x000001A599E82A08>
target_desc = 'shared_object'
objects = ['build\\temp.win32-cpython-37\\Release\\xxmodule.obj']
output_filename = 'build\\lib.win32-cpython-37\\xx.cp37-win_amd64.pyd'
output_dir = 'C:\\Users\\RUNNER~1\\AppData\\Local\\Temp\\tmpb5c38b31\\foo\\build\\lib.win32-cpython-37'
libraries = []
library_dirs = ['D:\\a\\distutils\\distutils\\.tox\\python\\libs', 'C:\\hostedtoolcache\\windows\\Python\\3.7.9\\x64\\libs', 'C:\\hos...lib\\x86', 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\lib\\x86', ...]
runtime_library_dirs = [], export_symbols = ['PyInit_xx'], debug = False
extra_preargs = None, extra_postargs = []
build_temp = 'build\\temp.win32-cpython-37\\Release', target_lang = 'c'

    def link(
        self,
        target_desc,
        objects,
        output_filename,
        output_dir=None,
        libraries=None,
        library_dirs=None,
        runtime_library_dirs=None,
        export_symbols=None,
        debug=0,
        extra_preargs=None,
        extra_postargs=None,
        build_temp=None,
        target_lang=None,
    ):
    
        if not self.initialized:
            self.initialize()
        objects, output_dir = self._fix_object_args(objects, output_dir)
        fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
        libraries, library_dirs, runtime_library_dirs = fixed_args
    
        if runtime_library_dirs:
            self.warn(
                "I don't know what to do with 'runtime_library_dirs': "
                + str(runtime_library_dirs)
            )
    
        lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
        if output_dir is not None:
            output_filename = os.path.join(output_dir, output_filename)
    
        if self._need_link(objects, output_filename):
            ldflags = self._ldflags[target_desc, debug]
    
            export_opts = ["/EXPORT:" + sym for sym in (export_symbols or [])]
    
            ld_args = (
                ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
            )
    
            # The MSVC linker generates .lib and .exp files, which cannot be
            # suppressed by any linker switches. The .lib files may even be
            # needed! Make sure they are generated in the temporary build
            # directory. Since they have different names for debug and release
            # builds, they can go into the same directory.
            build_temp = os.path.dirname(objects[0])
            if export_symbols is not None:
                (dll_name, dll_ext) = os.path.splitext(
                    os.path.basename(output_filename)
                )
                implib_file = os.path.join(build_temp, self.library_filename(dll_name))
                ld_args.append('/IMPLIB:' + implib_file)
    
            if extra_preargs:
                ld_args[:0] = extra_preargs
            if extra_postargs:
                ld_args.extend(extra_postargs)
    
            output_dir = os.path.dirname(os.path.abspath(output_filename))
            self.mkpath(output_dir)
            try:
                log.debug('Executing "%s" %s', self.linker, ' '.join(ld_args))
                self.spawn([self.linker] + ld_args)
            except DistutilsExecError as msg:
>               raise LinkError(msg)
E               distutils.errors.LinkError: command 'C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.32.31326\\bin\\HostX86\\x86\\link.exe' failed with exit code 1120

D:\a\distutils\distutils\distutils\_msvccompiler.py:531: LinkError
---------------------------- Captured stdout call -----------------------------
xxmodule.c

   Creating library build\temp.win32-cpython-37\Release\xx.cp37-win_amd64.lib and object build\temp.win32-cpython-37\Release\xx.cp37-win_amd64.exp

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyBaseObject_Type

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyType_GenericNew

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyExc_KeyError

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyErr_Occurred

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyObject_GenericGetAttr

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyLong_FromLong

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyDict_GetItemWithError

xxmodule.obj : error LNK2001: unresolved external symbol __imp___Py_NoneStruct

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyDict_SetItemString

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyExc_AttributeError

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyErr_SetString

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyObject_Free

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyErr_ExceptionMatches

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyModule_AddObject

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyType_Ready

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyErr_NewException

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyDict_New

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyList_GetItem

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyUnicode_Type

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyModuleDef_Init

xxmodule.obj : error LNK2001: unresolved external symbol __imp___Py_NotImplementedStruct

xxmodule.obj : error LNK2001: unresolved external symbol __imp___PyObject_New

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyObject_Print

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyList_SetItem

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyDict_DelItemString

xxmodule.obj : error LNK2001: unresolved external symbol __imp__PyArg_ParseTuple

build\lib.win32-cpython-37\xx.cp37-win_amd64.pyd : fatal error LNK1120: 26 unresolved externals

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions