Reputation: 3726
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.
Upvotes: 4
Views: 576
Reputation: 70213
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.
Upvotes: 5