Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake unit testing - Unresolved external symbol

Tags:

c++

cmake

I am rather new to C++ and CMake. I'm trying to make a library, and I'm getting the errors when I try to run my unit tests. From my research I've already gathered what the "Unresolved external symbol" errors mean, but I'm unable to figure out how to fix it.

Here's my project structure:

lib
  glfw - GLFW source folder
src
  ogl-renderer.cpp
  ogl-renderer.h
  CMakeLists.txt
  ...additional source files
test
  ogl-test.cpp
  ogl-test.h
  CMakeLists.txt
CMakeLists.txt

CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

project("ogl-renderer")

set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)

add_subdirectory ("lib/glfw-3.3.2")

add_subdirectory ("src")
add_subdirectory ("test")

enable_testing()

add_test (ogl-renderer olg-test)

src/CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)

add_library (ogl-renderer "engine/renderer.cpp" "engine/renderer.h" "engine/renderer.cpp" "engine/renderer.h" "engine/Window.cpp" "engine/Window.h" "engine/Shape.cpp" "engine/Shape.h" "engine/message-queue.cpp" "engine/message-queue.h" "engine/messages/window-mgmt.h" "engine/messages/window-mgmt.cpp")

target_link_libraries(ogl-renderer glfw)

test/CMakeLists.txt:

add_executable (ogl-test "ogl-test.cpp" "ogl-test.h")

target_link_libraries(ogl-test ogl-renderer)

test/ogl-test.cpp:

#include "../src/ogl-renderer.h"

void testWindow() {
    NglRenderer::startRenderer();

    int windowId = NglRenderer::createWindow("Test", 640, 480);
}

int main() {
    testWindow();
}

Errors:

Error   LNK2019 unresolved external symbol "void __cdecl NglRenderer::startRenderer(void)" (?startRenderer@NglRenderer@@YAXXZ) referenced in function "void __cdecl testWindow(void)" (?testWindow@@YAXXZ)  C:\Users\chansen\source\repos\ogl-renderer\out\build\x64-Debug\ogl-renderer C:\Users\chansen\source\repos\ogl-renderer\out\build\x64-Debug\ogl-test.cpp.obj 1

Error   LNK2019 unresolved external symbol "int __cdecl NglRenderer::createWindow(char *,int,int)" (?createWindow@NglRenderer@@YAHPEADHH@Z) referenced in function "void __cdecl testWindow(void)" (?testWindow@@YAXXZ) C:\Users\chansen\source\repos\ogl-renderer\out\build\x64-Debug\ogl-renderer C:\Users\chansen\source\repos\ogl-renderer\out\build\x64-Debug\ogl-test.cpp.obj 1

I am able to fix it by always including the .h and .cpp files in every location, but I want to figure this out the right way. I understand that I need to compile the source project into a library, then link that to the test executable, but I can't figure out how to do it correctly. I'm not even entirely certain how correct my CMakeList.txt files even are. I either guessed or copied on all these configurations.

like image 730
chrispytoes Avatar asked Nov 16 '22 08:11

chrispytoes


1 Answers

Each CMakeLists.txt file defines a project to be compiled. And each project must contain all of its files, dependencies and build options.

So "test/CMakeLists.txt" must contain all relevant test source files. And "src/CMakeLists.txt" must contain all relevant src source files. This is why adding the .h and .cpp files fixed the error.

After each project is configured, linked libraries are defined with target_link_libraries().

For example in src the line target_link_libraries(ogl-renderer glfw) will link to glfw. And in test the line target_link_libraries(ogl-test ogl-renderer) will link to your src executable.

As long as the target_link_libraries() commands make sense, linking will be automated.

Some threads with more information:

  • What does enable_testing() do in cmake?
  • How to start working with GTest and CMake
like image 100
rmrrm Avatar answered Dec 14 '22 22:12

rmrrm