0

Thank you very much in advance for reading this long post! I am trying to configure a CMake project to work with Boost and Catch2 but boost fails to link from a certain folder. For short version just skip to Problem. I will explain the setup and then the problem.

Setup:

libstdc++.so.6 (libc6,x86-64) => /lib64/libstdc++.so.6
libstdc++.so.6 (libc6) => /lib/libstdc++.so.6
Red Hat Enterprise Linux Server release 7.6 (Maipo)
gcc (GCC) 8.2.1 20180905 (Red Hat 8.2.1-3)

(installed from devtoolset 8, standard on the system is: gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) ) I am currently trying to setup a cmake build system. Unfortunately on the current development machine boost was already installed so my boost resides at

BOOST_INCLUDE_DIR=/opt/boost/boost_1_69_0/boost/ 
BOOST_LIB_DIR=/opt/boost/current/stage/release/lib/

When i looked at /opt/boost/boost_1_69_0/boost/ i can see that the correct version is there #define BOOST_LIB_VERSION "1_69" Also the libraries i know that they are version 1_69 because of their compiled name libboost_math_tr1f-gcc8-mt-x64-1_69.so.1.69.0

Unfortunately the system already had installed boost, so /usr/include/boost/version.hpp contains #define BOOST_LIB_VERSION "1_53"

This is my current tree

├── bin
│   ├── debug
│   │   └── libtest_utility.a
│   └── release
│       └── libtest_utility.a
├── build
│   ├── debug
│   └── release
├── CMakeLists.txt
├── include
│   └── test_utility.h
├── src
│   ├── exmaple.cpp
│   └── test_utility.cpp
└── test
    ├── bin
    │   ├── debug
    │   └── release
    ├── build
    │   ├── debug
    │   └── release
    ├── CMakeLists.txt
    └── src
        ├── main2.cpp
        └── main.cpp

and these are my 2 Cmake files:

cmake_minimum_required(VERSION 3.13)

set (NAME "test_utility")

set (TestUtility_VERSION_MAJOR 0)
set (TestUtility_VERSION_MINOR 1)
set (TestUtility_VERSION_PATCH 0)
set (TestUtility_VERSION_STRING ${TestUtility_VERSION_MAJOR}.${TestUtility_VERSION_MINOR}.${TestUtility_VERSION_PATCH})

project(TestUtility  
        VERSION ${TestUtility_VERSION_STRING}
        DESCRIPTION "Testing the library target utility in Cmake"
        LANGUAGES CXX)

set (DEV_ROOT $ENV{DEV_ROOT})
set (BOOST_INCLUDE_DIR $ENV{BOOST_INCLUDE_DIR})
set (BOOST_LIB_DIR $ENV{BOOST_LIB_DIR})

set (PROJECT_SOURCES "${DEV_ROOT}/${NAME}/src/test_utility.cpp"
                     "${DEV_ROOT}/${NAME}/include/test_utility.h"  )


add_library (${NAME} STATIC ${PROJECT_SOURCES})

target_include_directories (${NAME} PUBLIC  "${DEV_ROOT}/${NAME}/include"
                                    PRIVATE "${BOOST_INCLUDE_DIR}")
target_link_directories (${NAME} PRIVATE ${BOOST_LIB_DIR})
target_link_options(${NAME} PRIVATE "-Wl --verbose")

if(CMAKE_BUILD_TYPE MATCHES DEBUG)
  target_link_libraries(${NAME}  libboost_regex-gcc8-mt-d-x64-1_69.a)
ELSEIF(CMAKE_BUILD_TYPE MATCHES RELEASE)
  target_link_libraries(${NAME}  libboost_regex.a)
ENDIF()

set_target_properties(${NAME} PROPERTIES VERSION ${TestUtility_VERSION_STRING}
                                         CXX_STANDARD 17
                                         CXX_STANDARD_REQUIRED ON
                                         ARCHIVE_OUTPUT_DIRECTORY_DEBUG  "${DEV_ROOT}/${NAME}/bin/debug"
                                         ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${DEV_ROOT}/${NAME}/bin/release")

Test Cmake File:

cmake_minimum_required(VERSION 3.13)

set (NAME "test_utility")
set (TEST_NAME "test_${NAME}")


set (TestUtility_VERSION_MAJOR 0)
set (TestUtility_VERSION_MINOR 1)
set (TestUtility_VERSION_PATCH 0)
set (TestUtility_VERSION_STRING ${TestUtility_VERSION_MAJOR}.${TestUtility_VERSION_MINOR}.${TestUtility_VERSION_PATCH})


project(Test_TestUtility  
        VERSION ${TestUtility_VERSION_STRING}
        DESCRIPTION "Testing the library target utility in Cmake"
        LANGUAGES CXX)


set (DEV_ROOT $ENV{DEV_ROOT})
set (BOOST_INCLUDE_DIR $ENV{BOOST_INCLUDE_DIR})
set (BOOST_LIB_DIR $ENV{BOOST_LIB_DIR})
set (CATCH_INCLUDE_DIR $ENV{CATCH_INCLUDE_DIR})


set (PROJECT_SOURCES "${DEV_ROOT}/${NAME}/test/src/main.cpp"
                     "${DEV_ROOT}/${NAME}/src/test_utility.cpp"
                     "${DEV_ROOT}/${NAME}/include/test_utility.h"  )

add_executable (${TEST_NAME} ${PROJECT_SOURCES})

target_include_directories (${TEST_NAME} PUBLIC  "${DEV_ROOT}/${NAME}/include"
                                    PRIVATE "${BOOST_INCLUDE_DIR}"
                                    PRIVATE "${CATCH_INCLUDE_DIR}") 
target_link_directories (${TEST_NAME} PRIVATE ${BOOST_LIB_DIR})

if(CMAKE_BUILD_TYPE MATCHES DEBUG)
  target_link_libraries(${TEST_NAME}  libboost_regex-gcc8-mt-d-x64-1_69.a)
ELSEIF(CMAKE_BUILD_TYPE MATCHES RELEASE)
  target_link_libraries(${TEST_NAME}  libboost_regex.a)
ENDIF()

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_USE_CXX11_ABI=1")

set_target_properties(${TEST_NAME} PROPERTIES VERSION ${TestUtility_VERSION_STRING}
                                         CXX_STANDARD 17
                                         CXX_STANDARD_REQUIRED ON
                                         RUNTIME_OUTPUT_DIRECTORY_DEBUG  "${DEV_ROOT}/${NAME}/test/bin/debug"
                                         RUNTIME_OUTPUT_DIRECTORY_RELEASE "${DEV_ROOT}/${NAME}/test/bin/release")

add_test(NAME ${TEST_NAME}
         COMMAND ${NAME} )

Problem When i run cmake ../.. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE in the actual build folder everything build perfectly. When i run it in the build folder of the tests i get the following linking error /usr/include/boost/regex/v4/regex_match.hpp:50: undefined reference to boost::re_detail::perl_matcher<__gnu_cxx::__normal_iterator<char const*, std::string>, std::allocator<boost::sub_match<__gnu_cxx::__normal_iterator<char const*, std::string> > >, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::match() .

SO i added the ABI flag and tried again and same problem. I don't understand though how it can link from the source folder but not from the test folder.

This is the code of my test_utility.cpp

void boostTestFunc()
{
  std::string line = "Subject: Re: Lalalala";
  boost::regex pat( "^Subject: (Re: |Aw: )*(.*)" );
  boost::smatch matches;
  if (boost::regex_match(line, matches, pat))
  {
    std::cout << matches[2] << std::endl;
  }
}

Update link output:

 Linking CXX executable ../../bin/release/test_test_utility
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/test_test_utility.dir/link.txt --verbose=1
/opt/rh/devtoolset-8/root/usr/bin/c++  
-D_GLIBCXX_USE_CXX11_ABI=1  -O3 -DNDEBUG   CMakeFiles/test_test_utility.dir/src/main.cpp.o CMakeFiles/test_test_utility.dir/net/nas/uxhome/name/TestCmake/test_utility/src/test_utility.cpp.o  -o ../../bin/release/test_test_utility-0.1.0  -L/opt/boost/current/stage/release/lib -Wl,-rpath,/opt/boost/current/stage/release/lib -Wl,-Bstatic -lboost_regex -Wl,-Bdynamic

Update2 compilation output:

/usr/local/bin/cmake -S/net/nas/uxhome/name/TestCmake/test_utility/test -B/net/nas/uxhome/name/TestCmake/test_utility/test/build/release --check-build-system CMakeFiles/Makefile.cmake 0
/usr/local/bin/cmake -E cmake_progress_start /net/nas/uxhome/name/TestCmake/test_utility/test/build/release/CMakeFiles /net/nas/uxhome/name/TestCmake/test_utility/test/build/release/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/release'
make -f CMakeFiles/test_test_utility.dir/build.make CMakeFiles/test_test_utility.dir/depend
make[2]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/release'
cd /net/nas/uxhome/name/TestCmake/test_utility/test/build/release && /usr/local/bin/cmake -E cmake_depends "Unix Makefiles" /net/nas/uxhome/name/TestCmake/test_utility/test /net/nas/uxhome/name/TestCmake/test_utility/test /net/nas/uxhome/name/TestCmake/test_utility/test/build/release /net/nas/uxhome/name/TestCmake/test_utility/test/build/release /net/nas/uxhome/name/TestCmake/test_utility/test/build/release/CMakeFiles/test_test_utility.dir/DependInfo.cmake --color=
make[2]: Leaving directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/release'
make -f CMakeFiles/test_test_utility.dir/build.make CMakeFiles/test_test_utility.dir/build
make[2]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/release'

Update3: I have complied the test_utility into a lib and now in Cmake i am only calling main and linking with that library but the linking fails, although that library/archive(static) is built and linked succesfully [11:54] Linux [name@machine:/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug]> make VERBOSE=1 /usr/local/bin/cmake -S/net/nas/uxhome/name/TestCmake/test_utility/test -B/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug --check-build-system CMakeFiles/Makefile.cmake 0 /usr/local/bin/cmake -E cmake_progress_start /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/progress.marks

make -f CMakeFiles/Makefile2 all
make[1]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug'
make -f CMakeFiles/test_test_utility.dir/build.make CMakeFiles/test_test_utility.dir/depend
make[2]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug'
cd /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug && /usr/local/bin/cmake -E cmake_depends "Unix Makefiles" /net/nas/uxhome/name/TestCmake/test_utility/test /net/nas/uxhome/name/TestCmake/test_utility/test /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug /net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/test_test_utility.dir/DependInfo.cmake --color=
Dependee "/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/test_test_utility.dir/DependInfo.cmake" is newer than depender "/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/test_test_utility.dir/depend.internal".
Dependee "/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug/CMakeFiles/test_test_utility.dir/depend.internal".
Scanning dependencies of target test_test_utility
make[2]: Leaving directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug'
make -f CMakeFiles/test_test_utility.dir/build.make CMakeFiles/test_test_utility.dir/build
make[2]: Entering directory '/net/nas/uxhome/name/TestCmake/test_utility/test/build/debug'
[ 50%] Building CXX object CMakeFiles/test_test_utility.dir/src/main.cpp.o
/opt/rh/devtoolset-8/root/usr/bin/c++   -I/net/nas/uxhome/name/TestCmake/test_utility/include -I/opt/boost/boost_1_69_0/boost -I/usr/local/include/catch2  -D_GLIBCXX_USE_CXX11_ABI=0  -g   -Wall -Wextra -pedantic -std=gnu++17 -o CMakeFiles/test_test_utility.dir/src/main.cpp.o -c /net/nas/uxhome/name/TestCmake/test_utility/test/src/main.cpp
[100%] Linking CXX executable ../../bin/debug/test_test_utility
eucristian
  • 391
  • 3
  • 17
  • 1
    Can you sow the build command line and the link command line? – Matthieu Brucher Jan 22 '19 at 21:21
  • 2
    @MatthieuBrucher "They that sow the build command, shall reap the coredump" (sorry, hope no offense!) – SergeyA Jan 22 '19 at 21:23
  • None taken, will update the problem with the linking lines of make VERBOSE=1 – eucristian Jan 22 '19 at 21:25
  • Same build folder for debug and release? – Matthieu Brucher Jan 22 '19 at 21:32
  • And the compilation command line? – Matthieu Brucher Jan 22 '19 at 21:33
  • diferent build folders with different options. -cmake ../.. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG. Also the one that is working is the "non-unit test version". The unit test version fails on both release and debug. will update the problem with the compilation output – eucristian Jan 22 '19 at 21:33
  • Good morning StackOverflow, anyone has any ideas regarding the problem above? – eucristian Jan 23 '19 at 09:00
  • There is no compilation output in here. There is make output but this particular run of make did not invoke any compiler. – n. m. could be an AI Jan 23 '19 at 11:34
  • Is your boost compiled with the same compiler and same -std= flag as your other code? – n. m. could be an AI Jan 23 '19 at 11:38
  • I didn't add any because the compilation does not fail, it is only [ 50%] Building CXX object CMakeFiles/test_test_utility.dir/src/main.cpp.o [100%] Linking CXX executable ../../bin/release/test_test_utility and then the linking fails with the message above – eucristian Jan 23 '19 at 11:41
  • Yes to the compiler, not sure about the flags though. i am not sure about the flag (" -std=c++17"). would this make a difference? – eucristian Jan 23 '19 at 11:45
  • I have also built the test_utility into a static library and everything worked out perfectly there, now the only thing that does not link is the test which just calls a function from libtest_utility.a. So the lib links with boost the test doesn't...my life sucks! Probably a small mistake somwhere but i don't see it :((( – eucristian Jan 23 '19 at 11:59
  • You have `-D_GLIBCXX_USE_CXX11_ABI=0` in effect when compiling `main.cpp` It's probably not going to work. Find where it is set and disable it. – n. m. could be an AI Jan 23 '19 at 12:27
  • i was using 1, set it to 0 just for this example. It's 1 usually. with or without it makes no difference. Even if i totally remove the flag it does not matter. – eucristian Jan 23 '19 at 12:37
  • "So the lib links with boost the test doesn't" - **Static libraries are not linked** on creation. Replace *STATIC* with *SHARED* in your `CMakeLists.txt`, and you will got the same linking error as for the test. – Tsyvarev Jan 23 '19 at 13:59
  • I am sorry. i am a bit confused. I had the impression that for Static Libraries the linker links everything at compile/link time. https://stackoverflow.com/questions/2649334/difference-between-static-and-shared-libraries – eucristian Jan 23 '19 at 14:29
  • 1
    It is very difficult to shoot at a moving target. If you have a question about your code, FREEZE THE CODE and ask a question. If you update the question with updated code, explicitly state what you have done. – n. m. could be an AI Jan 23 '19 at 15:09
  • Since your error message mentions `std::string` and not `std::_cxx11::basic_string`, I would expect that your code is compiled with the old ABI. Issue `make clean`, make sure C++11 ABI is being used, and recompile. – n. m. could be an AI Jan 23 '19 at 15:13
  • you are right. Sorry for this. the only thing that i have played with since asking the question is -D_GLIBCXX_USE_CXX11_ABI=0. Everything else still stands. i will also update the questions. Thank you very much – eucristian Jan 23 '19 at 15:14
  • when you are talking about recompile you also mean that i should recompile BOOST, right? – eucristian Jan 23 '19 at 15:17
  • 1
    Check how boost is compiled. Do `nm -C libboost_regex.a | grep string` and also same with the shared lib (use nm -CD). Do you see std::string or std::__cxx11::basic_string names? I would expect you should see cxx11 throughout. – n. m. could be an AI Jan 23 '19 at 15:44
  • Thank you very much, it seems that Boost is compiled with std::string in it, furthermore it seems that also my library has std::string. I am doing now research on how to do this. I was under impression that devtoolset-8 comes with gcc 8.2 and a new libstdc++ – eucristian Jan 23 '19 at 18:01
  • As an aside why don't you simply `find_package()` to depend on Boost in your `CmakeLists.txt` ? Specify the correct version and you don't have the muck about as much with paths and environment variables. See: https://stackoverflow.com/questions/6646405/how-do-you-add-boost-libraries-in-cmakelists-txt You might have to invoke `cmake` a bit differently `cmake -DCMAKE_PREFIX_PATH=/opt/...` – user268396 Jan 23 '19 at 20:15

0 Answers0