使用自己的库使用cmake进行未定义的引用

时间:2016-02-01 08:46:20

标签: c++ cmake

我有以下目录结构:

-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

helper项目中,会生成两个库:libh_a.alibh_b.alibh_a.a用于构建libh_b.a。文件如下:

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();
}

首先我从cmake ../src helper/build运行cmake ../src(没有错误消息),而proj_c/build的{​​{1}}运行

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()'

问题似乎是h_b.cpp,但libh_b.a之前已经构建而没有错误。

1 个答案:

答案 0 :(得分:5)

第一个问题是找不到您的库。在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

(使用DOC find_library()选项将通用的“图书馆路径”替换为更有帮助的内容。)

find_library()之后添加支票可以克服这种“无声失败”:

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

(对于较大的项目,您将设置一个FindXyz.cmake模块来查找依赖项,您可以通过find_package( Xyz REQUIRED )调用它来避免静默失败。但是这样,以及写入时可用的帮助函数这样一个模块,是一个独立的主题。)

故障本身是由于您使用find_library

时出现问题
find_library(h_a PATHS ../../helper/build/h_a)

你告诉CMake在哪里查看,以及在哪个变量中存储结果,而不是

使用:

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

这将解决-NOTFOUND。 (也适用于h_b。)

然而,由于......

,您仍会收到链接器错误
target_link_libraries(
    proj_c
    h_a
    h_b
)

...链接订单。 proj_c查找func_b(),但未在h_a中找到, h_b中找到它,而func_a()则需要-lh_a -lh_b未找到,因为链接器仅对库列表进行单次传递。

在命令行上指定proj_c时也是如此。

根据依赖关系链切换库(h_b取决于h_a取决于target_link_libraries( proj_c h_b h_a ) ):

[HttpPost]
[ODataRoute("PostUpdate")]
public async Task<string> PostUpdate(HttpRequestMessage eventsToUpdate)
{

 //Do something
}

这将有效。