CMake, cppunitの実行で「clang: error: linker command failed with exit code 1」のリンクエラー

# 環境

- Mac OS 10.12.6
- clang Apple LLVM version 9.0.0 (clang-900.0.39.2)
- cmake version 3.12.4

# 症状

cppunitをbrewでインストールして使用したところ以下のようなエラーが発生した。

```bash
$ 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
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)
```

これでリンクエラーは解消した。

# 結論

コンパイラ、リンカエラーはちゃんと読まないと、えらい時間を取られる。