Используйте cmake для условной генерации исходных входных файлов - PullRequest
2 голосов
/ 11 июля 2011

Я использую cmake с проектом C ++.Я хочу использовать предварительно скомпилированные заголовки в GCC.

Я хочу запустить cmake один раз, а затем, при запуске make, я хочу, чтобы это произошло:

  1. Запустить мойпользовательский инструмент (скрипт Python) на всем дереве исходного кода.Он генерирует precompiled.h заголовки в некоторых подкаталогах.Его цель - сканировать * .h и * .cpp на наличие # include и перемещать их в общие файлы precompiled.h.
  2. генерировать предварительно скомпилированные заголовки GCC (g++ -c precompiled.h -o precompiled.h.gch) ТОЛЬКО при изменении файла precompiled.h после шага1.
  3. создание устаревших целей (после шага 2. потому что я хочу использовать файл .gch)

Мне удавалось добавлять зависимости, поэтому всякий раз, когда я строю какую-либо цель, мойВыполнение цели скрипта Python (это ужасно, потому что теперь каждая цель должна зависеть от одной цели global_init).Также я могу изменить свой скрипт на python, чтобы он не изменял precompiled.h, когда в этом нет необходимости.

Но я не знаю, что делать дальше.Есть ли способ сказать cmake, что он должен запустить мой собственный скрипт, и ПОСЛЕ ТОГО, ЧТОБЫ определить, должен ли быть создан precompiled.h.gch?Теперь это всегда сборка (этот файл содержит много # include, так что это занимает некоторое время).В основном:

  1. Выполнение скрипта Python -> precompiled.h МОЖЕТ БЫТЬ обновлено
  2. Изучить временную метку precompiled.h и, если она новее -> build precompiled.h.gch
  3. Стандартные шаги компиляции

Я смотрел во многих местах, но способ вычисления зависимостей в cmake (и make) кажется слишком слабым для выполнения этой задачи.

В этом вопросе: lazy c ++ компиляция всегда происходит после выполнения lazycpp.Это не будет оптимальным в моем случае.

1 Ответ

7 голосов
/ 12 июля 2011

Следующие команды CMake могут служить отправной точкой для вашего проекта:

add_custom_target(scanner COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/scanner.py"
    COMMENT "Scanning include files ..."
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")

Эта команда охватывает шаг 1. Она вызывает ваш скрипт на python, который может обновить существующие файлы precompiled.h в CMAKE_CURRENT_SOURCE_DIR.

add_custom_command(OUTPUT precompiled.h.gch
    COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS} 
    -c "${CMAKE_CURRENT_SOURCE_DIR}/precompiled.h" -o precompiled.h.gch
    DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/precompiled.h"
    IMPLICIT_DEPENDS CXX "${CMAKE_CURRENT_SOURCE_DIR}/precompiled.h")

add_custom_target(generate_precompiled DEPENDS
    "${CMAKE_CURRENT_BINARY_DIR}/precompiled.h.gch")

add_dependencies(generate_precompiled scanner)

Эти команды охватывают шаг 2. Предварительно скомпилированный заголовок создается с помощью пользовательской команды, которая неявно зависит от precompiled.h и от других заголовков, включенных в precompiled.h.precompiled.h.gch генерируется в каталоге CMAKE_CURRENT_BINARY_DIR.Поскольку генерация предварительно скомпилированного заголовка требует обновления precompiled.h скриптом python, мы добавляем зависимость целевого уровня от цели scanner.

include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})

add_executable(main main.cpp)

set_target_properties(main PROPERTIES COMPILE_FLAGS "-include precompiled.h -H")

add_dependencies(main generate_precompiled)

Эти команды добавляют стандартные шаги компиляции, которые генерируют исполняемый файл main.Предварительно скомпилированный заголовок включен в качестве заголовка по умолчанию с ключом gcc -include.CMAKE_CURRENT_BINARY_DIR, содержащий precompiled.h.gch, добавляется в качестве включаемого каталога.gcc будет извлекать precompiled.h.gch оттуда, когда включен precompiled.h (см. Использование предварительно скомпилированных заголовков ).

Наконец, целевая зависимость от generate_precompiled гарантирует, что предварительно скомпилированный заголовок обновляется, еслинеобходимо.

...