【发布时间】:2021-12-26 16:34:25
【问题描述】:
总而言之,我有一个对象目标 (a_object),它是链接到共享库 (base) 的 PUBLIC。对象目标编译得很好,但是当我将该对象目标链接到可执行文件 (main) 时,在构建该可执行文件时,base 库中的函数出现未定义符号错误。
更多详情:
项目树
src
+---base
| CMakeLists.txt
| parser_helper.cpp
| parser_helper.hpp
|
\---module
a.cpp
a.hpp
CMakeLists.txt
main.cpp
源文件:
base/parser_helper.hpp
#include <istream>
#include <string>
namespace base {
class line : public std::string {
public:
friend auto operator>>(std::istream& is, line& line) -> std::istream&;
};
} // namespace base
base/parser_helper.hpp
#include "base/parser_helper.hpp"
namespace {
using base::line;
} // namespace
auto base::operator>>(std::istream& is, line& line) -> std::istream& {
return std::getline(is, line);
}
base/CMakeLists.txt
add_library(base SHARED parser_helper.cpp parser_helper.hpp)
target_compile_options(base PRIVATE ...)
target_compile_features(base PRIVATE ...)
target_include_directories(base PRIVATE ...)
module/a.hpp
#include <istream>
namespace longlp {
void f(std::istream& input_stream);
...
} // namespace longlp
module/a.cpp
#include "module/a.hpp"
#include <algorithm>
#include <iterator>
#include "base/parser_helper.hpp"
namespace {
using base::line;
} // namespace
namespace longlp {
void f(std::istream& input_stream) {
std::for_each(std::istream_iterator<line>(input_stream),
std::istream_iterator<line>(),
[](const line& line) {
// ...
});
}
} // namespace longlp
module/main.cpp
#include <sstream>
#include "module/a.hpp"
int main() {
std::stringstream input("123\n123");
longlp::f(input);
return 0;
}
module/CMakeLists.txt
add_library(a_object OBJECT)
target_sources(a_object PRIVATE a.cpp a.hpp)
target_compile_options(a_object PRIVATE ...)
target_compile_features(a_object PRIVATE ...)
target_include_directories(a_object PRIVATE ...)
target_link_libraries(a_object PUBLIC base)
add_executable(main)
target_sources(main PRIVATE main.cpp)
target_compile_options(main PRIVATE ...)
target_compile_features(main PRIVATE ...)
target_include_directories(main PRIVATE ...)
target_link_libraries(main PRIVATE a_object)
构建main时的错误日志
[build] lld-link: error: undefined symbol: class std::basic_istream<char, struct std::char_traits<char>> & __cdecl base::operator>>(class std::basic_istream<char, struct std::char_traits<char>> &, class base::line &)
[build] >>> referenced by C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\iterator:290
[build] >>> src/module/CMakeFiles/a_object.dir/a.cpp.obj:(private: void __cdecl std::istream_iterator<class base::line, char, struct std::char_traits<char>, __int64>::_Getval(void))
单独构建a_object 时没有出错。从Cmake documentation on linking Object target,我认为只需将a_object 链接到main 就足够了,我错过了什么吗?
【问题讨论】:
-
您使用的是哪个编译器/构建系统?如果它是带有默认编译器的 Visual Studio,那么对于类和运算符,您肯定会在
parse_helper.hpp中缺少__dllspec(dllimport)/_dllspec(dllexport)... 但是我怀疑您使用的是 Visual Studio 默认编译工具,因为这会导致 base.lib 没有被创建,因为没有导出的符号......顺便说一句:有没有特定的理由不使用std::istream& operator>>(std::istream& is, line& line);并在这里使用拖尾返回类型?恕我直言,这只会使代码更长更难阅读而没有任何好处。
标签: c++ cmake undefined-reference undefined-symbol