環境
- Mac OS 10.12.6
- clang Apple LLVM version 9.0.0 (clang-900.0.39.2)
- cmake version 3.12.4
症状
cppunitをbrewでインストールして使用したところ以下のようなエラーが発生した。
$ cmake ..
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/dynamonda/workspace/cpp/cppunit/build
$ make
[ 25%] Linking CXX executable counter_test
Undefined symbols for architecture x86_64:
"CppUnit::SourceLine::SourceLine(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)", referenced from:
CounterTest::test_init() in CounterTest.cpp.o
CounterTest::test_incr() in CounterTest.cpp.o
CounterTest::test_clear() in CounterTest.cpp.o
"CppUnit::SourceLine::~SourceLine()", referenced from:
CounterTest::test_init() in CounterTest.cpp.o
CounterTest::test_incr() in CounterTest.cpp.o
CounterTest::test_clear() in CounterTest.cpp.o
"CppUnit::TestResult::addListener(CppUnit::TestListener*)", referenced from:
_main in Main.cpp.o
"CppUnit::TestResult::TestResult(CppUnit::SynchronizedObject::SynchronizationObject*)", referenced from:
_main in Main.cpp.o
"CppUnit::TestResult::~TestResult()", referenced from:
_main in Main.cpp.o
"CppUnit::TestRunner::run(CppUnit::TestResult&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in Main.cpp.o
"CppUnit::TestRunner::addTest(CppUnit::Test*)", referenced from:
_main in Main.cpp.o
"CppUnit::TestRunner::TestRunner()", referenced from:
_main in Main.cpp.o
"CppUnit::TestRunner::~TestRunner()", referenced from:
_main in Main.cpp.o
"CppUnit::AdditionalMessage::AdditionalMessage(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
void CppUnit::assertEquals<int>(int const&, int const&, CppUnit::SourceLine, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in CounterTest.cpp.o
"CppUnit::CompilerOutputter::write()", referenced from:
_main in Main.cpp.o
"CppUnit::CompilerOutputter::CompilerOutputter(CppUnit::TestResultCollector*, std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in Main.cpp.o
"CppUnit::CompilerOutputter::~CompilerOutputter()", referenced from:
_main in Main.cpp.o
"CppUnit::TestFactoryRegistry::getRegistry(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
_main in Main.cpp.o
CppUnit::AutoRegisterSuite<CounterTest>::AutoRegisterSuite() in CounterTest.cpp.o
"CppUnit::TestFactoryRegistry::registerFactory(CppUnit::TestFactory*)", referenced from:
CppUnit::AutoRegisterSuite<CounterTest>::AutoRegisterSuite() in CounterTest.cpp.o
"CppUnit::TestFactoryRegistry::unregisterFactory(CppUnit::TestFactory*)", referenced from:
CppUnit::AutoRegisterSuite<CounterTest>::~AutoRegisterSuite() in CounterTest.cpp.o
"CppUnit::TestFactoryRegistry::isValid()", referenced from:
CppUnit::AutoRegisterSuite<CounterTest>::~AutoRegisterSuite() in CounterTest.cpp.o
"CppUnit::TestResultCollector::TestResultCollector(CppUnit::SynchronizedObject::SynchronizationObject*)", referenced from:
_main in Main.cpp.o
"CppUnit::TestResultCollector::~TestResultCollector()", referenced from:
_main in Main.cpp.o
"CppUnit::BriefTestProgressListener::BriefTestProgressListener()", referenced from:
_main in Main.cpp.o
"CppUnit::BriefTestProgressListener::~BriefTestProgressListener()", referenced from:
_main in Main.cpp.o
"CppUnit::TestSuiteBuilderContextBase::addTest(CppUnit::Test*)", referenced from:
CounterTest::addTestsToSuite(CppUnit::TestSuiteBuilderContextBase&) in CounterTest.cpp.o
"CppUnit::TestSuiteBuilderContextBase::TestSuiteBuilderContextBase(CppUnit::TestSuite&, CppUnit::TestNamer const&, CppUnit::TestFixtureFactory&)", referenced from:
CounterTest::suite() in CounterTest.cpp.o
"CppUnit::TestSuiteBuilderContextBase::~TestSuiteBuilderContextBase()", referenced from:
CounterTest::suite() in CounterTest.cpp.o
"CppUnit::TestSuiteBuilderContextBase::~TestSuiteBuilderContextBase()", referenced from:
CppUnit::TestSuiteBuilderContext<CounterTest>::~TestSuiteBuilderContext() in CounterTest.cpp.o
"CppUnit::Message::~Message()", referenced from:
CppUnit::AdditionalMessage::~AdditionalMessage() in CounterTest.cpp.o
"CppUnit::Asserter::failNotEqual(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, CppUnit::SourceLine const&, CppUnit::AdditionalMessage const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
void CppUnit::assertEquals<int>(int const&, int const&, CppUnit::SourceLine, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) in CounterTest.cpp.o
"CppUnit::TestCase::run(CppUnit::TestResult*)", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::TestCase::TestCase(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)", referenced from:
CppUnit::TestCaller<CounterTest>::TestCaller(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void (CounterTest::*)(), CounterTest*) in CounterTest.cpp.o
"CppUnit::TestCase::~TestCase()", referenced from:
CppUnit::TestCaller<CounterTest>::TestCaller(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, void (CounterTest::*)(), CounterTest*) in CounterTest.cpp.o
CppUnit::TestCaller<CounterTest>::~TestCaller() in CounterTest.cpp.o
"CppUnit::TestNamer::TestNamer(std::type_info const&)", referenced from:
CounterTest::getTestNamer__() in CounterTest.cpp.o
"CppUnit::TestNamer::~TestNamer()", referenced from:
CounterTest::getTestNamer__() in CounterTest.cpp.o
"CppUnit::TestSuite::TestSuite(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)", referenced from:
CounterTest::suite() in CounterTest.cpp.o
"CppUnit::TestSuccessListener::wasSuccessful() const", referenced from:
_main in Main.cpp.o
"CppUnit::TestSuiteBuilderContextBase::getTestNameFor(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
CounterTest::addTestsToSuite(CppUnit::TestSuiteBuilderContextBase&) in CounterTest.cpp.o
"CppUnit::TestSuiteBuilderContextBase::makeTestFixture() const", referenced from:
CppUnit::TestSuiteBuilderContext<CounterTest>::makeFixture() const in CounterTest.cpp.o
"CppUnit::Test::findTestPath(CppUnit::Test const*, CppUnit::TestPath&) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::Test::findTestPath(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, CppUnit::TestPath&) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::Test::getChildTestAt(int) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::Test::resolveTestPath(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::Test::checkIsValidIndex(int) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::Test::findTest(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::TestCase::getName() const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::TestLeaf::countTestCases() const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::TestLeaf::doGetChildTestAt(int) const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"CppUnit::TestLeaf::getChildTestCount() const", referenced from:
vtable for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"typeinfo for CppUnit::TestSuiteBuilderContextBase", referenced from:
typeinfo for CppUnit::TestSuiteBuilderContext<CounterTest> in CounterTest.cpp.o
"typeinfo for CppUnit::TestCase", referenced from:
typeinfo for CppUnit::TestCaller<CounterTest> in CounterTest.cpp.o
"vtable for CppUnit::TestSuiteBuilderContextBase", referenced from:
CppUnit::TestSuiteBuilderContextBase::TestSuiteBuilderContextBase(CppUnit::TestSuiteBuilderContextBase const&) in CounterTest.cpp.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [counter_test] Error 1
make[1]: *** [CMakeFiles/counter_test.dir/all] Error 2
make: *** [all] Error 2
リンクエラーでCppUnitが読み取れてないっぽい…?
解決
CMakeLists.txt
にライブラリ追加の一文が抜けていただけだった。
cmake_minimum_required(VERSION 3.8)
enable_language(CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(counter_test
Main.cpp
Counter.cpp
Counter.h
CounterTest.cpp
)
# これ
target_link_libraries(counter_test cppunit)
これでリンクエラーは解消した。
結論
コンパイラ、リンカエラーはちゃんと読まないと、えらい時間を取られる。