【问题标题】:C++ linker finds header but cannot find .cpp file (using cmake, gcc)C++ 链接器找到标头但找不到 .cpp 文件(使用 cmake、gcc)
【发布时间】:2021-04-09 10:34:46
【问题描述】:

我正在尝试在项目中包含一个项目。 相关结构如下:

projectA
       /CMakeLists.txt (PA1)
       /src
           /main.cpp
       /req/projectB
                   /CMakeLists.txt (PB1)
                   /src
                       /projb.hpp
                       /projb.cpp
                       /CMakeLists.txt (PB2)

编译后,如果我注释掉 projb.cpp 中的所有内容(并在标头中定义),则链接成功,但由于未定义的引用(对 projb.cpp 中定义的任何函数)而失败。

-(PA1)-

add_subdirectory("req/projectB")

include_directories(${PROJECT_NAME} "req/projectB/src")

add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} INTERFACE projectB)

-(PB1)-

add_subdirectory(src)

-(PB2)-

add_library(projectB projb.hpp projb.cpp)

main.cpp

int main() {
    project_b::doStuff();
    return 1;
}

projb.hpp

namespace project_b {

    void doStuff(); // fails
    
    void doStuff() {} // works if nothing defined in .cpp
    // (only one or the other version is declared not both)

} // end namespace

projb.cpp

namespace project_b {
    
    void doStuff() {} // fails with undefined reference error when called from main

} // end namespace

【问题讨论】:

  • 链接器根本不查看 .cpp 文件。运行make VERBOSE=1查看实际编译命令。
  • 我就是这样运行 make
  • 这在您的帖子中并不明显。如果projb.cpp没有被编译,为什么其中定义的东西是未定义的呢?
  • 当我签入构建文件夹时,projectB 的库就在那里。
  • 但它们不用于构建可执行文件

标签: c++ gcc cmake linker-errors undefined-reference


【解决方案1】:

INTERFACE 之后的库被附加到链接接口,不用于链接。

见:https://cmake.org/cmake/help/latest/command/target_link_libraries.html

所以,我建议将 INTERFACE 更改为 PUBLIC 或 PRIVATE

【讨论】:

  • 试过使用 PUBLIC 和 PRIVATE,还是不行
  • @R.Smyth 为我工作,也许取消注释 projb.cpp?
  • 是的。仍然失败。
  • @R.Smyth 请发布make VERBOSE=1的完整输出。
  • 另外,在构建之前删除CMakeCache.txt 并执行make clean
【解决方案2】:

原来我认为不相关的 projectA 的另一部分实际上非常相关。

因此我只需要添加这一行:

# projAadep is included by main.cpp from projectA
target_link_libraries(projAdep PRIVATE projectB)

在这一行之前:

target_link_libraries(${PROJECT_NAME} PUBLIC projectB)

我的理解是通过使用:

target_link_libraries(${PROJECT_NAME} list of all used libs here)

这是所有必要的。

当我注释掉各种东西以使make VERBOSE=1 的输出只包含最相关的部分时,我发现了这一点,它编译并链接成功。然后这导致我进行更多测试以找出它成功链接的原因,等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多