CMake 2.6 Notes: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
No edit summary
(Add explicit preformat markup)
Line 15: Line 15:
Preprocessor definitions may now be added to builds with much finer granularity than in previous versions of CMake.  There is a new property called <code>COMPILE_DEFINITIONS</code> that is defined directories, targets, and source files.  For example, the code
Preprocessor definitions may now be added to builds with much finer granularity than in previous versions of CMake.  There is a new property called <code>COMPILE_DEFINITIONS</code> that is defined directories, targets, and source files.  For example, the code


<pre>
   add_library(mylib src1.c src2.c)
   add_library(mylib src1.c src2.c)
   add_executable(myexe main1.c)
   add_executable(myexe main1.c)
 
 
   set_property(
   set_property(
     DIRECTORY
     DIRECTORY
Line 30: Line 31:
     PROPERTY COMPILE_DEFINITIONS C CV=3
     PROPERTY COMPILE_DEFINITIONS C CV=3
     )
     )
</pre>


will build the source files with these definitions:
will build the source files with these definitions:


<pre>
   src1.c:  -DA -DAV=1 -DB -DBV=2 -DC -DCV=3
   src1.c:  -DA -DAV=1 -DB -DBV=2 -DC -DCV=3
   src2.c:  -DA -DAV=1 -DB -DBV=2
   src2.c:  -DA -DAV=1 -DB -DBV=2
   main2.c:  -DA -DAV=1
   main2.c:  -DA -DAV=1
</pre>


When the <code>add_definitions</code> command is called with flags like "<code>-DX</code>" the definitions are extracted and added to the current directory's <code>COMPILE_DEFINITIONS</code> property.  When a new subdirectory is created with <code>add_subdirectory</code> the current state of the directory-level property is used to initialize the same property in the subdirectory.
When the <code>add_definitions</code> command is called with flags like "<code>-DX</code>" the definitions are extracted and added to the current directory's <code>COMPILE_DEFINITIONS</code> property.  When a new subdirectory is created with <code>add_subdirectory</code> the current state of the directory-level property is used to initialize the same property in the subdirectory.
Line 41: Line 45:
Note in the above example that the <code>set_property</code> command will actually '''set''' the property and replace any existing value.  The command provides the <code>APPEND</code> option to help add more definitions without removing existing ones.  For example, the code
Note in the above example that the <code>set_property</code> command will actually '''set''' the property and replace any existing value.  The command provides the <code>APPEND</code> option to help add more definitions without removing existing ones.  For example, the code


<pre>
   set_property(
   set_property(
     SOURCE src1.c
     SOURCE src1.c
     APPEND PROPERTY COMPILE_DEFINITIONS D DV=4
     APPEND PROPERTY COMPILE_DEFINITIONS D DV=4
     )
     )
</pre>


will add the definitions "<code>-DD -DDV=4</code>" when building <code>src1.c</code>.
will add the definitions "<code>-DD -DDV=4</code>" when building <code>src1.c</code>.
Line 50: Line 56:
Definitions may also be added on a per-configuration basis using the <code>COMPILE_DEFINITIONS_<CONFIG></code> property.  For example, the code
Definitions may also be added on a per-configuration basis using the <code>COMPILE_DEFINITIONS_<CONFIG></code> property.  For example, the code


<pre>
   set_property(
   set_property(
     TARGET mylib
     TARGET mylib
     PROPERTY COMPILE_DEFINITIONS_DEBUG MYLIB_DEBUG_MODE
     PROPERTY COMPILE_DEFINITIONS_DEBUG MYLIB_DEBUG_MODE
     )
     )
</pre>


will build sources in mylib with <code>-DMYLIB_DEBUG_MODE</code> only when compiling in a <code>Debug</code> configuration.
will build sources in mylib with <code>-DMYLIB_DEBUG_MODE</code> only when compiling in a <code>Debug</code> configuration.
Line 63: Line 71:
Consider these libraries:
Consider these libraries:


<pre>
   /path/to/libfoo.a
   /path/to/libfoo.a
   /path/to/libfoo.so
   /path/to/libfoo.so
</pre>


Previously if someone wrote
Previously if someone wrote


<pre>
   target_link_libraries(myexe /path/to/libfoo.a)
   target_link_libraries(myexe /path/to/libfoo.a)
</pre>


CMake would generate this code to link it:
CMake would generate this code to link it:


<pre>
   ... -L/path/to -Wl,-Bstatic -lfoo -Wl,-Bdynamic ...
   ... -L/path/to -Wl,-Bstatic -lfoo -Wl,-Bdynamic ...
</pre>


This worked most of the time, but some platforms (such as OS X) do not  
This worked most of the time, but some platforms (such as OS X) do not  
Line 81: Line 95:
Now CMake will generate this code:
Now CMake will generate this code:


<pre>
   ... /path/to/libfoo.a ...
   ... /path/to/libfoo.a ...
</pre>


This guarantees that the correct library is chosen.  However there are some side-effects that affect compatibility with existing projects (documented in the next two subsections).
This guarantees that the correct library is chosen.  However there are some side-effects that affect compatibility with existing projects (documented in the next two subsections).
Line 89: Line 105:
Projects used to be able to write this (wrong) code and it would work by accident:
Projects used to be able to write this (wrong) code and it would work by accident:


<pre>
   add_executable(myexe myexe.c)
   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so B)
   target_link_libraries(myexe /path/to/libA.so B)
</pre>


where "<code>B</code>" is meant to link "<code>/path/to/libB.so</code>".  This code is incorrect  
where "<code>B</code>" is meant to link "<code>/path/to/libB.so</code>".  This code is incorrect  
Line 98: Line 116:
A.  The correct code would be
A.  The correct code would be


<pre>
   link_directories(/path/to)
   link_directories(/path/to)
   add_executable(myexe myexe.c)
   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so B)
   target_link_libraries(myexe /path/to/libA.so B)
</pre>


or even better
or even better


<pre>
   add_executable(myexe myexe.c)
   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)
   target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)
</pre>


In order to support projects that have this bug, we've added a  
In order to support projects that have this bug, we've added a  
Line 116: Line 138:
System libraries on UNIX-like systems are typically provided in <code>/usr/lib</code> or <code>/lib</code>.  These directories are considered implicit linker search paths because linkers automatically search these locations even without a flag like <code>-L/usr/lib</code>.  Consider the code
System libraries on UNIX-like systems are typically provided in <code>/usr/lib</code> or <code>/lib</code>.  These directories are considered implicit linker search paths because linkers automatically search these locations even without a flag like <code>-L/usr/lib</code>.  Consider the code


<pre>
   find_library(M_LIB m)
   find_library(M_LIB m)
   target_link_libraries(myexe ${M_LIB})
   target_link_libraries(myexe ${M_LIB})
</pre>


Typically the <code>find_library</code> command would find the math library
Typically the <code>find_library</code> command would find the math library


<pre>
   /usr/lib/libm.so
   /usr/lib/libm.so
</pre>


Some platforms provide multiple versions of libraries corresponding to different architectures.  For example, on an IRIX machine one might find the libraries
Some platforms provide multiple versions of libraries corresponding to different architectures.  For example, on an IRIX machine one might find the libraries


<pre>
   /usr/lib/libm.so        (ELF o32)
   /usr/lib/libm.so        (ELF o32)
   /usr/lib32/libm.so      (ELF n32)
   /usr/lib32/libm.so      (ELF n32)
   /usr/lib64/libm.so      (ELF 64)
   /usr/lib64/libm.so      (ELF 64)
</pre>


On a Solaris machine one might find
On a Solaris machine one might find


<pre>
   /usr/lib/libm.so          (sparcv8 architecture)
   /usr/lib/libm.so          (sparcv8 architecture)
   /usr/lib/sparcv9/libm.so  (sparcv9 architecture)
   /usr/lib/sparcv9/libm.so  (sparcv9 architecture)
</pre>


Unfortunately <code>find_library</code> may not know about all the architecture-specific system search paths used by the linker.  In fact when it finds <code>/usr/lib/libm.so</code> it may be finding a library of incorrect architecture.  If the link computation were to produce the line
Unfortunately <code>find_library</code> may not know about all the architecture-specific system search paths used by the linker.  In fact when it finds <code>/usr/lib/libm.so</code> it may be finding a library of incorrect architecture.  If the link computation were to produce the line


<pre>
   ... /usr/lib/libm.so ...
   ... /usr/lib/libm.so ...
</pre>


the linker might complain if <code>/usr/lib/libm.so</code> does not match the architecture it wants.
the linker might complain if <code>/usr/lib/libm.so</code> does not match the architecture it wants.
Line 142: Line 174:
One solution to this problem is for the link computation to recognize that the library is in a system directory and ask the linker to search for the library.  It could produce the link line
One solution to this problem is for the link computation to recognize that the library is in a system directory and ask the linker to search for the library.  It could produce the link line


<pre>
   ... -lm ...
   ... -lm ...
</pre>


and the linker would search through its architecture-specific implicit link directories to find the correct library.  Unfortunately this solution suffers from the original problem of distinguishing between static and shared versions:
and the linker would search through its architecture-specific implicit link directories to find the correct library.  Unfortunately this solution suffers from the original problem of distinguishing between static and shared versions:


<pre>
   /usr/lib/libm.a
   /usr/lib/libm.a
   /usr/lib/libm.so
   /usr/lib/libm.so
</pre>


In order to ask the linker to find the static system library of the correct architecture it must produce the link line
In order to ask the linker to find the static system library of the correct architecture it must produce the link line


<pre>
   ... -Wl,-Bstatic -lm ... -Wl,-Bshared ...
   ... -Wl,-Bstatic -lm ... -Wl,-Bshared ...
</pre>


This solution directly contradicts the original motivation to give the linker paths to libraries instead of <code>-l</code> options: not all platforms have an option like <code>-Bstatic</code>.
This solution directly contradicts the original motivation to give the linker paths to libraries instead of <code>-l</code> options: not all platforms have an option like <code>-Bstatic</code>.
Line 165: Line 203:
Users can override this behavior by using the IMPORTED targets feature:
Users can override this behavior by using the IMPORTED targets feature:


<pre>
   add_library(math STATIC IMPORTED)
   add_library(math STATIC IMPORTED)
   set_property(TARGET math PROPERTY IMPORTED_LOCATION /usr/lib/libm.a)
   set_property(TARGET math PROPERTY IMPORTED_LOCATION /usr/lib/libm.a)
   add_executable(foo foo.c)
   add_executable(foo foo.c)
   target_link_libraries(foo math) # will link using full path
   target_link_libraries(foo math) # will link using full path
</pre>


=CMake Policy Mechanism=
=CMake Policy Mechanism=

Revision as of 18:33, 24 April 2018

This page documents some of the changes and new features available in CMake 2.6.

Exporting and Importing Targets

Please see our tutorial on Exporting and Importing Targets.

Packages

Please see our tutorial on Packaging.

Preprocessor Definitions

Preprocessor definitions may now be added to builds with much finer granularity than in previous versions of CMake. There is a new property called COMPILE_DEFINITIONS that is defined directories, targets, and source files. For example, the code

  add_library(mylib src1.c src2.c)
  add_executable(myexe main1.c)
  
  set_property(
    DIRECTORY
    PROPERTY COMPILE_DEFINITIONS A AV=1
    )
  set_property(
    TARGET mylib
    PROPERTY COMPILE_DEFINITIONS B BV=2
    )
  set_property(
    SOURCE src1.c
    PROPERTY COMPILE_DEFINITIONS C CV=3
    )

will build the source files with these definitions:

  src1.c:   -DA -DAV=1 -DB -DBV=2 -DC -DCV=3
  src2.c:   -DA -DAV=1 -DB -DBV=2
  main2.c:  -DA -DAV=1

When the add_definitions command is called with flags like "-DX" the definitions are extracted and added to the current directory's COMPILE_DEFINITIONS property. When a new subdirectory is created with add_subdirectory the current state of the directory-level property is used to initialize the same property in the subdirectory.

Note in the above example that the set_property command will actually set the property and replace any existing value. The command provides the APPEND option to help add more definitions without removing existing ones. For example, the code

  set_property(
    SOURCE src1.c
    APPEND PROPERTY COMPILE_DEFINITIONS D DV=4
    )

will add the definitions "-DD -DDV=4" when building src1.c.

Definitions may also be added on a per-configuration basis using the COMPILE_DEFINITIONS_<CONFIG> property. For example, the code

  set_property(
    TARGET mylib
    PROPERTY COMPILE_DEFINITIONS_DEBUG MYLIB_DEBUG_MODE
    )

will build sources in mylib with -DMYLIB_DEBUG_MODE only when compiling in a Debug configuration.

Link Line Generation

CMake 2.6 implements a new approach to generating link lines for targets.

Consider these libraries:

   /path/to/libfoo.a
   /path/to/libfoo.so

Previously if someone wrote

   target_link_libraries(myexe /path/to/libfoo.a)

CMake would generate this code to link it:

   ... -L/path/to -Wl,-Bstatic -lfoo -Wl,-Bdynamic ...

This worked most of the time, but some platforms (such as OS X) do not support the -Bstatic or equivalent flag. This made it impossible to link to the static version of a library without creating a symlink in another directory and using that one instead.

Now CMake will generate this code:

   ... /path/to/libfoo.a ...

This guarantees that the correct library is chosen. However there are some side-effects that affect compatibility with existing projects (documented in the next two subsections).

Missing Linker Search Directories

Projects used to be able to write this (wrong) code and it would work by accident:

   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so B)

where "B" is meant to link "/path/to/libB.so". This code is incorrect because it asks CMake to link to B but does not provide the proper linker search path for it. It used to work by accident because the -L/path/to would get added as part of the implementation of linking to A. The correct code would be

   link_directories(/path/to)
   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so B)

or even better

   add_executable(myexe myexe.c)
   target_link_libraries(myexe /path/to/libA.so /path/to/libB.so)

In order to support projects that have this bug, we've added a compatibility feature that adds the "-L/path/to" paths for all libraries linked with full paths even though the linker will not need those paths to find the main libraries. See policy CMP0003 for details.

Linking to System Libraries

System libraries on UNIX-like systems are typically provided in /usr/lib or /lib. These directories are considered implicit linker search paths because linkers automatically search these locations even without a flag like -L/usr/lib. Consider the code

  find_library(M_LIB m)
  target_link_libraries(myexe ${M_LIB})

Typically the find_library command would find the math library

  /usr/lib/libm.so

Some platforms provide multiple versions of libraries corresponding to different architectures. For example, on an IRIX machine one might find the libraries

  /usr/lib/libm.so         (ELF o32)
  /usr/lib32/libm.so       (ELF n32)
  /usr/lib64/libm.so       (ELF 64)

On a Solaris machine one might find

  /usr/lib/libm.so          (sparcv8 architecture)
  /usr/lib/sparcv9/libm.so  (sparcv9 architecture)

Unfortunately find_library may not know about all the architecture-specific system search paths used by the linker. In fact when it finds /usr/lib/libm.so it may be finding a library of incorrect architecture. If the link computation were to produce the line

  ... /usr/lib/libm.so ...

the linker might complain if /usr/lib/libm.so does not match the architecture it wants.

One solution to this problem is for the link computation to recognize that the library is in a system directory and ask the linker to search for the library. It could produce the link line

  ... -lm ...

and the linker would search through its architecture-specific implicit link directories to find the correct library. Unfortunately this solution suffers from the original problem of distinguishing between static and shared versions:

  /usr/lib/libm.a
  /usr/lib/libm.so

In order to ask the linker to find the static system library of the correct architecture it must produce the link line

  ... -Wl,-Bstatic -lm ... -Wl,-Bshared ...

This solution directly contradicts the original motivation to give the linker paths to libraries instead of -l options: not all platforms have an option like -Bstatic. Fortunately the platforms that do not provide such flags also tend to not have architecture-specific implicit link directories.

The solution used by CMake is:

  • Libraries not in implicit system locations are linked by passing the file path to the linker
  • Libraries in implicit system locations are linked by
    • passing the -l option if a flag like -Bstatic is available
    • passing the file path to the linker otherwise

Users can override this behavior by using the IMPORTED targets feature:

  add_library(math STATIC IMPORTED)
  set_property(TARGET math PROPERTY IMPORTED_LOCATION /usr/lib/libm.a)
  add_executable(foo foo.c)
  target_link_libraries(foo math) # will link using full path

CMake Policy Mechanism

CMake 2.6 introduces a new mechanism for backwards compatibility support. See CMake/Policies for more information.



CMake: [Welcome | Site Map]