diff options
Diffstat (limited to 'waflib/Tools/fc_config.py')
-rw-r--r-- | waflib/Tools/fc_config.py | 283 |
1 files changed, 283 insertions, 0 deletions
diff --git a/waflib/Tools/fc_config.py b/waflib/Tools/fc_config.py new file mode 100644 index 0000000..f9c97fa --- /dev/null +++ b/waflib/Tools/fc_config.py @@ -0,0 +1,283 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! http://waf.googlecode.com/git/docs/wafbook/single.html#_obtaining_the_waf_file + +import re,shutil,os,sys,string,shlex +from waflib.Configure import conf +from waflib.TaskGen import feature,after_method,before_method +from waflib import Build,Utils +FC_FRAGMENT=' program main\n end program main\n' +FC_FRAGMENT2=' PROGRAM MAIN\n END\n' +def fc_flags(conf): + v=conf.env + v['FC_SRC_F']=[] + v['FC_TGT_F']=['-c','-o'] + v['FCINCPATH_ST']='-I%s' + v['FCDEFINES_ST']='-D%s' + if not v['LINK_FC']:v['LINK_FC']=v['FC'] + v['FCLNK_SRC_F']=[] + v['FCLNK_TGT_F']=['-o'] + v['FCFLAGS_fcshlib']=['-fpic'] + v['LINKFLAGS_fcshlib']=['-shared'] + v['fcshlib_PATTERN']='lib%s.so' + v['fcstlib_PATTERN']='lib%s.a' + v['FCLIB_ST']='-l%s' + v['FCLIBPATH_ST']='-L%s' + v['FCSTLIB_ST']='-l%s' + v['FCSTLIBPATH_ST']='-L%s' + v['FCSTLIB_MARKER']='-Wl,-Bstatic' + v['FCSHLIB_MARKER']='-Wl,-Bdynamic' + v['SONAME_ST']='-Wl,-h,%s' +def check_fortran(self,*k,**kw): + self.check_cc(fragment=FC_FRAGMENT,compile_filename='test.f',features='fc fcprogram',msg='Compiling a simple fortran app') +def check_fc(self,*k,**kw): + kw['compiler']='fc' + if not'compile_mode'in kw: + kw['compile_mode']='fc' + if not'type'in kw: + kw['type']='fcprogram' + if not'compile_filename'in kw: + kw['compile_filename']='test.f90' + if not'code'in kw: + kw['code']=FC_FRAGMENT + return self.check(*k,**kw) +def fortran_modifier_darwin(conf): + v=conf.env + v['FCFLAGS_fcshlib']=['-fPIC','-compatibility_version','1','-current_version','1'] + v['LINKFLAGS_fcshlib']=['-dynamiclib'] + v['fcshlib_PATTERN']='lib%s.dylib' + v['FRAMEWORKPATH_ST']='-F%s' + v['FRAMEWORK_ST']='-framework %s' + v['LINKFLAGS_fcstlib']=[] + v['FCSHLIB_MARKER']='' + v['FCSTLIB_MARKER']='' + v['SONAME_ST']='' +def fortran_modifier_win32(conf): + v=conf.env + v['fcprogram_PATTERN']=v['fcprogram_test_PATTERN']='%s.exe' + v['fcshlib_PATTERN']='%s.dll' + v['implib_PATTERN']='lib%s.dll.a' + v['IMPLIB_ST']='-Wl,--out-implib,%s' + v['FCFLAGS_fcshlib']=[] + v.append_value('FCFLAGS_fcshlib',['-DDLL_EXPORT']) + v.append_value('LINKFLAGS',['-Wl,--enable-auto-import']) +def fortran_modifier_cygwin(conf): + fortran_modifier_win32(conf) + v=conf.env + v['fcshlib_PATTERN']='cyg%s.dll' + v.append_value('LINKFLAGS_fcshlib',['-Wl,--enable-auto-image-base']) + v['FCFLAGS_fcshlib']=[] +def check_fortran_dummy_main(self,*k,**kw): + if not self.env.CC: + self.fatal('A c compiler is required for check_fortran_dummy_main') + lst=['MAIN__','__MAIN','_MAIN','MAIN_','MAIN'] + lst.extend([m.lower()for m in lst]) + lst.append('') + self.start_msg('Detecting whether we need a dummy main') + for main in lst: + kw['fortran_main']=main + try: + self.check_cc(fragment='int %s() { return 0; }\n'%(main or'test'),features='c fcprogram',mandatory=True) + if not main: + self.env.FC_MAIN=-1 + self.end_msg('no') + else: + self.env.FC_MAIN=main + self.end_msg('yes %s'%main) + break + except self.errors.ConfigurationError: + pass + else: + self.end_msg('not found') + self.fatal('could not detect whether fortran requires a dummy main, see the config.log') +GCC_DRIVER_LINE=re.compile('^Driving:') +POSIX_STATIC_EXT=re.compile('\S+\.a') +POSIX_LIB_FLAGS=re.compile('-l\S+') +def is_link_verbose(self,txt): + assert isinstance(txt,str) + for line in txt.splitlines(): + if not GCC_DRIVER_LINE.search(line): + if POSIX_STATIC_EXT.search(line)or POSIX_LIB_FLAGS.search(line): + return True + return False +def check_fortran_verbose_flag(self,*k,**kw): + self.start_msg('fortran link verbose flag') + for x in['-v','--verbose','-verbose','-V']: + try: + self.check_cc(features='fc fcprogram_test',fragment=FC_FRAGMENT2,compile_filename='test.f',linkflags=[x],mandatory=True) + except self.errors.ConfigurationError: + pass + else: + if self.is_link_verbose(self.test_bld.err)or self.is_link_verbose(self.test_bld.out): + self.end_msg(x) + break + else: + self.end_msg('failure') + self.fatal('Could not obtain the fortran link verbose flag (see config.log)') + self.env.FC_VERBOSE_FLAG=x + return x +LINKFLAGS_IGNORED=[r'-lang*',r'-lcrt[a-zA-Z0-9\.]*\.o',r'-lc$',r'-lSystem',r'-libmil',r'-LIST:*',r'-LNO:*'] +if os.name=='nt': + LINKFLAGS_IGNORED.extend([r'-lfrt*',r'-luser32',r'-lkernel32',r'-ladvapi32',r'-lmsvcrt',r'-lshell32',r'-lmingw',r'-lmoldname']) +else: + LINKFLAGS_IGNORED.append(r'-lgcc*') +RLINKFLAGS_IGNORED=[re.compile(f)for f in LINKFLAGS_IGNORED] +def _match_ignore(line): + for i in RLINKFLAGS_IGNORED: + if i.match(line): + return True + return False +def parse_fortran_link(lines): + final_flags=[] + for line in lines: + if not GCC_DRIVER_LINE.match(line): + _parse_flink_line(line,final_flags) + return final_flags +SPACE_OPTS=re.compile('^-[LRuYz]$') +NOSPACE_OPTS=re.compile('^-[RL]') +def _parse_flink_line(line,final_flags): + lexer=shlex.shlex(line,posix=True) + lexer.whitespace_split=True + t=lexer.get_token() + tmp_flags=[] + while t: + def parse(token): + if _match_ignore(token): + pass + elif token.startswith('-lkernel32')and sys.platform=='cygwin': + tmp_flags.append(token) + elif SPACE_OPTS.match(token): + t=lexer.get_token() + if t.startswith('P,'): + t=t[2:] + for opt in t.split(os.pathsep): + tmp_flags.append('-L%s'%opt) + elif NOSPACE_OPTS.match(token): + tmp_flags.append(token) + elif POSIX_LIB_FLAGS.match(token): + tmp_flags.append(token) + else: + pass + t=lexer.get_token() + return t + t=parse(t) + final_flags.extend(tmp_flags) + return final_flags +def check_fortran_clib(self,autoadd=True,*k,**kw): + if not self.env.FC_VERBOSE_FLAG: + self.fatal('env.FC_VERBOSE_FLAG is not set: execute check_fortran_verbose_flag?') + self.start_msg('Getting fortran runtime link flags') + try: + self.check_cc(fragment=FC_FRAGMENT2,compile_filename='test.f',features='fc fcprogram_test',linkflags=[self.env.FC_VERBOSE_FLAG]) + except: + self.end_msg(False) + if kw.get('mandatory',True): + conf.fatal('Could not find the c library flags') + else: + out=self.test_bld.err + flags=parse_fortran_link(out.splitlines()) + self.end_msg('ok (%s)'%' '.join(flags)) + self.env.LINKFLAGS_CLIB=flags + return flags + return[] +def getoutput(conf,cmd,stdin=False): + if stdin: + stdin=Utils.subprocess.PIPE + else: + stdin=None + env=conf.env.env or None + try: + p=Utils.subprocess.Popen(cmd,stdin=stdin,stdout=Utils.subprocess.PIPE,stderr=Utils.subprocess.PIPE,env=env) + if stdin: + p.stdin.write('\n') + stdout,stderr=p.communicate() + except: + conf.fatal('could not determine the compiler version %r'%cmd) + else: + if not isinstance(stdout,str): + stdout=stdout.decode(sys.stdout.encoding) + if not isinstance(stderr,str): + stderr=stderr.decode(sys.stdout.encoding) + return stdout,stderr +ROUTINES_CODE="""\ + subroutine foobar() + return + end + subroutine foo_bar() + return + end +""" +MAIN_CODE=""" +void %(dummy_func_nounder)s(void); +void %(dummy_func_under)s(void); +int %(main_func_name)s() { + %(dummy_func_nounder)s(); + %(dummy_func_under)s(); + return 0; +} +""" +def link_main_routines_tg_method(self): + def write_test_file(task): + task.outputs[0].write(task.generator.code) + bld=self.bld + bld(rule=write_test_file,target='main.c',code=MAIN_CODE%self.__dict__) + bld(rule=write_test_file,target='test.f',code=ROUTINES_CODE) + bld(features='fc fcstlib',source='test.f',target='test') + bld(features='c fcprogram',source='main.c',target='app',use='test') +def mangling_schemes(): + for u in['_','']: + for du in['','_']: + for c in["lower","upper"]: + yield(u,du,c) +def mangle_name(u,du,c,name): + return getattr(name,c)()+u+(name.find('_')!=-1 and du or'') +def check_fortran_mangling(self,*k,**kw): + if not self.env.CC: + self.fatal('A c compiler is required for link_main_routines') + if not self.env.FC: + self.fatal('A fortran compiler is required for link_main_routines') + if not self.env.FC_MAIN: + self.fatal('Checking for mangling requires self.env.FC_MAIN (execute "check_fortran_dummy_main" first?)') + self.start_msg('Getting fortran mangling scheme') + for(u,du,c)in mangling_schemes(): + try: + self.check_cc(compile_filename=[],features='link_main_routines_func',msg='nomsg',errmsg='nomsg',mandatory=True,dummy_func_nounder=mangle_name(u,du,c,"foobar"),dummy_func_under=mangle_name(u,du,c,"foo_bar"),main_func_name=self.env.FC_MAIN) + except self.errors.ConfigurationError: + pass + else: + self.end_msg("ok ('%s', '%s', '%s-case')"%(u,du,c)) + self.env.FORTRAN_MANGLING=(u,du,c) + break + else: + self.end_msg(False) + self.fatal('mangler not found') + return(u,du,c) +def set_lib_pat(self): + self.env['fcshlib_PATTERN']=self.env['pyext_PATTERN'] +def detect_openmp(self): + for x in['-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp']: + try: + self.check_fc(msg='Checking for OpenMP flag %s'%x,fragment='program main\n call omp_get_num_threads()\nend program main',fcflags=x,linkflags=x,uselib_store='OPENMP') + except self.errors.ConfigurationError: + pass + else: + break + else: + self.fatal('Could not find OpenMP') + +conf(fc_flags) +conf(check_fortran) +conf(check_fc) +conf(fortran_modifier_darwin) +conf(fortran_modifier_win32) +conf(fortran_modifier_cygwin) +conf(check_fortran_dummy_main) +conf(is_link_verbose) +conf(check_fortran_verbose_flag) +conf(check_fortran_clib) +feature('link_main_routines_func')(link_main_routines_tg_method) +before_method('process_source')(link_main_routines_tg_method) +conf(check_fortran_mangling) +feature('pyext')(set_lib_pat) +before_method('propagate_uselib_vars','apply_link')(set_lib_pat) +conf(detect_openmp)
\ No newline at end of file |