CMake 2.6 Notes: Difference between revisions

From KitwarePublic
Jump to navigationJump to search
(Remove leading space rectangles from preformatted blocks)
(Replace content with link to new CMake community wiki)
 
Line 1: Line 1:
__TOC__
{{CMake/Template/Moved}}


This page documents some of the changes and new features available in CMake 2.6.
This page has moved [https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/notes/2.6 here].
 
=Exporting and Importing Targets=
 
Please see our tutorial on [[CMake/Tutorials/Exporting_and_Importing_Targets|Exporting and Importing Targets]].
 
=Packages=
 
Please see our tutorial on [[CMake/Tutorials/Packaging|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 <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_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
  )
</pre>
 
will build the source files with these definitions:
 
<pre>
src1.c:  -DA -DAV=1 -DB -DBV=2 -DC -DCV=3
src2.c:  -DA -DAV=1 -DB -DBV=2
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.
 
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(
  SOURCE src1.c
  APPEND PROPERTY COMPILE_DEFINITIONS D DV=4
  )
</pre>
 
will add the definitions "<code>-DD -DDV=4</code>" when building <code>src1.c</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(
  TARGET mylib
  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.
 
=Link Line Generation=
 
CMake 2.6 implements a new approach to generating link lines for targets.
 
Consider these libraries:
 
<pre>
/path/to/libfoo.a
/path/to/libfoo.so
</pre>
 
Previously if someone wrote
 
<pre>
target_link_libraries(myexe /path/to/libfoo.a)
</pre>
 
CMake would generate this code to link it:
 
<pre>
... -L/path/to -Wl,-Bstatic -lfoo -Wl,-Bdynamic ...
</pre>
 
This worked most of the time, but some platforms (such as OS X) do not
support the <code>-Bstatic</code> 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:
 
<pre>
... /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).
 
==Missing Linker Search Directories==
 
Projects used to be able to write this (wrong) code and it would work by accident:
 
<pre>
add_executable(myexe myexe.c)
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
because it asks CMake to link to <code>B</code> but does not provide the proper
linker search path for it.  It used to work by accident because the
<code>-L/path/to</code> would get added as part of the implementation of linking to
A.  The correct code would be
 
<pre>
link_directories(/path/to)
add_executable(myexe myexe.c)
target_link_libraries(myexe /path/to/libA.so B)
</pre>
 
or even better
 
<pre>
add_executable(myexe myexe.c)
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
compatibility feature that adds the "<code>-L/path/to</code>" 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 <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)
target_link_libraries(myexe ${M_LIB})
</pre>
 
Typically the <code>find_library</code> command would find the math library
 
<pre>
/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
 
<pre>
/usr/lib/libm.so        (ELF o32)
/usr/lib32/libm.so      (ELF n32)
/usr/lib64/libm.so      (ELF 64)
</pre>
 
On a Solaris machine one might find
 
<pre>
/usr/lib/libm.so          (sparcv8 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
 
<pre>
... /usr/lib/libm.so ...
</pre>
 
the linker might complain if <code>/usr/lib/libm.so</code> 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
 
<pre>
... -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:
 
<pre>
/usr/lib/libm.a
/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
 
<pre>
... -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>.
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 <code>-l</code> option if a flag like <code>-Bstatic</code> is available
** passing the file path to the linker otherwise
 
Users can override this behavior by using the IMPORTED targets feature:
 
<pre>
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
</pre>
 
=CMake Policy Mechanism=
 
CMake 2.6 introduces a new mechanism for backwards compatibility support.  See [[CMake/Policies]] for more information.
 
{{CMake/Template/Footer}}

Latest revision as of 15:41, 30 April 2018


The CMake community Wiki has moved to the Kitware GitLab Instance.

This page has moved here.