One common way to build source code on *NIX platforms is to use a configure
script. Under the hood, configure tries to build a bunch of test programs to determine which libraries you have accessible. It then generates a header file which gets included in the project that defines a bunch of macros conditionally so that the programmer can supply an alternative or build a stripped down version of a library/program if a particular "dependency" is missing. Is there anything functionally equivalent using numpy.distutils
?
As an example, here is my setup.py
:
from numpy.distutils.misc_util import Configuration
def configuration(parent_package='',top_path=None):
config = Configuration('pyggcm',parent_package,top_path)
#TODO: Currently, I have some macros to conditionally build the seek-code
#Unfortunately, that's not the best solution (by far). Perhaps if we
#changed to using stream access it would work better, without the need
#for these silly macros.
config.add_extension('_fortfile',sources=['_fortfile/_fortfile.F90'],
define_macros=[
('FSEEKABLE',1), #compiler provides fseek and ftell
('HAVE_STREAM',1) #compiler provides access='stream' for opening files. (f2003 standard)
])
config.add_extension('jrrle',sources=['jrrle/jrrle.f90'])
config.add_scripts(['scripts/ggcm_timehist',
'scripts/ggcm_plasmasheet',
'scripts/ggcm_plot'])
return config
from numpy.distutils.core import setup
setup(configuration=configuration)
This is unconditionally building the FSEEKABLE
code and would need to be manually edited if the users Fortran compiler doesn't support that (The macros wrap the fseek
and ftell
GNU intrinsic function). Is there a way to determine whether the Fortran compiler supplies those intrinsic functions?
Try this:
import os
import shutil
import tempfile
from distutils.ccompiler import new_compiler
def hasfunction(cc, funcname, include=None, extra_postargs=None):
tmpdir = tempfile.mkdtemp(prefix='hasfunction-')
devnull = oldstderr = None
try:
try:
fname = os.path.join(tmpdir, 'funcname.c')
f = open(fname, 'w')
if include is not None:
f.write('#include %s\n' % include)
f.write('int main(void) {\n')
f.write(' %s;\n' % funcname)
f.write('}\n')
f.close()
devnull = open(os.devnull, 'w')
oldstderr = os.dup(sys.stderr.fileno())
os.dup2(devnull.fileno(), sys.stderr.fileno())
objects = cc.compile([fname], output_dir=tmpdir,
extra_postargs=extra_postargs)
cc.link_executable(objects, os.path.join(tmpdir, 'a.out'))
except Exception as e:
return False
return True
finally:
if oldstderr is not None:
os.dup2(oldstderr, sys.stderr.fileno())
if devnull is not None:
devnull.close()
shutil.rmtree(tmpdir)
Example:
def detect_sse3():
"Does this compiler support SSE3 intrinsics?"
compiler = new_compiler()
return hasfunction(compiler, '__m128 v; _mm_hadd_ps(v,v)',
include='<pmmintrin.h>',
extra_postargs=['-msse3'])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With