2015-07-03 4 views
0

У меня есть инструмент, который генерирует файлы, содержащие определения и декларации. Эти файлы должны быть включены из других исходных файлов или заголовков - они не могут использоваться отдельно.Как сгенерировать включенные файлы с помощью 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, поскольку он считается запущенным на каждой сборке перед нормальной проверкой зависимостей. Но я хочу, чтобы этот шаг предварительной сборки иметь проверку зависимостей, так что она пропускается, если его входы старше своих выходов.)

ответ

1

Моих окончательное решение заключалось в том, чтобы сделать выход .h-файла входным для исполняемого файла.

Этот путь правильный.

Он фактически утверждает, что здание исполняемого зависит от данного файла, и, если этот файл OUTPUT для некоторого add_custom_command(), эта команда будет выполнена до здания исполняемого файла.


Другим способ заключается в создании необходимых заголовков на configuration этапе с помощью execute_process().В этом случае нет необходимости добавлять файлы заголовков в качестве источников для add_executable(): CMake имеет понятие автоопределяющих зависимостей для компиляции, поэтому test_didl будет восстановлен после регенерации test_didl_structs.h.

execute_process(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) 
# ... 
add_executable(test_didl test_didl.c) 

Недостаток этого подхода заключается в том, что после изменения ваших .py-файлов необходимо выполнить повторную настройку конфигурации вручную. Смотрите также, что question и ответьте на него. Другая проблема заключается в том, что заголовочный файл будет обновляться при каждом запуске конфигурации.

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