在 SConscript 中使用 Glob 时出现 scons 错误
scons error using Glob in SConscript
我遇到了一个相当奇怪的错误,涉及在 SConscript 中使用 scons 函数 Glob
。我的实际构建脚本更复杂,但我已将其缩小到以下最小示例。
在基础 SConstruct 中:
SConscript('SConscript',
variant_dir='build')
然后,在 SConscript 中:
Glob('*.cc')
这将退出,并显示错误消息 TypeError : Tried to lookup Dir 'build' as a File.
这已经在 v2.1.0 和 v2.3.0 中进行了测试。
我找到了很多解决方法,但没有一个是完全令人满意的。
- 如果我将 SConscript 移动到子目录,scons 运行时不会出错。但是,这将需要将我的整个 src 树移动到一个子目录,这感觉很乱。
- 如果我在运行 scons 之前创建目录
build
,scons 运行时不会出现错误。但是,这需要一个额外的步骤,并且空目录不能很好地与 git. 一起使用
- 我可以在调用 SConscript 之前添加一行
Execute(Mkdir('build'))
。但是,这在使用 scons -n
. 执行空运行时不起作用
- 我可以用
duplicate=False
调用 SConscript,这样可以防止错误。但是,据我了解文档,这可能会导致构建错误,具体取决于包含文件的位置。
我正在摸索,并没有真正理解问题的根本原因。这个问题有一个干净的解决方案吗?
编辑:有人要求我添加我的意图的其他详细信息,而不仅仅是导致错误消息的代码。我正在尝试制作一个构建文件,用于同时交叉编译 linux 可执行文件和 Windows 可执行文件。
首先,在SConstruct中设置编译环境。
import os
win32 = Environment()
win64 = Environment()
linux = Environment()
#Define the working directory
win32['SYS'] = 'win32'
win64['SYS'] = 'win64'
linux['SYS'] = 'linux'
#Define the compilers
win32.Replace(CXX='i686-w64-mingw32-g++')
win64.Replace(CXX='x86_64-w64-mingw32-g++')
#Define the appropriate file formats
win32.Replace(SHLIBPREFIX='')
win32.Replace(SHLIBSUFFIX='.dll')
win32.Replace(PROGSUFFIX='.exe')
win32.Append(LINKFLAGS='-static')
win64.Replace(SHLIBPREFIX='')
win64.Replace(SHLIBSUFFIX='.dll')
win64.Replace(PROGSUFFIX='.exe')
win64.Append(LINKFLAGS='-static')
for env in [win32,win64,linux]:
build_dir = os.path.join('build',env['SYS'])
exe = SConscript('SConscript',
variant_dir=build_dir,
exports=['env'])
然后,在 SConscript 中有实际的构建规则。
Import('env')
env.Append(CPPPATH=['include'])
for main in Glob('*.cc'):
env.Program([main, Glob('src/*.cc')])
当使用 scons -n
.
调用时,这会显示上面显示的错误消息
您的问题是您正在使用 variant_dir 将您的构建文件夹 "link" 设置为“.”作为您的源目录。结合默认的 "duplicate=1" 选项,这意味着 SCons 会尝试将所有源复制到 "build"...但后者也是源文件夹的一部分。这为各种复杂情况和循环依赖打开了大门。
干净的解决方案是将所有源代码放入它们自己的子目录中,例如"src",这样您就可以将包含的 SConscript 引用为
SConscript('src/SConscript', variant_dir='build')
这将使正确的事情发生。这是首选设置,即使您不喜欢这个约定,您也应该采用它,以免您以后遇到麻烦。
附加提示:您可以(并且应该)使用
节省一些启动时间
win32 = Environment()
win64 = win32.Clone()
linux = win32.Clone()
而不是
win32 = Environment()
win64 = Environment()
linux = Environment()
。在后一种情况下,您强制 SCons 连续三次在您的系统中搜索 compilers/tools ...只需执行一次,然后将 clone() 到不同的环境并使用您的构建特定设置进一步装饰它们.
我遇到了一个相当奇怪的错误,涉及在 SConscript 中使用 scons 函数 Glob
。我的实际构建脚本更复杂,但我已将其缩小到以下最小示例。
在基础 SConstruct 中:
SConscript('SConscript',
variant_dir='build')
然后,在 SConscript 中:
Glob('*.cc')
这将退出,并显示错误消息 TypeError : Tried to lookup Dir 'build' as a File.
这已经在 v2.1.0 和 v2.3.0 中进行了测试。
我找到了很多解决方法,但没有一个是完全令人满意的。
- 如果我将 SConscript 移动到子目录,scons 运行时不会出错。但是,这将需要将我的整个 src 树移动到一个子目录,这感觉很乱。
- 如果我在运行 scons 之前创建目录
build
,scons 运行时不会出现错误。但是,这需要一个额外的步骤,并且空目录不能很好地与 git. 一起使用
- 我可以在调用 SConscript 之前添加一行
Execute(Mkdir('build'))
。但是,这在使用scons -n
. 执行空运行时不起作用
- 我可以用
duplicate=False
调用 SConscript,这样可以防止错误。但是,据我了解文档,这可能会导致构建错误,具体取决于包含文件的位置。
我正在摸索,并没有真正理解问题的根本原因。这个问题有一个干净的解决方案吗?
编辑:有人要求我添加我的意图的其他详细信息,而不仅仅是导致错误消息的代码。我正在尝试制作一个构建文件,用于同时交叉编译 linux 可执行文件和 Windows 可执行文件。
首先,在SConstruct中设置编译环境。
import os
win32 = Environment()
win64 = Environment()
linux = Environment()
#Define the working directory
win32['SYS'] = 'win32'
win64['SYS'] = 'win64'
linux['SYS'] = 'linux'
#Define the compilers
win32.Replace(CXX='i686-w64-mingw32-g++')
win64.Replace(CXX='x86_64-w64-mingw32-g++')
#Define the appropriate file formats
win32.Replace(SHLIBPREFIX='')
win32.Replace(SHLIBSUFFIX='.dll')
win32.Replace(PROGSUFFIX='.exe')
win32.Append(LINKFLAGS='-static')
win64.Replace(SHLIBPREFIX='')
win64.Replace(SHLIBSUFFIX='.dll')
win64.Replace(PROGSUFFIX='.exe')
win64.Append(LINKFLAGS='-static')
for env in [win32,win64,linux]:
build_dir = os.path.join('build',env['SYS'])
exe = SConscript('SConscript',
variant_dir=build_dir,
exports=['env'])
然后,在 SConscript 中有实际的构建规则。
Import('env')
env.Append(CPPPATH=['include'])
for main in Glob('*.cc'):
env.Program([main, Glob('src/*.cc')])
当使用 scons -n
.
您的问题是您正在使用 variant_dir 将您的构建文件夹 "link" 设置为“.”作为您的源目录。结合默认的 "duplicate=1" 选项,这意味着 SCons 会尝试将所有源复制到 "build"...但后者也是源文件夹的一部分。这为各种复杂情况和循环依赖打开了大门。
干净的解决方案是将所有源代码放入它们自己的子目录中,例如"src",这样您就可以将包含的 SConscript 引用为
SConscript('src/SConscript', variant_dir='build')
这将使正确的事情发生。这是首选设置,即使您不喜欢这个约定,您也应该采用它,以免您以后遇到麻烦。
附加提示:您可以(并且应该)使用
节省一些启动时间win32 = Environment()
win64 = win32.Clone()
linux = win32.Clone()
而不是
win32 = Environment()
win64 = Environment()
linux = Environment()
。在后一种情况下,您强制 SCons 连续三次在您的系统中搜索 compilers/tools ...只需执行一次,然后将 clone() 到不同的环境并使用您的构建特定设置进一步装饰它们.