首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果使用自定义决定器,SCons将生成不完整的依赖树。

如果使用自定义决定器,SCons将生成不完整的依赖树。
EN

Stack Overflow用户
提问于 2022-01-24 18:29:55
回答 1查看 68关注 0票数 0

我试图用SCons构建一个flex-bison解析器,使用自定义决策器。(您可以在this question中了解更多关于决定器的信息,不过,细节可能与当前问题不太相关。)

文件:

我的SConstruct

代码语言:javascript
复制
env = DefaultEnvironment()

deciderEnv = env.Clone()
def source_and_target_decider(dependency, target, prev_ni, repo_node=None):
    src_old_csig = prev_ni.csig if hasattr(prev_ni, 'csig') else None
    src_new_csig = dependency.get_csig()
    tgt_stored_info = target.get_stored_info()
    tgt_old_csig = tgt_stored_info.ninfo.csig if hasattr(tgt_stored_info.ninfo, 'csig') else None
    tgt_new_csig = target.get_csig()
    return src_new_csig != src_old_csig or tgt_new_csig != tgt_old_csig
deciderEnv.Decider(source_and_target_decider)

deciderEnv['YACCFLAGS'] = ['-d']
deciderEnv['YACCHXXFILESUFFIX'] = '.hh'
bison_source = deciderEnv.CXXFile('src/test.yy.cc', 'src/test.yy')[0]

deciderEnv['LEXFLAGS'] = [f'--header-file=${{SOURCE}}.hh']
flex_source = deciderEnv.CXXFile('src/test.ll.cc', 'src/test.ll')[0]

Program('test', [bison_source, flex_source])

src/test.yy

代码语言:javascript
复制
%language "c++"

%code {
    int yylex(int*);
}

%token X

%%

everything: X {}

src/test.ll

代码语言:javascript
复制
%{
    #include "./test.yy.hh"
%}

%option c++

%%

. { return yy::parser::token::X; }

结果:

我运行一个命令scons ./src/test.ll.o。第一次运行它时,它工作正常。

代码语言:javascript
复制
flex --header-file=src/test.ll.hh -t src/test.ll > src/test.ll.cc
bison -d -o src/test.yy.cc src/test.yy
g++ -o src/test.ll.o -c src/test.ll.cc

SCons似乎明白,在编译src/test.ll.o之前,它需要使用bison生成src/test.yy.hh,因为src/test.ll.cc #include的标题是这样的。

但是,如果我随后删除.sconsign.dblite (保留其余的文件完整),SCons似乎在下一次构建过程中失去了这种理解。运行scons ./src/test.ll.o会产生:

代码语言:javascript
复制
flex --header-file=src/test.ll.hh -t src/test.ll > src/test.ll.cc
g++ -o src/test.ll.o -c src/test.ll.cc

只有在第二次调用它之后,它才决定构建src/test.yy.hh

代码语言:javascript
复制
bison -d -o src/test.yy.cc src/test.yy
g++ -o src/test.ll.o -c src/test.ll.cc

依赖树:

通常,依赖树(scons --tree=all src/test.ll.o)如下所示:

代码语言:javascript
复制
+-src/test.ll.o
  +-src/test.ll.cc
  | +-src/test.ll
  | +-/bin/flex
  +-src/test.yy.hh
  | +-src/test.yy
  | +-/bin/bison
  +-/bin/g++

但是,在删除.sconsign.dblite之后,它是不完整的:

代码语言:javascript
复制
+-src/test.ll.o
  +-src/test.ll.cc
  | +-src/test.ll
  | +-/bin/flex
  +-/bin/g++

进一步意见:

定制决定的最后一行似乎是罪魁祸首。具体来说,部分是or tgt_new_csig != tgt_old_csig。如果删除此部分,问题将不再发生。

但是,我不知道为什么这段特定的代码破坏了构建。

知道怎么解决这个问题吗?

EN

回答 1

Stack Overflow用户

发布于 2022-01-24 21:40:15

SCons在这里存储有关以前构建的信息。

如果您删除它,那么SCons将没有该信息,并将重建一切。

因为在你的决策中你正在设置:

代码语言:javascript
复制
tgt_old_csig = tgt_stored_info.ninfo.csig if hasattr(tgt_stored_info.ninfo, 'csig') else None

然后将None与当前csig进行比较,后者不相等,需要重新构建。

当您显式地删除tgt_stored_info的源时,您可能需要进行如下更改才能正常工作( sconsign文件)。

代码语言:javascript
复制
def source_and_target_decider(dependency, target, prev_ni, repo_node=None):
    src_old_csig = prev_ni.csig if hasattr(prev_ni, 'csig') else None
    src_new_csig = dependency.get_csig()
    tgt_stored_info = target.get_stored_info()
    tgt_old_csig = tgt_stored_info.ninfo.csig if hasattr(tgt_stored_info.ninfo, 'csig') else None
    tgt_new_csig = target.get_csig()

    if tgt_old_csig:
        return src_new_csig != src_old_csig or tgt_new_csig != tgt_old_csig
    else:
        return src_new_csig != src_old_csig

你为什么要删除.sconsign.dblite?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70838718

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档