bt2: honor build system compiler/linker preferences
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 1 Apr 2020 14:55:04 +0000 (10:55 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 1 Apr 2020 19:17:32 +0000 (15:17 -0400)
commitafdd1f8201f579d81959ce85759dcc62fcc0a85d
tree696b01d4b0f58990274f83b314a5516c522e3ea3
parent8b305066676fc7aa433e8eb668f9de8802008025
bt2: honor build system compiler/linker preferences

This is an attempt to fix the dreaded "compiling the Python native
module with a custom compiler or compiler-specific flag" problem.

The problem may arise when building with a CC different than what the
Python interpreter was compiled with.  It can manifests itself in two
different ways, as far as I know.  But in both cases, it's due to us
overriding the compiler and compiler flags when invoking setup.py to
build the native modules, and how distutils invokes the compiler and
linker to build the native modules.

Scenario 1
----------

Things fail when trying to compile with a compiler other than what
Python has been compiled with, and using in `CFLAGS` a compiler flag
unknown to the compiler Python has been compiled with.

For example, on Ubuntu 18.04, we get this when building with CC=clang
(the -Wtautological-constant-out-of-range-compare is a clang-specific
warning flag currently specified in configure.ac):

    x86_64-linux-gnu-gcc ... -Wtautological-constant-out-of-range-compare ... -o build/build_lib/bt2/_native_bt.cpython-38-x86_64-linux-gnu.so
    x86_64-linux-gnu-gcc: error: unrecognized command line option ‘-Wtautological-constant-out-of-range-compare’
    error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

This is due to the fact that:

- The default link command used by distutils to link shared objects uses
  its default compiler driver (gcc on Linux)
- It passes `CFLAGS` to the linker

Because of this, we end up passing a clang-specific warning flag to gcc,
which proceeds to error out.

To fix this, I have considered setting the LDSHARED variable to
override the command used for linking shared objects.  If the compiler
driver used to drive the linking is the same as the compiler driver used
for compiling, it should understand all the passed flags.

However, it is not obvious to do this right, especially, considering the
various platforms.  But most importantly, it is doesn't help with the
next scenario.

Scenario 2
----------

On Arch Linux (and presumably on Fedora too [1]), the flags passed by
distutils to the compiler contain `-fno-semantic-interposition`, which
is a gcc-specific flag.  When building with CC=clang, we therefore get
this when compiling:

    building 'bt2._native_bt' extension
    clang ... -fno-semantic-interposition ... -c bt2/native_bt.c -o build/temp.linux-x86_64-3.8/bt2/native_bt.o
    clang-9: error: unknown argument: '-fno-semantic-interposition'

clang errors out, because it gets passed a gcc-specific flag.

[1] https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup

The fix
-------

Two important distutils configuration variables are at play in this
problem:
  - LDSHARED: defines a command to link a build target
  - CFLAGS: contains the compiler flags used to build the python
    interpreter.

The configuration variables are changed on access by overriding
distutils' get_config_vars().

In the case of `LDSHARED`, distutils allows it to be specified as an
environment variable which would probably be cleaner (if it actually
works, I haven't tested). distutils seems to honor the environment
`CC` _sometimes_ (depending on whether or not it has performed the
`customize_compiler` step?)

The override always uses the environment `CC` and completely foregoes
the `LDSHARED` configuration variable if `LDFLAGS` are provided. If no
`LDFLAGS` are specified, the compiler is replaced in the LDSHARED
command.

Unfortunately, the CFLAGS environment variable is only appended to
the Python interpreter's build-time CFLAGS, which doesn't solve our
problem. get_cflags() completely overrides the CFLAGS configuration
variable to use babeltrace's build system-specified CFLAGS.

Drawbacks
---------

I can't think of a scenario where this doesn't work, but I'm afraid
this will break in non-trivial build environments.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: If3142ddb228758e63a986e735cb8f9d89dd39b67
Reviewed-on: https://review.lttng.org/c/babeltrace/+/3286
Tested-by: jenkins <jenkins@lttng.org>
src/bindings/python/bt2/Makefile.am
src/bindings/python/bt2/setup.py.in
This page took 0.025151 seconds and 4 git commands to generate.