quant
quant

Reputation: 23102

Can I make a library from multiple targets?

I'm trying to learn cmake and have started converting an old make project over to cmake. Here is a simplified version of the directory structure I now have:

CMakeLists.txt
  src/
    CMakeLists.txt
    main.cpp
    core/
      CMakeLists.txt
      /sourcecode, other cmakes, etc.
  test/
    CMakeLists.txt
    someTest.cpp

Currently, in my root CMakeLists.txt file I simply have this:

cmake_minimum_required(VERSION 2.8)
project(all)
add_subdirectory(src)
add_subdirectory(test)

What I wanted to do, was have a library created by core/CMakeLists.txt that can be used by both src/CMakeLists.txt to build the main executable, but also loaded by test/CMakeLists to build the unit tests.

So my src/core/CMakeLists.txt file currently looks sort of like this:

cmake_minimum_required(VERSION 2.8)                                             

project(core)                                                                   

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wpedantic -Wreorder -DBOOST_TEST_DYN_LINK -DBOOST_LOG_DYN_LINK ")

#some other directories in my core code:                                                          
add_subdirectory(display)                                                       
add_subdirectory(training)                                                      
add_subdirectory(utility)                                                       

#some packages I use...  
find_package(Boost 1.55.0                                                       
    COMPONENTS                                                                  
    log                                                                         
    program_options                                                             
    serialization                                                               
    thread                                                                      
    system                                                                      
    filesystem                                                                  
    REQUIRED)                                                                   

find_package(GLUT REQUIRED)                                                     
find_package(OpenGL REQUIRED)                                                   
find_package(Eigen3 REQUIRED)

include_directories(                                                            
    ${PROJECT_SOURCE_DIR}                                                       
    ${EIGEN3_INCLUDE_DIR})                                                      

target_link_libraries(core                                                                                                                           
    display                                                                     
    training                                                                    
    utility                                                                     
    ${Boost_LIBRARIES}                                                          
    ${OPENGL_LIBRARIES}                                                         
    ${GLUT_LIBRARY}                                                             
    ${OpenMP_LIBRARIES})                                                        

So the idea is that I now have a core target I can simply link against to run my tests, and everything should work. However, when I try to build main, for example, I get:

Cannot specify link libraries for target "core" which is not built by this
  project.

I thought this might be because core doesn't have a add_library command, but if I add add_library(core) I get this error:

You have called ADD_LIBRARY for library core without any source files. This typically indicates a problem with your CMakeLists.txt file

But I don't want to add any source files; I just want this target to link the targets in the core directory and produce a target I can link against from test.

Clearly I'm missing some core knowledge here, either with cmake or the toolchain itself. Help is appreciated :)

Upvotes: 1

Views: 640

Answers (1)

fenix688
fenix688

Reputation: 2615

If you only want to create a core target without source files, you need to declare it like an INTERFACE target. So, try to add the following code to your src/core/CMakeLists.txt:

cmake_minimum_required(VERSION 3.0) # REQUIRED 3.x.x version                                             

project(core)                                                                   

...

# Here declare your core_interface target
add_library(core_interface INTERFACE)                                                   

target_link_libraries(core_interface INTERFACE                                                                                                                           
    display                                                                     
    training                                                                    
    utility                                                                     
    ${Boost_LIBRARIES}                                                          
    ${OPENGL_LIBRARIES}                                                         
    ${GLUT_LIBRARY}                                                             
    ${OpenMP_LIBRARIES})  

As you can see, if you make this, you'll need to upgrade your CMake installed version.

Then, you'll build your tests or any executable, linking with this interface target directly:

add_executable(main main.cpp)
target_link_libraries(main core_interface)         

Upvotes: 2

Related Questions