[cmake-developers] portable way for linking (single) libraries statically or dynamically

Christoph Anton Mitterer calestyo at scientia.net
Thu Apr 5 22:30:48 EDT 2012


Hi Brad :)


On 4/3/2012 9:41 PM, Christoph Anton Mitterer wrote:
>CMake does this for several things but as you mentioned there are many
>abstractions, or "feature to flag maps", that are not available.

Yeah,.. and obviously it does not make sense to abstract every tiny 
speciality of any compiler out there, but are there any plans to 
introduce further abstraction for more general and commonly important 
things (as I've already mentioned some of them)?


>This would need to be done in two pieces.  The first piece is the
>language runtime libraries.  CMake uses the compiler front-end to
>invoke the linker so language runtime libraries are implicitly linked.
>Special flags to tell the compiler which runtime library to use would
>need to be mapped for each toolchain.

And you think this is not feasible?
Giving _abstract_ (i.e. compiler/toolchain transparent) control of the 
lower libs sounds at least quite useful to me, not only with respect to 
the question whether one wants to link ld/libc/libstdc++ statically or 
dynamically, but also on WHICH implementation to choose.
I mean you know that several GLIBC replacements are out there, and 
especially for tuning or in the embedded world people will probably be 
grateful if CMake gives them an easy "switch" to search for others and 
tell the tool chain to use them :)

(If you want, I can file a enhancement request bug on this,... just to 
keep it somewhere noted; I mean, if it's considered to be a good idea)


>The second piece is user-specified libraries:
...
>For libraries built in the current project CMake always links using
>the full path to the library file on disk.

Ok but this alone is just helpful to get the "right" library, right? 
And has nothing to do on whether I can selectively specify how it is 
linked?


>Libraries outside the project can be
>brought in in three ways:
>(1) Specify link_directories() and pass to target_link_libraries just
>name the library "x".  CMake will generate a link line with "-lx" (or
>the equivalent to -l for the toolchain in use) and let the linker
>search for the library.  This is discouraged as it is difficult to
>control which library will be found.

So basically link_directories() == deprecated...


>  One may also specify a library
>file name like "libx.a" and CMake will recognize that it looks like
>a static library and generate "-Wl,-Bstatic -lx" (or the equivalent
>for the toolchain) to tell the linker to look for a static library.

Is this a general thing? Or just working when link_directories() was 
used? I mean that depending on the filename, It automatically chooses 
per-library static or dynamic linking.

Nevertheless, if I have to specify the full name, e.g. libXXX.a, then 
I'm already leaving portability, right? Other platform => library XXX 
may have another name, e.g. XXX.dll .
So sounds not like a very portable solution to me, or do I get 
something wrong?


>(2) Use find_library() to locate the full path to a desired library.
>This will report the location in a variable which can be referenced
>in the target_link_libraries call.  If the library is NOT in an
>implicit link directory (like /usr/lib) then CMake will use the full
>path to the library file on the link line to guarantee it is used.

So far I always tried to avoid find_library (for no real special 
reason)... see my other reply on the cmake user list, where I ask for 
how things are done right (e.g. the pkg.config thingy)... so what's 
"THE" way?
Did I get this right, find_library, gives me the full path, e.g. 
/path/to/libXXX.so ... including the platform specific lib and .so, 
while I just specify XXX on the search command


>Unfortunately we currently convert libraries in implicit directories
>(like /usr/lib) to the "-lx" form because some toolchains substitute
>per-architecture alternatives under the hood so "/usr/lib/libx.a"
>actually needs to be "/usr/lib/$arch/libx.a".  However, find_library
>does not know to prefer the latter because it can't parse the binary
>format on every platform to detect libraries of proper architecture.
>Since that was implemented CMake has been enhanced to detect the
>implicit link directories for the toolchain/arch but find_library
>has not been taught to use the results.

So that means, eventually (when?) find_library will give me the full 
path for all libs, and you directly give them to (e.g. gcc) no longer 
using (e.g.) -L /path/to -lXXX, right?

Nevertheless, not sure if I understood find_library correctly (IIRC, 
the documentation didn't tell whether the name parameter was the full 
file name (e.g. libXXX.a) or just the library name (e.g. XXX).
In the former case, it wouldn't be portable, right? In the later case, 
I would have no way to tell whether I want static or dynamic linking.


>(3) Use find_package to locate a package configuration file of a
>CMake-aware project.  It should make its libraries available as
>IMPORTED targets whose library types and full paths are known:
>  http://www.cmake.org/Wiki/CMake/Tutorials#CMake_Packages

You mean this one? 
http://www.cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets

Well the problem with find_package is,... there are obviously not 
FindXXX.cmake files for any lib, e.g. I'm missing popt/pcre.
So I had to use FindPkgConfig... and not sure,.. but I think this 
doesn't export targets, but just some variables with paths and names.

Also, I'm not sure whether I fully understand the ideas here... for me 
a target is something that I build in my project... but I never build 
the external libarary...


>CMake will link imported libraries using the full path to the file
>on disk just as it does for libraries built within the project.

How does it know against which targets it should link the imported 
targets. (even though it seems that I can't use the feature at all with 
popt/etc.)


>A project using approach #2 can tell CMake to link a library using
>the full path even if it is in an implicit link directory by using
>the library through an imported target.  This allows one to force
>use of a specific library file.

Uhm how/why do you mix up approaches 2 and 3 now?


>In all cases it is better to specify the library by full path to
>its file.
So the compiler, at least gcc as far as I can see, doesn't behave 
differently (with respect to the generated code) between full path or 
-lXXX -L/path, right?


>  This is particularly important on platforms where the
>library file name cannot be used to distinguish shared from static
>and the toolchain has no equivalent to -Bstatic/-Bdynamic.

Uhm... no clue on the details how the selection process works there...


>The conclusion is that target_link_libraries can already be used
>to force linking to a specific library as shared or static.

Well I still don't see how I can do this fully portable, i.e. without 
having to make long if(UNIX)/elsif().... structures and appending all 
possible names XXX.dll, XXX.dynlib, libXXX.so, etc. pp. togeter.
Did I miss something?


>  What
>is missing is the specification for base (language runtime) libs.
You mean that find_library understands the architecture specific part 
for implict libs?


Thanks,
Chris.



More information about the cmake-developers mailing list