How do you export a system library using cmake?

How can I export the libraries that the cmake library depends on, so that an executable that depends on this library should not depend on the dependencies of this library?

This is a little sip, so here is an example:

dummy (application) ----> depends on liba

liba ----> depends on libpng

Compiling a dummy file generates errors:

-- Found LIBPNG -- Found LIBA -- Configuring done -- Generating done -- Build files have been written to: /home/doug/projects/dummy/build Linking C executable dummy ../deps/liba/build/liba.a(aco): In function `a_dummy': /home/doug/projects/dummy/deps/liba/src/ac:6: undefined reference to `png_sig_cmp' collect2: ld returned 1 exit status make[2]: *** [dummy] Error 1 make[1]: *** [CMakeFiles/dummy.dir/all] Error 2 make: *** [all] Error 2 

I can fix this by adding this to CMakeLists.txt for the dummy:

TARGET_LINK_LIBRARIES (dummy png)

However, the mannequin does not know how liba implements its api. At some point that might change to libjpg, or something else that would break the dummy application.

After getting some help from the cmake mailing list, I was redirected to this example to export things: http://www.cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file

However, after this approach, I was not stuck on this line:

export (TARGETS $ {LIBPNG_LIBRARY} FILE "$ {PROJECT_BINARY_DIR} /ALibraryDepends.cmake")

Clearly, I missed something; this export command looks like it is designed to export subprojects to a high level; i.e. nested projects inside liba.

However, this is not a problem.

When setting up liba (or any cmake library) I will always create a list of dependencies that are not part of this project.

How can I export those to display as part of LIBA_LIBRARY when I use find_package () to solve liba?

Using static libraries is not an option (a static library for something that references opengl? No.)

+6
source share
3 answers

Given your comment on arrowdodgerโ€™s answer about fear, installing something would ruin your system, which I decided to give a conceptual comment in the form of an answer because of its length.

The cmake chain project works through find_package, which searches for * Config.cmake and * -config.cmake files.

Project A CMakeLists.txt:

 #CMakeLists.txt project(A) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/AConfig.cmake share/A/cmake ) #AConfig.cmake message("Yepp, you've found me.") $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install .. $ make install 

Project B CMakeLists.txt:

 project(B) find_package(A) 

Then

 $ mkdir build $ cd build $ cmake -DCMAKE_INSTALL_PREFIX=/tmp/test-install .. $ make install 

leads to

 ... -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done Yepp, you've found me. 

B was found by A because he set AConfig.cmake to the location where cmake finds his "share / A / cmake" And they gave him the same value for CMAKE_INSTALL_PREFIX.

Now here's the thing. Let's think about what you can do in AConfig.cmake: AFAIK is all you want. But the most common task is to pull out information about A objects via include (), do some additional find_package invoctions for third-party package packages (TIP), and create variables

 A_LIBRARIES A_INCLUDE_DIRS 

What you want to include is the file created

 install(EXPORT A-targets DESTINATION share/A/cmake ) 

in A CMakeLists.txt, where the A-target refers to the global cmake variable that accumulates all the information about the target when used in

 install(TARGETS ... EXPORT A-targets ... ) 

statments. What was created with make install

 /tmp/test-install/share/A/cmake/A-targets.cmake 

which is next to AConfig.cmake in the same directory. Please take another look at the wiki page on how to use this file inside AConfig.cmake.

Regarding the export () command: This is convenient if your projects have become HUGE and require a significant amount to install them. To speed up the process, you want to use what is in A build / directory. This optimization is also explained on the wiki. It still works through find_package (), see

But I strongly recommend that you go on the usual make install route for now.

+6
source

I found my own solution to this problem using the above solution, which I leave for others:

In liba / CMakeLists.txt:

 # Self set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} "${PROJECT_SOURCE_DIR}/include") set(A_LIBRARIES ${A_LIBRARIES} "${PROJECT_BINARY_DIR}/liba.a") # Libpng FIND_PACKAGE(libpng REQUIRED) set(A_INCLUDE_DIRS ${A_INCLUDE_DIRS} ${LIBPNG_INCLUDE_DIRS}) set(A_LIBRARIES ${A_LIBRARIES} ${LIBPNG_LIBRARIES}) ADD_LIBRARY(a ${SOURCES}) # Includes INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS}) # Allow other projects to use this configure_file(AConfig.cmake.in "${PROJECT_BINARY_DIR}/AConfig.cmake") 

In liba / AConfig.cmake:

 set(A_LIBRARIES @ A_LIBRARIES@ ) set(A_INCLUDE_DIRS @ A_INCLUDE_DIRS@ ) 

In the dummy /CMakeLists.txt:

 FIND_PACKAGE(A REQUIRED) INCLUDE_DIRECTORIES(${A_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(dummy ${A_LIBRARIES}) 

This gives AConfig.cmake, which reads:

 set(A_LIBRARIES /home/doug/projects/dummy/deps/liba/build/liba.a;/usr/lib/libpng.so) set(A_INCLUDE_DIRS /home/doug/projects/dummy/deps/liba/include;/usr/include) 

And a detailed compiler that states:

 /usr/bin/gcc -std=c99 -g CMakeFiles/dummy.dir/src/main.co -o dummy -rdynamic ../deps/liba/build/liba.a -lpng 

This is exactly what I was looking for.

+2
source

If liba does not provide any dependency detection tools, you cannot do anything. If liba is the library you developed, and you use CMake to create it, then you must install the libaConfig.cmake file from liba itself, which will contain the necessary definitions. Then you include libaConfig in the dummy CMakeLists.txt to get information on how liba was created.

You can see how this is done in the LLVM project, the corresponding files have the cmake.in extension http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/

In the end, in a dummy project you should use

target_link_libraries( ${LIBA_LIBRARIES} )

include_directories( ${LIBA_INCLUDE_DIR} )

link_directories( ${LIBA_LIBRARY_DIR} )

If this liba is used only by a dummy, you can create it from one CMake project. This is more convenient since you do not need to install liba every time you recompile it, and every time you run make it will be automatically re-sorted using a dummy file. If you like this approach, the only thing you need to do is define in the liba 'CMakeLists.txt variables that you need with the PARENT_SCOPE parameter (see the set () command manual).

Finally, you can use shared libraries, so you don't have such a problem.

+1
source

Source: https://habr.com/ru/post/894962/


All Articles