To be summarized, I have an Object target ( a_object
) which is PUBLIC
linked to a Shared Library ( base
). The Object target is compiled fine, however when I link that Object target to an executable ( main
), I got undefined symbol error from a function in base
library when building that executable.
For more details:
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))
I got no error when building a_object
individually. From Cmake documentation on linking Object target , I think it is enough to just linking the a_object
to main
, am I missing something?
Writing the files straight into the add_library
instead of the target_sources
might work. Also, write a global CMakeLists.txt
file and link everything there.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.