[Distutils] distutils.command.build_clib: How to add additional compiler flags for cl.exe?

Erik Bray erik.m.bray at gmail.com
Thu Dec 3 14:20:02 EST 2015


On Sun, Nov 29, 2015 at 10:44 AM, Kim Walisch <kim.walisch at gmail.com> wrote:
> Hi,
>
> For distutils.command.build_clib the commonly used code below does not
> work for adding additional compiler flags (it works using
> distutils.command.build_ext):
>
> extra_compile_args = '-fopenmp'
>
> On Unix-like system I found a workaround which allows to specify
> additional compiler flags for distutils.command.build_clib:
>
> cflags = distutils.sysconfig.get_config_var('CFLAGS')
> distutils.sysconfig._config_vars['CFLAGS'] = cflags + " -fopenmp"
>
> Unfortunately this does not work with Microsoft's C/C++ compiler
> cl.exe.
>
> Does anybody know how I can add additional compiler flags for cl.exe
> and distutils.command.build_clib?
>
> Thanks and best regards!

Really what I think you want is a way to determine what compiler will
be used, and to add compiler arguments accordingly.  Unfortunately
distutils does not provide one easy way to determine what compiler it
will use--this is among the myriad ways it's not great for use as a
build system.

And yet there are several workarounds.  For starters you can try:

from distutils import ccompiler

compiler = ccompiler.get_default_compiler()

if compiler == 'msvc':
    # Add option for MS compiler
elif compiler == 'unix':
    # Add option for gcc
elif # etc....

This does not actually tell you what compiler executable will be
used--for that you have to dig around more.  This is telling you the
name of the compiler class in distutils that will be used.  But if you
want to pass arguments for cl.exe, it will be 'msvc'.

This also does not guarantee which compiler will actually be used--a
user can override that via a command-line argument or setup.cfg.  To
get around that I usually use a dummy 'Distribution' object to parse
any user arguments.  This isn't perfect either, but it's almost
exactly what happens when the setup() function is called--it just
stops before actually running any of the commands:

from distutils.dist import Distribution
from distutils import ccompiler

def get_compiler():
    dist = Distribution({'script_name': os.path.basename(sys.argv[0]),
                                'script_args': sys.argv[1:]})
    dist.parse_config_files()
    dist.parse_command_line()
    compiler = None

    for cmd in ['build', 'build_ext', 'build_clib']:
        compiler = dist.command_options.get(cmd, {}).get('compiler',
('', None))[1]
        if compiler is not None:
            break

    if compiler is None:
        return ccompiler.get_default_compiler()
    else:
        return compiler


I'd love to know if there is a better way in general to do this myself...


Erik


More information about the Distutils-SIG mailing list