У меня есть инструмент, который генерирует файлы, содержащие определения и декларации. Эти файлы должны быть включены из других исходных файлов или заголовков - они не могут использоваться отдельно.Как сгенерировать включенные файлы с помощью cmake?
Очевидное, что нужно сделать, это создать собственную команду для их создания. Мой CMakeLists.txt, который делает это, выглядит следующим образом. В настоящее время я использую это с генератором make-файлов GNU.
project(test_didl)
cmake_minimum_required(VERSION 3.0)
add_custom_command(
OUTPUT test_didl_structs.h test_didl_structs.c
COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/didl.py --decls=test_didl_structs.h --defs=test_didl_structs.c ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/didl.py ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py
MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_didl_structs.py)
add_executable(test_didl test_didl.c)
target_include_directories(test_didl PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(test_didl shared_lib)
test_didl.c очень просто:.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "test_didl_structs.h"
#include "test_didl_structs.c"
int main(void) {
}
Но на первой сборки, делают попытки построить test_didl.c, который, конечно, не удалось, потому что test_didl_structs * еще не генерируется , Естественно, перед первой успешной сборкой test_didl.c информация о зависимостях неизвестна, поэтому make не знает, для запуска команды python.
Я пробовал пользовательскую цель, но это нехорошо, потому что пользовательские цели считаются всегда грязными. Это означает, что файл C перекомпилируется в каждой сборке, а EXE связан. Такой подход не будет масштабироваться.
Мое окончательное решение было сделать вывод .h файл вход в исполняемый файл:
add_executable(test_didl test_didl.c test_didl_structs.h)
.h входы файлов рассматриваются как зависимости, но в противном случае не делать ничего интересного для Makefile генераторов. (В настоящее время я не заинтересован в других генераторах.)
Так что это работает, но это кажется немного уродливым. На самом деле это не означает, что пользовательские команды должны запускаться первыми, хотя на практике это, похоже, происходит. Я не совсем уверен, как, хотя (но я пока не готов к чтению CMake-генерируемых Makefile).
Это как это должно работать? Или есть что-то опрятное, которое я должен делать вместо этого?
(То, что я представляю себе, я полагаю, является чем-то вроде этапа предварительной сборки Visual Studio, поскольку он считается запущенным на каждой сборке перед нормальной проверкой зависимостей. Но я хочу, чтобы этот шаг предварительной сборки иметь проверку зависимостей, так что она пропускается, если его входы старше своих выходов.)