Search code examples
c++boost-test

Boost.Test linker error by use with precompiled headers (PCH)


I have a linker error when using Boost.Test with precompiled header (PCH) that does not occur without PCH. I use the dynamically linked library as described in Usage variants. How can I fix the error to use Boost.Test also with PCH?

The problem occurs at least with Fedora and boost 1.73 (has only dynamic libraries) and g++ 10/clang 11.

    $ cmake ../ && make
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/.../boost_test_pch/build
    [ 33%] Building CXX object CMakeFiles/boost_utf_pch.dir/test_driver.cpp.o
    [ 66%] Building CXX object CMakeFiles/boost_utf_pch.dir/test.cpp.o
    [100%] Linking CXX executable boost_utf_pch
    [100%] Built target boost_utf_pch

vs.

    $ cmake -DEDA_ENABLE_PCH=TRUE ../ && make
    -- Configuring done
    -- Generating done
    -- Build files have been written to: /home/.../boost_test_pch/build
    [ 25%] Building CXX object CMakeFiles/boost_utf_pch.dir/cmake_pch.hxx.gch
    [ 50%] Building CXX object CMakeFiles/boost_utf_pch.dir/test_driver.cpp.o
    cc1plus: warning: /home/.../boost_test_pch/build/CMakeFiles/boost_utf_pch.dir/cmake_pch.hxx.gch: not used because `BOOST_TEST_DYN_LINK' is defined [-Winvalid-pch]
    [ 75%] Building CXX object CMakeFiles/boost_utf_pch.dir/test.cpp.o
    [100%] Linking CXX executable boost_utf_pch
    /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/10/../../../../lib64/crt1.o: in function `_start':
    (.text+0x24): undefined reference to `main'
    collect2: error: ld returned 1 exit status
    make[2]: *** [CMakeFiles/boost_utf_pch.dir/build.make:138: boost_utf_pch] Error 1
    make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/boost_utf_pch.dir/all] Error 2
    make: *** [Makefile:103: all] Error 2

I can not do anything with the warning message before ...

Here the playground files:

  • CMakeLists.txt:

      project(boost_utf_pch LANGUAGES CXX)
      cmake_minimum_required(VERSION 3.18)
    
      add_executable(${PROJECT_NAME} "")
    
      find_package(Boost 1.73.0 REQUIRED COMPONENTS 
          unit_test_framework)
    
      target_sources(${PROJECT_NAME} PRIVATE
          test_driver.cpp test.cpp)
      target_link_libraries(${PROJECT_NAME} PRIVATE
          Boost::unit_test_framework)
    
      set_source_files_properties(test_driver.cpp
          APPEND PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK")
    
      option(EDA_ENABLE_PCH "Enable PCH" OFF)
      if (EDA_ENABLE_PCH)
          target_precompile_headers(${PROJECT_NAME} PRIVATE pch.hpp)
      endif()
    
  • pch.hpp

      #pragma once
      #include <boost/test/unit_test.hpp>
    
  • test.cpp

      #include <boost/test/unit_test.hpp>
    
      BOOST_AUTO_TEST_SUITE( my_test )
    
      BOOST_AUTO_TEST_CASE( test_case1 )
      {
        BOOST_TEST_WARN( sizeof(int) < 4U );
      }
    
      BOOST_AUTO_TEST_SUITE_END()
    
  • test_driver.cpp

      #define BOOST_TEST_MODULE "Boost.UTF PCH Test Suite"
      #include <boost/test/unit_test.hpp>
    

Solution

  • Alan Birtles got the hint into the right direction. I was not aware of the influence of the compiler switch BOOST_TEST_DYN_LINK for the single file in the context of PCH here. A definition for all files of the project in the style of:

        target_compile_definitions(${PROJECT_NAME} PRIVATE
            "BOOST_TEST_DYN_LINK")  
    

    incomprehensibly does not solve the problem. Only after setting the property SKIP_PRECOMPILE_HEADERS for driver 'main' it compiles and links as expected:

        project(boost_utf_pch LANGUAGES CXX)
        cmake_minimum_required(VERSION 3.18)
    
        add_executable(${PROJECT_NAME} "")
    
        find_package(Boost 1.73.0 REQUIRED COMPONENTS 
            unit_test_framework)
    
        target_sources(${PROJECT_NAME} PRIVATE
            test_driver.cpp test.cpp)
    
        target_link_libraries(${PROJECT_NAME} PRIVATE
            Boost::unit_test_framework)
    
        set_source_files_properties(test_driver.cpp
            APPEND PROPERTIES COMPILE_DEFINITIONS "BOOST_TEST_DYN_LINK")
        set_source_files_properties(test_driver.cpp
            PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
            
        option(EDA_ENABLE_PCH "Enable PCH" ON)
    
        if (EDA_ENABLE_PCH)
            target_precompile_headers(${PROJECT_NAME} PRIVATE pch.hpp)
        endif()