-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
bpo-35257: Avoid leaking the linker flags into distutils. #10900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
8da1451
to
6669fe8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something is wrong in this change, but I don't know what: "git clean -fdx; ./configure CC=clang --with-lto && make" fails with this PR, whereas it pass in the master branch. Failure:
clang -pthread -Xlinker -export-dynamic -o Programs/_testembed Programs/_testembed.o libpython3.8m.a -lpthread -ldl -lutil -lm -lm
Programs/python.oPrograms/_testembed.o: file not recognized: : file not recognized: file format not recognizedfile format not recognized
clang-7: error: linker command failed with exit code 1 (use -v to see invocation)clang-7:
error: linker command failed with exit code 1 (use -v to see invocation)
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
6669fe8
to
dc46afc
Compare
Updates based on some discussion with Victor. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments. I didn't test your updated PR yet.
Makefile.pre.in
Outdated
@@ -85,6 +85,10 @@ CONFIGURE_CFLAGS= @CFLAGS@ | |||
# Use it when a compiler flag should _not_ be part of the distutils CFLAGS | |||
# once Python is installed (Issue #21121). | |||
CONFIGURE_CFLAGS_NODIST=@CFLAGS_NODIST@ | |||
# LDFLAGS_NODIST is used in the same manner as CFLAGS_NODIST. | |||
# Use it when a linker flag should _not_ be part of the distutils LDFLAGS | |||
# once Python is installed (Issue #35257) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: "bpo-35257" syntax is now preferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted, will update.
@@ -147,7 +154,7 @@ CONFINCLUDEPY= $(CONFINCLUDEDIR)/python$(LDVERSION) | |||
SHLIB_SUFFIX= @SHLIB_SUFFIX@ | |||
EXT_SUFFIX= @EXT_SUFFIX@ | |||
LDSHARED= @LDSHARED@ $(PY_LDFLAGS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You would mind to add a comment explaining why PY_LDFLAGS (and not PY_LDFLAGS_NODIST) is used for LDSHARED?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to dig in a bit more into the buildsystem to figure out how they are used as my approach was a bit of trial and error for LDSHARED and BLDSHARED. Will try to offer a more comprehensive explanation.
Makefile.pre.in
Outdated
@@ -497,7 +504,7 @@ profile-run-stamp: | |||
touch $@ | |||
|
|||
build_all_generate_profile: | |||
$(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_GEN_FLAG)" LDFLAGS="$(LDFLAGS) $(PGO_PROF_GEN_FLAG)" LIBS="$(LIBS)" | |||
$(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_GEN_FLAG)" LDFLAGS_NODIST="$(LDFLAGS) $(PGO_PROF_GEN_FLAG)" LIBS="$(LIBS)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why $CFLAGS is passed as CFLAGS_NODIST :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the target for created the binary using profile guided optimizations, thus I followed the same pattern for ldflags as with the cflags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it's a bug: https://bugs.python.org/issue35499 and that you should write: LDFLAGS_NODIST="$(LDFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wrote PR #11219 to avoid modifying LDFLAGS here: https://bugs.python.org/issue35499#msg332079
Makefile.pre.in
Outdated
@@ -511,7 +518,7 @@ build_all_merge_profile: | |||
profile-opt: profile-run-stamp | |||
@echo "Rebuilding with profile guided optimizations:" | |||
-rm -f profile-clean-stamp | |||
$(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_USE_FLAG)" LDFLAGS="$(LDFLAGS)" | |||
$(MAKE) @DEF_MAKE_RULE@ CFLAGS_NODIST="$(CFLAGS) $(PGO_PROF_USE_FLAG)" LDFLAGS_NODIST="$(LDFLAGS)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why $CFLAGS is passed as CFLAGS_NODIST :-(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto: https://bugs.python.org/issue35499 write: LDFLAGS_NODIST="$(LDFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)".
@@ -0,0 +1,2 @@ | |||
Avoid leaking the linker flags into distutils when compiling | |||
C extensions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should mention LTO compilation with clang. Maybe: "Avoid leaking Link Time Optimization (LTO) flags in linker flags into distutils when compiling C extensions."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noted, will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LTO is targeted now as the one that shouldn't propagate to C extensions, however that should target the all the flags that are not intended for propagation to C extensions, so shouldn't we have a more generic description of it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so shouldn't we have a more generic description of it?
Keep the generic description, but add a sentence to explain in which case the bug was the most visible. For example:
"Avoid leaking the linker flags into distutils when compiling C extensions, especially Link Time Optimization (LTO) flags."
From what I see in this PR, LDFLAGS="$LDFLAGS $LTOFLAGS" replaced with LDFLAGS_NODIST="$LDFLAGS_NODIST $LTOFLAGS" is the major change of this PR. I don't see other linker flags only passed to LDFLAGS_NODIST. Maybe during the temporary profiling step for PGO? But that's not visible for users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed.
setup.py
Outdated
# modules (Issue #35257). | ||
ldflags = sysconfig.get_config_var('LDFLAGS') | ||
py_ldflags_nodist = sysconfig.get_config_var('PY_LDFLAGS_NODIST') | ||
sysconfig.get_config_vars()['LDFLAGS'] = ldflags + ' ' + py_ldflags_nodist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dislike putting more and more code at the module level :-( Would you mind to move these code (from clfags to sysconfig.get_config_vars()['LDFLAGS']) into a new subfunction (ex: "set_compiler_flags()") which does update sysconfig?
setup.py
Outdated
@@ -24,6 +24,12 @@ | |||
py_cflags_nodist = sysconfig.get_config_var('PY_CFLAGS_NODIST') | |||
sysconfig.get_config_vars()['CFLAGS'] = cflags + ' ' + py_cflags_nodist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why CFLAGS is used instead of PY_CFLAGS here? I would expect that setup.py would use the same CFLAGS than Makefile, something like $(PY_STDMODULE_CFLAGS).
Module/makesetup uses $(PY_BUILTIN_MODULE_CFLAGS).
setup.py
Outdated
@@ -24,6 +24,12 @@ | |||
py_cflags_nodist = sysconfig.get_config_var('PY_CFLAGS_NODIST') | |||
sysconfig.get_config_vars()['CFLAGS'] = cflags + ' ' + py_cflags_nodist | |||
|
|||
# Add special LDFLAGS reserved for building the interpreter and the stdlib | |||
# modules (Issue #35257). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto: bpo-35257
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_osx_support change LGTM
@vstinner I believe I addressed the current issues, didn't have time today to dig more to LDSHARED and BLDSHARED though. It works through all the configs I tested (--with-lto, --with-shared, using clang and more) and the flags do not propagate to distutils. I'd like to have it in 3.6 but maybe it can be added downstream only. Also @skrah is the author of the original code that added cflags_nodist, maybe you could take a look? |
By the way the issue first appeared due to https://bugs.python.org/issue31354 when 3.7 was the master branch. However I requested it to be backported to 3.6 which made this bug propagate to 3.6 as well. I realized it when working on backporting some lto+clang related fixes from master. |
@vstinner tested locally and this now builds fine with
and
which looks file to me |
Can you please merge master into your PR, to retrieve PR #11164 changes? And can you modify build_all_generate_profile: and profile-opt: to use LDFLAGS_NODIST="$(LDFLAGS_NODIST) $(PGO_PROF_GEN_FLAG)"? |
699ee3d
to
25ac429
Compare
Rebased on top of master. Didn't have time yet to test the changes though. |
When compiling 3rd party C extensions, the linker flags used by the compiler for the interpreter and the stdlib modules, will get leaked into distutils. In order to avoid that, the PY_CORE_LDFLAGS and PY_LDFLAGS_NODIST are introduced to keep those flags separated.
pythoninfo.py
25ac429
to
d1655f9
Compare
Thanks @stratakis for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7. |
Sorry, @stratakis and @vstinner, I could not cleanly backport this to |
GH-11264 is a backport of this pull request to the 3.7 branch. |
…H-11264) When compiling 3rd party C extensions, the linker flags used by the compiler for the interpreter and the stdlib modules, will get leaked into distutils. In order to avoid that, the PY_CORE_LDFLAGS and PY_LDFLAGS_NODIST are introduced to keep those flags separated. (cherry picked from commit cf10a75)
) (GH-11265) When compiling 3rd party C extensions, the linker flags used by the compiler for the interpreter and the stdlib modules, will get leaked into distutils. In order to avoid that, the PY_CORE_LDFLAGS and PY_LDFLAGS_NODIST are introduced to keep those flags separated. (cherry picked from commit cf10a75)
) (pythonGH-11264) When compiling 3rd party C extensions, the linker flags used by the compiler for the interpreter and the stdlib modules, will get leaked into distutils. In order to avoid that, the PY_CORE_LDFLAGS and PY_LDFLAGS_NODIST are introduced to keep those flags separated. (cherry picked from commit cf10a75)
This is the first draft of the PR addressing the propagation of LDFLAGS to C extensions built by distutils.
The work is based on acb8c52 where CFLAGS_NODIST was added for compiler flags aimed to be used only by the interpreter and the stdlib modules but not by 3rd party C extensions. This PR expands that to the linker flags.
While LDFLAGS are not leaked into python-config as CFLAGS are, this can be checked by compiling a simple C extension (e.g. psycopg2).
https://bugs.python.org/issue35257