Scons重新编译我的代码

时间:2015-10-09 23:06:18

标签: c++ bison scons

我在我的项目中使用scons。问题是我必须两次调用scons才能将构建转换为scons不会重新编译任何东西的状态。我的构建顺序如下:

  1. 调用bison生成要包含在C ++编译中的.cpp和.hh文件。
  2. 调用C ++编译器将C ++编译为二进制文件。
  3. 问题是scons在运行bison之前计算依赖关系,此时自动生成的.hh文件不存在。下次我运行scons时,它会检测到.hh文件的新依赖性并重新编译。在野牛运行并生成头文件后,如何告诉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。这四个文件,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;           }   
    ;
    %%
    

1 个答案:

答案 0 :(得分:0)

为了正确检测到您的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

您可以在UserGuide(http://scons.org/doc/production/HTML/scons-user.html)中找到有关上面使用的环境变量的更多信息,特别是在附录A“构造变量”中。

关于其他文件location.hhstack.hhposition.hh,最新版本的SCons yacc工具不支持这些文件。它看起来好像更新版本的yacc/bison添加了新的关键字,如%locations,这些关键字当前未被解析以发出正确的目标列表。如果您希望更改此内容,请访问我们的用户邮件列表scons-users@scons.org(另请参阅http://scons.org/lists.php),描述您的问题并提供有关所需关键字语法的更多信息。然后,我们可以通过扩展yacc工具来帮助您和所有其他用户。