Запустите команду оболочки (ctags) в cmake и сделайте

Я кодирую проект С++ в vim.

Я хотел бы запустить команду ctags (ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .), чтобы генерировать ссылки при запуске make.

Я думаю, что способ сделать это - использовать add_custom_command, но я запутался в том, как его интегрировать в CMakeLists.txt.

Ответ 1

Самый простой способ сделать это:

set_source_files_properties( tags PROPERTIES GENERATED true)
add_custom_command ( OUTPUT tags
    COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q . 
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} )
add_executable ( MyProjectOutput tags )

Первая строка сообщает CMake, что tags будет сгенерирован. add_custom_command CMake при необходимости генерирует tags, и, наконец, какая-то цель должна зависеть от tags. Рабочий каталог по умолчанию находится в дереве сборки, поэтому WORKING_DIRECTORY должен быть установлен в исходное дерево. Это эквивалентно записи Makefile:

tags:
    ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .

MyProjectOutput: tags
    # Whatever here...

Ответ 2

Ответы Daniel и Creak заставили меня начать, но я закончил с более сложным решением, которое, как я думал, я бы разделил:

# Add a top-level "tags" target which includes all files in both
# the build and source versions of src/*.
set_source_files_properties(tags PROPERTIES GENERATED true)
add_custom_target(tags
    COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q 
        ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
    COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/tags ${CMAKE_BINARY_DIR}
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

# ...but only make it a dependency of the project if the ctags program
# is available, else it will fail to build on Windows.
find_program(CTAGS_PATH ctags)
if(CTAGS_PATH)
    message(STATUS "Found ctags: ${CTAGS_PATH}")
    add_dependencies(MyProjecct tags)
endif(CTAGS_PATH)

Он делает несколько вещей, которые не имеют более простые решения:

  • Он добавляет только "теги" в зависимости от продукта первичной сборки (MyProject), если на самом деле есть программа ctags в системе. Мы не хотим разрушать сборку только потому, что это Windows, или потому что ctags просто еще не установлен в системе сборки.

  • Он извлекает символы из исходных файлов как в сборках, так и в исходных каталогах. Это имеет значение в нескольких случаях.

    Во-первых, вы можете использовать configure_file() и исходить из фона Autotools, поэтому вы назвали ваши исходные файлы *.in, что означает ctags -R не сканирует их. Это необходимо для сканирования сгенерированных версий в каталоге сборки. Например, у вас может быть src/mainheader.h.in в исходном дереве, причем номер версии проекта автоматически помещается в него как build/src/mainheader.h.

    Во-вторых, некоторые из ваших "исходных" файлов могут быть сгенерированы другими инструментами. В моем текущем проекте у меня есть несколько заголовочных файлов С++, которые генерируются скриптами Perl. Я хочу, чтобы символы из сгенерированных заголовков и скриптов Perl в файле тегов.

  • Он работает в подкаталоге.

    В проекте, над которым я сейчас работаю, основной продукт сборки сделан из src/* относительно корня проекта, и мне нужны только символы из этого поддерева в файле тегов. Я не хочу, чтобы он включал символы из модульных тестов, примеры или скрипты утилиты.

    Поскольку он предназначен для запуска в подкаталоге, он создает символическую ссылку на файл src/tags в верхней части каталога сборки, так что работает vi -t TagName. (Я предполагаю, что если ctags существует, ln тоже.)

Ответ 3

Новое решение:

Я думаю, что CMake изменился с момента предыдущего ответа.
Вот строки, которые я добавил в свой CMakeLists.txt(протестирован с версией 2.8.12):

# Add "tags" target and make my_project depending on this target.
set_source_files_properties(tags PROPERTIES GENERATED true)
add_custom_target(tags
    COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_dependencies(my_project tags)

И теперь он отлично работает!