What is the use of cmake namespaces if you can link without them? - cmake

I've been following the docs at https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html#creating-packages to create an installable package.
After adding the namespace to my project at the same place as suggested at that link, I was succesfully able to link using that namespace.
However, simply taking the namespace away with just the library name, I was still able to link against my library.
What is the use of the namespace in cmake if it isn't required? Or have I set up something incorrectly? I really don't want consumers of my library to just be able to type "graphics" - they should have to type the full "myLib::graphics" out.

The use is so that it is possible to use the namespace version. This is useful when a library is used via add_subdirectory/FetchContent, so the usage can be written the same way if it were to be switched to use find_package (which will import targets with the namespace prefix). If you're worried about target name clashes, just prefix your target names like myLib_graphics, and then use the EXPORT_NAME target property to remove the prefix for the export.

Related

Predeclare search location for anticipated find_library()-call

I want to include an external library as a subproject into my own project and link its target(s) statically against my own lib.
The said project somewhere in its CMake calls the following find-functions:
find_library(MBEDTLS_LIBRARY mbedtls)
find_library(MBEDX509_LIBRARY mbedx509)
find_library(MBEDCRYPTO_LIBRARY mbedcrypto)
The subproject expects mbedtls to already be installed somewhere on the system, but it didn't consider the fact that I want to link statically. My approach is to now FetchContent mbedtls and provide the find_library() calls with the prebuilt static libraries.
Now I need a way provide those find_library-calls with the right search directory, of course without modifying its source code. Can I somehow set a prefix path? I know I could probably set CMAKE_PREFIX_PATH but that seems like an ugly hack and it would probably affect other find_library()-calls within the project which also exist. Is there a more "constrained" way?
Can I somehow set a prefix path?
Setting a prefix path won't help find_library to locate the library, because command find_library searches the file at configuration stage, but the library is built only on build stage.
Instead, you may write the target name to the CACHE variable, which is passed to find_library as the first argument:
When find the result variable to be already set, find_library won't search the library file.
In most cases a project uses result of find_library in the call to target_link_libraries, so having the library target in the result variable will fit to the project's expectations.
Example:
FetchContent_Declare(mbedtls ...)
FetchContent_MakeAvailable(mbedtls)
set(MBEDTLS_LIBRARY MbedTLS::mbedtls CACHE INTERNAL "mbedtls library target")
With such setup the following
find_library(MBEDTLS_LIBRARY mbedtls)
will do nothing, since the variable MBEDTLS_LIBRARY is already set.
And if the project will use this variable like
target_link_libraries(<executable> ${MBEDTLS_LIBRARY})
then it effectively gets
target_link_libraries(<executable> MbedTLS::mbedtls)
Name of the target which should be assigned to the variable could sometime be found from the project's documentation, but otherwise you need to look into the project's sources (CMakeLists.txt).
E.g. in case of mbedtls project, the library target mbedtls is created with add_library() call, and MbedTLS::mbedtls is created as ALIAS for it.

Nested library namespace in CMake

When I see CMake libraries with namespaces they are always in the form
Parent::Component.
If I have a sufficiently large library, there may be subsections of that library that have components. I am wondering if it is possible/appropriate to do something like ParentProject::Subgouping::SpecificComponent or for a more real world example Raytracing::Math::Utils.
In short, can I use multiple namespaces in a CMake library name? If it is possible, is it a good idea?
In short, can I use multiple namespaces in a CMake library name?
Yes. A colon (:) is just like any other character in a CMake target name. However, the target_link_libraries command will interpret any argument containing :: in its name as a proper CMake target, rather than as a potential system library. So if you mis-type a target name or it otherwise doesn't exist, you'll get a useful error at configure time, rather than a broken build.
Having multiple instances of :: in the name behaves the same as having just one.
If it is possible, is it a good idea?
It's about as good an idea as nested namespaces are in C++. If it makes sense, do it. The only minor difference is that CMake has no using namespace equivalent, so they're slightly less convenient to type.
In several of my projects, I use a namespace like Project::Tools:: to hold any build-time tools (like custom code generators) that need to be built separately for the sake of cross-compilation (when CMAKE_CROSSCOMPILING_EMULATOR is not an option).

How to prevent the perl compiler from changing the name of dynamic link library

I'm making a perl6 package which contains some c source files that will be compiled into a dynamic link library. I found that the name of the library, such as libperl.so, will be changed into something like "A858A3D6EC5363B3D3F59B1.so" after "zef install". However, the name is used in python code as a module name(libperl). After the change, it is no longer a valid identifier. So, is it possible to prevent the change? If it is, what should I do?
I am not sure if it's possible to do that. Maybe it is.
Inspired by #raiph's link, however, I decided to create a soft link. Now the package works well.

Namespace collision with AFNetworking framework constants

If my static library is using AFNetworking and a client project is also using it, it seems like constants defined in AFNetworking will collide, causing the client project not to be able to build (duplicate symbol error). How are things like this resolved usually? What should framework creator do to avoid that?
Try the approach in this link:
http://blog.sigmapoint.pl/avoiding-dependency-collisions-in-ios-static-library-managed-by-cocoapods/
which he describes as:
Build library with prefixed symbols - in my opinion the best way. We
would like to add a prefix to all of the symbols in final .a file so
that e.g. AFHTTPSessionManager becomes
SIGMAPOINT_AFHTTPSessionManager. Your version of dependency is not
connected to version used by developer and no collisions occurs. The
only disadvantage is bigger output file because when someone uses the
same library the final file will contain the same symbols: once
prefixed and once not prefixed. But the whole build process will work
smooth and without errors. This is the solution we will investigate
further in this article.
This tool may help
https://github.com/cocoapods/cocoapods-packager

Converting static linked library to dynamic linked library under windows

I am in the midst of evaluating the benefits of changing our program from 30+ statically linked libraries to 30+ dynamically linked libraries. We hope by changing to DLL, it will reduce the link time.
One immediate problem is the requirement to add __declspec in front of all the classes to create the lib file for other dlls to link. Is there a way to get around that? Is there a flag in the compiler to force a lib generation so to make all classes inside the DLL available for export? If not, is there any existing script/program that will do that? That will certainly make the switch from statically linked library to a dynamic one a lot easier. If not, what is the rationale behind __declspec? Why not an option to make all dll functions exportable?
Thank you.
Perhaps it's too late, but have you looked into using a DEF file?
There is one another way to solve your problem.
You just need to create one definition file(.def) and export all the methods or class you want to share.
U will also have to set :
Properties->Linker->Input->Module Definition File -> add name of your created .def file.
Now use run time dynamic linking:
In project where you want to call the exported methods use LoadLibrary to get handle of your Dll and call the required method using GetProcAddress.