2

I am trying to build a project on Windows using CMake and MinGW.

When using the command mingw32-make.exe I got link errors for any boost library (except for unit_test library), as for example: "undefined reference to `boost::chrono::system_clock::now()'"

My boost installation is under C:\boost\ that contains both include and lib directories. I know that the boost installation is correct because if I use a handmade Makefile and I link the libraries with -l I can compile my project without any issue. So I guess the problem is related to how I link libraries in my CMakeLists.txt.

I tried these solution but they didn't work:

This is the CMakeLists I am using, that correctly finds the libraries, as printed by Boost_DEBUG:

CMAKE_MINIMUM_REQUIRED(VERSION 3.23) 
SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF)

SET(Boost_USE_STATIC_LIBS       ON)
SET(Boost_DETAILED_FAILURE_MSG  OFF)
SET(Boost_USE_MULTITHREADED     ON)
SET(Boost_THREADAPI             win32)
SET(BOOST_ROOT                  "C:\\boost")
SET(Boost_LIBRARY_DIR           "C:\\boost\\lib")
SET(Boost_INCLUDE_DIR           "C:/boost/include/boost-1_76")
SET(Boost_INCLUDE_DIRS          "C:/boost/include/boost-1_76")
SET(Boost_USE_STATIC_RUNTIME    OFF)  
SET(Boost_DEBUG                 ON) 

PROJECT(myproject LANGUAGES CXX)
find_package(Boost 1.76.0 
COMPONENTS 
    log
    system 
    timer
    chrono 
    unit_test_framework 
REQUIRED
)

add_executable(test_cmake test_cmake.cpp)
target_include_directories(test_cmake PRIVATE ${Boost_INCLUDE_DIRS})
target_include_directories(test_cmake PRIVATE ${Boost_LIBRARY_DIR}) 

target_link_libraries(test_cmake
 ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
 ${Boost_LIBRARIES}
)

This is the simple main file that can be compiled and produces "undefined reference to `boost::chrono::system_clock::now()'" error.

#define BOOST_AUTO_TEST_MAIN
#define BOOST_TEST_DYN_LINK
#include <boost/test/included/unit_test.hpp>
#include <turtle/mock.hpp>
// #include <boost/chrono.hpp> // I tried this too but it didn't work as well
#include <boost/chrono/chrono.hpp>
/**
 * @brief Test of boost chrono library
 */
BOOST_AUTO_TEST_CASE(test_boost_chrono) {
  auto start_time = boost::chrono::system_clock::now();

  int sleep_time = 1000;
  // boost::this_thread::sleep_for(boost::chrono::milliseconds(sleep_time));

  auto curr_time = boost::chrono::system_clock::now();

  auto diff_time = boost::chrono::duration_cast<boost::chrono::milliseconds>(curr_time - start_time);

  BOOST_CHECK(diff_time.count() > sleep_time);
  int epsilon = 10;
  BOOST_CHECK(diff_time.count() < (sleep_time + epsilon));
}

I think the problem is related to target_include_directories and target_link_libraries but I cannot understand which is the issue.

Do you have any suggestion?

Edit: This is what I get when compiling with mingw32-make.exe VERBOSE=1:

PS C:\Workspace\test_cmake_project_cmake\build> mingw32-make.exe VERBOSE=1
"C:\Program Files\CMake\bin\cmake.exe" -SC:\Workspace\test_cmake_project_cmake -BC:\Workspace\test_cmake_project_cmake\build --check-build-system CMakeFiles\Makefile.cmake 0
"C:\Program Files\CMake\bin\cmake.exe" -E cmake_progress_start C:\Workspace\test_cmake_project_cmake\build\CMakeFiles C:\Workspace\test_cmake_project_cmake\build\\CMakeFiles\progress.marks
C:/MinGW/bin/mingw32-make  -f CMakeFiles\Makefile2 all
mingw32-make[1]: Entering directory 'C:/Workspace/test_cmake_project_cmake/build'
C:/MinGW/bin/mingw32-make  -f test_cmake\CMakeFiles\test_cmake.dir\build.make test_cmake/CMakeFiles/test_cmake.dir/depend
mingw32-make[2]: Entering directory 'C:/Workspace/test_cmake_project_cmake/build'
"C:\Program Files\CMake\bin\cmake.exe" -E cmake_depends "MinGW Makefiles" C:\Workspace\test_cmake_project_cmake C:\Workspace\test_cmake_project_cmake\test_cmake C:\Workspace\test_cmake_project_cmake\build C:\Workspace\test_cmake_project_cmake\build\test_cmake C:\Workspace\test_cmake_project_cmake\build\test_cmake\CMakeFiles\test_cmake.dir\DependInfo.cmake --color=
Dependencies file "test_cmake/CMakeFiles/test_cmake.dir/test_cmake.cpp.obj.d" is newer than depends file "C:/Workspace/test_cmake_project_cmake/build/test_cmake/CMakeFiles/test_cmake.dir/compiler_depend.internal".
Consolidate compiler generated dependencies of target test_cmake
mingw32-make[2]: Leaving directory 'C:/Workspace/test_cmake_project_cmake/build'
C:/MinGW/bin/mingw32-make  -f test_cmake\CMakeFiles\test_cmake.dir\build.make test_cmake/CMakeFiles/test_cmake.dir/build
mingw32-make[2]: Entering directory 'C:/Workspace/test_cmake_project_cmake/build'
[ 50%] Linking CXX executable test_cmake.exe
cd /d C:\Workspace\test_cmake_project_cmake\build\test_cmake && "C:\Program Files\CMake\bin\cmake.exe" -E cmake_link_script CMakeFiles\test_cmake.dir\link.txt --verbose=1
"C:\Program Files\CMake\bin\cmake.exe" -E rm -f CMakeFiles\test_cmake.dir/objects.a
C:\MinGW\bin\ar.exe qc CMakeFiles\test_cmake.dir/objects.a @CMakeFiles\test_cmake.dir\objects1.rsp
C:\MinGW\bin\g++.exe -g -Wl,--whole-archive CMakeFiles\test_cmake.dir/objects.a -Wl,--no-whole-archive -o test_cmake.exe -Wl,--out-implib,libtest_cmake.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles\test_cmake.dir\linklibs.rsp
CMakeFiles\test_cmake.dir/objects.a(test_cmake.cpp.obj): In function `main':
C:/Workspace/test_cmake_project_cmake/test_cmake/test_cmake.cpp:6: undefined reference to `boost::chrono::system_clock::now()'
C:/Workspace/test_cmake_project_cmake/test_cmake/test_cmake.cpp:11: undefined reference to `boost::chrono::system_clock::now()'
collect2.exe: error: ld returned 1 exit status
mingw32-make[2]: *** [test_cmake\CMakeFiles\test_cmake.dir\build.make:99: test_cmake/test_cmake.exe] Error 1
mingw32-make[2]: Leaving directory 'C:/Workspace/test_cmake_project_cmake/build'
mingw32-make[1]: *** [CMakeFiles\Makefile2:97: test_cmake/CMakeFiles/test_cmake.dir/all] Error 2
mingw32-make[1]: Leaving directory 'C:/Workspace/test_cmake_project_cmake/build'
mingw32-make: *** [Makefile:90: all] Error 2

Edit:

It seems it was an issue of Visual Studio Code: maybe some variables were set with wrong values and CMake could not link boost.

Finally I have created a new project and I have used a minimal CMakeLists without setting any boost variable but BOOST_ROOT (SET(BOOST_ROOT "C:\\boost") and now it works!!

Unfortunately I did not find the real reason :(, but cleaning the project and starting from scretch helped! Thanks everybody!

  • Was the boost libraries at c:\Boost\lib built with MinGW? Remember that msvc ones will not work. The file names of the libs must not contain vc140, vc141 ... – drescherjm Sep 08 '22 at 13:02
  • Yes it is (I followed this guide https://gist.github.com/zrsmithson/0b72e0cb58d0cb946fc48b5c88511da8). The strange thing is that I can compile by command line, including the boost/include folder with -I and linking boost with -L and boost chrono with -l – Roberto Ciardi Sep 08 '22 at 13:10
  • To be a little "clearer" on what I mentioned above, these two commands work: `g++ -I"C:\boost\include\boost-1_76" -std=c++11 -c -o test_cmake\test_cmake.o test_cmake\test_cmake.cpp` `g++ -o test_cmake.exe -L"C:\boost\lib" .\test_cmake\test_cmake.o -lboost_chrono-mgw8-mt-x64-1_76` – Roberto Ciardi Sep 08 '22 at 13:11
  • What is your GCC major version in MinGW? As the boost library names are constructed using it, it has to be the same. Although the libraries may be ABI/API compatible CMake FindBoost expects them being equal. – vre Sep 08 '22 at 15:11
  • Please try configure and build with `set(CMAKE_VERBOSE_MAKEFILE ON)` and show an error output. – 273K Sep 08 '22 at 15:48
  • What is `Boost_LIBRARIES` set to in `CMakeLists.txt`? It should contain the Boost libraries your code depends on. – Brecht Sanders Sep 08 '22 at 18:57
  • @vre This is what I get typing `gcc --version`: `gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0`. But I don't know what to do with this information... – Roberto Ciardi Sep 09 '22 at 09:19
  • @273K: I don't get any error on CMake. – Roberto Ciardi Sep 09 '22 at 09:21
  • @BrechtSanders: printing Boost_LIBRARIES at the end, with `message(${Boost_LIBRARIES})` I get `Boost::chrono` that is exactly what I expected – Roberto Ciardi Sep 09 '22 at 09:21
  • When I build your code (without the line `#include `) I from command line in my environment with `g++ -c -o test_cmake.o test_cmake.cpp && g++ -o test_cmake.exe test_cmake.o -lboost_chrono` it builds fine. Can you build in verbose mode (`make VERBOSE=1` or `ninja -v`) and check there really is a linker flag like `-lboost_chrono`? – Brecht Sanders Sep 09 '22 at 10:03
  • @BrechtSanders as I said a few comments above I can build the project from command line as well. I have edited the question adding the result of `mingw32-make.exe VERBOSE=1`. Thank you for helping me :) – Roberto Ciardi Sep 09 '22 at 11:08
  • Link flags are passed via file `CMakeFiles\test_cmake.dir\link.txt`, can you post the contats of that too? – Brecht Sanders Sep 09 '22 at 11:17
  • @BrechtSanders `"C:\Program Files\CMake\bin\cmake.exe" -E rm -f CMakeFiles\test_cmake.dir/objects.a` `C:\MinGW\bin\ar.exe qc CMakeFiles\test_cmake.dir/objects.a @CMakeFiles\test_cmake.dir\objects1.rsp` `C:\MinGW\bin\g++.exe -g -Wl,--whole-archive CMakeFiles\test_cmake.dir/objects.a -Wl,--no-whole-archive -o test_cmake.exe -Wl,--out-implib,libtest_cmake.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles\test_cmake.dir\linklibs.rsp` – Roberto Ciardi Sep 12 '22 at 06:48
  • I have cleaned the project and rebuilt without setting Boost variables, also without setting boost static libraries, and now it works! I guess my settings were conflicting with VSC settings and I did not notice it because I had added those to solve other problems... – Roberto Ciardi Sep 13 '22 at 07:51

0 Answers0