【发布时间】:2020-12-25 18:04:33
【问题描述】:
我正在波恩大学的一门课程中学习现代 C++。
我在grass.h 文件中声明了一个类,并在相应的grass.cpp 文件中实现了它。同样,在另一个tools.h-tools.cpp 声明-实现对中是一个函数,它接受对上面定义的类对象的引用。最后,main.cpp 文件从第一对初始化一个 Grass 对象,并将其从第二对传递给函数。我能够编译main.cpp 并从这些命令行指令中获得所需的输出:
c++ -std=c++11 -g -c grass.cpp -o grass.o
c++ -std=c++11 -g -c tools.cpp -o tools.o
c++ -std=c++11 -g main.cpp grass.o tools.o -o main
但无法使用 CMake 执行此操作。我不知道命令行指令叫什么(链接和编译?)。
这里是代码示例“grass.h”:
#include <string>
#pragma once
class Grass
{
private:
int green_;
std::string name_;
public:
Grass(int green, std::string name): green_{green}, name_{name} {}
int get_green() const; // getter functions for
const std::string& get_green_name() const; // both private members
};
这些函数只是返回值并在“grass.cpp”中实现。
然后我有一个“tools.h”:
#include <iostream>
#include "grass.h"
#pragma once
void PrintGrass(Grass& grObj);
这个函数只是打印来自 Grass 的 getter 函数的值。
最后,main.cpp 包含:
int main ()
{
Grass grObj{10, "ABC"};
PrintGrass(grObj);
cout << endl;
return 0;
}
CMake 错误发生在 100% Linking CXX executable main.错误在 tools.cpp 中:
undefined reference to `Grass::get_green_name[abi:cxx11]()' 和
undefined reference to `Grass::get_green()'。
这意味着程序无法找到这些函数的定义,对吧? CMake 文件如下所示:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
add_library(grass grass.cpp)
add_library(tools tools.cpp)
add_executable(main main.cpp)
target_link_libraries(main grass tools)
如何使用 CMake 完成这项工作?非常感谢您的帮助。
【问题讨论】:
-
这不是 CMake 错误。它是一个链接器错误,抱怨未定义的引用。这意味着您已经在grass.h 中声明了
get_green()和get_green_name(),但您还没有在grass.cpp 文件中实现它们。 -
我对cmake了解不多,但我猜
target_link_libraries和gcc中的常规-l标志一样脆弱,它会丢弃当时不使用的库。请改用target_link_libraries(main tools grass)。 -
或者只是不使用库,我不确定你为什么选择这条路线。
add_executable(main main.cpp grass.cpp tools.cpp)会起作用。 -
您的工作版本不构建库并与它们链接。除非您真的打算为每个文件构建一个库,否则您只需要
set行和add_executable(main main.cpp grass.cpp tools.cpp)。 -
@Yksisarvinen CMake 能够在已知依赖关系的情况下解决链接排序问题。在此示例中,
tools库依赖于grass库,但未在任何地方指定。解决此问题的正确方法是添加另一行target_link_libraries(tools grass)。 PS。我建议使用target_link_libraries(x PUBLIC y),以便 CMake 知道我们使用的是现代语法。