CMAKE: Build library and link against it

2020-06-12 02:46发布

问题:

I'm trying to use cmake (on Linux with GNU make and g++) to build a project with two sub-directories: MyLib and MyApp. MyLib contains source for a static library; MyApp needs to link against that library. I'm trying to build on Linux with generated makefiles using the following CMakeLists.txt:

cmake_minimum_required (VERSION 2.6)
project (MyProj)
include_directories (MyLib)
file(GLOB MyLibSrc MyLib/*.cpp)
add_library(MyLibrary STATIC ${MyLibSrc})
file(GLOB MyAppSrc MyApp/*.cpp)
add_executable(MyApplication ${MyAppSrc})
target_link_libraries(MyApplication MyLibrary)

This 'almost' works. It fails at link time because while it generates libMyLibrary.a - it is in the root. When I add:

link_directories(${MyProj_BINARY_DIR})

it makes no difference.

I've got a few (inter-linked) questions:

  1. What's the best way to coerce cmake into building my library and executable into a 'staging directory' — say MyStage — to keep targets separate from source?
  2. How do I convince cmake to link the application against the library?
  3. If I wanted to build a debug and a release version, what's the best way to extend my cmake scripts to do this — making sure that the debug application links against the debug library and the release application against the release library?

I'm a relative newcomer to cmake. I've read what I can find on the web, but find myself struggling to get my library to link with my executable. This sort of a configuration, to my mind, should be quite common. An example from which to crib would be very helpful, but I've not found one.

回答1:

  1. Use "out of the source build". Make a directory used only for build and while in it, call

    cmake <path to the sources, it may be relative>
  2. Either use

    link_directories(${MyProj_BINARY_DIR}/MyLib)

    or make CMakeLists.txt in each subdirectory - that would be better for project larger than very small.

  3. This is a bit tricky, check out CMAKE_BUILD_TYPE in the docs (you can set it and/or "if" by it). You can also set it from command line:

    cmake -DCMAKE_BUILD_TYPE=Debug


回答2:

Well, it is better to read this example and do exactly as suggested.

cmake_minimum_required (VERSION 2.6)
project (MyProj CXX)
add_subdirectory(MyLib)
add_subdirectory(MyApp)

Then for each subdirectory specified, CMakeLists.txt files are created

MyLib\CMakeLists.txt

file(GLOB SRC_FILES *.cpp)
add_library(MyLib ${SRC_FILES})

MyApp\CMakeLists.txt

file(GLOB SRC_FILES *.cpp)
add_executable(MyApp ${SRC_FILES})
target_link_libraries(MyApp MyLib) 


回答3:

I've discovered the 'optimal' solution to (1)... so, thought I should post it here:

SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY MyStage)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY MyStage)

The thing that confused me previously is that static libraries are not considered a LIBRARY by Cmake - they're considered to be ARCHIVEs.



回答4:

Do not add libraries and executables in the root Cmakelists.txt. Add these libraries and executables in Cmakelists.txt of subdirectories.