Я использую scons в моем проекте. Проблема в том, что я должен дважды называть «scons», чтобы построить сборку в состоянии, когда scons не перекомпилирует ничего. Моя последовательность сборки выглядит следующим образом:Scons перекомпилирует мой код
- Позвоните в bison для создания файлов .cpp и .hh для включения в компиляцию C++.
- Позвоните компилятору 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; }
;
%%
Попробуйте сделать вашу цель зависеть от сгенерированного файла 'program = Program (...); env.Depends (program, generated_sources); ' – melak47
Попробуйте запустить: scons --tree = обрезать и вставить или вывести результат. SCons не нуждается в файле заголовка, чтобы знать, что он будет там. Для этого нужны эмиттеры. Это хорошо изношенный путь, поэтому, вероятно, это нечто незначительное, что делает его неработоспособным. – bdbaddog
Выше я добавил вывод из бегущих счётчиков с параметром --tree = prune 1st. время и 2-й раз. Вы можете видеть, что scons находит зависимость от созданных bison файлов .hh только во второй раз, когда он был запущен. – HeMan