0

I was writing a cmake project file with multiple dependencies, and when it tried to link boost-filesystem, it threw and undefined symbol error. The curious thing is that if the cmake file for boost was run independently of the larger project cmake file, it would link with any c++11 code just fine.

CMake Project file:

...
add_subdirectory(External/boost)
target_link_libraries(${PROJECT_NAME} boost_filesystem)
...
target_compile_options(${PROJECT_NAME} PUBLIC -stdlib=libc++)
target_compile_options(${PROJECT_NAME} PUBLIC -std=c++1y)
...

CMake boost file:

set(SRCS
libs/filesystem/src/codecvt_error_category.cpp
libs/filesystem/src/operations.cpp
libs/filesystem/src/path.cpp
libs/filesystem/src/path_traits.cpp
libs/filesystem/src/portability.cpp
libs/filesystem/src/unique_path.cpp
libs/filesystem/src/utf8_codecvt_facet.cpp
libs/filesystem/src/windows_file_codecvt.cpp
libs/smart_ptr/src/sp_collector.cpp
libs/smart_ptr/src/sp_debug_hooks.cpp
libs/system/src/error_code.cpp
)

include_directories(boost)

add_library(boost_filesystem STATIC ${SRCS})

target_compile_options(boost_filesystem PRIVATE -stdlib=libc++)
target_compile_options(boost_filesystem PRIVATE -std=c++11)

Part of the error in question:

Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find_last_of(char const*, unsigned long, unsigned long) const", referenced from:
  ArgsProcess::process(int, char const**) in ArgsProcess.cpp.o
  (anonymous namespace)::filename_pos(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long) in libboost_filesystem.a(path.cpp.o)
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find_first_of(char const*, unsigned long, unsigned long) const", referenced from:
  • Like I said, the boost compiled independently of the project file could be linked fine with code built against libc++. – ayylmao Dec 13 '15 at 04:35
  • Building one for C++11 and one for C++17 is slightly suspect - and [std::string::find_last_of](http://en.cppreference.com/w/cpp/string/basic_string/find_last_of) changed slightly in C++14. Try building both for either C++11 or C++17? – melak47 Dec 13 '15 at 04:42
  • building both with c++14 still leads to the same error – ayylmao Dec 13 '15 at 04:45

1 Answers1

0

I suspect your problem may be that you are setting compiler flags but not the linker flags. Rather than trying to set the additional compiler/linker flags explicitly yourself, you may get better results by using CMake's support for controlling which C++ version to build with. Try setting the following two variables near the beginning of your top level CMakeLists.txt file:

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

By setting these variables, you set the default for which C++ version all subsequently defined targets will use (unless they explicitly override this choice with target properties). You also explicitly state whether compiler extensions are enabled, which can change which standard C++ library is linked in. The combination of these three variables frees you from having to know the different compiler/linker flags to use on each platform. You may find the following article useful for more information on this CMake feature:

https://crascit.com/2015/03/28/enabling-cxx11-in-cmake/

Craig Scott
  • 9,238
  • 5
  • 56
  • 85