Skip to content

BUG: distutils: fix building mixed C/Fortran extensions#20886

Merged
charris merged 1 commit intonumpy:mainfrom
rgommers:fix-fortran-linkage
Jan 24, 2022
Merged

BUG: distutils: fix building mixed C/Fortran extensions#20886
charris merged 1 commit intonumpy:mainfrom
rgommers:fix-fortran-linkage

Conversation

@rgommers
Copy link
Member

In SciPy we had a couple of cases where we build a Python extension with C source files but linked against static libraries built from Fortran code. Those should be using the Fortran linker, but this was broken in 1.22.0 by gh-19713 (the PR that introduced C++ in NumPy).

This fixes a few issues in the build_ext command, and documents better what is going on there.

Should close SciPy issues scipy/scipy#8325 and scipy/scipy#15414.

In the build log, this should show up:

WARN: resetting extension 'scipy.integrate._quadpack' language from 'c' to 'f77'.

And then the resetting should actually happen. So not this:

INFO: building 'scipy.integrate._quadpack' extension
INFO: compiling C sources
INFO: C compiler: /home/rgommers/anaconda3/envs/scipy-dev/bin/x86_64-conda-linux-gnu-cc -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -fPIC

INFO: compile options: '-DHAVE_CBLAS -Iscipy/_lib/src -I/home/rgommers/anaconda3/envs/scipy-dev/lib/python3.9/site-packages/numpy/core/include -Ibuild/src.linux-x86_64-3.9/numpy/distutils/include -I/home/rgommers/anaconda3/envs/scipy-dev/include/python3.9 -c'
extra options: '-msse -msse2 -msse3'
INFO: x86_64-conda-linux-gnu-cc: scipy/integrate/_quadpackmodule.c
 
INFO: /home/rgommers/anaconda3/envs/scipy-dev/bin/x86_64-conda-linux-gnu-cc -shared -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-rpath,/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-rpath-link,/home/rgommers/anaconda3/envs/scipy-dev/lib -L/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-rpath,/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-rpath-link,/home/rgommers/anaconda3/envs/scipy-dev/lib -L/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-rpath,/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-rpath-link,/home/rgommers/anaconda3/envs/scipy-dev/lib -L/home/rgommers/anaconda3/envs/scipy-dev/lib -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/rgommers/anaconda3/envs/scipy-dev/include build/temp.linux-x86_64-3.9/scipy/integrate/_quadpackmodule.o -L/home/rgommers/anaconda3/envs/scipy-dev/lib -Lbuild/temp.linux-x86_64-3.9 -lquadpack -lmach -lopenblas -lopenblas -o scipy/integrate/_quadpack.cpython-39-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.9/link-version-scipy.integrate._quadpack.map

But this:

INFO: building 'scipy.integrate._quadpack' extension
INFO: compiling C sources
INFO: C compiler: /home/rgommers/anaconda3/envs/scipy-dev/bin/x86_64-conda-linux-gnu-cc -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -DNDEBUG -D_FORTIFY_SOURCE=2 -O2 -isystem /home/rgommers/anaconda3/envs/scipy-dev/include -fPIC

INFO: compile options: '-DHAVE_CBLAS -Iscipy/_lib/src -I/home/rgommers/code/numpy/numpy/core/include -Ibuild/src.linux-x86_64-3.9/numpy/distutils/include -I/home/rgommers/anaconda3/envs/scipy-dev/include/python3.9 -c'
extra options: '-msse -msse2 -msse3'
INFO: x86_64-conda-linux-gnu-cc: scipy/integrate/_quadpackmodule.c

INFO: /home/rgommers/anaconda3/envs/scipy-dev/bin/x86_64-conda-linux-gnu-gfortran -Wall -g -Wall -g -shared -Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,-rpath,/home/rgommers/anaconda3/envs/scipy-dev/lib -Wl,-rpath-link,/home/rgommers/anaconda3/envs/scipy-dev/lib -L/home/rgommers/anaconda3/envs/scipy-dev/lib build/temp.linux-x86_64-3.9/scipy/integrate/_quadpackmodule.o -L/home/rgommers/anaconda3/envs/scipy-dev/lib -L/home/rgommers/anaconda3/envs/scipy-dev/bin/../lib/gcc/x86_64-conda-linux-gnu/9.4.0/../../../../x86_64-conda-linux-gnu/lib/../lib -L/home/rgommers/anaconda3/envs/scipy-dev/bin/../lib/gcc/x86_64-conda-linux-gnu/9.4.0/../../../../x86_64-conda-linux-gnu/lib/../lib -Lbuild/temp.linux-x86_64-3.9 -lquadpack -lmach -lopenblas -lopenblas -lgfortran -o scipy/integrate/_quadpack.cpython-39-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.9/link-version-scipy.integrate._quadpack.map

In SciPy we had a couple of cases where we build a Python extension
with C source files but linked against static libraries built from
Fortran code. Those should be using the Fortran linker, but this
was broken in 1.22.0 by numpygh-19713 (the PR that introduced C++ in NumPy).

This fixes a few issues in the `build_ext` command, and documents better
what is going on there.

Should close SciPy issues 8325 and 15414.
@charris
Copy link
Member

charris commented Jan 24, 2022

Thanks Ralf.

@rgommers rgommers deleted the fix-fortran-linkage branch January 24, 2022 16:32
Copy link
Contributor

@tylerjereddy tylerjereddy left a comment

Choose a reason for hiding this comment

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

Just to report on the results downstream, this does seem to fix the issue we are seeing with SciPy 1.7.3 missing symbols when built with latest NumPy using spack.

There are some unrelated curiosities I had to patch separately:

  • version handling at untagged commits looks a bit fragile maybe, perhaps spacks fault, not sure about the versioneer stuff:
==> [2022-01-24-09:06:59.729376] '/vast/home/treddy/github_projects/spack/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/python-3.9.9-dpafrcjrc3ajwmfwm6jpvrfn2fuolebn/bin/python3.9' '-s' 'setup.py' '--no-user-cfg' 'build'
Traceback (most recent call last):
  File "/ram/tmp/treddy/spack-stage/spack-stage-py-numpy-fix-fortran-linkage-2x66mvauoa65wm5krimrheektwfp4twc/spack-src/setup.py", line 64, in <module>
    raise RuntimeError(f'Cannot parse version {FULLVERSION}')
RuntimeError: Cannot parse version 0+untagged.1.g1e83f83

Looks like the numexpr package isn't compatiable with NumPy main yet, which is probably fair until there's an actual release. FWIW, here's the traceback (the py-numpy version was artificially set to something high by me to use a "fake tag" on a debug version of Ralf's branch):

==> Installing py-numexpr-2.7.3-32jnylupzrtvdk5aatwpxtaaqas5gvug
==> No binary for py-numexpr-2.7.3-32jnylupzrtvdk5aatwpxtaaqas5gvug found: installing from source
==> Using cached archive: /vast/home/treddy/github_projects/spack/var/spack/cache/_source-cache/archive/00/00d6b1518605afe0ed10417e0ff07123e5d531c02496c6eed7dd4b9923238e1e.tar.gz
==> No patches needed for py-numexpr
==> py-numexpr: Executing phase: 'build'
==> Error: ProcessError: Command exited with status 1:
    '/vast/home/treddy/github_projects/spack/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/python-3.9.9-dpafrcjrc3ajwmfwm6jpvrfn2fuolebn/bin/python3.9' '-s' 'setup.py' '--no-user-cfg' 'build'

2 errors found in build log:
     288    INFO: compile options: '-I/vast/home/treddy/github_projects/spack/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/py-numpy-1.28.0-6jc4hgb7r7umhyjaltfgjkzv6tl5x4dv/lib/python3.9/site-packages/numpy/core/include -Ibuild/src.linux-x86_64-3.9/numpy/distutils/include -I/vast/home/treddy/github_projects/spa
            ck/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/python-3.9.9-dpafrcjrc3ajwmfwm6jpvrfn2fuolebn/include/python3.9 -c'
     289    extra options: '-funroll-all-loops -msse -msse2 -msse3'
     290    INFO: g++: numexpr/interpreter.cpp
     291    INFO: g++: numexpr/module.cpp
     292    INFO: g++: numexpr/numexpr_object.cpp
     293    numexpr/interpreter.cpp: In function 'PyObject* NumExpr_run(NumExprObject*, PyObject*, PyObject*)':
  >> 294    numexpr/interpreter.cpp:1272:59: error: 'NPY_ARRAY_UPDATEIFCOPY' was not declared in this scope; did you mean 'NPY_ITER_UPDATEIFCOPY'?
     295     1272 |                                         NPY_ARRAY_ALIGNED|NPY_ARRAY_UPDATEIFCOPY);
     296          |                                                           ^~~~~~~~~~~~~~~~~~~~~~
     297          |                                                           NPY_ITER_UPDATEIFCOPY
  >> 298    error: Command "/vast/home/treddy/github_projects/spack/lib/spack/env/gcc/g++ -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -fPIC -fPIC -I/vast/home/treddy/github_projects/spack/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/py-numpy-1.28.0-6jc4hgb7r7umhyjaltfgjkzv6tl5x4dv/lib/pytho
            n3.9/site-packages/numpy/core/include -Ibuild/src.linux-x86_64-3.9/numpy/distutils/include -I/vast/home/treddy/github_projects/spack/opt/spack/linux-centos8-skylake_avx512/gcc-9.4.0/python-3.9.9-dpafrcjrc3ajwmfwm6jpvrfn2fuolebn/include/python3.9 -c numexpr/interpreter.cpp -o build/temp.linux-x86_64-3.9
            /numexpr/interpreter.o -MMD -MF build/temp.linux-x86_64-3.9/numexpr/interpreter.o.d -funroll-all-loops -msse -msse2 -msse3" failed with exit status 1
     299    INFO:
     300    ########### EXT COMPILER OPTIMIZATION ###########
     301    INFO: Platform      :
     302      Architecture: x64
     303      Compiler    : gcc
     304    


@seberg
Copy link
Member

seberg commented Jan 24, 2022

That error is because we removed NPY_ARRAY_UPDATEIFCOPY from the headers, because it does not exist/work anymore (it was deprecated very long ago).

I was wondering if we should just keep the symbol around, at least for a bit, but I would hope that numexpr is just very old here?

@rgommers
Copy link
Member Author

Thanks for testing Tyler! Guess we're good then once this lands in numpy 1.22.2.

version handling at untagged commits looks a bit fragile maybe, perhaps spacks fault, not sure about the versioneer stuff:

I don't have energy for it right now, but if we do the build system conversion later this year I'd like to rip it out. versioneer has been way too fragile.

@WarrenWeckesser
Copy link
Member

version handling at untagged commits looks a bit fragile maybe, perhaps spacks fault, not sure about the versioneer stuff:

That looks like the problem that occurs when you clone the main branch of the numpy git repo with --depth=1. That gets just the most recent commit, so the checkout won't have the most recently tagged commit. versioneer looks for a tagged commit to construct the numpy version. (See, for example, #19119; I also encountered this issue in ufunclab.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants