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

Cmake: борется с зависимостями add_custom_command

Я пытаюсь получить файл, созданный командой add_custom_command в одном каталоге, в зависимости от add_custom_command в другом каталоге.

В первом каталоге (lib/core) у меня есть команда сборки, которая выглядит так:

add_custom_command(
    OUTPUT libcore.bc
    COMMAND tartln -filetype=bc -link-as-library -o libcore.bc ${STDLIB_BC_FILES}
    DEPENDS ${STDLIB_BC_FILES} tartln
    COMMENT "Linking libcore.bc")

Во втором каталоге у меня есть команда, которая использует вывод этой команды:

add_custom_command(OUTPUT ${OBJ_FILE}
    COMMAND tartln -disable-fp-elim -filetype=obj -o ${OBJ_FILE} ${BC_FILE}
        "${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
    MAIN_DEPENDENCY "${BC_FILE}" 
    DEPENDS "${PROJECT_BINARY_DIR}/lib/core/libcore.bc"
    COMMENT "Linking Tart bitcode file ${BC_FILE}")

Однако, когда я пытаюсь построить, я получаю следующую ошибку:

make[3]: *** No rule to make target `lib/core/libcore.bc', needed by `test/stdlib/ReflectionTest.o'.  Stop.

Одна странная вещь, которую я вижу, заключается в том, что путь в сообщении об ошибке является относительным, а не абсолютным путем, несмотря на то, что я знаю, что ${PROJECT_BINARY_DIR} - полный, правильный путь. Я не знаю, является ли это проблемой или просто странностью make.

Я также попытался создать целевой уровень верхнего уровня для библиотеки libcore в каталоге lib/core:

add_custom_target(libcore DEPENDS libcore.bc libcore.deps)

И затем используя это в предложении DEPENDS. Странная вещь в том, что это работает в первый раз, когда вы делаете чистую сборку, но выдает ошибку при любой последующей сборке. В любом случае, я понимаю, что DEPENDS должен работать только для зависимостей файлов, поэтому это не похоже на правильное решение. (Как у вас есть пользовательская команда, которая зависит от целевого уровня верхнего уровня?)

Я также старался помещать абсолютные пути везде, без эффекта.

4b9b3361

Ответ 1

Документация cmake говорит о параметре DEPENDS:

Параметр DEPENDS указывает файлы, от которых зависит команда. Если        любая зависимость - это OUTPUT другой пользовательской команды в том же        каталог (файл CMakeLists.txt). CMake автоматически передает другой        пользовательская команда в цель, в которой эта команда построена. Если        DEPENDS указывает любую цель (созданную командой ADD_ *) a        зависимость уровня цели создана, чтобы убедиться, что цель построена        перед любой целью, используя эту пользовательскую команду.

Поэтому я думаю, что вам нужно будет определить цель с помощью add_custom_target и зависеть от этого.

В документации для add_custom_target говорится:

Зависимости, перечисленные с аргументом DEPENDS может ссылаться на файлы и выходы пользовательских команд, созданных с помощью add_custom_command() в том же каталоге (файл CMakeLists.txt).

Итак, вам нужно будет использовать add_custom_command и add_custom_target следующим образом:

  • В первом каталоге, создающем файл bc, вы делаете

    add_custom_command(OUTPUT libcore.bc ... ) # just as in your question  add_custom_target (LibCoreBC DEPENDS libcore.bc)

  • Во втором каталоге вы

    add_custom_command (OUT ${OBJ_FILE} DEPENDS LibCoreBC ....)

Ответ 2

Это не ответ, но пояснение к одному из ваших ответов выше.

В соответствии с документами cmake пользовательская цель, созданная add_custom_target, всегда считается устаревшей и всегда построена.

IMO, документы cmake должны сказать вместо этого:

Пользовательская цель, созданная add_custom_target, всегда считается устаревшей и всегда построена, , но только при запросе.

Это означает, что если все ваши цели отмечены как EXCLUDE_FROM_ALL, и у вас есть команды add_custom_target, которые создают новые цели, и вы вводите make из командной строки без заданных целей, цели, добавленные с помощью add_custom_target не. Но если вы явно укажете их в командной строке make, то они будут построены. Кроме того, существует ключевое слово ALL, которое вы можете указать add_custom_target, чтобы заставить их быть встроенными как часть всего правила, которое, как я считаю, означает, когда make выполняется без аргументов.

Ответ 3

Я не думаю, что add_custom_target будет работать для того, чего я хочу. Согласно документам cmake, пользовательская цель, созданная add_custom_target, всегда считается устаревшей и всегда строится.

Проблема в том, что я пытаюсь вывести результат из одного add_custom_command и подавать его на вход другого add_custom_command в другой каталог. Я хочу, чтобы это произошло только в том случае, если исходный исходный файл устарел - если я использовал add_custom_target, то вывод всегда будет перестроен, даже если исходный файл не изменился. Учитывая, что есть сотни этих исходных файлов, это сделает сборку очень медленной.

Вот то, что я пытаюсь сделать: у меня есть программа, которая генерирует .bc файл (бит-код LLVM) с заданным исходным файлом. Есть много этих исходных файлов, которые создают много .bc файлов.

Вторая программа преобразует все файлы .bc в один файл .obj(объект ELF). Таким образом, шаги преобразования выглядят следующим образом:

   source file -> .bc     (via add_custom_command)
   .bc         -> .obj    (via add_custom_command)
   .obj        -> .exe    (via add_executable)

Исходные файлы исходного кода находятся в разных каталогах, потому что они являются библиотеками классов - я не хочу, чтобы каждый код для каждого класса был помещен в тот же каталог.