I\'m coding a c++ project in vim.
I\'d like to run a ctags
command (ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
) to generate referen
The most basic way to do this is:
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 )
The first line tells CMake
that tags
will be generated. The add_custom_command
is CMake
will generate tags
when needed, and finally, some target needs to depend on tags
. The default working directory is in the build tree, so WORKING_DIRECTORY
must be set to your source tree. This is equivalent a Makefile entry:
tags:
ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
MyProjectOutput: tags
# Whatever here...
New solution:
I think CMake changed since the previous answer was given.
Here is the lines I added in my CMakeLists.txt (tested with version 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)
And it works perfectly now!
Daniel's and Creak's answers got me started, but I ended up with a more complex solution that I thought I'd share:
# 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)
It does several things that the simpler solutions do not:
It only adds "tags" as a dependency of the primary build product (MyProject
) if there is actually a ctags
program on the system. We don't want to break the build just because this is Windows, or because ctags
simply hasn't been installed yet on the build system.
It extracts symbols from source files in both the build and source directories. This matters in a couple of cases.
First, you might be using configure_file() and come from an Autotools background, so you've named your true source files *.in
, which means ctags -R
won't scan them. You need it to scan the generated versions in the build directory. For example, you might have src/mainheader.h.in
in your source tree, with the project version number automatically subbed into it as build/src/mainheader.h
.
Second, some of your "source" files might be generated by other tools. In my current project, I have a couple of C++ header files that are generated by Perl scripts. I want symbols from both the generated headers and the Perl scripts in the tags file.
It works in a subdirectory.
In the project I'm working on right now, the primary build product is made from src/*
relative to the project root, and I only want symbols from that subtree in the tags file. I don't want it to include symbols from the unit tests, the examples, or the utility scripts.
Because it is designed to run in a subdirectory, it creates a symlink to the src/tags
file in the top of the build directory, so that vi -t TagName
works. (I'm assuming here that if ctags
exists, ln
does, too.)