[CMake] header files with visual studio
Michael Hertling
mhertling at online.de
Thu Nov 11 06:23:28 EST 2010
On 11/10/2010 12:30 AM, Oliver kfsone Smith wrote:
> Michael Hertling said the following on 11/6/2010 7:39 AM:
>> stored in the ${CMAKE_BINARY_DIR}/filelist.dat script as an assignment
>> to the variable FILELIST. Subsequently, this filelist.dat is read via
>> INCLUDE(), so CMake keeps track of it, i.e. changing the filelist.dat
>> results in a rebuild. Finally, the filelist custom target regenerates
>> filelist.dat by executing filelist.cmake. Hence, each time the set of
>> *.c files in CMAKE_SOURCE_DIR changes, a "make filelist" will update
>> filelist.dat, and the following "make" will rebuild - taking into
>> account the refreshed list of source files. Maybe, this approach
>> can be adapted to platforms other than *nix and large projects.
> I already have the source files split up into their myriad sub-projects,
> all I really want is to tap into the dependency generator to get a list
> of header files pertinent to any given project.
AFAIK, CMake's built-in dependency scanner offers no interface to hook
in, but possibly, you might use an external tool to achieve your goal:
# ${CMAKE_SOURCE_DIR}/CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(HEADERS C)
IF(NOT EXISTS ${CMAKE_BINARY_DIR}/main.headers)
EXECUTE_PROCESS(
COMMAND ${CMAKE_COMMAND}
-DSOURCE=${CMAKE_SOURCE_DIR}/main.c
-DOUTPUT=${CMAKE_BINARY_DIR}/main.headers
-DVARIABLE=HEADERS
-P ${CMAKE_SOURCE_DIR}/headers.cmake
)
ENDIF()
INCLUDE(${CMAKE_BINARY_DIR}/main.headers)
MESSAGE("HEADERS: ${HEADERS}")
ADD_EXECUTABLE(main main.c ${HEADERS})
ADD_CUSTOM_TARGET(headers
COMMAND ${CMAKE_COMMAND}
-DSOURCE=${CMAKE_SOURCE_DIR}/main.c
-DOUTPUT=${CMAKE_BINARY_DIR}/main.headers
-DVARIABLE=HEADERS
-P ${CMAKE_SOURCE_DIR}/headers.cmake
)
# ${CMAKE_SOUIRCE_DIR}/headers.cmake:
EXECUTE_PROCESS(COMMAND gcc -MM ${SOURCE} OUTPUT_VARIABLE HEADERS)
STRING(REGEX REPLACE "^.*: ${SOURCE}" "" HEADERS "${HEADERS}")
STRING(REGEX REPLACE " \\\\\n " "\n" HEADERS "${HEADERS}")
FILE(WRITE ${OUTPUT}.in "SET(${VARIABLE}\n${HEADERS})\n")
CONFIGURE_FILE(${OUTPUT}.in ${OUTPUT} COPYONLY)
This is the same approach as in my previous example with the exception
of the filelist.cmake script replaced by headers.cmake. The latter one
makes use of gcc's -MM option to scan a source file's included headers
and writes the list to a file in the form of a SET() command. In turn,
the file is included in CMakeLists.txt to define the HEADERS variable
mentioned in the "main" target's sources. Initially, the headers are
scanned by an explicit invocation of headers.cmake, and after having
added/removed/renamed a header, triggering the "headers" target does
that job, so a subsequent build will reconfigure at first due to the
updated include file. In addition, CONFIGURE_FILE() in headers.cmake
ensures the include file isn't touched if nothing has changed, hence
the headers target doesn't cause unnecessary rebuilds.
This approach can be seen to work on *nix, but it might be possible
to adapt for other platforms and to enhance for extensive projects:
1. Make header.cmake operate on a list of source files.
2. Provide each of the sub-projects with its own headers target.
3. Provide the top-level project with a headers targets and set up
dependencies of the latter on the sub-projects' ones, so building
the top-level headers target will update the header file lists of
the entire project resulting in reconfiguration and maybe rebuild.
Clearly, the downside is the usage of an external dependency scanner.
Regards,
Michael
> In particular, this is useful for performing search operations.
>
> Remember: Visual Studio allows you to constrain multi-file searches a
> number of ways, one of which is "Just this project".
>
> When you have thousands of header files, having every header in your
> codebase arbitrarily crammed into your project file means that every
> project-only search is going to return too many results.
More information about the CMake
mailing list