Difference between revisions of "CMake FAQ"

From KitwarePublic
Jump to navigationJump to search
Line 70: Line 70:
  
 
=== How can I generate a source file during the build? ===
 
=== How can I generate a source file during the build? ===
 
 
The ADD_CUSTOM_COMMAND command can be used to generate a source file that is then included in another target.  For example:
 
The ADD_CUSTOM_COMMAND command can be used to generate a source file that is then included in another target.  For example:
  
Line 100: Line 99:
 
In both of the above cases, the source file named as the OUTPUT argument of the ADD_CUSTOM_COMMAND command will automatically have the GENERATED source file property set to true.  The source may then be referenced without the ${CMAKE_CURRENT_BINARY_DIR} part of the path.
 
In both of the above cases, the source file named as the OUTPUT argument of the ADD_CUSTOM_COMMAND command will automatically have the GENERATED source file property set to true.  The source may then be referenced without the ${CMAKE_CURRENT_BINARY_DIR} part of the path.
 
Note that use of the "LOCATION" target property requires CMake 2.0 or higher.
 
Note that use of the "LOCATION" target property requires CMake 2.0 or higher.
 +
 +
In some cases, the program doing the generation may generate more than one file that needs to be part of the build.  In this case, some dummy custom commands must be created to "chain" the outputs so that the files are created in the correct order. 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 but only specify one of the outputs
 +
  ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output1.cpp
 +
    COMMAND ${MY_GENERATOR_EXE}
 +
    ARGS ${FOO_BINARY_DIR} ${FOO_SOURCE_DIR}/input.txt
 +
    DEPENDS ${MY_GENERATOR_EXE}
 +
    MAIN_DEPENDENCY ${FOO_SOURCE_DIR}/input.txt
 +
    )
 +
  # add the second output and run the dummy command echo but make sure that output1.cpp
 +
  # is the DEPEND for this command.  Once output1.cpp exists output2.h will also be created.
 +
  ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output2.h
 +
    COMMAND echo
 +
    DEPENDS ${FOO_BINARY_DIR}/output1.cpp
 +
    )
 +
  # do the same thing for output3.cpp
 +
  ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output3.cpp
 +
    COMMAND echo
 +
    DEPENDS ${FOO_BINARY_DIR}/output1.cpp
 +
    )
 +
  # now create an executable using the input files
 +
  ADD_EXECUTABLE(generated ${FOO_BINARY_DIR}/output1.cpp
 +
                ${FOO_BINARY_DIR}/output3.cpp ${FOO_SOURCE_DIR}/input.txt)
  
 
== Running CMake ==
 
== Running CMake ==

Revision as of 12:17, 9 August 2004

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 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 current release of CMake is 2.0. This release is available at:

http://www.cmake.org/HTML/Download.html

Nightly development can be accessed through CVS.

See http://www.cmake.org/HTML/Download.html for more information.

CMake roadmap and release schedule

CMake 2.0 is out and CMake 2.2 will probably happen in late 2004 or early 2005. Depending on funding and time there may be support for FORTRAN, native Java, and cross-compiling. The bug tracker at www.cmake.org/Bug also has a number of feature requests for CMake. These feature requests typically et rolled into future versions of CMake.

Edit this entry / Log info / Last changed on Wed Jun 9 08:41:44 2004 by Andy

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.

Using CMake

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?

Is there any way to get the "current working directory" in a CMake variable?

You can use the following:

CMAKE_CURRENT_SOURCE_DIR: points to your current source directory 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.

The CACHE and FORCE options on the SET command can be used 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 generate a source file during the build?

The ADD_CUSTOM_COMMAND command can be used to generate a source file that is then included in another target. For example:

 ADD_CUSTOM_COMMAND(
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.c
   COMMAND ${CMAKE_COMMAND}
   ARGS -E 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 it to produce the executable. Whenever bar.c changes foo.c will be regenerated and the executable rebuilt. This even works 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}
   ARGS ${CMAKE_CURRENT_BINARY_DIR}/generated.c
        ${CMAKE_CURRENT_SOURCE_DIR}/some_input.txt
   DEPENDS ${MY_GENERATOR_EXE}
           ${CMAKE_CURRENT_SOURCE_DIR}/some_input.txt
   )
 ADD_EXECUTABLE(generated generated.c)

It is assumed in this example that the my_generator program accepts as its first argument the full path to the source file to generate. The second argument is used as input for the generator. When either the generator source or the sample input changes, the generated.c source will be regenerated.

In both of the above cases, the source file named as the OUTPUT argument of the ADD_CUSTOM_COMMAND command will automatically have the GENERATED source file property set to true. The source may then be referenced without the ${CMAKE_CURRENT_BINARY_DIR} part of the path. Note that use of the "LOCATION" target property requires CMake 2.0 or higher.

In some cases, the program doing the generation may generate more than one file that needs to be part of the build. In this case, some dummy custom commands must be created to "chain" the outputs so that the files are created in the correct order. 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 but only specify one of the outputs
 ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output1.cpp
   COMMAND ${MY_GENERATOR_EXE} 
   ARGS ${FOO_BINARY_DIR} ${FOO_SOURCE_DIR}/input.txt
   DEPENDS ${MY_GENERATOR_EXE} 
   MAIN_DEPENDENCY ${FOO_SOURCE_DIR}/input.txt
   )
 # add the second output and run the dummy command echo but make sure that output1.cpp 
 # is the DEPEND for this command.  Once output1.cpp exists output2.h will also be created.
 ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output2.h
   COMMAND echo
   DEPENDS ${FOO_BINARY_DIR}/output1.cpp
   )
 # do the same thing for output3.cpp
 ADD_CUSTOM_COMMAND(OUTPUT ${FOO_BINARY_DIR}/output3.cpp
   COMMAND echo
   DEPENDS ${FOO_BINARY_DIR}/output1.cpp
   )
 # now create an executable using the input files 
 ADD_EXECUTABLE(generated ${FOO_BINARY_DIR}/output1.cpp 
                ${FOO_BINARY_DIR}/output3.cpp ${FOO_SOURCE_DIR}/input.txt)

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 string. 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

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.

Platform-specific questions

How can I apply resources on Mac OSX 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 shared objects (.so) under Linux.

In Windows, there are two types of library, a static library and an import library (both called .lib). In Windows, building A.dll will also build the import library A.lib (which is not the static library).

Conclusion: There is no need to find a .dll for linking.

Some more details can be found here: http://cphoenix.best.vwh.net/winvunix.html

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 this command can be WIN32 which indicates that the executable (when compiled on windows) is a windows app (using WinMain) not a console app (using main)....

How to use MFC with CMake

To use MFC, the CMAKE_MFC_FLAG variable must be set to 6.

This can be set in a CMakeLists.txt file and will enable MFC in the application. It should be set to 6. 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 6) 
ADD_EXECUTABLE(CMakeSetup WIN32 ${SRCS})

Miscellaneous questions

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 rename library after it is created?

Let say you do are creating library named Foo to the new name Bar. Foo is created with command: ADD_LIBRARY(Foo SHARED ${Foo_sources})

The following will rename the library after it is created (requires CMake 1.8 or later):

 # Set the existing library name:
 SET(LIB_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}Foo${CMAKE_SHARED_LIBRARY_SUFFIX})
 
 # Set new library name:
 SET(NEW_LIB_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}Bar${CMAKE_SHARED_LIBRARY_SUFFIX})
 
 # Copy:
 ADD_CUSTOM_COMMAND(
   TARGET Foo
   POST_BUILD
   COMMAND ${CMAKE_COMMAND}
   ARGS -E copy
     ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/${LIB_NAME}
     ${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/${NEW_LIB_NAME}
   )

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/

Which regular expressions are supported by cmake?

The MATCHES and MATCHALL uses a regular expression, not a wild card. Here are the meanings of the metacharacters in the cmake regular expression:

^ 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.

Why does CMake use full paths, or can I copy my build tree?

CMake uses full paths because:

  1. configured header files may have full paths in them, and moving those files without re-configuring would cause upredicatble behavior.
  2. because cmake supports out of source builds, if custom commands used relative paths to the source tree, the would not work when they are run in the build tree because the current directory would be incorrect.
  3. on Unix systems rpaths are 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:

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. However, cmake is not run every time a build is done. Currently (cmake 1.6.X, and cmake 1.7.x ) do not support fixing a moved binary tree. This feature may be added before 1.8. If that feature were added, it would still require cmake to be re-run by hand each time a build tree is moved.

CMake does not generate a "make distclean" target. Why?

CMake generates many files related to the build system, but since CMakeLists.txt files can run scripts and other arbitrary commands, there is no way it can keep track of 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. There is a "make clean" target that will 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.

Since the source tree is never changed, no distclean target is needed. A fresh build can be achieved by removing the build tree or creating a separate build tree.

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/PREFIX/...". This is useful for package maintainers.

Running "make clean" does not remove custom command outputs. Why?

Since CMake 2.0 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. Please see question 5.6 for more details.