3.11.4.2. Simple error¶
Examples on GitHub
Here is an example of trivial “undefined reference” error with diagnostic and, of course, fix instructions.
Library boo
:
# boo/CMakeLists.txt
add_library(boo Boo.hpp Boo.cpp)
// boo/Boo.hpp
#ifndef BOO_HPP_
#define BOO_HPP_
class Boo {
public:
int boo(int, int);
};
#endif // BOO_HPP_
// boo/Boo.cpp
#include "boo/Boo.hpp"
int Boo::boo(int, int) {
return 0x42;
}
Library foo
use library boo
but since we are trying to trigger an error
the target_link_libraries
directive is intentionally missing:
# foo/CMakeLists.txt
add_library(foo Foo.cpp Foo.hpp)
// foo/Foo.hpp
#ifndef FOO_HPP_
#define FOO_HPP_
class Foo {
public:
int foo(int, char);
};
#endif // FOO_HPP_
// foo/Foo.cpp
#include "foo/Foo.hpp"
#include "boo/Boo.hpp"
int Foo::foo(int, char) {
Boo boo;
return boo.boo(14, 15);
}
Final baz
executable:
# Top-level CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(baz)
include_directories(${CMAKE_CURRENT_LIST_DIR}) # for '#include <boo/Boo.hpp>'
add_subdirectory(boo)
add_subdirectory(foo)
add_executable(baz main.cpp)
target_link_libraries(baz foo)
#include "foo/Foo.hpp"
int main() {
Foo foo;
return foo.foo(144, 'x');
}
Generate project:
[library-examples]> rm -rf _builds
[library-examples]> cmake -Hlink-error -B_builds
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /.../library-examples/_builds
First let’s build library boo
:
[library-examples]> cmake --build _builds --target boo
-- Configuring done
-- Generating done
-- Build files have been written to: /.../library-examples/_builds
Scanning dependencies of target boo
[ 50%] Building CXX object boo/CMakeFiles/boo.dir/Boo.cpp.o
[100%] Linking CXX static library libboo.a
[100%] Built target boo
An attempt to build executable baz
will fail with link error:
> cmake --build _builds --target baz
Scanning dependencies of target foo
[ 25%] Building CXX object foo/CMakeFiles/foo.dir/Foo.cpp.o
[ 50%] Linking CXX static library libfoo.a
[ 50%] Built target foo
Scanning dependencies of target baz
[ 75%] Building CXX object CMakeFiles/baz.dir/main.cpp.o
[100%] Linking CXX executable baz
foo/libfoo.a(Foo.cpp.o): In function `Foo::foo(int, char)':
Foo.cpp:(.text+0x35): undefined reference to `Boo::boo(int, int)'
collect2: error: ld returned 1 exit status
CMakeFiles/baz.dir/build.make:95: recipe for target 'baz' failed
make[3]: *** [baz] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/baz.dir/all' failed
make[2]: *** [CMakeFiles/baz.dir/all] Error 2
CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/baz.dir/rule' failed
make[1]: *** [CMakeFiles/baz.dir/rule] Error 2
Makefile:118: recipe for target 'baz' failed
make: *** [baz] Error 2
Use nm
tool to verify that symbol is indeed undefined:
> nm --undefined-only --demangle _builds/foo/libfoo.a
Foo.cpp.o:
U __stack_chk_fail
U Boo::boo(int, int)
Library boo
has it:
> nm --defined-only --demangle _builds/boo/libboo.a
Boo.cpp.o:
0000000000000000 T Boo::boo(int, int)
So library foo
depends on library boo
, every time we are linking
foo
we have to link boo
too. This can be expressed by
target_link_libraries
command. Fix:
--- /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/library-examples/link-error/foo/CMakeLists.txt
+++ /home/docs/checkouts/readthedocs.org/user_builds/cgold/checkouts/latest/docs/examples/library-examples/link-error-fix/foo/CMakeLists.txt
@@ -1,3 +1,4 @@
# foo/CMakeLists.txt
add_library(foo Foo.cpp Foo.hpp)
+target_link_libraries(foo PUBLIC boo)
Should work now:
[library-examples]> rm -rf _builds
[library-examples]> cmake -Hlink-error-fix -B_builds
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /.../library-examples/_builds
[library-examples]> cmake --build _builds
Scanning dependencies of target boo
[ 16%] Building CXX object boo/CMakeFiles/boo.dir/Boo.cpp.o
[ 33%] Linking CXX static library libboo.a
[ 33%] Built target boo
Scanning dependencies of target foo
[ 50%] Building CXX object foo/CMakeFiles/foo.dir/Foo.cpp.o
[ 66%] Linking CXX static library libfoo.a
[ 66%] Built target foo
Scanning dependencies of target baz
[ 83%] Building CXX object CMakeFiles/baz.dir/main.cpp.o
[100%] Linking CXX executable baz
[100%] Built target baz