[Distutils] special compiler options for only one file

Andrew Dalke dalke at dalkescientific.com
Tue Apr 23 02:21:30 CEST 2013


Hi Erik,

On Apr 11, 2013, at 7:43 PM, Erik Bray wrote:
> One possible solution, albeit more complex code-wise than compiling
> that single file as a static lib, would be to subclass the compiler
> class you want to use and override its _compile() method, which is the
> one responsible for compiling a single file.  You can then override
> the arguments in there.  Look, for example, at
> distutils.unixcompiler.UnixCCompiler._compile.

I shudder every time I think about subclassing one of the compiler
classes. I've done it before, based on suggestions from this list,
but I had no sense of how it actually worked.

Instead, I wrote a wrapper script, at the end of this email, which
can be used like this:

   env CC=$PWD/filter_gcc python setup.py build

It sniffs the command-line and keeps "-mssse3" for the right file,
otherwise it removes that option. It then calls gcc with the tweaked
arguments.

Unlike subclassing, I understand how this one works. :)

Cheers,


				Andrew
				dalke at dalkescientific.com


#!/usr/bin/env python

# chemfp by default assumes the --with-ssse3 flag, which enables
# compiler-specific option to enable the SSSE3 intrinsics.
# 
# You can disable this using --without-ssse3.
#
# The code which requires the SSSE3 specific intrinsics will only be
# run when chemfp, at run-time, determines that the CPU supports the
# SSSE3 instruction set. This is as it should be. Unfortunately, the
# -mssse3 compiler flag also tells gcc that it's okay to use
# SSSE3-specific instructions in the rest of the code. This causes a
# bus error if chemfp is then used on a CPU which doesn't support the
# correct instruction set. Unfortunately, I don't have the ability to
# use a non-ssse3 code path for this case.
#
# This is only a problem if:
#   - you use the same binary on multiple platforms, where
#   - some machines do not have the SSSE3 instruction set AND
#   - some machines have the SSSE3 instruction set AND
#   - the machines with the SSSE3 instruction set do not support POPCNT.
#
# (If all of your SSSE3 machines also support POPCNT then it's okay to
# use --without-ssse3, because the POPCNT instruction is always faster
# than the SSSE3-based popcount implementation.)
#
# This script, filter_gcc, is a workaround for the problem. Only one
# file needs the -mssse3 option. The best solution is to tell Python's
# setup.py to compile src/popcount_SSSE3.c with -mssse3 enabled and to
# leave out that flag for the other files. Unfortunately, setup.py
# doesn't make that easy.
#
# filter_gcc acts as a filter layer between setup.py and gcc. It's
# used like this:
#
#   env CC=$PWD/filter_gcc python setup.py build
#
# This tells setup.py to use $PWD/filter_gcc (ie, this script) as an
# alternate C compiler. This script run and checks if setup.py is
# attempting to compile popcount_SSSE3.c. If so, it leaves the -mssse3
# flag in place (if it exists). Otherwise, it removes the flag (if it
# exists).

import sys
import subprocess

CC = "gcc"  # The real C compiler

args = sys.argv[1:]
#print "Called with", args

# Check to see if I should remove the "-mssse3" flag from the args.
remove_mssse3 = True
for arg in args:
    if "popcount_SSSE3.c" in arg:
        remove_mssse3 = False
        break

if remove_mssse3:
    # Go ahead and remove the "-mssse3"
    try:
        args.remove("-mssse3")
    except ValueError:
        # This can happen if someone does:
        #    env CC=$PWD/filter_gcc python setup.py build --without-ssse3
        pass

assert args, "Missing exec args"

# Use the correct C compiler
args = [CC] + args
#print "  -->", " ".join(args)

# Run the new command, and report any errors.
try:
    retcode = subprocess.call(args)
except OSError, err:
    cmd = " ".join(args)
    raise SystemExit("Failed to execute %r: %s" % (cmd, err))

if retcode:
    raise SystemExit(retched)




More information about the Distutils-SIG mailing list