KBriggs
KBriggs

Reputation: 1412

Where are these extra compiler flags coming from when using setup.py to compile a Cython extension?

I am trying to compile a simple little hello world example to get a feel for Cython. It works, but the compilation is littered with flags that I do not want. Following the example here I was able to clean up most of the unwanted flags, but a few persist in spite of my best efforts to control the environment variables. The last comment in the linked question indicates that the extra flags might be bakes into the compiler by the vendor, but I have verified that this is unlikely by using several different compilers, all of which default to the same extra flags.

My call to setup.py looks like this:

CC="gcc" CXX="g++" OPT="" CFLAGS="-O3 -D_GNU_SOURCE" BASECFLAGS="" LDFLAGS="" CCSHARED="" LDSHARED="gcc -shared" PY_CORE_FLAGS="" PY_CFLAGS="" AR="" ARFLAGS="" CPPFLAGS="" CPP="" SHLIB_SUFFIX="" python3 setup.py build_ext --inplace

setup.py is very simple:

from setuptools import Extension, setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize([Extension("hellotest", ["hellotest.pyx"])], language_level="3")
)

And finally, the output of gcc during the compilation, with the unwanted flags enclosed in square brackets:

gcc [-DNDEBUG -g -fwrapv -O2 -Wall] -O3 -D_GNU_SOURCE -fPIC -I./ -I. -I/usr/include/python3.6m -c hellotest.c -o build/temp.linux-x86_64-3.6/hellotest.o
gcc [-DNDEBUG -g -fwrapv -O2 -Wall] -O3 -D_GNU_SOURCE -fPIC -I./ -I. -I/usr/include/python3.6m -c ./funcs.c -o build/temp.linux-x86_64-3.6/./funcs.o
gcc -shared -O3 -D_GNU_SOURCE build/temp.linux-x86_64-3.6/hellotest.o build/temp.linux-x86_64-3.6/./funcs.o -o build/lib.linux-x86_64-3.6/hellotest.cpython-36m-x86_64-linux-gnu.so

Does anyone have any idea where they are finding their way into the compiler options?

Upvotes: 2

Views: 1270

Answers (1)

ead
ead

Reputation: 34326

Setuptools inherits a lot of functionality from distutils and finding out the cflags for building of the c-extensions is one of them.

When build_ext command is run, it calls distutils.sysconfig.customize_compiler(), which in its turn calls distutils.sysconfig.get_config_vars():

def customize_compiler(compiler):
    ...
        (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
            get_config_vars('CC', 'CXX', 'CFLAGS',
                            'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
   ...

to get the default cflags, which will be later extended by the values from the CFLAGS-environment variable and from setup-file and passed to the compiler.

get_config_vars() parses (at least on Linux) the makefile and also config-header, i.e. pyconfig.h, and thus gets the cflags (among other things) with which the current Python-executable was built. The very same cflags are then used to build extensions.

If needed, one can manipulate those built-in flags, as I have shown for example in this SO-post. Whether it is a smart thing to do is another question.


It is a little bit more subtle on Windows, where get_config_vars() doesn't provide that much information - so other tricks are used to build with right options (see for example this SO-post).

Upvotes: 4

Related Questions