Bug 1724190 - Inconsistent output from python3-config
Summary: Inconsistent output from python3-config
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Fedora
Classification: Fedora
Component: python3
Version: 30
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Victor Stinner
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2019-06-26 12:33 UTC by Mattias Ellert
Modified: 2019-09-17 13:46 UTC (History)
12 users (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2019-09-17 13:46:42 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Mattias Ellert 2019-06-26 12:33:03 UTC
Description of problem:

python3-config has two different options --libs and --ldflags.

The python2-config output of these options are consistent:

$ python2-config --libs
-lpython2.7 -lpthread -ldl -lutil -lm
$ python2-config --ldflags
-lpython2.7 -lpthread -ldl -lutil -lm -Xlinker -export-dynamic

However the the python3-config output is inconsistent:

$ python3-config --libs
-lpython3.7m -lcrypt -lpthread -ldl  -lutil -lm 
$ python3-config --ldflags
 -L/usr/lib64 -lpython3.7m -lcrypt -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic

The -L/usr/lib64 should not be there. /usr/lib64 is in the default search path for libraries so it is not needed. And Having it in the -L flags can cause side effects that are not intended.

If python is configured with --prefix /usr and the python library is installed in a default path neither --libs nor --ldflags should contain the -L flag pointing to the install location of the library. If it is configured with some other --prefix and the library is not in the default path both --libs and --ldflags should have the -L flag.

The python 3.8 from copr has the same issue:

# python3-config --libs
 -lcrypt -lpthread -ldl  -lutil -lm -lm 
# python3-config --ldflags
 -L/usr/lib64  -lcrypt -lpthread -ldl  -lutil -lm -lm 
# python3-config --libs --embed
-lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm -lm 
# python3-config --ldflags --embed
 -L/usr/lib64 -lpython3.8 -lcrypt -lpthread -ldl  -lutil -lm -lm 

Here the -L should not appear at all without --embed, since there is no need to indicate the install location of the library when it is not mentioned in an -l flag.
With the --embed flag it should not be there in neither --libs nor --ldflags if the library is in a default library path and be in both --libs and --ldflags if it is not.

Version-Release number of selected component (if applicable):

python3-devel-3.7.3-3.fc30
python3-devel-3.8.0~b1-1.fc31

How reproducible:
Always

Steps to Reproduce:
1. python3-config --libs
2. python3-config --ldflags

Actual results:
-L/usr/lib64 appears in the output in an inconsistent way.

Expected results:
-L/usr/lib64 does not appear in the output.

Comment 1 Miro Hrončok 2019-06-26 13:36:05 UTC
> And Having it in the -L flags can cause side effects that are not intended

It would really help to see how dangerous this actually is. Do you have some examples?

Comment 2 Mattias Ellert 2019-06-27 09:34:38 UTC
If for example you are building something against a non-system version of a library, while you have a system version of that library installed. You would then have -L/<path to non-system version> in your LDFLAGS. If some configure script then adds -L/usr/lib64 to your LDFLAGS from python-config you might link to the system version instead, depending on in which order the Makefiles puts the options together.

If your are building a new version of a software of which you already have an older version installed. If the software provides both libraries and executables, the executables should be linked to the new version of the library you just built and not the system version in /usr/lib64. Depending on how the Makefiles are written you might get the wrong version if -L/usr/lib64 is added to LDFLAGS.

pkg-config --libs does not generate any -L flags if the .pc file contains "libdir=/usr/lib64", "Libs: -L${libdir}".

Comment 3 Victor Stinner 2019-07-08 12:58:49 UTC
The logic to detect the "system library path(s)" looks highly platform dependent. Maybe Python configure script should get an optional --with-system-libdir=PATH which would strip -L option in python-config if it's value is equal to PATH.

> pkg-config --libs does not generate any -L flags if the .pc file contains "libdir=/usr/lib64", "Libs: -L${libdir}".

Right. On my Fedora 30, /usr/lib64/pkgconfig/python3.pc contains "Libs: -L${libdir} -lpython3.7m" with "libdir=/usr/lib64", but "pkg-config python3 --libs" only returns "-lpython3.7m": no -L flag.

pkg-config:

* https://github.com/pkgconf/pkgconf/tree/master/libpkgconf
* https://src.fedoraproject.org/rpms/pkgconf/blob/master/f/pkgconf.spec

pkg-config has a --keep-system-libs flag: "pkg-config python3 --libs  --keep-system-libs" returns "-L/usr/lib64 -lpython3.7m" as expected.

pkg-config uses PKG_CONFIG_SYSTEM_LIBRARY_PATH environment variable if set, otherwise it uses &personality->filter_libdirs. "SystemLibraryPaths" value (&personality->filter_libdirs) can be read using the command:
---
$ pkg-config --dump-personality
Triplet: default
DefaultSearchPaths: /usr/lib64/pkgconfig /usr/share/pkgconfig
SystemIncludePaths: /usr/include
SystemLibraryPaths: /usr/lib64
---

The default personality uses SYSTEM_LIBDIR, macro defines by CMakeLists.txt, extract:
---
SET(libdir ${prefix}/lib)
SET(system_libdir "${libdir}" CACHE STRING "specify the system library directory (default LIBDIR)")
SET(SYSTEM_LIBDIR "${system_libdir}")
ADD_DEFINITIONS(-DSYSTEM_LIBDIR=\"${system_libdir}\")
---

But Fedora specfile of pkgconf overrides the system libdir:
---	
%configure --disable-static \
           --with-pkg-config-dir=%{pkgconf_libdirs} \
           --with-system-includedir=%{_includedir} \
           --with-system-libdir=%{_libdir}
---
https://src.fedoraproject.org/rpms/pkgconf/blob/master/f/pkgconf.spec#_110

Comment 4 Victor Stinner 2019-07-08 13:04:20 UTC
The workaround is to not use Python specific specific script "python3-config", but use pkg-config instead: "pkg-config python3 --libs" works as you expect ;-)

Comment 5 Haïkel Guémar 2019-07-26 06:55:18 UTC
I agree with using pkg-config, but it still broken as of today. As you see, in the pkgconfig file from copr python3.8, the Libs line is empty.
I suspect this issue was introduced during the lifecycle of this ticket though.


cat /usr/lib64/pkgconfig/python3.pc 
# See: man pkg-config
prefix=/usr
exec_prefix=/usr
libdir=/usr/lib64
includedir=/usr/include

Name: Python
Description: Build a C extension for Python
Requires:
Version: 3.8
Libs.private: -lcrypt -lpthread -ldl  -lutil -lm
Libs:
Cflags: -I${includedir}/python3.8

Comment 6 Miro Hrončok 2019-07-26 09:44:23 UTC
Haïkel, that is not what this bug is about, but a deliberate change in Python 3.8 described if https://docs.python.org/dev/whatsnew/3.8.html#debug-build-uses-the-same-abi-as-release-build

tl;dr: extension modules are no longer linked to libpython, if you need to link to libpython, you are "embedding Python" (using Py_Initialize...) and you need to use a different pkg-config file.

Comment 7 Victor Stinner 2019-09-17 13:46:42 UTC
python3-config is coming from the CPython projet, so I report the bug upstream:
https://bugs.python.org/issue38199


Note You need to log in before you can comment on or make changes to this bug.