Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion numpy/distutils/command/build_ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def _process_unlinkable_fobjects(self, objects, libraries,
unlinkable_fobjects = list(unlinkable_fobjects)

# Expand possible fake static libraries to objects
for lib in libraries:
for lib in libraries[:]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment above this line that [:] is on purpose, to not modify the original list? Otherwise the next over-eager code cleanup may undo the fix again.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added an explanation is latest push, feel free to resolve or suggest different wording

for libdir in library_dirs:
fake_lib = os.path.join(libdir, lib + '.fobjects')
if os.path.isfile(fake_lib):
Expand Down
65 changes: 65 additions & 0 deletions numpy/distutils/tests/test_build_ext.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'''Tests for numpy.distutils.build_ext.'''

import os
import shutil
import subprocess
import sys
from textwrap import indent, dedent
import pytest

@pytest.mark.slow
def test_multi_fortran_libs_link(tmp_path):
'''
Ensures multiple "fake" static libraries are correctly linked.
see gh-18295
'''
# make some dummy sources
with open(tmp_path / '_dummy1.f', 'w') as fid:
fid.write(indent(dedent('''\
FUNCTION dummy_one()
RETURN
END FUNCTION'''), prefix=' '*6))
with open(tmp_path / '_dummy2.f', 'w') as fid:
fid.write(indent(dedent('''\
FUNCTION dummy_two()
RETURN
END FUNCTION'''), prefix=' '*6))
with open(tmp_path / '_dummy.c', 'w') as fid:
# doesn't need to load - just needs to exist
fid.write('int PyInit_dummyext;')

# make a setup file
with open(tmp_path / 'setup.py', 'w') as fid:
srctree = os.path.join(os.path.dirname(__file__), '..', '..', '..')
fid.write(dedent(f'''\
def configuration(parent_package="", top_path=None):
from numpy.distutils.misc_util import Configuration
config = Configuration("", parent_package, top_path)
config.add_library("dummy1", sources=["_dummy1.f"])
config.add_library("dummy2", sources=["_dummy2.f"])
config.add_extension("dummyext", sources=["_dummy.c"], libraries=["dummy1", "dummy2"])
return config


if __name__ == "__main__":
import sys
sys.path.insert(0, r"{srctree}")
from numpy.distutils.core import setup
setup(**configuration(top_path="").todict())'''))

# build the test extensino and "install" into a temporary directory
build_dir = tmp_path
subprocess.check_call([sys.executable, 'setup.py', 'build', 'install',
'--prefix', str(tmp_path / 'installdir'),
'--record', str(tmp_path / 'tmp_install_log.txt'),
],
cwd=str(build_dir),
)
# get the path to the so
so = None
with open(tmp_path /'tmp_install_log.txt') as fid:
for line in fid:
if 'dummyext' in line:
so = line.strip()
break
assert so is not None