Repository navigation
03 Build Targets
Previous: 02 CMake Project
Most of the Squeak Game Engine is designed to be a dynamic library (Windows .dll, Linux .so), which can be shared between several games or other applications, including the editor. This has the following advantages:
- Less duplication of code.
- Smaller game executables.
- Library can be swapped out easily.
This design requires at least two binaries for development: The dynamic library (sge-lib) and a test application to demonstrate the library's features (test-app). Building multiple binaries means we must use multiple build targets in CMake.
A new CMakeLists.txt in the project root directory delegates the build to the CMakeLists.txt in each of two new subdirectories, sge-lib and test-app:
cmake_minimum_required(VERSION 3.16)
project(squeak-game-engine)
# Language and compiler options
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_definitions(-c -Wall)
#create all executables and libraries in the root of the build directory
set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# GLFW
# Don't build docs, tests, or examples
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
# Build GLFW
set(GLFW_DIR ${PROJECT_SOURCE_DIR}/lib/glfw)
add_subdirectory(${GLFW_DIR} ${CMAKE_CURRENT_BINARY_DIR}/glfw)
#library must be built first
add_subdirectory(sge-lib)
add_subdirectory(test-app)The two new set() lines tells CMake to place generated executables and libraries in the root build directory. This is important because the executable requires the library to be in the same folder or in some folder listed in the PATH environment variable.
GLFW is still built separately. As we will see later it is then included as a library when building sge-lib.
The add_subdirectory() function tells CMake to process the CMakeLists.txt in the given directory, which will create the build target.
After GLFW is dealt with, the two calls to add_subdirectory() create first the SGE library and then the test application.
Here is the CMakeLists.txt in sge-lib:
#sge-lib
# Add source files
file(GLOB_RECURSE SOURCE_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# Add header files
file(GLOB_RECURSE HEADER_FILES
${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp)
add_library(
sge-lib SHARED
${SOURCE_FILES}
${HEADER_FILES}
#build glad inside sge-lib
${PROJECT_SOURCE_DIR}/lib/glad/include/glad/glad.h
${PROJECT_SOURCE_DIR}/lib/glad/include/KHR/khrplatform.h
${PROJECT_SOURCE_DIR}/lib/glad/src/glad.c
)
target_link_libraries(sge-lib glfw ${GLFW_LIBRARIES}) #add glfw to the sge-lib library
# Add directory sge-lib/src/ to the include path of the sge-lib target (the library this file is responsible for building). This allows test-app to include sge-lib's own header files.
# PUBLIC means any other target using this library needs to have the library's include path added to it.
# CMAKE_CURRENT_SOURCE_DIR refers to the folder containing the currently-being-processed CMakeLists (sge-lib, in this example)
target_include_directories(sge-lib PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
#append glad's include directory to the include path as well
target_include_directories(sge-lib PUBLIC "${PROJECT_SOURCE_DIR}/lib/glad/include")After adding the source and include files, add_library() identifies this target as a shared library, which will produce a .so binary as its result. Also included here are the source and header files from the Glad library as Glad is included in the library code.
target_link_libraries() includes GLFW when compiling sge-lib. The compiler flags listed in the previous dev log were removed as they were not in the GLFW building guide.
The two calls to target_include_directories() with PUBLIC specified mean that any executable which uses sge-lib as a library can include header files from both the sge-lib code and from Glad.
Here is the CMakeLists.txt in test-app:
# Copy resource files into build
# Copy shaders
file(GLOB SHADERS ${PROJECT_SOURCE_DIR}/res/shaders/*.glsl)
file(COPY ${SHADERS} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/../res/shaders)
add_executable(test src/main.cpp)
target_link_libraries(test PRIVATE sge-lib)Everything should be familiar here. In add_executable() no glob is used for the test application as it is not expected to grow in complexity enough to warrant it; new source files can just be added as needed.
Due to potential naming conflicts on unix-like systems with the directory build/test-app, the executable is called test and not test-app in target_link_libraries().
First, the src directory in the project root directory is deleted as it is no longer needed.
Three new files belong in sge-lib/src: shader_s.h, render.h, and render.cpp. These files contain mostly the same tutorial code from learnopengl.com used in the previous dev log, just in a different layout to test the build system. There is no main.cpp as this is a library and therefore has no entry point.
There is only one source file in test-app/src: main.cpp. It is short enough to list entirely here, as all it does is call run() defined in render.h.
#include <render.h>
int main()
{
run();
return 0;
}The result should be the same colored triangle from before. To build and run from the project root directory:
mkdir build
cd build
cmake ..
make
./test
Next: 04