Подтвердить что ты не робот

Как работать "scons: warning: для целевой цели были определены две разные среды"

Предположим, что у меня есть файл SConstruct, который выглядит следующим образом:

env = Environment()

env.Program("a", ["a.c", "util.c"])
env.Program("b", ["b.c", "util.c"])

Эта сборка работает корректно без предупреждений об ошибках SCons. Однако, если я изменяю это, чтобы указать разные библиотеки для каждой сборки Program (фактические библиотеки не актуальны):

env.Program("a", ["a.c", "util.c"], LIBS="m")
env.Program("b", ["b.c", "util.c"], LIBS="c")

то я получаю предупреждение:

scons: warning: Two different environments were specified for target util.o,
        but they appear to have the same action: $CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES

Это, по-видимому, вызвано создателем Program, автоматически создающим новую среду для создания источников, хотя это только переменная LIBS, которая отличается (и поэтому только шаг ссылки должен иметь другую среду). Я могу обойти это, сделав что-то вроде:

util = env.Object("util.c")
env.Program("a", ["a.c"] + util, LIBS="m")
env.Program("b", ["b.c"] + util, LIBS="c")

Для построения util.c используется один конструктор Object, а затем с использованием предварительно скомпилированного объектного файла в каждой сборки Program, тем самым избегая предупреждения. Однако это не обязательно. Есть ли более элегантный способ обойти эту проблему? Или это на самом деле ошибка в SCons, которая должна быть исправлена?

Контекст: у меня есть почти 2000 исходных файлов C, скомпилированных в 20 библиотек и 120 исполняемых файлов с большим количеством общих источников. Я создал файл SConstruct из предыдущей проприетарной системы сборки, используя преобразование script, которое я написал. Существует около 450 предупреждающих сообщений "Две разные среды", созданных SCons для полной сборки с использованием текущего SConstruct.

4b9b3361

Ответ 1

Я нашел обходное решение, которое не связано с созданием дополнительных переменных для хранения узлов объектного файла:

env.Program("a", ["a.c", env.Object("util.c")], LIBS="m")
env.Program("b", ["b.c", env.Object("util.c")], LIBS="c")

Это изолирует сборку util.c в пределах одной среды. Хотя он указан дважды, один раз для каждого Program, SCons не предупреждает об этом, потому что тот же источник построен с тем же env объектом. Конечно, SCons только компилирует источник один раз в этом случае.

Ответ 2

Вы можете использовать функцию Split и специальный помощник, чтобы упростить процесс сборки для больших проектов:

def create_objs(SRCS, path=""):
    return [env.Object(path+src+".cpp") for src in SRCS]

prg1 = Split("file_1 file_2 file_N")
prg2 = Split("file_2 file_5 file_8")

env.Program("a", create_objs(prg1), LIBS="x")
env.Program("b", create_objs(prg2), LIBS="y")

Объектные файлы создаются только один раз, и их можно использовать в нескольких сборках. Надеюсь, это поможет...

Ответ 3

Одна из проблем, которые я обнаружил в своем коде, заключалась в том, что я неправильно использовал путь к целевому объекту. Или в других словах у меня была директива dir варианта, но вместо использования BUILDPATH я закончил использование моего исходного кода исходного кода. Таким образом, Scons находил объект, сгенерированный в целевом BUILDPATH и исходном пути.