CMake FAQ: Difference between revisions
Bullestock (talk | contribs) m (Fixed typo) |
Karlkoehler (talk | contribs) |
||
Line 284: | Line 284: | ||
<pre> | <pre> | ||
MESSAGE("ENV{PATH}") | MESSAGE("$ENV{PATH}") | ||
</pre> | </pre> | ||
Revision as of 17:59, 5 June 2007
General information and availability
What is CMake?
CMake is a cross-platform, open-source make system. CMake is used to control the software compilation process using simple platform-independent and compiler-independent configuration files. CMake generates native makefiles and workspaces that can be used in the compiler environment of your choice. CMake is quite sophisticated: it is possible to support complex environments requiring system configuration, preprocessor generation, code generation, and template instantiation. Please go to http://www.cmake.org/HTML/About.html to learn more about CMake.
What is the current release?
The latest release of CMake is always available at: http://www.cmake.org/HTML/Download.html
From there, you can fetch CMake binaries for Windows or several Unix variants, or you can download the source code of CMake.
You can also access nightly development through CVS; see http://www.cmake.org/HTML/Download.html for more information. You may also browse the cvs repository online.
CMake roadmap and release schedule
CMake 2.4 is out. The bug tracker at http://www.cmake.org/Bug also has a number of feature requests for CMake. These feature requests typically et rolled into future versions of CMake.
I found a Bug! What should I do?
Please report the bug in our bug tracker: http://www.cmake.org/Bug
Please make sure to look at the old bugs not to include duplicates, include detailed instructions of the bug and how to reproduce it.
I want a new feature in CMake. What should I do?
Report a feature request in our Bug tracker http://www.cmake.org/Bug
Please make sure to look at the old feature requests not to include duplicates, include detailed instructions of the feature and proposed implementation.
What is the most recent version covered by the Mastering CMake book?
The Mastering CMake version 2.2 book thoroughly covers CMake 2.2.3 and earlier. Since the printing of the book CMake 2.4 has been released but the book is by no means out of date.
The following features have been added since printing the book:
- New INSTALL command (cmake --help-command INSTALL)
- New LIST command (cmake --help-command LIST)
- Updated FIND_PATH, FIND_PROGRAM, and FIND_FILE commands to be more powerful (cmake --help-command FIND_PATH)
- RPATH and Mac OS X install_name support (cmake --help-command SET_TARGET_PROPERTIES)
- CPack Beta (not finished or documented)
- EXECUTE_PROCESS was added and replaces EXEC_PROGRAM
- Other changes have been bug fixes and internal CMake restructuring
Running CMake
Is there an option to produce more 'verbose' compiling?
Set CMAKE_VERBOSE_MAKEFILE to ON. This will make generator to produce all outputs, including compiler lines.
If you are on Windows using Borland or NMake Makefiles, then you will see lines like:
cl @c:\DOCUME~1\ANDY~1.KIT\LOCALS~1\Temp\nma03504
The reason for this is that Borland and Microsoft Visual Studio make programs have limitation on the length of command strings. They overcome this limitation by writing arguments to the file and then pass file to the program.
If you actually want to see what the command looks like, set CMAKE_START_TEMP_FILE and CMAKE_END_TEMP_FILE to "".
On Makefile generators, there is a shortcut by setting Makefile variable VERBOSE to 1. For example on UNIX:
make VERBOSE=1
and Windows:
nmake /S force silent mode, overrides (CMAKE_VERBOSE_MAKFILE)
Is there a way to skip checking of dependent libraries when compiling?
Using the Makefile Generator
When using the Makefile generator under *nix you can append "/fast" to your target name. For example:
make target_name/fast
Under Windows use a backslash instead:
make target_name\fast
Using Visual Studio >= 7.1
If you have Visual Studio .NET 7.1 or greater you can use the native option to right click on a project and choose to build just that project.
Using Visual Studio <= 7.0
CMake doesn't try to compile all dependent libraries when you compile a library but it will do so for binary targets. You can't avoid this however you can take advantage of CTRL+F7 to manually compile a source file for the affected target and then relink it by right clicking on it and choosing Link. You'll have to ensure that all dependent libraries are made up-to-date however or suffer through Visual's slow check.
I set a cmake variable in my environment, but it didn't change anything. Why?
CMake build settings are stored in the CMake cache corresponding to a project's build tree. They are called CMake "cache entries" and have no relation to your command shell's environment variables. Use a CMake GUI (CMakeSetup on Windows or ccmake on UNIX) or the wizard mode (cmake -i) to edit cache entries. Initial values may also be specified for a build by using the -D command line argument to cmake when it is first run to produce a new build tree.
I change CMAKE_C_COMPILER in the GUI but it changes back on the next configure step. Why?
Once a build tree is created with a given compiler it cannot be changed. There are a variety of implementation reasons for this policy. In order to choose a different compiler create a new build tree and set the CC and CXX environment variables to the compiler you want before running CMake.
NOTE: While I don't know what the preferred method of doing it is, I do know that the advice above (to set CC and CXX env vars) is in direct conflict with advice somewhere else that says not to use env vars to control CMAKE... Hopefully someone that knows a little more than I will fix this discrepancy.
In CCMake, typing full paths is tedious. Is there a better way?
Since CMake 1.6, you can use tab completion in the path entries in CCMake. All you do is type first couple of characters and press <TAB> key. CCMake will examine the current typed path and try to expand it to some existing path. If that is possible, it will do it. If not, it will not do anything.
For example:
/usr/loc<TAB>
will expand to
/usr/local/
Out-of-source build trees
What is an "out-of-source" build?
When your build generates files, they have to go somewhere. An in-source build puts them in your source tree. An out-of-source build puts them in a completely separate directory, so that your source tree is unchanged.
In the first example, an in-place build is performed, i.e., the binaries are placed in the same directory as the source code.
cd Hello ccmake . make
In the second example, an out-of-place build is performed, i.e., the source code, libraries, and executables are produced in a directory separate from the source code directory(ies).
mkdir HelloBuild cd HelloBuild ccmake ../Hello make
Out-of-source builds are recommended, as you can build multiple variants in separate directories, e.g., HelloBuildDebug, HelloBuildRelease.
Note: Before performing an out-of-source build ensure that any possible CMake generated in-source build information is removed from the source directory, e.g., CMakeFiles directory, and CMakeCache.txt.
I run an out-of-source build but CMake generates in-source anyway. Why?
This means that there is a CMakeCache.txt file in the source tree, possibly as part of an existing in-source build. If CMake is given the path to a directory with a CMakeCache.txt file, it assumes the directory is a build tree. Therefore if one runs "cmake ../mysrc" to build out-of-source but there is a mysrc/CMakeCache.txt file then cmake will treat mysrc as the build tree.
This is a side-effect of the feature that allows "cmake ." to be used to regenerate a build tree. The behavior will not be changed because mixing in-source and out-of-source builds is not safe anyway (configured headers may be found in the wrong place).
Why does CMake use full paths, or can I copy my build tree?
CMake uses full paths because:
- configured header files may have full paths in them, and moving those files without re-configuring would cause upredictable behavior.
- because cmake supports out of source builds, if custom commands used relative paths to the source tree, they would not work when they are run in the build tree because the current directory would be incorrect.
- on Unix systems rpaths might be built into executables so they can find shared libraries at run time. If the build tree is moved old executables may use the old shared libraries, and not the new ones.
Can the build tree be copied or moved?
The short answer is NO. The reason is because full paths are used in CMake, see above. The main problem is that cmake would need to detect when the binary tree has been moved and rerun. Often when people want to move a binary tree it is so that they can distribute it to other users who may not have cmake in which case this would not work even if cmake would detect the move.
The workaround is to create a new build tree without copying or moving the old one.
CMake does not generate a "make distclean" target. Why?
Some build trees created with GNU autotools have a "make distclean" target that cleans the build and also removes Makefiles and other parts of the generated build system. CMake does not generate a "make distclean" target because CMakeLists.txt files can run scripts and arbitrary commands; CMake has no way of tracking exactly which files are generated as part of running CMake. Providing a distclean target would give users the false impression that it would work as expected. (CMake does generate a "make clean" target to remove files generated by the compiler and linker.)
A "make distclean" target is only necessary if the user performs an in-source build. CMake supports in-source builds, but we strongly encourage users to adopt the notion of an out-of-source build. Using a build tree that is separate from the source tree will prevent CMake from generating any files in the source tree. Because CMake does not change the source tree, there is no need for a distclean target. One can start a fresh build by deleting the build tree or creating a separate build tree.
(If a CMakeLists.txt uses ADD_CUSTOM_COMMAND to generate source files in the source tree, not the build tree, then in CMake 2.2 or higher "make clean" will remove them. See next question.)
Running "make clean" does not remove custom command outputs. Why?
In CMake 2.2 and higher custom command outputs should be removed by make clean. Make sure you are using at least this version. Prior to CMake 2.2 custom command outputs were not automatically added to the list of files to clean. In CMake 2.0 the developer can specify a list of files to be deleted. This can be done using SET_DIRECTORY_PROPERTIES setting property ADDITIONAL_MAKE_CLEAN_FILES to the list of files.
We however strongly recommend using an "out-of-source" build which never writes any files to the source tree. Using a separate source and build tree greatly reduces the need for "make clean" and "make distclean" targets to clean away files that differ between builds.
Writing CMakeLists.txt
How to have backward and forward compatibility?
CMake by default maintains quite a bit of backwards compatibility to support older projects that used earlier versions of CMake. This backwards compatibility comes at the expense of allowing new CMakeLists.txt to use deprecated features and still work. To deal with this problem, CMake always creates a cache entry called CMAKE_BACKWARDS_COMPATIBILITY and sets it to the version (major.minor) of CMake currently running. During the "Configure" step, CMake will support enough backward compatibility features to simulate the version of CMake specified by this cache entry's value. When a new version of CMake is run on an old project and reports errors, one can set CMAKE_BACKWARDS_COMPATIBILITY to an older version of CMake to solve the problem.
A good practice for project developers that use CMake is to add code like this to the RELEASE version of the source tree:
IF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 2.0) SET(CMAKE_BACKWARDS_COMPATIBILITY 2.0 CACHE STRING "Latest version of CMake when this project was released." FORCE) ENDIF(CMAKE_BACKWARDS_COMPATIBILITY GREATER 2.0)
That way whenever someone tries to build the release with a later version of CMake, the necessary backward compatibility level will already be set. DO NOT keep this code in the development version of the source tree. When a new version of CMake is released, it is good practice to fix the problems it reports in the source tree instead of abusing the backward compatibility features.
When a new version of CMake is released that adds some features, it is nice to be able to take advantage of them in your project. However, doing so will cause other developers that have not yet upgraded to the new CMake to get errors when attempting to build the source. In order to have CMake tell them that they need to upgrade, your project should contain a line like this:
CMAKE_MINIMUM_REQUIRED(VERSION 2.0)
at the top of your main CMakeLists.txt file. This will tell older versions of CMake that they are too old to build this project and produce a message telling the user they need to upgrade to a more recent version of CMake.
How do I get the current source or binary directory?
The variable CMAKE_CURRENT_SOURCE_DIR contains the absolute path to your current source directory, while CMAKE_CURRENT_BINARY_DIR points to the equivalent binary directory.
Why are my CMake variables not updated in the GUI after a SET command?
The cache variables listed in the GUI when you press "Configure" are used to initialize the values seen by the code in CMakeLists.txt files.
Changes made by the code are used during the configure step and seen by the generators but are not stored back into the cache. For example:
SET(BUILD_SHARED_LIBS ON)
will turn on building of shared libraries for the directory containing the command and all subdirectories, but the change will not appear in the GUI.
You can use the CACHE and FORCE options on the SET command to change variables in a way that will be reflected in the GUI. Run
cmake --help-command SET
to see full instructions for the command.
How can I change the default build mode and see it reflected in the GUI?
Adapt the following commands in your CMakeList.txt (this example sets the Release With Debug Information mode):
IF(NOT CMAKE_BUILD_TYPE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) ENDIF(NOT CMAKE_BUILD_TYPE)
How do I generate an executable, then use the executable to generate a file?
You must use GET_TARGET_PROPERTY to obtain the location of the generated executable. Some platforms put executables in separate directories according to their build type, i.e. MSVC typically has subdirectories for "Debug" and "Release" builds. For the DEPENDS part of the command, you can either use DOIT_EXE or just simply use the name of the target. This will ensure that the target doit is built before any target that uses the output from the custom command.
ADD_EXECUTABLE(doit ${DOIT_SOURCE_FILES}) GET_TARGET_PROPERTY(DOIT_EXE doit LOCATION) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/someoutput.txt COMMAND ${DOIT_EXE} ${CMAKE_CURRENT_SOURCE_DIR}/someinput.txt ${CMAKE_CURRENT_BINARY_DIR}/someoutput.txt DEPENDS doit )
How can I generate a source file during the build?
The ADD_CUSTOM_COMMAND command lets you generate a source file that you can then include in another target. For example:
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.c COMMAND ${CMAKE_COMMAND} copy ${CMAKE_CURRENT_SOURCE_DIR}/bar.c ${CMAKE_CURRENT_BINARY_DIR}/foo.c DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bar.c ) ADD_EXECUTABLE(foo foo.c)
This will create an executable by copying bar.c to foo.c and then compiling foo.c to produce foo. CMake allows you to put generate source files in the current source or binary directory, so we were careful to output foo.c to the current binary directory. When we add foo.c to foo, CMake will look in either directory for it. Even if foo.c does not yet exist, CMake is smart enough to notice that a custom command creates it. (For the file named as the OUTPUT, CMake has its GENERATED source file property set to true.)
You can also use ADD_CUSTOM_COMMAND when the generator command is another executable built in the same project:
ADD_EXECUTABLE(my_generator my_generator.c) GET_TARGET_PROPERTY(MY_GENERATOR_EXE my_generator LOCATION) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/generated.c COMMAND ${MY_GENERATOR_EXE} ${CMAKE_CURRENT_BINARY_DIR}/generated.c ${CMAKE_CURRENT_SOURCE_DIR}/some_input.txt DEPENDS my_generator ${CMAKE_CURRENT_SOURCE_DIR}/some_input.txt ) ADD_EXECUTABLE(generated generated.c)
For this example, we assumed that the my_generator program accepts as its first argument the full path to the source file to generate, and the second argument is input for the generator. When either the generator source or the sample input changes, the generated.c source will be regenerated.
Sometimes, the program doing the generation may generate multiple output files that each need to be part of the build. CMake 2.4 or higher supports having multiple files listed in the OUTPUT section. For example, suppose you had a program that read input.txt and generated three files output1.cpp, output2.h, and output3.cpp, and that those three files needed to be compiled into an executable program. The cmake list file for that would look like this:
PROJECT(FOO) # make sure cmake addes the binary directory for the project to the include path INCLUDE_DIRECTORIES(${FOO_BINARY_DIR}) # add the executable that will do the generation ADD_EXECUTABLE(my_generator my_generator.cxx) GET_TARGET_PROPERTY(MY_GENERATOR_EXE my_generator LOCATION) # add the custom command that will generate all three files ADD_CUSTOM_COMMAND( OUTPUT ${FOO_BINARY_DIR}/output1.cpp ${FOO_BINARY_DIR}/output2.h ${FOO_BINARY_DIR}/output3.cpp COMMAND ${MY_GENERATOR_EXE} ${FOO_BINARY_DIR} ${FOO_SOURCE_DIR}/input.txt DEPENDS my_generator MAIN_DEPENDENCY ${FOO_SOURCE_DIR}/input.txt ) # now create an executable using the generated files ADD_EXECUTABLE(generated ${FOO_BINARY_DIR}/output1.cpp ${FOO_BINARY_DIR}/output2.h ${FOO_BINARY_DIR}/output3.cpp)
CMake 2.4 allows you to generate a header file. Because generated headers often cause unnecessary rebuilds, you should try to avoid them; consider using the CONFIGURE_FILE command to prepare the header at CMake time. If you must generate a header file, use code like this:
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/bar.h ${CMAKE_CURRENT_BINARY_DIR}/foo.h DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/bar.h ) ADD_EXECUTABLE(foo foo.c ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
This is like the first example above, except that it generates a header instead of a C file. The header might not exist when the build system scans foo.c's dependencies, so there is no way for CMake to know that this target requires foo.h unless we can tell it that foo.h may exist in the future. We give CMake this knowledge by listing the generated header file in the set of source fiels for the target. (This requires CMake 2.4. Previous versions of CMake required use of the OBJECT_DEPENDS source file property.)
I use EXEC_PROGRAM but the result is not set in subdirectories. Why?
An unfortunate holdover from ancient CMake versions is that certain commands are "inherited" into subdirectories and others are not. EXEC_PROGRAM is not inherited. What this means is that when the listfile code from a parent directory executes in a subdirectory the EXEC_PROGRAM command is left out. Therefore the code executes differently. This problem was fixed in CMake 2.2, but for older versions you will have to cache the result:
EXEC_PROGRAM(my-program OUTPUT_VARIABLE MY_OUTPUT) SET(MY_OUTPUT "${MY_OUTPUT}" CACHE INTERNAL "")
This will store the result in a global location so it will be available in the subdirectory. Be sure to choose a descriptive name for MY_OUTPUT to avoid conflict in the global setting.
How can I get or set environment variables?
CMake names environment variables using an ENV prefix and surrounding the names in curly braces. Here is an example:
MESSAGE("$ENV{PATH}")
Reading variables will work in any version of CMake. Writing to them works in CMake 2.2 and higher using the following syntax:
SET(ENV{HELLO} "World")
Note that there is currently no way to tell apart an empty environment variable value from a variable that is not set at all.
One should avoid using environment variables for controlling the flow of CMake code (such as in IF commands). The build system generated by CMake may re-run CMake automatically when CMakeLists.txt files change. The environment in which this is executed is controlled by the build system and may not match that in which CMake was originally run. If you want to control build settings on the CMake command line, you need to use cache variables set with the -D option. The settings will be saved in CMakeCache.txt so that they don't have to be repeated every time CMake is run on the same build tree.
Isn't the "Expression" in the "ELSE (Expression)" confusing?
Traditional CMakeLists.txt files require the following syntax. In the IF syntax, the ELSE section requires the same (Expression) as the IF section. This makes the script kind of hard to follow, for example:
IF(WIN32) ...do something... ELSE(WIN32) ...do something else... ENDIF(WIN32)
You might think that the ELSE section, here containing "...do something else...", is for the WIN32 portion of the script. That is not so! It is actually handling the NOT WIN32 section.
If you find this too confusing you can enable the CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS option which will allow you to use a slightly more conventional syntax where the ELSE() and ENDIF() constructs can be empty:
SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
IF(WIN32) ...do something... ELSEIF(APPLE) ...do something else... ELSE() ...do something else... ENDIF()
Which regular expressions are supported by CMake?
When using MATCHES or MATCHALL in an IF command, or using any of the STRING(REGEX ...) commands, CMake expects regular expressions, not globs (wild cards). CMake uses the same regular expression engine above all platforms. Here are the meanings of the metacharacters:
^ Matches at beginning of a line $ Matches at end of a line . Matches any single character [ ] Matches any character(s) inside the brackets [^ ] Matches any character(s) not inside the brackets - Matches any character in range on either side of a dash * Matches preceding pattern zero or more times + Matches preceding pattern one or more times ? Matches preceding pattern zero or once only () Saves a matched expression and uses it in a later match
Example: "[-][L]([^ ;])+" matches all strings beginning with -L and ending with a space or a semicolon, the usual linkdirs under Linux.
Here is how to catch a part of a string. The variable test is filled with some content, and then we want to catch the "me":
SET(test "hello world ! catch: me if you can") STRING(REGEX REPLACE ".*catch: ([^ ]+).*" "\\1" result "${test}" ) MESSAGE(STATUS "result= ${result}")
This is slightly tricky. The part inside the brackets is available in \\1 . CMake will copy the variable test to the variable result, but then it will replace everything that the regular expression matches with \\1. This means the first regular expression has to match the whole string and the part we want to catch has to be put in parens.
-- result= me
For those of you who know Perl, the equivalent Perl code could be:
$test = "hello world ! catch: me if you can"; $result = $test; $result =~ s/.*catch: ([^ ]+).*/$1/; print "-- result= $result\n";
There are other ways to do this in Perl, but this is how we do it in CMake because \\1 does not become a variable like $1 does in perl, so there is no SET(result ${\\1}) in CMake.
How can I build multiple modes without switching ?
To build multiple modes (e.g. Debug and Release) in one shot without constantly running cmake -DCMAKE_BUILD_TYPE=Debug and cmake -DCMAKE_BUILD_TYPE=Release in source tree create a directory for builds eg.:
Project-directory/ /Build
Inside you can place as many target directories for out-of-source build modes as you want, e.g.:
Project-directory/ /Build /Debug /Release
In each of these directories issue a command (assuming that you have CMakeLists.txt directly in Project-directory)
cmake -DCMAKE_BUILD_TYPE=type_of_build ../../
to create a cmake cache configured for requested build type.
Now you can make each build just by entering appropriate directory and executing a make command.
How can I extend the build modes with a custom made one ?
The following code snipet (taken from a CMakeLists.txt) adds a Maintainer mode:
SET( CMAKE_CXX_FLAGS_MAINTAINER "-Wall -Wabi" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE ) SET( CMAKE_C_FLAGS_MAINTAINER "-Wall -pedantic" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE ) SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE ) SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE ) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_MAINTAINER CMAKE_C_FLAGS_MAINTAINER CMAKE_EXE_LINKER_FLAGS_MAINTAINER CMAKE_SHARED_LINKER_FLAGS_MAINTAINER ) # Update the documentation string of CMAKE_BUILD_TYPE for GUIs SET( CMAKE_BUILD_TYPE "" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Maintainer." FORCE )
Notes: this will only work with gcc (since the flags would need to be declined with the possible compilers). Additionaly this will override a CMAKE_BUILD_TYPE previously set in the CMakeLists.txt...
Finding and using external packages
How do I use CMake to generate SWIG wrapper libraries?
CMake version 2 includes a module that supports the generation of SWIG wrapper libraries. The SWIG package defines the following macros: SWIG_ADD_MODULE and SWIG_LINK_LIBRARIES.
# This example shows how to use python # Currently these languages have been tested: # perl tcl ruby php4 pike FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(PythonLibs) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(CMAKE_SWIG_FLAGS "") SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall") SWIG_ADD_MODULE(example python example.i example.cxx) SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})
# This example shows how to use tcl PROJECT(TCL_WRAP) SET ( MODULE_NAME project ) SET ( INTERFACE_FILES project.i) SET ( SRC_FILES Vertex.h Vertex.cxx Shapes.h Shapes.cxx ) FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) # Look for TCL INCLUDE_DIRECTORIES(${TCL_INCLUDE_PATH}) FIND_LIBRARY(TCL_LIBRARY NAMES tcl tcl84 tcl83 tcl82 tcl80 PATHS /usr/lib /usr/local/lib) IF (TCL_LIBRARY) TARGET_ADD_LIBRARY (${MODULE_NAME} TCL_LIBRARY) ENDIF (TCL_LIBRARY) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(CMAKE_SWIG_FLAGS "-c++") SET_SOURCE_FILES_PROPERTIES(${INTERFACE_FILES} PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(${INTERFACE_FILES} PROPERTIES CMAKE_SWIG_FLAGS "-includeall") SWIG_ADD_MODULE(${MODULE_NAME} tcl ${INTERFACE_FILES} ${SRC_FILES}) SWIG_LINK_LIBRARIES(${MODULE_NAME} ${TCL_LIBRARIES})
How do I use CMake to build LaTeX documents?
Use the following approach. Note that you have to set LATEX_COMPILE to LaTeX executable, DVIPDF_COMPILE to dvi to pdf converter. Also, the LaTeX source is TDocument.tex and the result is called TDocument.pdf. Note that this uses commands in CMake version 1.8 or later.
PROJECT(Document) IF(LATEX_COMPILE) ADD_CUSTOM_COMMAND( OUTPUT ${Document_BINARY_DIR}/TDocument.dvi DEPENDS ${Document_BINARY_DIR}/TDocument.tex COMMAND ${LATEX_COMPILE} ARGS ${Document_SOURCE_DIR}/TDocument.tex ) ENDIF(LATEX_COMPILE) IF(DVIPDF_COMPILE) ADD_CUSTOM_COMMAND( OUTPUT ${Document_BINARY_DIR}/TDocument.pdf DEPENDS ${Document_BINARY_DIR}/TDocument.dvi COMMAND ${DVIPDF_COMPILE} ARGS ${Document_SOURCE_DIR}/TDocument.dvi ) ENDIF(DVIPDF_COMPILE)
ADD_CUSTOM_TARGET(LaTeXDocument ALL echo DEPENDS ${Document_BINARY_DIR}/TDocument.pdf )
The following uses commands in CMake version 2.0 and later
PROJECT(Document) # # Find LaTeX # FIND_PACKAGE(LATEX)
IF(LATEX_COMPILER) ADD_CUSTOM_COMMAND( OUTPUT ${Document_BINARY_DIR}/TDocument.dvi COMMAND ${LATEX_COMPILER} ARGS ${Document_SOURCE_DIR}/TDocument.tex DEPENDS ${Document_SOURCE_DIR}/TDocument.tex COMMENT "Tex2dvi" )
IF(DVIPS_CONVERTER) ADD_CUSTOM_COMMAND( OUTPUT ${Document_BINARY_DIR}/TDocument.ps COMMAND ${DVIPS_CONVERTER} ARGS ${Document_BINARY_DIR}/TDocument.dvi -o ${Document_BINARY_DIR}/TDocument.ps DEPENDS ${Document_BINARY_DIR}/TDocument.dvi COMMENT "dvi2ps" ) IF(PS2PDF_CONVERTER) ADD_CUSTOM_COMMAND( OUTPUT ${Document_BINARY_DIR}/TDocument.pdf COMMAND ${PS2PDF_CONVERTER} ARGS ${Document_BINARY_DIR}/TDocument.ps DEPENDS ${Document_BINARY_DIR}/TDocument.ps COMMENT "ps2pdf" )
ADD_CUSTOM_TARGET(LaTeXDocument ALL echo DEPENDS ${Document_BINARY_DIR}/TDocument.pdf ) ENDIF(PS2PDF_CONVERTER) ENDIF(DVIPS_CONVERTER) ENDIF(LATEX_COMPILER)
How do I get LaTeX references to be correct?
When your latex document contains references (e.g. \ref{...} command) you get to run two passes of latex. In the most general case, i.e. when additionally your document uses a bibtex bibliography, you shall need three passes of latex (and one pass of bibtex):
- latex (first pass: for bibtex to have an .aux file)
- bibtex (for generating the .bbl file)
- latex (second pass)
- latex (third pass)
The following code snippet illustrates how you can "pervert" the bibtex and latex generated auxilary files (.aux, .log, .dvi, .bbl...) to create an "artificial" set of CMake dependencies. The side-effect of those dependencies should hopefully be the above described sequence of calls to latex and bibtex
ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.aux DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/UsersManual.tex COMMAND ${LATEX_COMPILER} ARGS -interaction=batchmode ${CMAKE_CURRENT_BINARY_DIR}/UsersManual COMMENT "Latex (first pass)" ) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.bbl DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.aux COMMAND ${BIBTEX_COMPILER} ARGS -terse ${CMAKE_CURRENT_BINARY_DIR}/UsersManual COMMENT "Bibtex" ) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.dvi DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.bbl COMMAND ${LATEX_COMPILER} ARGS -interaction=batchmode ${CMAKE_CURRENT_BINARY_DIR}/UsersManual COMMENT "Latex (second pass)" ) ADD_CUSTOM_COMMAND( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.log DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.bbl ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.dvi COMMAND ${LATEX_COMPILER} ARGS -interaction=batchmode ${CMAKE_CURRENT_BINARY_DIR}/UsersManual COMMENT "Latex (third pass)" ) # Eventually trigger the whole process ADD_CUSTOM_TARGET(LaTeXDocument ALL echo DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/UsersManual.log )
How can I set TEXINPUTS for a LaTeX compilation?
First note that most often you can avoid using TEXINPUTS by copying all the necessary files (.tex source file and included graphic files e.g. .eps files) from your PROJECT_SOURCE_DIR hirarchy to your PROJECT_BINARY_DIR subdir [refer to CONFIGURE_FILE with the COPYONLY flag set for copying files]. Since by default latex uses the current working directory as value for TEXINPUTS you should be all set. As expected, this trick is quick AND dirty since your concerned PROJECT_BINARY_DIR subdir now contains files that are NOT generated by CMake (in the sense that those files are not the result of a system command but were merely duplicated)...
If you consider it is cleaner or easier to define a TEXINPUTS environment variable [the latex command probably misses a -I flag] you can find an example in the InsightDocuments cvs archive (refer to the section "cvs access" near the bottom of Kitware's ITK download page) or use google with keywords "ITK_TEXINPUTS CONFIGURE_FILE". Look at InsightDocuments/CourseWare/Training/Vis2003/Latex/CMakeLists.txt and search for e.g. "LaTeXWrapper.sh.in".
Roughly the mechanism goes:
- SET ITK_TEXINPUTS with the desired TEXINPUTS
- CONFIGURE_FILE "InsightDocuments/CourseWare/Training/Vis2003/LaTeXWrapper.sh.in" which generates an sh shell script setting the shell variable TEXINPUTS prior to running the latex command
- use ADD_CUSTOM_COMMAND to invoke this shell script
This very example is Win32 portable (except that LaTeXWrapper.bat.in generates a .bat shell script)
Library questions
No. Each library you build must have a unique target name, i.e. the "libname" field of the ADD_LIBRARY command. That way, CMake can track dependencies separately for each library. Libraries can have the same OUTPUT_NAME, see the SET_TARGET_PROPERTIES command, but this is not the default.
In practice, most libraries have different defines and compiler flags for the shared vs. static cases. So you would have to build all your library objects twice anyways.
Set the OUTPUT_NAME of your shared and static libraries to the same thing.
ADD_LIBRARY(foo SHARED ${foo_sources}) ADD_LIBRARY(foo-static STATIC ${foo_sources}) // The library target "foo" already has a default OUTPUT_NAME of "foo", so we don't need to change it. // The library target "foo-static" has a default OUTPUT_NAME of "foo-static", so change it. SET_TARGET_PROPERTIES(foo-static PROPERTIES OUTPUT_NAME "foo")
If you are building your shared and static libraries in the same directory, you will also need the following to keep your shared and static libraries from clobbering each other during the build.
SET_TARGET_PROPERTIES(foo PROPERTIES CLEAN_DIRECT_OUTPUT 1) SET_TARGET_PROPERTIES(foo-static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
How do I rename a library after it has already been built?
You don't rename it. It's been built! Its name is whatever CMakeLists.txt says it's supposed to be.
Perhaps you want to copy the library to a different name. But, are you sure that's what you want to do? You could just change the name in your ADD_LIBRARY command or change its OUTPUT_NAME property. If you really really want to copy the library to a different name, try:
GET_TARGET_PROPERTY(LIB_NAME Foo LOCATION) GET_TARGET_PROPERTY(Bar_prefix Foo PREFIX) GET_TARGET_PROPERTY(Bar_suffix Foo SUFFIX) SET(NEW_LIB_NAME ${Bar_prefix}Bar${Bar_suffix}) ADD_CUSTOM_COMMAND( TARGET Foo POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${LIB_NAME} ${NEW_LIB_NAME} )
On Windows you may also want to copy the .dll import lib, using the same approach as above, but with IMPORT_PREFIX and IMPORT_SUFFIX. Problem: LOCATION only refers to 1 file, the .dll. What is a simple way to get the location of the import lib? Could provide a complicated way, but that's annoying.
Does CMake support "convenience" libraries?
No. CMake does not currently support convenience libraries. A "convenience" library, as GNU libtool calls it, is an archive of objects to be mixed into other libraries. Other libraries "link" to the convenience library, but the convenience library does not export any symbols; GNU libtool never installs the convenience library; no programs ever link to the convenience library.
This does not mean that a project using convenience libraries cannot be converted to CMake. Instead the source files may be listed in each target that needs them. They will be built for each target separately using all the preprocessor definitions and flags configured for that target.
This question arises when one has a library B which links to some library A. When a third target, say C, links to B, CMake will automatically include C to A also. When the libraries are static, then this is always necessary. When the libraries are shared, then this is necessary on some platforms but not others. The decision was made to make this consistent across all platforms and library types for simplicity and reliability.
We have never seen a real case when this causes a problem. The most commonly suggested example is when A is a static library then both B and C get copies of it. On most platforms this is already an error because it is not safe to link static libraries into shared libraries: there is no way to ensure that the static libraries contain relocatable objects (built with -fPIC or equivalent flag).
In the future CMake may distinguish between the linking interface (what libraries are needed for C to use library B) and the linking implementation (what libraries are needed to create B in the first place). This has not yet been implemented.
Installation questions
Does CMake's "make install" support DESTDIR?
Yes, when a makefile generator is used. After the build completes, one may run "make install" to install any files the project configured to be installed. Running
make install DESTDIR="/home/me/mydist"
will cause the installation to copy files to "/home/me/mydist/${CMAKE_INSTALL_PREFIX}/...". This is useful for package maintainers.
Can I do "make uninstall" with CMake?
By default, CMake does not provide the "make uninstall" target, so you cannot do this. We do not want "make uninstall" to remove useful files from the system.
If you want an "uninstall" target in your project, then nobody prevents you from providing one. You need to delete the files listed in install_manifest.txt file. Here is how to do it. First create file cmake_uninstall.cmake.in in the top-level directory of the project:
IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF("${rm_retval}" STREQUAL 0) ELSE("${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF("${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file)
Then in the top-level CMakeLists.txt add the following logic:
CONFIGURE_FILE( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
Now you will have an "uninstall" target at the top-level directory of your build tree.
Instead of creating an "uninstall" target, Unix users could enter this command in the shell:
xargs rm < install_manifest.txt
Distribution questions
Where is "make dist"?
According to this post from 2004, they're working on it, but it will take some time.
What is the best way to distribute source code for a cmake-based project?
Tarball example:
cd /tmp mkdir project-1.0 cp -a /path/to/source/* project-1.0 tar -cvzf project-1.0.tgz project-1.0
What's the best way to distribute binaries for a cmake-based project?
This is pretty much a "cook's choice" decision since associated functionality is not built in to cmake, but perhaps creating an OS-specific package, like an RPM, a deb package, a Windows installer, an OS X .dmg, etc. would be the right approach.
Platform-specific questions
How can I apply resources on Mac OS X automatically?
Using ADD_CUSTOM_COMMAND. For example, let's say you are creating executable MyExecutable, which needs the resources file Carbon.r. All you do is add custom rule which is executed after the executable is linked:
ADD_EXECUTABLE(MyExecutable ${MyExecutable_SRCS}) SET(MyExecutable_PATH ${EXECUTABLE_OUTPUT_PATH}) IF(NOT MyExecutable_PATH) SET(MyExecutable_PATH ${CMAKE_CURRENT_BINARY_DIR}) ENDIF(NOT MyExecutable_PATH)
IF(APPLE) FIND_PROGRAM(VTK_APPLE_RESOURCE Rez /Developer/Tools) IF(VTK_APPLE_RESOURCE) ADD_CUSTOM_COMMAND(SOURCE MyExecutable COMMAND ${VTK_APPLE_RESOURCE} ARGS Carbon.r -o ${MyExecutable_PATH}/MyExecutable TARGET MyExecutable) ENDIF(VTK_APPLE_RESOURCE) ENDIF(APPLE)
This will execute:
/Developer/Tools/Rez Carbon.r -o /binary/path/MyExecutable
after MyExecutable is linked.
Why does FIND_LIBRARY not find .DLL libraries under WIN32?
For those who come from a Unix background to MS Windows:
You never link directly to the .dll, you have to link against the import library .lib for the .dll.
Linking against dynamic libraries (.dll under Windows) is quite different from linking against ELF shared objects (.so) under platforms like Linux or NetBSD. In Windows, there are two types of library, a static library and an import library (both confusingly use the .lib extension, however). In Windows, when you build an import library (A.lib) you will get a corresponding (A.dll) that you only need at runtime. At compile time you will need the import library.
Conclusion: There is no need to find a .dll for linking. You only need to find the .lib import library.
Some more details can be found here: [1].
Why am I getting a linker error to _mainCRTStartup under WIN32?
Your program is a GUI application using WinMain (/subsystem:windows) and not a console application using main. You have to use the WIN32 option with the ADD_EXECUTABLE command.
ADD_EXECUTABLE(exename WIN32 source1 source2 ... sourceN)
The second argument to ADD_EXECUTABLE can be WIN32. This indicates that the executable, when compiled on Windows, is a Windows app (using WinMain) and not a console app (using main). Please note that on Unix platforms, CMake ignores the WIN32 and the compiler will use "main" in any case.
Why do I get this error: nafxcwd.lib(appcore.obj) : error LNK2001: unresolved external symbol ___argv
This is because the application is using both the static and dll versions of the MFC library. To fix the problem, you can do the following:
SET(CMAKE_MFC_FLAG 2) # force the IDE to use static MFC ADD_DEFINITIONS(-D_AFXDLL) # make sure if afx.h is included the dll MFC is used
How to use MFC with CMake
To use MFC, the CMAKE_MFC_FLAG variable must be set as follows:
0: Use Standard Windows Libraries 1: Use MFC in a Static Library 2: Use MFC in a Shared DLL
This can be set in a CMakeLists.txt file and will enable MFC in the application. It should be set to 1 or 2. This is used in visual studio 6 and 7 project files. The CMakeSetup dialog uses MFC and the CMakeLists.txt looks like this:
ADD_DEFINITIONS(-D_AFXDLL) SET(CMAKE_MFC_FLAG 2) ADD_EXECUTABLE(CMakeSetup WIN32 ${SRCS})
How To Put Files in Folders in Visual Studio Projects
The Visual Studio IDE supports putting files into folders. CMake can be used to put files in folders with the SOURCE_GROUP command.
SOURCE_GROUP(name [REGULAR_EXPRESSION regex] [FILES src1 src2 ...])
Defines a group into which sources will be placed in project files. This is mainly used to setup file tabs in Visual Studio. Any file whose name is listed or matches the regular expression will be placed in this group provided the source file is being passed to ADD_EXECUTABLE or ADD_LIBRARY.
For example: SOURCE_GROUP(FooFiles FILES foo.cxx) SOURCE_GROUP(BarFiles FILES bar.cxx) ADD_LIBRARY(foo foo.cxx bar.cxx)
In the event a file matches multiple groups, the LAST group that explicitly lists the file will be favored, if any. If no group explicitly lists the file, the LAST group whose regular expression matches the file will be favored. For backwards compatibility this command is also supports the format SOURCE_GROUP(name regex).
As a convenience to developers CMake automatically adds standard header files to a "Header Files" folder and standard source files to a "Source Files" folder for Visual Studio Projects. This can be overridden via the SOURCE_GROUP method documented above.
How to create Visual Studio 6 Projects that contain only a single build type
For Visual Studio.NET (version 7.0 and above) it is possible to set the CMAKE_CONFIGURATION_TYPES variable to the build type(s) (Debug/Release/...) that you want. This does not work for Visual Studio 6. There is however a way to achieve this. To create your own set of configurations:
- Create a directory in which you copy the files *.dsptemplate and CMakeVisualStudio6Configurations.cmake from CMake's Templates directory.
- Edit the .cmake file and change the SET(CMAKE_CONFIGURATION_TYPES ...) line to set the build types that you want in your set.
- Edit the *Header.dsptemplate files to contain only the configuration types you want in your set.
- In your CMakeLists.txt file, set the MSPROJECT_TEMPLATE_DIRECTORY to the directory that you created.
That's it. Run CMake and your new configuration files will be created.
Note: Editing the *Header.dsptemplates files should be done very carefully. Here are some guidelines:
- You MUST remove the targets that you do not want in your set at the bottom of the file (e.g. '# Name "OUTPUT_LIBNAME - Win32 MinSizeRel"') - You can remove the '!IF "$(CFG)" == ...' until '!ELSEIF "$(CFG)" == ...' or '!ELSEIF "$(CFG)" == ...' until '!ENDIF' lines for the configurations you do not want. Make sure that the resulting code still starts with '!IF ...' and ends with '!ENDIF' with any number of '!ELSEIF' sections in between. If you create templates for a single configuration (aka makefile), it is possible to remove everything starting from '!IF' until and including '!ENDIF' and leave only the contents of the relevant section intact. - Do not edit the lines starting with '!MESSAGE' as the changes may - and probably will - corrupt your resulting DSP files. The only thing I was able to change without corrupting the DSP is to remove the irrevant configurations from the "Possible choices for configuration are:" list.
If you have only a single configuration in your set, you may want to get rid of the intermediate dir that MsDev creates. You can do that by setting:
- PROP BASE Output_Dir ""
- PROP BASE Intermediate_Dir ""
- PROP Intermediate_Dir ""
- PROP Output_Dir "LIBRARY_OUTPUT_PATH"
or
- PROP Output_Dir "EXECUTABLE_OUTPUT_PATH"
Additionally you should then also edit the '# ADD LINK32' line in the DLLHeader.dsptemplate file. Change for example '/out:"LIBRARY_OUTPUT_PATHDebug/OUTPUT_LIBNAMEDEBUG_POSTFIX.dll"' into '/out:"LIBRARY_OUTPUT_PATHOUTPUT_LIBNAMEDEBUG_POSTFIX.dll"' (Note that the configuration name and also the slash are removed).
It is even possible to rename the pre-defined configurations of CMake in this way. Let's say you prefer 'PreProduction' over 'RelWithDebInfo'. You can change the name in the *.dsptemplate files, but you should also change it in the CMakeVisualStudio6Configurations.cmake file. Be careful, however. Only entries relevant to the configuration name should be changed. Do not change the /debug options and the entries that contain the build type in capital characters. Internally in CMake the build type will still remain 'RelWithDebInfo', so also the CMAKE_BUILD_TYPE should be set to the old value. You can only change the way it is named in MSDev.
Note: Apparently MsDev as command-line build tool only performs a partial check on the build type. It will match all configuration types that CONTAIN the build type in their name. (e.g. if you have renamed RelWithDebInfo to DebugRelease, Debug will build Debug and DebugRelease, Release will build Release and DebugRelease. This may be exactly what you want, but be warned.)
Can CMake set the Debugging/Working Directory property in Visual Studio projects?
No. The value of this property is not stored in the project files. It is stored in extra files created by the IDE when a solution is loaded (VS .NET 2003 uses a hidden .suo file next to the .sln solution file). The format of these files is not known to CMake and cannot be generated. In some versions of VS the files are binary and not human readable.
Why does CMakeSetup with the message "LINK : fatal error LNK1104: cannot open file 'user32.lib'" while configuring a project?
The path to the SDK libs (user32.lib) must be added by the IDE when the project generator "Visual Studio 8 2005" is used, because cmake uses VCExpress.exe and on the fly generated project files to check for compiling (VCExpress.exe reads some config files for the compiler/linker options)
So add the sdk lib path (...\Microsoft Platform SDK\Lib) at Tools->Options->Projects and Solutions->VC++ Directories->Library files
How can I avoid the error "Arg list too long" when running make?
This error is sometimes encountered when building a static library with many object files using Unix make command. It typically looks something like this:
gmake[2]: execvp: /bin/sh: Arg list too long
When make tries to run the archiver program to build the static library the shell it uses complains that the argument list is too long. In some shells this can be fixed by setting an environment variable such as ARG_MAX to extend the length of the command line it will allow.