4

I have the folllowing directory structure:

-project -helper -build -include -h_a.h -h_b.h -src -h_a -h_a.cpp -CMakeLists.txt -h_b -h_b.cpp -CMakeLists.txt -CMakeLists.txt -proj_c -build -src -main.cpp -CMakeLists.txt 

In the helper project two libraries are generated: libh_a.a and libh_b.a. libh_a.a is used to build libh_b.a. The files are the following:

helper/src/CMakeLists.txt:

cmake_minimum_required(VERSION 2.6) project(helper) set(CMAKE_CXX_FLAGS "-Wall -g -std=c++11") add_subdirectory(h_a) add_subdirectory(h_b) 

helper/src/h_a/CMakeLists.txt:

project(h_a) add_library(h_a h_a.cpp) 

helper/src/h_a/h_a.cpp

void func_a(){} 

helper/src/h_b/CMakeLists.txt:

project(h_b) add_library(h_b h_b.cpp) target_link_libraries( h_b STATIC h_a ) 

helper/src/h_b/h_b.cpp:

#include "../../include/h_a.h" void func_b(){ func_a(); } 

proj_c/src/CMakeLists.txt:

cmake_minimum_required(VERSION 3.2) project(proj_c) find_library(h_a PATHS ../../helper/build/h_a) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../helper/build/h_a) find_library(h_b PATHS ../../helper/build/h_b) link_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../helper/build/h_b) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "../bin/") add_executable(proj_c main.cpp) target_link_libraries( proj_c h_a h_b ) 

proj_c/src/main.cpp:

#include "../../helper/include/h_b.h" int main(){ func_b(); } 

First I run cmake ../src from helper/build (no error messsages) than cmake ../src from proj_c/build and I got

proj_c/src/../../helper/build/h_b/libh_b.a(h_b.cpp.o): In function `func_b()': helper/src/h_b/h_b.cpp:4: undefined reference to `func_a()' 

It seems that the problem is with h_b.cpp, but libh_b.a was built previously without errors.

1
  • Unrelated generic CMake suggestion: set( CMAKE_CXX_STANDARD 11 ) to set C++11 platform-independently. Set CMAKE_BUILD_TYPE to Debug (instead of adding -g to CMAKE_CXX_FLAGS) to get debug information compiled in platform-independently. Check for CMAKE_COMPILER_IS_GNUCC before setting -Wall. Commented Feb 1, 2016 at 9:02

1 Answer 1

5

The first problem is that your libraries aren't found. In proj_c/build/CMakeCache.txt:

//Path to a library. h_a:FILEPATH=h_a-NOTFOUND //Path to a library. h_b:FILEPATH=h_b-NOTFOUND 

(Use the DOC option to find_library() to get the generic "Path to a library" replaced with something more helpful.)

This kind of "silent failure" can be overcome by adding a check after find_library():

if ( NOT h_a ) message( FATAL_ERROR "Library h_a not found in ${CMAKE_CURRENT_SOURCE_DIR}/../../helper/build/h_a" ) endif() 

(For larger projects you will have a FindXyz.cmake module set up for finding dependencies, which you can call via find_package( Xyz REQUIRED ) to avoid silent failure. But that, and the helper functions available to you when writing such a module, are a subject all of its own.)

The failure itself is due to a problem with your use of find_library:

find_library(h_a PATHS ../../helper/build/h_a) 

You tell CMake where to look, and in which variable to store the result, but not what to look for.

Use:

find_library(h_a NAMES h_a PATHS ../../helper/build/h_a) 

This will resolve the -NOTFOUND. (Apply for h_b as well.)

You will still get the linker error though, because of...

target_link_libraries( proj_c h_a h_b ) 

...linking order. proj_c looks for func_b(), does not find it in h_a, does find it in h_b, which in turn requires func_a(), which isn't found because the linker is making a single pass over the library list only.

It's the same with specifyling -lh_a -lh_b on the command line.

Switch the libraries around according to the dependency chain (proj_c depends on h_b depends on h_a):

target_link_libraries( proj_c h_b h_a ) 

That will work.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.