0

I have here a class called engine and im trying to use, but when i include it i get LNK2019 error. Im running Visual Studio 2019 x86_64 compiler. Any ideas what could be wrong? I have constructor and destructor defined in cpp file.

#pragma once

namespace NRD {

    const int SCREEN_WIDTH(1280);
    const int SCREEN_HEIGHT(720);

    class Engine {
    public:
        Engine();
        Engine(const Engine&) = delete;
        Engine& operator=(const Engine&) = delete;
        ~Engine();

        static Engine& Ref() {
            static Engine reference;
            return reference;
        }
    };

    static Engine& Core = Engine::Ref();
}

Here is my cpp file:

#include "nrdengine/engine.h"
#include "nrdengine/service_locator.h"
#include "platform/glfw_window.h"

#include <iostream>

namespace NRD {
    Engine::Engine() {
        std::cout << "Initializing window!" << std::endl;

        ServiceLocator::Provide(new CustomWindow());
    }

    Engine::~Engine() {
        ServiceLocator::GetWindow()->DestroyWindow();
    }
}
[build] main.obj : error LNK2019: unresolved external symbol "public: __cdecl NRD::Engine::Engine(void)" (??0Engine@NRD@@QEAA@XZ) referenced in function "public: static class NRD::Engine & __cdecl NRD::Engine::Ref(void)" (?Ref@Engine@NRD@@SAAEAV12@XZ) [C:\Users\Dawid\Desktop\NRD-Engine\build\nrdengine_cpp_application.vcxproj]
[build] main.obj : error LNK2019: unresolved external symbol "public: __cdecl NRD::Engine::~Engine(void)" (??1Engine@NRD@@QEAA@XZ) referenced in function "void __cdecl `public: static class Engine::Ref & __cdecl NRD::Engine::Ref(void)'::`2'::`dynamic atexit destructor for 'reference''(void)" (??__Freference@?1??Ref@Engine@NRD@@SAAEAV12@XZ@YAXXZ) [C:\Users\Dawid\Desktop\NRD-Engine\build\nrdengine_cpp_application.vcxproj]
[build] C:\Users\Dawid\Desktop\NRD-Engine\build\Debug\nrdengine_cpp_application.exe : fatal error LNK1120: 2 unresolved externals [C:\Users\Dawid\Desktop\NRD-Engine\build\nrdengine_cpp_application.vcxproj]

I have two CMakeList files (one for Engine project, one for App)

APP:

cmake_minimum_required(VERSION 3.5)
project(nrdengine_cpp_application VERSION 0.0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)

add_subdirectory(external/engine)

file(GLOB_RECURSE SOURCE_FILES
    ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
    ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
    
#nrdengine_cpp_application.exe
add_executable(nrdengine_cpp_application ${SOURCE_FILES})

target_link_libraries(nrdengine_cpp_application PUBLIC nrdengine_cpp_engine)
target_include_directories(nrdengine_cpp_application PUBLIC nrdengine_cpp_engine)

ENGINE:

cmake_minimum_required(VERSION 3.5)
project(nrdengine_cpp_engine VERSION 0.0.1 LANGUAGES C CXX)

set(CMAKE_CXX_STANDARD 17)

#add external libs
#find_package(OpenGL REQUIRED)

# install python and Jinja2
set(GLAD_SOURCES_DIR "${PROJECT_SOURCE_DIR}/external/glad")
add_subdirectory("${GLAD_SOURCES_DIR}/cmake" glad_cmake)

add_subdirectory(external/glfw)
add_subdirectory(external/glm)
add_subdirectory(external/assimp)

file(GLOB_RECURSE SOURCE_FILES 
    ${CMAKE_SOURCE_DIR}/src/*.c
    ${CMAKE_SOURCE_DIR}/src/*.cpp)

glad_add_library(glad_gl_core_mx_31 REPRODUCIBLE MX API gl:core=3.1)

add_library(nrdengine_cpp_engine ${SOURCE_FILES})

target_include_directories(nrdengine_cpp_engine
    PUBLIC
        $<INSTALL_INTERFACE:include>
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        glm
    PRIVATE
        glfw
        assimp
)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
        glm
    PRIVATE
        glad_gl_core_mx_31
        glfw
        assimp
)```
kapilarny
  • 13
  • 1
  • 4
  • Can we see your CMakeLists.txt too, please? – Botje Nov 29 '21 at 19:20
  • You show us the declarations for the `Engine` constructor and destructor, but where are they *defined* (implemented)? Do you build with that source file? – Some programmer dude Nov 29 '21 at 19:20
  • Does this answer your question? [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – ListsOfArrays Nov 29 '21 at 19:21
  • @kapilarny that's just the same header file again. Please [edit your question](https://stackoverflow.com/posts/70160138/edit) with your CMakeLists.txt – Botje Nov 29 '21 at 19:29
  • @ListsOfArrays unfortunately no – kapilarny Nov 29 '21 at 19:29
  • No external links please! Such links can go away at any time, making your question kind of worthless. Instead keep questions self-contained, with all information needed in the question itself. Please take some time to read [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). And please learn how to [edit] your questions to improve them. – Some programmer dude Nov 29 '21 at 19:30
  • Where is the cpp file that contains `NRD::Engine::Engine()` located relative to your project root? And does the problem go away if you explicitly rebuild your CMake project? Because [the CMake documentation explicitly warns against using it for source files](https://cmake.org/cmake/help/v3.22/command/file.html?highlight=file#glob-recurse), for reasons you just stumbled into. – Botje Nov 29 '21 at 20:20

1 Answers1

1

I'm kinda guessing since your question is kinda hard to answer since it could be a lot of things. But here is my inference.


It's not recommended to glob your source files like you are doing here.

file(GLOB_RECURSE SOURCE_FILES 
    ${CMAKE_SOURCE_DIR}/src/*.c
    ${CMAKE_SOURCE_DIR}/src/*.cpp)

NOTE: My suggestion requires 3.13 or higher version of CMake.

This causes lots of issues and might be the cause of your problems. Please see this post by one of the CMake maintainers on how to add source files to your project.

https://crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources/

TLDR:

Make a CMakeLists.txt in your src/ directory like so.

target_sources(foobar PRIVATE
   engine.cpp
   engine.h
)

And make sure to call add_subdirectory(src) to process that new CMakeLists.txt

If you are interested in why globbing in build systems in general is bad. I can provide links.