CMake 2.6 Notes: Difference between revisions
Line 29: | Line 29: | ||
... /path/to/libfoo.a ... | ... /path/to/libfoo.a ... | ||
This guarantees that the correct library is chosen. | This guarantees that the correct library is chosen. However there are some side-effects. | ||
==Missing Linker Search Directories== | |||
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: | |||
add_executable(myexe myexe.c) | add_executable(myexe myexe.c) | ||
Line 65: | Line 66: | ||
in the top of the build tree. | in the top of the build tree. | ||
==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 | |||
find_library(M_LIB m) | |||
target_link_libraries(myexe ${M_LIB}) | |||
Typically the <code>find_library</code> command would find the math library | |||
/usr/lib/libm.so | |||
In CMake 2.4 and lower this value would be assigned directly to <code>M_LIB</code>. Then the link line generation would split off the link directory <code>/usr/lib</code> and the library <code>libm.so</code> and produce the | |||
... -lm ... | |||
Note that the <code>-L/usr/lib</code> option is left out because it is an implicit linker search path. The linker would see <code>-lm</code> and search for the math library. Typically the linker would find /usr/lib/libm.so too. However some platforms provide multiple versions of libraries correesponding 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) | |||
When the linker sees <code>-lm</code> it in fact searches the system path corresponding to the current architecture. Internally it might use <code>-L/usr/lib/sparcv9</code> instead of <code>-L/usr/lib</code>. | |||
In CMake 2.6 the code | |||
target_link_libraries(myexe /usr/lib/libm.so) | |||
would generate the link line | |||
... /usr/lib/libm.so ... | |||
no matter what architecture is getting linked. This might cause the linker to complain if <code>/usr/lib/libm.so</code> does not match the architecture it wants. This is not a problem with the link line computation. CMake is linking <code>myexe</code> to the library to which it was told to link. | |||
The problem is created because <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. The solution is for the command to recognize that when it finds a library in a system search path that it should ask the linker to find the correct version of the library at link time. Consider the original example: | |||
find_library(M_LIB m) | |||
target_link_libraries(myexe ${M_LIB}) | |||
In CMake 2.6 the <code>find_library</code> command will set <code>M_LIB</code> to contain just "<code>libm.so</code>" when it finds <code>/usr/lib/libm.so</code>. The link command will then be | |||
target_link_libraries(myexe libm.so) | |||
which will be converted to the link command line | |||
... -lm ... | |||
and the linker will locate the correct version of the library. If <code>find_library</code> does not find the library in an implicit link directory it will report the full path as usual. The user might also edit the cache to set <code>M_LIB</code> to a full path. In both cases the full path given to target_link_libraries will be preserved on the final link line. |
Revision as of 14:47, 28 January 2008
Exporting and Importing Targets
Linking
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.
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. The compatibility mode is enabled when a
link line contains a non-full-path library (like B
) and either
CMAKE_BACKWARDS_COMPATIBILITY
is set to 2.4 or lower or
CMAKE_LINK_OLD_PATHS
is set to true.
If you are trying to build a project and run into this problem, a quick-fix is to run
cmake -DCMAKE_LINK_OLD_PATHS:BOOL=ON .
in the top of the build tree.
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
In CMake 2.4 and lower this value would be assigned directly to M_LIB
. Then the link line generation would split off the link directory /usr/lib
and the library libm.so
and produce the
... -lm ...
Note that the -L/usr/lib
option is left out because it is an implicit linker search path. The linker would see -lm
and search for the math library. Typically the linker would find /usr/lib/libm.so too. However some platforms provide multiple versions of libraries correesponding 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)
When the linker sees -lm
it in fact searches the system path corresponding to the current architecture. Internally it might use -L/usr/lib/sparcv9
instead of -L/usr/lib
.
In CMake 2.6 the code
target_link_libraries(myexe /usr/lib/libm.so)
would generate the link line
... /usr/lib/libm.so ...
no matter what architecture is getting linked. This might cause the linker to complain if /usr/lib/libm.so
does not match the architecture it wants. This is not a problem with the link line computation. CMake is linking myexe
to the library to which it was told to link.
The problem is created because 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. The solution is for the command to recognize that when it finds a library in a system search path that it should ask the linker to find the correct version of the library at link time. Consider the original example:
find_library(M_LIB m) target_link_libraries(myexe ${M_LIB})
In CMake 2.6 the find_library
command will set M_LIB
to contain just "libm.so
" when it finds /usr/lib/libm.so
. The link command will then be
target_link_libraries(myexe libm.so)
which will be converted to the link command line
... -lm ...
and the linker will locate the correct version of the library. If find_library
does not find the library in an implicit link directory it will report the full path as usual. The user might also edit the cache to set M_LIB
to a full path. In both cases the full path given to target_link_libraries will be preserved on the final link line.