为什么SCons构建的成功取决于variant_dir名称?
我对这样的行为感到厌烦得要死。因此,在 SConstruct 文件中,我们有最后一个字符串,如下所示:
import compilers, os
env = Environment(ENV = os.environ, TOOLS = ['default'])
def set_compiler(compiler_name):
env.Replace(FORTRAN = compiler_name)
env.Replace(F77 = compiler_name)
env.Replace(F90 = compiler_name)
env.Replace(F95 = compiler_name)
def set_flags(flags):
env.Replace(FORTRANFLAGS = flags)
env.Replace(F77FLAGS = flags)
env.Replace(F90FLAGS = flags)
env.Replace(F95FLAGS = flags)
mod_dir_prefix = {
"gfortran": "-J ",
"ifort": "-???",
"pgfortran": "-module "
}
flags = {
("gfortran", "debug"): "-O0 -g -Wall -Wextra -pedantic -fimplicit-none -fbounds-check -fbacktrace",
("gfortran", "release"): "-O3",
("pgfortran", "debug"): "-O0 -g -C -traceback",
("pgfortran", "release"): "-O4"
}
if not GetOption('clean'):
print "\nAvailable Fortran compilers:\n"
for k, v in compilers.compilers_dict().iteritems():
print "%10s : %s" % (k, v)
compiler = raw_input("\nChoose compiler: ")
set_compiler(compiler)
debug_or_release = raw_input("\nDebug or release: ")
set_flags(flags[(compiler, debug_or_release)])
env.Replace(FORTRANMODDIRPREFIX = mod_dir_prefix[compiler])
env.Replace(LINK = compiler)
env.Replace(LINKCOM = "$LINK -o $TARGET $LINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS")
env.Replace(LINKFLAGS = "")
env.Replace(FORTRANMODDIR = '#Mod')
Export('env')
SConscript('Sources/SConscript', variant_dir='Build', duplicate=0)
compilers.py 是我自己的模块,用于查找一些可用的 Fortran 编译器。
在 Sources 文件夹中,我们有几个 Fortran 源文件。
Sources\SConscript
Import('env')
env.Program('app', Glob('*.f90'))
Scons 支持 Fortran,一切正常。
gfortran -o Temp\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Temp\math.o -c -O3 -JMod Sources\math.f90
gfortran -o Temp\sorts.o -c -O3 -JMod Sources\sorts.f90
gfortran -o Temp\utils.o -c -O3 -JMod Sources\utils.f90
gfortran -o Temp\main.o -c -O3 -JMod Sources\main.f90
gfortran -o Temp\app.exe Temp\kinds.o Temp\main.o Temp\math.o Temp\sorts.o Temp\utils.o
scons: done building targets.
将variant_dir名称重命名为#Bin
或#Build
后,我们收到错误消息:
gfortran -o Bin\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Bin\main.o -c -O3 -JMod Sources\main.f90
Sources\main.f90:3.11:
USE sorts
1
Fatal Error: Can't open module file 'sorts.mod' for reading at (1): No such file or directory
当然编译顺序很重要。但为什么它依赖于variant_dir名称呢?看起来像一个错误,但也许我做错了什么。
PS 此行为不依赖于重复
变量值。
PPS 在使用 Python 2.7 的 Windows 和使用 Python 2.5.1 的 Mac OS X 上使用 SCons 2.0.1 进行了测试。
I am bored to death with such behavior. So in SConstruct file we have the last string like this one:
import compilers, os
env = Environment(ENV = os.environ, TOOLS = ['default'])
def set_compiler(compiler_name):
env.Replace(FORTRAN = compiler_name)
env.Replace(F77 = compiler_name)
env.Replace(F90 = compiler_name)
env.Replace(F95 = compiler_name)
def set_flags(flags):
env.Replace(FORTRANFLAGS = flags)
env.Replace(F77FLAGS = flags)
env.Replace(F90FLAGS = flags)
env.Replace(F95FLAGS = flags)
mod_dir_prefix = {
"gfortran": "-J ",
"ifort": "-???",
"pgfortran": "-module "
}
flags = {
("gfortran", "debug"): "-O0 -g -Wall -Wextra -pedantic -fimplicit-none -fbounds-check -fbacktrace",
("gfortran", "release"): "-O3",
("pgfortran", "debug"): "-O0 -g -C -traceback",
("pgfortran", "release"): "-O4"
}
if not GetOption('clean'):
print "\nAvailable Fortran compilers:\n"
for k, v in compilers.compilers_dict().iteritems():
print "%10s : %s" % (k, v)
compiler = raw_input("\nChoose compiler: ")
set_compiler(compiler)
debug_or_release = raw_input("\nDebug or release: ")
set_flags(flags[(compiler, debug_or_release)])
env.Replace(FORTRANMODDIRPREFIX = mod_dir_prefix[compiler])
env.Replace(LINK = compiler)
env.Replace(LINKCOM = "$LINK -o $TARGET $LINKFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS")
env.Replace(LINKFLAGS = "")
env.Replace(FORTRANMODDIR = '#Mod')
Export('env')
SConscript('Sources/SConscript', variant_dir='Build', duplicate=0)
compilers.py is my own module to find some Fortran compilers which are available.
In Sources folder we have a couple of Fortran source files.
Sources\SConscript
Import('env')
env.Program('app', Glob('*.f90'))
Scons supports Fortran and everything works fine.
gfortran -o Temp\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Temp\math.o -c -O3 -JMod Sources\math.f90
gfortran -o Temp\sorts.o -c -O3 -JMod Sources\sorts.f90
gfortran -o Temp\utils.o -c -O3 -JMod Sources\utils.f90
gfortran -o Temp\main.o -c -O3 -JMod Sources\main.f90
gfortran -o Temp\app.exe Temp\kinds.o Temp\main.o Temp\math.o Temp\sorts.o Temp\utils.o
scons: done building targets.
After renaming variant_dir name to let say #Bin
or #Build
we get error message:
gfortran -o Bin\kinds.o -c -O3 -JMod Sources\kinds.f90
gfortran -o Bin\main.o -c -O3 -JMod Sources\main.f90
Sources\main.f90:3.11:
USE sorts
1
Fatal Error: Can't open module file 'sorts.mod' for reading at (1): No such file or directory
Of course the order of compilation matters. But why it depends on variant_dir name? Seems like a bug, but maybe I'm doing something wrong.
P.S. This behavior doesn't depend on duplicate
variable value.
P.P.S. Tested with SCons 2.0.1 on Windows with Python 2.7 and Mac OS X with Python 2.5.1.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是对旧线程的回复,但我几乎遇到了同样的问题,需要挖掘解决方案。
首先,您的构建顺序可能已关闭,因为 Fortran 的依赖关系扫描器无法正常工作。尝试运行
它实际上不会编译任何东西,但会显示命令,最后会打印 Scons 看到的依赖关系树。
一个可能的解决方案:
尝试添加行(我添加了您的上下文源):
env.Replace(FORTRANMODDIR = '#Mod')
env.Replace(FORTRANPATH = '.' ]
导出('env')
目录
据我了解,路径是相对于 SConscript 文件的“虚拟”位置(即 src 目录或变体
build
目录),这应该添加包含源代码的 文件到扫描仪的搜索路径。在我的 scons 版本(2.3.0)中,我无法使用
duplicate=0
参数,因为它会自动将原始源目录插入到模块路径中,导致命令行看起来像-module build/ -module src/
(ifort) 并基本上覆盖了我不弄乱源目录的偏好。不过,这可能是一个错误。This is a reply to an old thread, but I had virtually the same problem and needed to dig around for a solution.
Firstly, your build order is probably off because the dependency scanner for Fortran does not work properly. Try running
which won't actually compile anything but show you the commands and in the end will print the dependency tree as Scons sees it.
A possible solution:
Try adding the line (I added your source for context):
env.Replace(FORTRANMODDIR = '#Mod')
env.Replace(FORTRANPATH = '.' ]
Export('env')
As far as I understand, paths are relative to the "virtual" location of the SConscript file (i.e. the src directory or the variant
build
directory), this should add the directory containing the source files to the scanner's search path.In my version of scons (2.3.0), I cannot use the
duplicate=0
argument, since it automatically inserts the original source directory into the module path, causing the command line to look like-module build/ -module src/
(ifort) and essentially overriding my preference not to clutter the source directory. This might be a bug, though.