Build System - dprandle/nsengine GitHub Wiki

There are two scripts which build the engine – one for Unix systems and one for Windows. These are “build.sh” and “build.bat” respectively. CMake is the build system of choice – the scripts just setup some CMake settings and copy the generated lib files and dependencies once building is finished.

Why copy the lib files? Since the engine is built statically, none of the dependencies are linked in. This means that any new project using nsengine needs to link in the dependencies. The needed libraries are included in the repository in the “deps” folder, so the build scripts copy all required libraries to the nsengine/lib folder (which is created on build) in order to make it easy to link in all necessary libraries. Just add a single link directory and then link to the libs.

An easy way to handle this that ensures your project won’t break if new versions of nsengine are released is to do the following:

  1. Clone nsengine and build it using either build.sh (Unix) or build.bat (Windows)
  2. Create a folder in your project’s directory called “deps” or something like that. In that folder create another folder called “nsengine”, and in that folder create two folders – one called “include” and another called “lib”.
  3. Now copy all header files from nsengine/include to your_project/deps/nsengine/include, and all lib files from nsengine/lib to your_project/deps/nsengine/lib

Now you can commit the engine lib files and header files as part of your project’s repository. If there are updates to nsengine that you would like to add in to your project, you can just repeat the above replacing the files. This way if the changes somehow break your project, you can easily roll them back.

OpenGL is the only library that the engine uses that is not copied to this folder – this is because OpenGL is a system library that each system will know how to find. Usually just linking to the opengl library will work without doing anything else.

Here is an example of a CMakeLists.txt file for a simple project that uses nsengine. The comments attempt to explain it.

# set the project name
project(sample_project)

# whoever compiles this must have this version of cmake or newer
cmake_minimum_required(VERSION 2.8)

# create a variable called "TARGET" and set it to sample_proj - this will be used to set the exe name
set(TARGET sample_proj)

# Set the location with all of the c and/or cpp files - I usually keep mine in a folder called "src"
# The PROJECT_SOURCE_DIR is CMake variable that contains the name of the directory that this CMakeLists.txt file is in
# In CMake you use ${...} with ... as the name of the variable to get the value of the variable
set(SAMPLE_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)

# Set the location where all of the header files will be and assign it to SAMPLE_INCLUDE_DIR - I usually keep mine in "include" folder
set(SAMPLE_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)

# nsengine include dir (copied engine's files in to here)
# note: You might be wondering why I have a folder called nsengine inside nsengine/include - why not just directly put the header files in nsengine/include instead of nsengine/include/nsengine?
# The reason is that sometimes people like to have clean separation in their include statements - so they can write #include <nsengine/nssignal.h> instead of just <nssignal.h>
# In this project I am expecting to use just <nssignal.h> though, so I have added the entire nsengine/include/nsengine - but if you like the separation just add nsengine/include then
set(NSENGINE_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/deps/nsengine/include/nsengine)


# Set project includes dir - this is where the compiler will search when saying #include <blabla.h>
# This is in addition to the default system directories that the compiler will search for header files
include_directories(
    "${SAMPLE_INCLUDE_DIR}"
    "${NSENGINE_INCLUDE_DIR}"
    )

# This glob command finds all files that end in cpp or c in SAMPLE_SOURCE_DIR and adds them to the variable SRC_FILES
file(GLOB SRC_FILES
"${SAMPLE_SOURCE_DIR}/*.cpp"
"${SAMPLE_SOURCE_DIR}/*.c"
)

# Set the header files - this is only used in the "add_custom_target" call below to correctly show the header files in Qt creator
# Without adding the custom target, the header files don't show up in Qt Creator
file(GLOB HEADER_FILES
"${SAMPLE_INCLUDE_DIR}/*.h"
)

# This is a variable then can be set on calling cmake - mainly useful for windows. Changing this to x86 will build the project in 32 bit.
set(PLATFORM "x64" CACHE STRING "Platform for which to run cmake (run for each build type)")

# This causes debug builds to append the letter "d" to all libraries and executables that are generated
set(CMAKE_DEBUG_POSTFIX d)

# Preprocessor definitions - Some of the libraries that the engine uses require certain preprocessor vars to be defined
# For now the easiest thing to do is require projects that use nsengine to define them - which is the line below
add_definitions(-DGLEW_MX -DGLEW_STATIC -DSTB_IMAGE_WRITE_IMPLEMENTATION -DSTB_IMAGE_IMPLEMENTATION)
# Eventually I will figure out how to make the above line not necessary

# This enables and disables a bunch of logging and error checking stuff depending on if
# we are building in debug or release
if (${CMAKE_BUILD_TYPE} STREQUAL Debug)
  add_definitions(-DNSDEBUG)
endif()

# Setup custom compiler and linker arguments depending on if unix or windows
if (UNIX)
    # only needed for unix compilers
    add_definitions(-std=c++11)

    # Set compiler flags for c++
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fms-extensions")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")

    # Make it so the executable is created in bin
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin)
elseif (WIN32)
    # Set MSVC compiler flags for c++
    set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} /WX /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMT" )
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")

    # Windows can build for 32 bit and 64 bit - unix doesn't support this very well
    set(PLATFORM "x64" CACHE STRING "Platform for which to run cmake (run for each build type)")

    # Make it so the executable is created in bin/platform (windows builds either x64 or x86)
    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin/${PLATFORM})
endif()

# Now add the directory with the engine libs to the linker's search path when trying
# to find libs
link_directories(${PROJECT_SOURCE_DIR}/deps/nsengine/lib/${PLATFORM})

# Output message to console to verify directory is correct
message("Adding link directory: ${PROJECT_SOURCE_DIR}/deps/nsengine/lib/${PLATFORM}")

# This is here simply so Qt shows the files correctly in the project window
add_custom_target(headers SOURCES ${HEADER_FILES})
add_custom_target(sources SOURCES ${SRC_FILES})

# This actually adds a target exe using the src files glob from earlier
add_executable(${TARGET} ${SRC_FILES})

# set the debug postfix on the exe
set_target_properties(${TARGET} PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})

# This is a specific thing for visual studio - it makes visual studio generate the exe in the correct directory
if (WIN32)
    set_target_properties(${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} )
    set_target_properties(${TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} )
endif (WIN32)

# Link all libraries
# The order here kind of matters - nsmath and nsengine need to go first cause they are missing symbols
# defined by later libs

# Find opengl - the lib will be set to OPENGL_LIBRARIES
find_package(OpenGL REQUIRED)
if(NOT OPENGL_FOUND)
    message(ERROR "Error: OpenGL not found on your system - please make sure you have it downloaded.")
endif(NOT OPENGL_FOUND)

# Now link each library - some windows libs have weird names
target_link_libraries(${TARGET}
debug nsengined
optimized nsengine
debug nsmathd
optimized nsmath
debug freetyped
optimized freetype
general ${OPENGL_LIBRARIES}
)

if (UNIX)
    target_link_libraries(${TARGET}
    debug assimpd
    optimized assimp
    debug glfwd
    optimized glfw
    general sndfile
    general openal)
elseif (WIN32)
    target_link_libraries(${TARGET}
    general assimp-vc140-mt
    debug glfw3ddll
    optimized glfw3dll
    general libsndfile-1
    general OpenAL32
    DbgHelp)
endif()

# and that does it
⚠️ **GitHub.com Fallback** ⚠️