2015-10-09 3 views
1

Я использую scons в моем проекте. Проблема в том, что я должен дважды называть «scons», чтобы построить сборку в состоянии, когда scons не перекомпилирует ничего. Моя последовательность сборки выглядит следующим образом:Scons перекомпилирует мой код

  1. Позвоните в bison для создания файлов .cpp и .hh для включения в компиляцию C++.
  2. Позвоните компилятору C++ для компиляции C++ в двоичный файл.

Проблема заключается в том, что 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 option 1st. Время:

SCons --tree = подрезать

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;   } 
; 
%% 
+0

Попробуйте сделать вашу цель зависеть от сгенерированного файла 'program = Program (...); env.Depends (program, generated_sources); ' – melak47

+0

Попробуйте запустить: scons --tree = обрезать и вставить или вывести результат. SCons не нуждается в файле заголовка, чтобы знать, что он будет там. Для этого нужны эмиттеры. Это хорошо изношенный путь, поэтому, вероятно, это нечто незначительное, что делает его неработоспособным. – bdbaddog

+0

Выше я добавил вывод из бегущих счётчиков с параметром --tree = prune 1st. время и 2-й раз. Вы можете видеть, что scons находит зависимость от созданных bison файлов .hh только во второй раз, когда он был запущен. – HeMan

ответ

0

Для правильной обнаружения того, что ваш bison/yacc вызов также создает файл заголовка, SCons необходим флаг «-d» командной строки можно установить. Затем соответствующий эмиттер автоматически добавляет заголовочный файл в список целей, и он включается в качестве неявной зависимости для исходного файла 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.hh, stack.hh и position.hh, они не поддерживаются в последней версии Scons' yacc Tool.Мне кажется, что в более поздних версиях yacc/bison добавлены новые ключевые слова, такие как %locations, которые в настоящее время не обрабатываются, чтобы исправить правильный список целей. Если вы хотите, чтобы это было изменено, перейдите в наш список рассылки пользователей по адресу [email protected] (см. Также http://scons.org/lists.php), опишите вашу проблему и предоставите дополнительную информацию о синтаксисе требуемых ключевых слов. Затем мы можем попытаться помочь вам и всем другим пользователям, расширив инструмент yacc.

+0

Спасибо за ввод, но он все еще перекомпилирует файл C++. Если вы выдаете 'scons --debug = explain', он сообщает, что он перекомпилирует, потому что обнаружил новые зависимости от location.hh, stack.hh и position.hh – HeMan

+0

Я не вижу, чтобы эти файлы генерировались в SConstruct. Откуда они? Кроме того, они не включены в ваш основной файл «hello.cpp», поэтому почему SCOS добавить их как неявные зависимости? Ваше текущее состояние информации на самом деле не имеет смысла, а это значит, что оно неполное. Пожалуйста, предоставьте минимальный рабочий пример (MWE), который демонстрирует вашу фактическую проблему. – dirkbaechle

+0

Я добавил файл фиктивного бизона «parser.yy». Это вместе с hello.cpp, hello.h и файлом SConscript должен заполнить рабочий пример, демонстрирующий проблему. – HeMan

Смежные вопросы