Undefined reference to Boost timer::auto_cpu_timer

2019-08-14 07:06发布

问题:

I have a CMake project which uses the unit_test_framework and filesystem libraries from boost. I'm trying to use boost::timer::auto_cpu_timer and can't get it to link on Ubuntu 12.04. The build on Win32 works fine.

The code in question.

#include <boost/timer/timer.hpp>

long some_function()
{
    boost::timer::auto_cpu_timer t;
    ...rest omitted...
}

I use boost 1.52.0 which was build by hand (complete; versioned; d, mt, mt-d, mt-s, mt-sd, s, sd; static and shared).

I'm using the following configuration in the main CMakeLists.txt (finds boost; works correctly)

set (Boost_USE_STATIC_LIBS ON)
set (Boost_USE_MULTITHREADED ON)
if (MSVC)   
    set (Boost_USE_STATIC_RUNTIME OFF)
else () 
    set (Boost_USE_STATIC_RUNTIME ON)
endif ()

find_package (
    Boost ${BOOST_VERSION_MAJOR}.${BOOST_VERSION_MINOR}.${BOOST_VERSION_MICRO} COMPONENTS           
    system filesystem unit_test_framework chrono timer REQUIRED
)

if (Boost_FOUND)
    include_directories (${Boost_INCLUDE_DIRS})
endif ()

In the subproject for the executable I'm using the following instructions. The Win32 project wouldn't link without chrono. I also tried it with rt and pthread libraries (pthread from the distribution) to no avail.

target_link_libraries (
    <exename> ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ${Boost_CHRONO_LIBRARY} ${Boost_TIMER_LIBRARY}       
    <other company libs>
)

It is the resulting command that gives me the error. I added the -Q -v -Wl,-t part to see what the linker is trying to do. (boost was also compiled with the -std=c++0x flag, otherwise filesystem wouldn't work)

/usr/bin/c++ -Q -v -Wl,-t -Wextra -fPIC -std=c++0x  -Wextra -fPIC -std=c++0x -D_DEBUG \
    <our object files> -o ../bin/<exe name> -rdynamic \
    <some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_system-gcc46-mt-sd-1_52.a \
    <some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_filesystem-gcc46-mt-sd-1_52.a \
    <some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a \
    <some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_timer-gcc46-mt-sd-1_52.a \
    <some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_chrono-gcc46-mt-sd-1_52.a \
    <our other static libs>

The log from the linker.

/usr/bin/ld: mode elf_i386
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crt1.o
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crti.o
/usr/lib/gcc/i686-linux-gnu/4.6/crtbegin.o
/lib/i386-linux-gnu/libpthread.so.0
-lrt (/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/librt.so)
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_system-gcc46-mt-sd-1_52.a)error_code.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_filesystem-gcc46-mt-sd-1_52.a)operations.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_filesystem-gcc46-mt-sd-1_52.a)path.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)framework.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)progress_monitor.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)results_collector.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)results_reporter.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)test_tools.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)unit_test_log.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)unit_test_main.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)unit_test_monitor.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)unit_test_parameters.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)unit_test_suite.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)xml_log_formatter.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)xml_report_formatter.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)compiler_log_formatter.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)debug.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)execution_monitor.o
(<some dir>/libs/boost_1_52_0/stage_x86/lib/libboost_unit_test_framework-gcc46-mt-sd-1_52.a)plain_report_formatter.o
<our object files>
-lstdc++ (/usr/lib/gcc/i686-linux-gnu/4.6/libstdc++.so)
-lm (/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/libm.so)
-lgcc_s (/usr/lib/gcc/i686-linux-gnu/4.6/libgcc_s.so)
/lib/i386-linux-gnu/libc.so.6
(/usr/lib/i386-linux-gnu/libc_nonshared.a)elf-init.oS
(/usr/lib/i386-linux-gnu/libc_nonshared.a)stat64.oS
(/usr/lib/i386-linux-gnu/libc_nonshared.a)lstat64.oS
(/usr/lib/i386-linux-gnu/libc_nonshared.a)stack_chk_fail_local.oS
/lib/i386-linux-gnu/ld-linux.so.2
-lgcc_s (/usr/lib/gcc/i686-linux-gnu/4.6/libgcc_s.so)
/usr/lib/gcc/i686-linux-gnu/4.6/crtend.o
/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/crtn.o

It seems that it is not using anything from the timer library. This is the part I don't understand. Has anybody experienced a similar problem? Am I missing a dependency? The resulting error is simply:

<some file>.cpp:(.text+0x38): undefined reference to `boost::timer::auto_cpu_timer::auto_cpu_timer(short)'
<some file>.cpp:(.text+0x4e8): undefined reference to `boost::timer::auto_cpu_timer::~auto_cpu_timer()'
<some file>.cpp:(.text+0x543): undefined reference to `boost::timer::auto_cpu_timer::~auto_cpu_timer()'

I hope I didn't forget to mention anything. Thanks in advance for any advice.

回答1:

If you're running into problems with undefined references from static libraries, you can try to tell the linker explicitly to include the whole archive, even if it (for some reason) thinks that it's not needed. The relevant compiler option is -Wl,--whole-archive and has to be placed before the static libraries it should affect. More background can be found in this question.