The project presents a static library with tests. I add the fftw3 library to it as a submodule, but Microsoft Visual Studio 2017 cannot find this library.
Project Structure:
└───fftw3
└───googletest
└───output_64
└───src
└───tests
└───CMakeLists.txt
└───tests.cpp
└───CMakeLists.txt
└───FFT_lib.cpp
└───FFT_lib.h
└───.gitignore
└───.gitmodules
└───CMakeLists.txt
└───config_folder_and_run_cmake.bat
config_folder_and_run_cmake.bat
git submodule init
git submodule update
"c:\Program Files\CMake\bin\cmake.exe" ^
-H. ^
-Boutput_64 ^
-G"Visual Studio 15 2017 Win64" ^
%*
pause
CMakeLists.txt
cmake_minimum_required(VERSION 3.9.3)
#set the project name
project(FFT)
#set the directories into which libraries and executable files will be collected
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
if(MSVC)
add_compile_options(
$<$<CONFIG:>:/MT>
$<$<CONFIG:Debug>:/MTd>
$<$<CONFIG:Release>:/MT>
)
endif()
set(CMAKE_CXX_STANDARD 14)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(SRC_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/src)
add_subdirectory(src)
add_subdirectory(googletest)
add_subdirectory(fftw3)
.gitmodules
[submodule "googletest"]
path = googletest
url = https://github.com/google/googletest
[submodule "fftw3"]
path = fftw3
url = https://github.com/FFTW/fftw3
src\CMakeLists.txt
set(SOURCES
FFT_lib.h
FFT_lib.cpp
)
add_library(FFT_lib ${SOURCES})
target_include_directories(FFT_lib PUBLIC ${SRC_ROOT_DIR})
source_group(TREE ${CMAKE_CURRENT_LIST_DIR} FILES ${SOURCES})
#in solution, this library is located in the FFT_lib folder
set_property(TARGET FFT_lib PROPERTY FOLDER "FFT_lib")
add_subdirectory(tests)
src\tests\CMakeLists.txt
set(SOURCES
tests.cpp
)
add_executable(FFT_test ${SOURCES})
# 1. Test library
# 2. gest
# 3. fftw3
target_link_libraries(FFT_test PUBLIC FFT_lib)
target_link_libraries(FFT_test PUBLIC gtest_main)
target_link_libraries(FFT_test PUBLIC fftw3)
set_property(TARGET FFT_test PROPERTY FOLDER "tests/FFT_test")
src\tests\tests.cpp
#include <gtest/gtest.h>
#include "FFT_lib.h"
#include <fftw3.h> //cannot open source file
#include <complex>
#include <vector>
TEST(simple_test, test)
{
using namespace std;
vector<complex<double> > data(64, 1.);
fftw_plan plan = fftw_plan_dft_1d(data.size(), (fftw_complex*)&data[0], (fftw_complex*)&data[0], FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(plan);
fftw_destroy_plan(plan);
EXPECT_TRUE(true);
}
int main(int argc, char* argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Linker errors:
1>------ Build started: Project: fftw3, Configuration: Debug x64 ------
2>------ Build started: Project: FFT_test (tests\FFT_test\FFT_test), Configuration: Debug x64 ------
2>tests.cpp
2>C:\Work\...\Task-2.2\src\tests\tests.cpp(5): fatal error C1083: Cannot open include file: 'fftw3.h': No such file or directory
2>Done building project "FFT_test.vcxproj" -- FAILED.
1> Creating library C:/Work/.../Task-2.2/output_64/fftw3/Debug/fftw3.lib and object C:/Work/.../Task-2.2/output_64/fftw3/Debug/fftw3.exp
1>conf.c.obj : error LNK2001: unresolved external symbol fftw_solvtab_dft_standard
1>conf.c.obj : error LNK2001: unresolved external symbol fftw_solvtab_rdft_r2cf
1>conf.c.obj : error LNK2001: unresolved external symbol fftw_solvtab_rdft_r2cb
1>conf.c.obj : error LNK2001: unresolved external symbol fftw_solvtab_rdft_r2r
1>C:\Work\...\Task-2.2\output_64\bin\Debug\fftw3.dll : fatal error LNK1120: 4 unresolved externals
1>Done building project "fftw3.vcxproj" -- FAILED.
========== Build: 0 succeeded, 2 failed, 8 up-to-date, 0 skipped ==========
conf.c.obj is inside the fftw3 library.
In your top-level CMake file, you dive into the src directory first, before adding the googletest and fftw3 sub-directories. So, when you reference the gtest_main and fftw3 targets in your src\tests\CMakeLists.txt file, they are undefined:
target_link_libraries(FFT_test PUBLIC FFT_lib)
# The targets linked here are not yet defined.
target_link_libraries(FFT_test PUBLIC gtest_main)
target_link_libraries(FFT_test PUBLIC fftw3)
You should re-order your top-level CMake file such that CMake can find the dependencies first, then add the src sub-directory:
add_subdirectory(googletest)
add_subdirectory(fftw3)
add_subdirectory(src)
You will also likely need to add the include directory for the fftw3 headers (path containing fftw3.h), with something like this:
add_executable(FFT_test ${SOURCES})
target_include_directories(FFT_test PRIVATE /path/to/fftw3-headers)
Related
I am trying to link a static library which I have compiled from the assimp source to my executable CMake project so that it does not have to compile assimp as often since it's such a large library.
I compiled it using CMake with the following commands:
git clone https://github.com/assimp/assimp/
cd assimp
mkdir build
cd build
cmake -DBUILD_SHARED_LIBS=OFF ../CMakeLists.txt
cmake --build .
My project structure looks like this:
.
OpenGL
├── OpenGL
│ ├── res
│ ├── src
│ | └── (my .cpp and .h files)
│ └── CMakeLists.txt
├── libraries
│ └── glfw, glew, imgui...
└── CMakeLists.txt
I now copy assimp/include and assimp/build/bin/Debug/config.h to OpenGL/libraries/assimp/include,
then assimp/build/lib/Debug to OpenGL/libraries/assimp/lib
My CMakeLists.txt(s) look like this:
cmake_minimum_required(VERSION 3.8)
project(OpenGL LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_FIND_DEBUG_MODE)
if (NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.1")
endif()
if (CMAKE_BUILD_TYPE STREQUAL Debug)
add_definitions(-DDEBUG) # preprocessor macro
else()
if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup") # if running on release mode remove the cmd prompt on windows
endif()
endif()
add_subdirectory(OpenGL)
add_subdirectory(libraries/glfw)
add_subdirectory(libraries/glew)
add_subdirectory(libraries/nativefiledialog)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/libraries/glfw/include
${CMAKE_CURRENT_SOURCE_DIR}/libraries/glew/include
OpenGL/src
libraries
libraries/stb
libraries/assimp/include
libraries/nativefiledialog/src/include
)
and
cmake_minimum_required(VERSION 3.8)
file(GLOB_RECURSE OpenGL_sources *.cpp ../libraries/imgui/*.cpp ../libraries/stb/*.cpp)
add_executable(${PROJECT_NAME} ${OpenGL_sources} "src/engine/input/Key.cpp" "src/engine/input/Buttons.h" "src/engine/input/Button.h" "src/engine/input/Button.cpp" "src/engine/input/MouseButton.h" "src/engine/input/MouseButton.cpp" "src/engine/rendering/objects/Model.h" "src/engine/rendering/objects/Model.cpp")
target_link_libraries(${PROJECT_NAME} PUBLIC
glfw
libglew_static
${CMAKE_SOURCE_DIR}/libraries/assimp/lib/assimp-vc143-mtd.lib
nativefiledialog
)
or
cmake_minimum_required(VERSION 3.8)
add_library( assimp STATIC IMPORTED )
set_property( TARGET assimp PROPERTY IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libraries/assimp/lib/assimp-vc143-mtd.lib)
file(GLOB_RECURSE OpenGL_sources *.cpp ../libraries/imgui/*.cpp ../libraries/stb/*.cpp)
add_executable(${PROJECT_NAME} ${OpenGL_sources} "src/engine/input/Key.cpp" "src/engine/input/Buttons.h" "src/engine/input/Button.h" "src/engine/input/Button.cpp" "src/engine/input/MouseButton.h" "src/engine/input/MouseButton.cpp" "src/engine/rendering/objects/Model.h" "src/engine/rendering/objects/Model.cpp")
target_link_libraries(${PROJECT_NAME} PUBLIC
glfw
libglew_static
assimp
nativefiledialog
)
(Both configurations give the same error)
Running cmake .. from OpenGL/build successfully completes which I think means that CMake was able to find the assimp library.
Now when I run cmake --build . I am greeted with the following error.
assimp-vc143-mtd.lib(AssbinLoader.obj) : error LNK2019: unresolved external symbol uncompress referenced in function "public: virtual void __cdecl Assimp::AssbinImporter::InternReadFile(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,struct aiScene *,class Assimp::IOSystem *)" (?InternReadFile#AssbinImporter#Assimp##UEAAXAEBV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##PEAUaiScene##PEAVIOSystem#2##Z) [F:\dev\cpp\OpenGL\build\OpenGL\OpenGL.vcxproj]
assimp-vc143-mtd.lib(Compression.obj) : error LNK2019: unresolved external symbol inflate referenced in function "public: unsigned __int64 __cdecl Assimp::Compression::decompress(void const *,unsigned __int64,class std::vector<char,class std::allocator<char> > &)" (?decompress#Compression#Assimp##QEAA_KPEBX_KAEAV?$vector#DV?$allocator#D#std###std###Z) [F:\dev\cpp\OpenGL\build\OpenGL\OpenGL.vcxproj]
etc...
I believe this means that the function bodies were not found which should be compiled within the .lib.
How do I successfully link the library?
These functions (uncompress and inflate) belong to the ZLIB library. Although assimp CMake links ZLIB in order to use it - which is enough to build assimp by itself, you have to link ZLIB directly to your executable as well in order to use it in your executable context.
I'm trying to build a simple C++ program in Visual Studio 2017. I had no issues while doing it on Linux but for some reason it doesn't work on Windows.
Here is the program:
// CMakeProject1.cpp : Defines the entry point for the application.
//
#include "CMakeProject1.h"
#include "fmt/core.h"
#include "fmt/xchar.h"
#include "spdlog/sinks/win_eventlog_sink.h"
#include "spdlog/sinks/msvc_sink.h"
#include "spdlog/sinks/wincolor_sink.h"
#include "spdlog/spdlog.h"
#include <exception>
#include <vector>
int main()
{
std::vector<spdlog::sink_ptr> sinks;
sinks.push_back(std::make_shared<spdlog::sinks::win_eventlog_sink_mt>("me"));
sinks.push_back(std::make_shared<spdlog::sinks::msvc_sink_mt>());
sinks.push_back(std::make_shared<spdlog::sinks::wincolor_stdout_sink_mt>());
auto logger = std::make_shared<spdlog::logger>("main-logger", begin(sinks), end(sinks));
SPDLOG_LOGGER_CALL(logger, spdlog::level::info, L"{}", L"Hello World!");
return 0;
}
Here is my CMakeLists.txt
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required(VERSION 3.20)
get_filename_component(Project ${CMAKE_CURRENT_SOURCE_DIR} NAME)
string(REPLACE " " "-" Project ${Project})
project(${Project} CXX C)
set(CMAKE_VERBOSE_MAKEFILE ON)
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 8.0.1
)
FetchContent_MakeAvailable(fmt)
if (NOT fmt_POPULATED)
FetchContent_Populate(fmt)
add_subdirectory(${fmt_SOURCE_DIR} ${fmt_BINARY_DIR})
endif()
message(STATUS "fmt_SOURCE_DIR = ${fmt_SOURCE_DIR}")
message(STATUS "fmt_BINARY_DIR = ${fmt_BINARY_DIR}")
FetchContent_Declare(
spdlog
GIT_REPOSITORY https://github.com/gabime/spdlog.git
GIT_TAG v1.9.2
)
FetchContent_MakeAvailable(spdlog)
if (NOT spdlog_POPULATED)
FetchContent_Populate(spdlog)
set(SPDLOG_BUILD_EXAMPLES OFF)
set(SPDLOG_BUILD_BENCH OFF)
set(SPDLOG_BUILD_TESTS OFF)
add_subdirectory(${spdlog_SOURCE_DIR} ${spdlog_BINARY_DIR})
endif()
message(STATUS "spdlog_SOURCE_DIR = ${spdlog_SOURCE_DIR}")
message(STATUS "spdlog_BINARY_DIR = ${spdlog_BINARY_DIR}")
set(SourceDir ${CMAKE_CURRENT_SOURCE_DIR})
set(ExecutableSources ${SourceDir}/main.cpp)
set(LinkLibraries fmt::fmt spdlog::spdlog)
set(Executable ${Project})
message(STATUS CMAKE_VERSION = ${CMAKE_VERSION})
message(STATUS LinkLibraries = ${LinkLibraries})
add_executable(${Executable} ${ExecutableSources})
add_definitions(-DSPDLOG_WCHAR_TO_UTF8_SUPPORT)
target_compile_options(${Executable} PUBLIC ${CompilationFlags})
target_link_libraries(${Executable} PUBLIC ${LinkLibraries})
The way I generate a build files is the same way I do it on Linux
mkdir build
cd build
cmake ..
I then open the solution in Visual Studio 2017 and build it. However I'm getting the following errors:
4>main.cpp
4>main.obj : error LNK2019: unresolved external symbol "void __cdecl spdlog::details::os::wstr_to_utf8buf(class fmt::v8::basic_string_view<wchar_t>,class fmt::v8::basic_memory_buffer<char,250,class std::allocator<char> > &)" (?wstr_to_utf8buf#os#details#spdlog##YAXV?$basic_string_view#_W#v8#fmt##AAV?$basic_memory_buffer#D$0PK#V?$allocator#D#std###56##Z) referenced in function "protected: void __thiscall spdlog::logger::log_<wchar_t const (&)[13]>(struct spdlog::source_loc,enum spdlog::level::level_enum,class fmt::v8::basic_string_view<wchar_t>,wchar_t const (&)[13])" (??$log_#AAY0N#$$CB_W#logger#spdlog##IAEXUsource_loc#1#W4level_enum#level#1#V?$basic_string_view#_W#v8#fmt##AAY0N#$$CB_W#Z)
4>main.obj : error LNK2019: unresolved external symbol "void __cdecl spdlog::details::os::utf8_to_wstrbuf(class fmt::v8::basic_string_view<char>,class fmt::v8::basic_memory_buffer<wchar_t,250,class std::allocator<wchar_t> > &)" (?utf8_to_wstrbuf#os#details#spdlog##YAXV?$basic_string_view#D#v8#fmt##AAV?$basic_memory_buffer#_W$0PK#V?$allocator#_W#std###56##Z) referenced in function "protected: virtual void __thiscall spdlog::sinks::win_eventlog::win_eventlog_sink<class std::mutex>::sink_it_(struct spdlog::details::log_msg const &)" (?sink_it_#?$win_eventlog_sink#Vmutex#std###win_eventlog#sinks#spdlog##MAEXABUlog_msg#details#4##Z)
4>C:\Users\user\source\repos\CMakeProject1\build\Debug\CMakeProject1.exe : fatal error LNK1120: 2 unresolved externals
4>Done building project "CMakeProject1.vcxproj" -- FAILED.
========== Rebuild All: 3 succeeded, 1 failed, 0 skipped ==========
It looks like Visual Studio 2017 is not linking against the libraries. Does anyone know how to fix it?
Expanding on #fabian's comment, you should
set(SPDLOG_WCHAR_TO_UTF8_SUPPORT ON)
before the add_subdirectory call to have CMake set that preprocessor symbol for you.
So I followed a tutorial Introduction to Google Test and CMake, which was working fine. But when I move the project folder to another directory, the project breaks and gives me this error:
FAILED: test/ExampleTests.exe
.
.
.
[build] LINK : warning LNK4098: defaultlib 'LIBCMTD' conflicts with use of other libs; use
/NODEFAULTLIB:library
[build] test\ExampleTests.exe : fatal error LNK1169: one or more multiply defined symbols found
[build] ninja: build stopped: subcommand failed.
[build] Build finished with exit code 1
There's more to that but I don't want to bombard you with the stuff in between.
I moved the folder from Desktop\Example to Desktop\HelloWorld\Example.I tried deleting the build folder that it created and hitting F7 again but it kept giving me the error.
Folder structure
build\
googletest\
test\
|CMakeLists.txt
| ExampleTests.cpp
CMakeLists.txt
Example.cpp
Example.hpp
CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
set(This Example)
project(${This} C CXX)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
enable_testing()
add_subdirectory(googletest)
set(Headers Example.hpp
)
set(Sources Example.cpp
)
add_library(${This} STATIC ${Sources} ${Headers})
add_subdirectory(test)
test\CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
set(This ExampleTests)
set(Sources
ExampleTests.cpp
)
add_executable(${This} ${Sources})
target_link_libraries(${This} PUBLIC
gtest_main
Example
)
add_test(
NAME ${This}
COMMAND ${This}
)
ExampleTests.cpp:
#include <gtest/gtest.h>
TEST(ExampleTest, blah)
{
ASSERT_EQ(true, true);
}
Example.cpp:
#include "Example.hpp"
void Example::test()
{
int x = 5;
}
Example.hpp:
#ifndef EXAMPLE_HPP
#define EXAMPLE_HPP
class Example
{
public:
void test();
};
#endif
So I asked the original uploader of the video that I linked to for a solution and this solves my problem.
Moving it to another folder will usually break things unless you clean out the build folder (just delete it or don't move it with the rest of the files). The build folder contains intermediate build products that have path names in them, as well as CMake's cache (CMakeCache.txt) which also contains path names.
When I move to another directory I just move all the files, except for the build folder like he stated, opened up VS Code and it compiled.
I'm trying to create a library that links against allegro5 media library using CMake. And then, I want to use my library in an executable.
My directory structure is:
src
|----core
|------src
|------tests
|------CMakeLists.txt
|----main.cpp
|----CMakeLists.txt
The CMakeLists.txt file inside the core folder is:
set(MY_HEADERS #My header files here)
set(MY_SRC #My source files here)
add_library(MyLib ${MY_HEADERS} ${MY_SRC})
target_include_directories(MyLib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
## Allegro Lib
set(ALLEGRO_DIR "${PROJECT_SOURCE_DIR}/packages/allegro5/include")
if(WIN32)
file(GLOB ALLEGRO_LIB "${PROJECT_SOURCE_DIR}/packages/allegro5/windows/x86/lib/*.lib")
add_library(Allegro SHARED IMPORTED)
set_target_properties(Allegro PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${ALLEGRO_DIR}
IMPORTED_IMPLIB ${ALLEGRO_LIB}
)
target_link_libraries(MyLib PRIVATE Allegro)
file(GLOB ALLEGRO_DLL "${PROJECT_SOURCE_DIR}/packages/allegro5/windows/x86/bin/*.dll")
foreach(dll ${ALLEGRO_DLL})
add_custom_command(TARGET MyLib POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${dll} $<TARGET_FILE_DIR:MyLib>)
endforeach()
endif()
Now in my, top level CMakeLists.txt is:
cmake_minimum_required(VERSION 3.15)
project(MyProject)
enable_testing()
add_subdirectory(core)
add_executable(MyGame main.cpp)
target_link_libraries(MyGame MyLib)
In my IDE (Visual Studio) I see that the include statement for "allegro5/allegro.h" in my source files is inside core folder is giving me the warning "Cannot find directory allegro5 in search paths ... in context of ../src/main.cpp".
When I build the project I get the errors:
Cannot open source file 'allegro5/allegro'
Cannot open include file 'allegro5/allegro.h': No such file or directory.
This error only happens if I reference MyLib in main.cpp. (My main does not have any code, just a hello world statement):
// #include "MyLib.hpp"
int main(int argc, const char *argv[])
{
/*const auto engine = &MyLib::EngineManager::getInstance();
engine->start();
const auto display = &MyLib::DisplayManager::getInstance();
auto displayConfig = DisplayConfig();
displayConfig.fullscreen = false;
const auto displayId = display->createDisplay(displayConfig);*/
}
I guess this has something to do with the visibility I'm setting somewhere? I can't quite figure out how to fix. Appreciate your help, thanks!
EDIT:
When PRIVATE to PUBLIC, I get the following linker error:
LNK2019 unresolved external symbol __imp_al_install_system referenced in function "public: static void __cdecl mylib::EngineManager::start(void)" (?start#EngineManager#mylib##SAXXZ) C:\Users\xxx\src\out\build\x64-Debug\src C:\Users\xxx\src\out\build\x64-Debug\main.cpp.obj
The include directory for allegro5 is defined as ALLEGRO_DIR in your CMake:
${PROJECT_SOURCE_DIR}/packages/allegro5/include
Therefore, with the #include "allegro5/allegro.h", the full path to the header file would be appended:
${PROJECT_SOURCE_DIR}/packages/allegro5/include/allegro5/allegro.h
Be sure this path is correct and the file exists.
In addition, you set the INTERFACE include directories on the imported Allegro target, but you link it to MyLib using the PRIVATE keyword. This means the usage requirements of Allegro are not propagated to the MyGame. You should use PUBLIC for this link step instead if you want the INTERFACE_INCLUDE_DIRECTORIES of Allegro to also be transitively propagated to MyGame:
target_link_libraries(MyLib PUBLIC Allegro)
CMake has a good example demonstrating this in their documentation.
I've been bashing my head against this problem for the last few days (my repo is linked down below). I want CMake to generate a MSVC solution for which the Engine project is linked to the Demo project. While the .lib and .dll files are correctly generated and added to the projects in MSVC, I still get unresolved linker symbol errors from the Demo project referencing symbols from the Engine project. The Engine.lib file is correctly added to Demo's dependencies, and so are the headers. I have no globals for which I'd need to use the generated exported headers. What's the issue here?
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(P_SentryAll)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
include(GenerateExportHeader)
# glob source and header files
file(GLOB_RECURSE EngineSources SENTRY.Engine/*.cpp SENTRY.Engine/*.hpp)
file(GLOB_RECURSE CoreSources SENTRY.Core/*.cpp SENTRY.Core/*.hpp)
file(GLOB_RECURSE RenderSources SENTRY.Render/*.cpp SENTRY.Render/*.hpp)
file(GLOB_RECURSE DemoSources SENTRY.Demo/*.cpp SENTRY.Demo/*.hpp)
file(GLOB_RECURSE EngineHeaders SENTRY.Engine/*.hpp)
file(GLOB_RECURSE CoreHeaders SENTRY.Core/*.hpp)
add_subdirectory(SENTRY.Core)
add_subdirectory(SENTRY.Engine)
add_subdirectory(SENTRY.Render)
add_subdirectory(SENTRY.Demo)
Root/Sentry.Core/CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
# define project
project(P_SentryCore)
add_library(SentryCore SHARED ${CoreSources})
target_include_directories(SentryCore PUBLIC src/module)
generate_export_header(SentryCore)
install(TARGETS SentryCore DESTINATION lib)
install(FILES ${CoreHeaders} DESTINATION include/SentryCore)
Root/Sentry.Engine/CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
project(P_SentryEngine)
add_library(SentryEngine SHARED ${EngineSources})
target_link_libraries(SentryEngine PUBLIC SentryCore)
target_include_directories(SentryEngine PUBLIC src/engine)
generate_export_header(SentryEngine)
install(TARGETS SentryEngine DESTINATION lib)
install(FILES ${EngineHeaders} DESTINATION include/SentryEngine)
Root/Sentry.Demo/CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
# define project
project(P_SentryDemo)
add_executable(SentryDemo ${DemoSources})
target_link_libraries(SentryDemo PUBLIC SentryEngine)
include_directories(SENTRY.Engine/src/engine SENTRY.Core/src/module)
# packaging
install(TARGETS SentryDemo DESTINATION build)
Error:
1>------ Build started: Project: ZERO_CHECK, Configuration: Debug x64 ------
2>------ Build started: Project: SentryEngine, Configuration: Debug x64 ------
2>Engine.cpp
2>Auto build dll exports
2> Creating library C:/Users/main/Desktop/Projects/SENTRY/Build/SENTRY.Engine/Debug/SentryEngine.lib and object C:/Users/main/Desktop/Projects/SENTRY/Build/SENTRY.Engine/Debug/SentryEngine.exp
2>SentryEngine.vcxproj -> C:\Users\main\Desktop\Projects\SENTRY\Build\SENTRY.Engine\Debug\SentryEngine.dll
3>------ Build started: Project: SentryDemo, Configuration: Debug x64 ------
3>SENTRY.Demo.obj : error LNK2019: unresolved external symbol "public: void __cdecl Engine<__int64,struct std::ratio<1,1000000> >::Init(void)" (?Init#?$Engine#_JU?$ratio#$00$0PECEA##std####QEAAXXZ) referenced in function main
3>SENTRY.Demo.obj : error LNK2019: unresolved external symbol "public: void __cdecl Engine<__int64,struct std::ratio<1,1000000> >::Run(void)" (?Run#?$Engine#_JU?$ratio#$00$0PECEA##std####QEAAXXZ) referenced in function main
3>SENTRY.Demo.obj : error LNK2019: unresolved external symbol "public: void __cdecl Engine<__int64,struct std::ratio<1,1000000> >::RegisterModule(class Module<__int64,struct std::ratio<1,1000000> > *)" (?RegisterModule#?$Engine#_JU?$ratio#$00$0PECEA##std####QEAAXPEAV?$Module#_JU?$ratio#$00$0PECEA##std#####Z) referenced in function main
3>C:\Users\main\Desktop\Projects\SENTRY\Build\SENTRY.Demo\Debug\SentryDemo.exe : fatal error LNK1120: 3 unresolved externals
3>Done building project "SentryDemo.vcxproj" -- FAILED.
4>------ Skipped Build: Project: INSTALL, Configuration: Debug x64 ------
4>Project not selected to build for this solution configuration
========== Build: 2 succeeded, 1 failed, 2 up-to-date, 1 skipped ==========
Repo
The line in Root/Sentry.Demo/CMakeLists.txt:
include_directories(SENTRY.Engine/src/engine SENTRY.Core/src/module)
appears to be incorrect. It uses relative paths, so I don't believe these are valid paths in your project:
Root/Sentry.Demo/SENTRY.Engine/src/engine
Root/Sentry.Demo/SENTRY.Core/src/module
Prefer to use absolute paths wherever possible, through use of the CMAKE_SOURCE_DIR variable. This variable provides the path to the top-level source directory. So try something like this instead:
include_directories(
${CMAKE_SOURCE_DIR}/SENTRY.Engine/src/engine
${CMAKE_SOURCE_DIR}/SENTRY.Core/src/module
)
I took another look at your repo, and perhaps more importantly, you must have the full definition of Engine template functions in the header file, not the source file.
So move these function definitions to the header file, within your Engine class definition:
template<typename T_rep, typename T_ratio>
void Engine<T_rep, T_ratio>::Init()
{
for (auto& module_ : Modules)
{
module_->Init();
}
}
template<typename T_rep, typename T_ratio>
void Engine<T_rep, T_ratio>::Run()
{
RunUpdateLoop = true;
auto TPStart = std::chrono::steady_clock::now();
auto TPEnd = TPStart;
while (RunUpdateLoop)
{
auto deltaT = TPEnd - TPStart;
TPStart = std::chrono::steady_clock::now();
for (auto& module_ : Modules)
{
module_->Run((deltaT));
}
TPEnd = std::chrono::steady_clock::now();
}
}
template<typename T_rep, typename T_ratio>
void Engine<T_rep, T_ratio>::RegisterModule(Module<T_rep, T_ratio>* ToRegister)
{
Modules.push_back(ToRegister);
}
This should help get you on the right track.