我希望使用 SCons 作为我构建主要基于 Qt 的应用程序的首选方法。我只是在学习 SCons,我正在努力寻找有关该主题的文档或教程。任何人都可以指出我正确的方向吗?
这是一个开始,但还有更好的吗?
(我主要在 Windows 上工作)
亲切的问候,
我写了一个python函数,比如替换字符串,并在scons脚本中调用.
def Replace(env, filename, old, new):
with open(filename,"r+") as f:
d = f.read()
d = d.replace(old, new)
f.truncate(0)
f.seek(0)
f.write(d)
f.close()
env.AddMethod(Replace,'Replace')
Run Code Online (Sandbox Code Playgroud)
在SConscript中
lib = env.SharedLibrary('lib', object, extra_libs)
tmp = env.Command([],[],[env.Replace(somefile, 'A', 'b')] )
env.Depends(tmp,lib )
Run Code Online (Sandbox Code Playgroud)
我期望在lib构建之后运行Replace()方法.但是scons总是在第一轮脚本解析短语中运行Replace().似乎我错过了一些依赖.
我的项目使用SCons来管理构建过程.我想支持多个编译器,所以我决定使用,AddOption这样用户就可以在命令行中指定使用哪个编译器(默认情况下是当前编译器所用的编译器).
AddOption('--compiler', dest = 'compiler', type = 'string', action = 'store', default = DefaultEnvironment()['CXX'], help = 'Name of the compiler to use.')
Run Code Online (Sandbox Code Playgroud)
我希望能够为各种编译器提供内置的编译器设置(包括特定编译器的最大警告级别等).这是我目前首次尝试解决方案的方式:
if is_compiler('g++'):
from build_scripts.gcc.std import cxx_std
from build_scripts.gcc.warnings import warnings, warnings_debug, warnings_optimized
from build_scripts.gcc.optimizations import optimizations, preprocessor_optimizations, linker_optimizations
elif is_compiler('clang++'):
from build_scripts.clang.std import cxx_std
from build_scripts.clang.warnings import warnings, warnings_debug, warnings_optimized
from build_scripts.clang.optimizations import optimizations, preprocessor_optimizations, linker_optimizations
Run Code Online (Sandbox Code Playgroud)
但是,我不确定该is_compiler()功能是什么样的.我的第一个想法是直接比较编译器名称(例如'clang ++')与用户传入的内容.但是,当我尝试使用时,这立即失败了scons --compiler=~/data/llvm-3.1-obj/Release+Asserts/bin/clang++.
所以我觉得我会变得更聪明并且使用这个功能
cxx = GetOption('compiler')
def is_compiler (compiler):
return cxx[-len(compiler):] == compiler
Run Code Online (Sandbox Code Playgroud)
这只会查看编译器字符串的结尾,以便忽略目录.不幸的是,'clang …
我在基于scons重构构建系统时遇到了一些问题.我们有一个C/C++源代码树,它包含几个不同的输出对象(dll,可执行文件,测试可执行文件),以及我们的源文件的某种异构布局(尽管它大多数位于带有src/和inc/目录的'module' 目录中).
当前设置的一个最大问题是我们真的希望所有这些构建产品默认使用一致的编译器选项构建.我们当前的布局有一个主SConstruct文件,在子目录中调用许多子SConscript文件,然后构建更大的构建产品(.a例如).默认情况下,SConscript()scons中的函数不会将当前构造环境对象传递或继承到被调用的SConstruct文件.这意味着目前所有这些子SConstript文件都使用自己不同的构造环境.
我正在尝试组合的新布局有一个主构建环境,它在源树根处放在一起,包含我们需要的所有必需的CFLAGS和构建定义.我想这样的施工环境要传递到子SConscript文件,使我知道,每一个.c和.cpp我们构建树文件正在建有相同的命令行.
不过,我不确定如何在scons中这样做.有Import()和Export()函数,但那些基本上是丑陋的全局变量 - 调用SConstruct文件没有很多控制子SConstruct文件使用全局变量做什么Export().是否有任何干净的方法基本上将子SConscript文件作为参数处理当前构造环境,而不必让它必须修改它?有点像:
master_env = Environment()
master_env.Append( CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ] )
### add other stuff that we want everything to use
SConscript( 'somelibrary/SConstruct', inherited_environment=master_env.Clone() )
### master_env has now been used to build a
### .dll in somelibrary/, but any variations
### made to somelibrary/SConstruct's inherited
### env haven't contaminated master_env
Run Code Online (Sandbox Code Playgroud)
我知道我可以做一些笨拙的事情,有点像这样:
clobber_env = Environment() …Run Code Online (Sandbox Code Playgroud) 我负责构建多个RPM.我为每个RPM包提供了pristine SPEC文件,我有BASH脚本,它们设置了必要的环境并构建了RPM.
我想使用实际的构建工具(如make)来构建这些RPM.通过这样做,我希望消除对自定义,混淆BASH脚本的需求,转而使用清晰,可维护的配置文件(类似于make的Makefile).但是,使用POSIX制作和保持make文件集是最新的可能与维护我目前用于构建RPM包的BASH脚本一样多.像cmake和automake这样的程序包含make命令的功能是有原因的 - 这些工具更具表现力,允许更小,更清晰的配置文件.
但是,使用autoconf/automake似乎也是一个糟糕的选择,因为它们似乎专门为C和C++开发而构建.有人建议我使用scons,但是这似乎是最好的选择(由于它的配置文件是实际的python脚本),它也适用于特定的语言.
使用我的SPEC文件作为"源代码"和环境作为"依赖项"(例如设置制作RPM所需的rpmbuild目录树结构),是否有一个很好的构建工具可以用来替换我的BASH脚本以获得更清洁,更多可维护的RPM构建解决方案?
编辑:当我说"构建工具"时,我似乎不清楚我需要什么.我已经使用rpmbuild作为'编译器',我使用SPEC文件(以及二进制文件的相关源代码)'编译'RPMs作为'源代码'.我要求一个可以协调这个过程的工具.
超级简单,完全无聊的设置:我有一个充满 .hpp 和 .cpp 文件的目录。其中一些 .cpp 文件需要构建到可执行文件中;自然,这些 .cpp 文件 #include 某些 .hpp 文件在同一目录中,然后可能包含其他文件,等等。这些 .hpp 文件中的大多数都有相应的 .cpp 文件,也就是说:如果 some_application.cpp #includes foo.hpp,无论是直接的还是传递性的,那么很可能还有一个 foo.cpp 文件需要编译并链接到 some_application 可执行文件中。
超级简单,但我仍然不知道构建它的“最佳”方式是什么,无论是在 SCons 还是 CMake(我都没有任何专业知识,除了在最后一天左右盯着文档和变得悲伤)。我担心我想要的那种解决方案实际上不可能(或至少非常复杂)在大多数构建系统中实现,但如果是这样,很高兴知道这一点,这样我就可以放弃并且不那么挑剔了. 当然,我希望我是错的,考虑到我对构建系统(一般来说,尤其是 CMake 和 SCons)一无所知,这并不奇怪。
当然,CMake 和 SCons 都可以自动检测到 some_application.cpp 需要重新编译,只要它依赖的任何头文件(直接或传递)发生变化,因为它们可以很好地“解析”C++ 文件以挑选出那些依赖关系。好的,太好了:我们不必手动列出每个 .cpp-#includes-.hpp 依赖项。但是:我们仍然需要决定在实际生成每个可执行文件时需要将哪些目标文件子集发送到链接器。
据我了解,处理这部分问题的两个最直接的替代方法是:
CMake 或 SCons 能否以任何远程直接的方式做得比这更好?我看到了一堆有限的方法来处理自动生成的依赖关系图,但没有通用的交互方式(“好吧,构建系统,你认为依赖关系是什么?啊。好吧,基于此,添加遵循依赖项并再次思考:...”)。我也不是对此感到惊讶。不过,我还没有在任一构建系统中找到一种特殊用途的机制来处理超级常见的情况,在这种情况下,链接时依赖项应该反映相应的编译时 #include 依赖项。我在阅读文档时(诚然有些草率)错过了什么,还是每个人都选择了选项 (B) 并悄悄地讨厌自己和/或他们的构建系统?
我正在尝试在Scons中定义一个预处理器宏来构建一个更大的C/C++项目.
我正在使用的其中一个库需要ALIGN定义.更具体地说,如果我添加
#define ALIGN(x) __attribute((aligned(x)))
Run Code Online (Sandbox Code Playgroud)
对于所述库的头文件,它编译得很好.但是,我应该能够在构建时指定它,因为这是库打算使用的方式.我知道在CMake中,我可以用类似的东西来定义宏
SET(ALIGN_DECL "__attribute__((aligned(x)))")
Run Code Online (Sandbox Code Playgroud)
像这样在Scons中定义常量
myEnv.Append(CPPDEFINES = ['IAMADEFINEDCONSTANT'])
Run Code Online (Sandbox Code Playgroud)
工作正常,但以这种方式定义宏不起作用.是什么赋予了?
编辑:修正错字
下午好。
我在 Scons 中有一个构建脚本:
EnsureSConsVersion(0,14);
import string
import os
import os.path
import glob
import sys
import methods
methods.update_version()
# scan possible build platforms
platform_list = [] # list of platforms
platform_opts = {} # options for each platform
platform_flags = {} # flags for each platform
active_platforms=[]
active_platform_ids=[]
platform_exporters=[]
global_defaults=[]
for x in glob.glob("platform/*"):
if (not os.path.isdir(x)):
continue
tmppath="./"+x
sys.path.append(tmppath)
import detect
if (os.path.exists(x+"/export/export.cpp")):
platform_exporters.append(x[9:])
if (os.path.exists(x+"/globals/global_defaults.cpp")):
global_defaults.append(x[9:])
if (detect.is_active()):
active_platforms.append( detect.get_name() )
active_platform_ids.append(x);
if (detect.can_build()):
x=x.replace("platform/","") # rest of …Run Code Online (Sandbox Code Playgroud) 我在按照官方文档中的指示构建 gem5 时遇到了很多问题。
这些是我使用过的命令:
git clone https://gem5.googlesource.com/public/gem5
cd gem5
python2 `which scons` build/MIPS/gem5.opt
Run Code Online (Sandbox Code Playgroud)
这导致此输出:
scons: Reading SConscript files ...
Warning: Your compiler doesn't support incremental linking and lto at the same time, so lto is being disabled. To force lto on anyway, use the --force-lto option. That will disable partial linking.
Checking for C header file Python.h... (cached) yes
Checking for C library python2.7... (cached) yes
Checking for C library pthread... (cached) yes
Checking for C library dl... (cached) yes …Run Code Online (Sandbox Code Playgroud)