我在我的项目中使用 scons。问题是我必须两次调用 scons 才能使构建达到 scons 不重新编译任何东西的状态。我的构建顺序如下:
- 调用 bison 生成 .cpp 和 .hh 文件以包含在 C++ 编译中。
- 调用C++编译器将C++编译成二进制。
问题是 scons 在运行 bison 之前计算依赖关系,此时自动生成的 .hh 文件不存在。下次我运行 scons 时,它会检测到对 .hh 文件的新依赖并重新编译。 bison 运行并生成头文件后,如何告诉 scons 做依赖链?
这是一个演示问题的 SConscript 示例。
Program(target = 'hello', source = 'hello.cpp')
CXXFile (source='parser.yy', target=['parser.cc'])
Depends('hello.cpp', 'parser.cc')
这是使用 --tree=prune 选项 1st 运行 scons 的输出。时间:
scons --tree=prune
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
bison -o parser.cc parser.yy
g++ -o hello.o -c hello.cpp
g++ -o hello hello.o
+-.
+-SConstruct
+-hello
| +-hello.o
| | +-hello.cpp
| | | +-parser.cc
| | | +-parser.yy
| | | +-/usr/local/bin/bison
| | +-hello.h
| | +-/bin/g++
| +-/bin/g++
+-[hello.cpp]
+-hello.h
+-[hello.o]
+-[parser.cc]
+-parser.yy
scons: done building targets.
这是第二次运行的输出。你可以看到 scons 只有在第二次运行时才发现对 bison 生成的 .hh 文件的依赖,这就是它重新编译的原因。
# scons --tree=prune
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
g++ -o hello.o -c hello.cpp
+-.
+-SConstruct
+-hello
| +-hello.o
| | +-hello.cpp
| | | +-parser.cc
| | | +-parser.yy
| | | +-/usr/local/bin/bison
| | +-hello.h
| | +-parser.hh
| | +-location.hh
| | +-stack.hh
| | +-position.hh
| | +-/bin/g++
| +-/bin/g++
+-[hello.cpp]
+-hello.h
+-[hello.o]
+-location.hh
+-[parser.cc]
+-parser.hh
+-parser.yy
+-position.hh
+-stack.hh
scons: done building targets.
hello.cpp 看起来像这样:
#include "hello.h"
#include "parser.hh"
int main() {
return 0;
}
和 hello.h:
#define foo 1
这是 parser.yy 。这 4 个文件,hello.cpp、hello.h、parser.yy 和 SConscript 应该构成一个完整的工作示例来演示该问题。
{
%}
%start input
%defines
%skeleton "lalr1.cc"
%locations
%initial-action
{
@$.begin.filename = @$.end.filename = &driver.streamname;
};
%define api.value.type {double}
%token NUM
%left '-' '+'
%left '*' '/'
%precedence NEG
%right '^'
%%
input:
%empty
| input line
;
line:
'\n'
| exp '\n' { printf ("\t%.10g\n", $1); }
;
exp:
NUM { $$ = $1; }
;
%%
最佳答案
为了正确检测到您的 bison/yacc
调用也在创建头文件,SCons 需要设置“-d
”命令行标志。然后相应的 Emitter 自动将头文件添加到目标列表中,并将其作为源文件 hello.cpp
的隐式依赖项包含在内,而无需通过 Depends() 指定显式依赖项
。
以下 SConstruct
在我这边似乎工作正常:
env = Environment(YACCHXXFILESUFFIX='.hh',
YACCFLAGS=['-d'])
env.CXXFile('parser.cc', 'parser.yy')
env.Program('hello', 'hello.cpp')
请注意我是如何实例化命名构建环境 env
的,这样我就可以更轻松地操作其设置。文件后缀的设置是必须的,因为不管什么原因,SCons中默认的是*.hpp
。
您可以在用户指南 ( http://scons.org/doc/production/HTML/scons-user.html ) 中找到有关上面使用的环境变量的更多信息,尤其是在附录 A“构造变量”中。
关于附加文件location.hh
、stack.hh
和position.hh
,最新版本的SCons不支持它们' yacc
工具。在我看来,较新版本的 yacc/bison
添加了新的关键字,如 %locations
,目前尚未解析这些关键字以发出正确的目标列表。如果您希望对此进行更改,请访问我们的用户邮件列表 scons-users@scons.org
(另请参阅 http://scons.org/lists.php),描述您的问题并提供有关语法的更多信息所需的关键字。然后我们可以尝试通过扩展 yacc
工具来帮助您和所有其他用户。
关于c++ - Scons 重新编译我的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33048378/