mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-19 08:29:18 +02:00
A baked heightfield was trusted for as long as its file was readable, and the logic container while the .scn was older than it: an edited include went unnoticed by both, and node keys leaned on file dates, so merely touching a file changed them. And cooking only ever happened as a side effect of starting a scenery. Every cooked artifact now has a manifest beside it - <scenario>.ehf.deps, <scenario>.logic.deps - listing each file it was made from with its size, modification time and a hash of its content (simulation/cookdeps). The parser records what it includes as it reads, so the list is exactly what the load read. An artifact is current when every listed file still has its content: size and time are the quick check, and when either differs the content is hashed, so a touched or copied file does not force a rebuild and an edited one always does. A file added to the scenery cannot be in a manifest; the files read are compared with it after the load, and a mismatch sends the terrain to be baked on the next start - the new file's nodes, whose keys are unknown, are drawn as geometry meanwhile - and the logic, cooked from the loaded state, is cooked at once. The terrain depends on what the scenario includes and not on the scenario file itself, which the launcher rewrites on every start; the logic depends on both, since events can be written in either, and costs milliseconds to cook again. With the manifest vouching for file content, a triangle node's key is its file, line, include parameters and placement, without the date. -cook loads a scenery, brings whatever is stale up to date, and quits: the step that prepares a scenery ahead of play. It closes the window directly, as there is no simulation to wind down; a quit command waited a minute in the queue for one. Baking on a first start stays as the fallback, and -nobaketerrain still turns it off. Tried on a copy of baltyk with a terrain include of its own: a fresh cook bakes and cooks everything, a second finds nothing to do, a touched file changes nothing, an edited include is caught by its hash and both artifacts are rebuilt, and a new include has the logic recooked at once and the terrain on the next run. A cooking run of baltyk takes 5.5 s with nothing stale and 10.7 s with everything to do.
819 lines
26 KiB
CMake
819 lines
26 KiB
CMake
cmake_minimum_required(VERSION 3.28) # 3.28+: FILE_SET CXX_MODULES
|
|
if(POLICY CMP0058)
|
|
cmake_policy(SET CMP0058 NEW)
|
|
endif()
|
|
if(POLICY CMP0074)
|
|
cmake_policy(SET CMP0074 NEW)
|
|
endif()
|
|
if(POLICY CMP0069)
|
|
cmake_policy(SET CMP0069 NEW)
|
|
endif()
|
|
|
|
include(CheckCXXSymbolExists)
|
|
|
|
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
|
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/CMake_modules/")
|
|
|
|
set(DEPS_DIR ${DEPS_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/ref")
|
|
project("eu07")
|
|
|
|
# Clang is the compiler this project is built and tested with: clang on Linux,
|
|
# clang-cl on Windows, both pinned to 22 in CI. MSVC still configures and is not
|
|
# rejected, but nothing verifies it. GCC is not supported: its lazy loading of
|
|
# module interfaces is broken here, and working around it costs roughly twice
|
|
# the memory per compiler process.
|
|
if (NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang|MSVC")
|
|
message(FATAL_ERROR
|
|
"Unsupported compiler: ${CMAKE_CXX_COMPILER_ID}. "
|
|
"Build with Clang (CI uses 22) or MSVC.")
|
|
endif()
|
|
|
|
# Only Platform/Windows-MSVC.cmake passes /DWIN32; the GNU-driver platform files
|
|
# do not. Plenty of third-party code tests the unprefixed WIN32 rather than
|
|
# _WIN32 - asio and AMD's FSR2 among it, the latter swapping in POSIX shims for
|
|
# wcscpy_s and _countof that then collide with the real CRT. Define it here,
|
|
# before any add_subdirectory, so every target sees what an MSVC build saw.
|
|
if (WIN32 AND NOT MSVC)
|
|
add_compile_definitions(WIN32)
|
|
endif()
|
|
|
|
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined")
|
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize=undefined -Wformat")
|
|
#set(CMAKE_LD_FLAGS "${CMAKE_LD_FLAGS} -fsanitize=address -fsanitize=undefined")
|
|
|
|
string(TIMESTAMP VERSION_YEAR "%y")
|
|
string(TIMESTAMP VERSION_MONTH "%m")
|
|
string(TIMESTAMP VERSION_DAY "%d")
|
|
|
|
# Use these as version numbers
|
|
set(VERSION_MAJOR ${VERSION_YEAR})
|
|
set(VERSION_MINOR ${VERSION_MONTH})
|
|
set(VERSION_PATCH ${VERSION_DAY})
|
|
|
|
set(VERSION_STRING "${VERSION_YEAR}.${VERSION_MONTH}.${VERSION_DAY}")
|
|
|
|
|
|
set(CMAKE_CXX_STANDARD 20)
|
|
|
|
file(GLOB HEADERS "*.h"
|
|
"Console/*.h"
|
|
"McZapkie/*.h"
|
|
"gl/*.h"
|
|
"network/*.h"
|
|
"vr/*.h"
|
|
"network/backend/*.h"
|
|
"widgets/*.h"
|
|
"launcher/*.h"
|
|
"extras/*.h"
|
|
"global_include/*.h"
|
|
"simulation/*.h"
|
|
"scene/*.h"
|
|
"rendering/*.h"
|
|
"audio/*.h"
|
|
"environment/*.h"
|
|
"application/*.h"
|
|
"input/*.h"
|
|
"scripting/*.h"
|
|
"model/*.h"
|
|
"utilities/*.h"
|
|
"world/*.h"
|
|
"vehicle/*.h")
|
|
|
|
set(GLOBAL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
set(GLOBAL_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/global_include")
|
|
set(IMGUI_DIR "${CMAKE_CURRENT_SOURCE_DIR}/imgui")
|
|
|
|
if (APPLE)
|
|
set (CMAKE_FIND_FRAMEWORK LAST)
|
|
endif()
|
|
|
|
option(WITH_OPENGL_MODERN "Compile with OpenGL modern renderer" ON)
|
|
option(WITH_OPENGL_LEGACY "Compile with OpenGL legacy renderer" ON)
|
|
option(WITH_PYTHON "Python 3.14 embedded scripting" ON)
|
|
option(WITH_UART "Compile with libserialport" ON)
|
|
option(WITH_LUA "Compile with lua scripting support" ON)
|
|
option(WITH_OPENVR "Compile with OpenVR" OFF)
|
|
option(WITH_ZMQ "Compile with cppzmq" OFF)
|
|
option(WITH_CRASHPAD "Compile with crashpad" OFF)
|
|
option(WITH_DISCORD_RPC "Compile with DISCORD RICH PRESENCE" ON)
|
|
option(USE_LTO "Use link-time optimization" OFF)
|
|
option(WITH_BETTER_RENDERER "Experimental multi-backend renderer based on NVRHI" ON)
|
|
option(GENERATE_PDB "Generate executable with program debugging symbols" ON)
|
|
option(ENABLE_MCC "Enable multicore compilation" ON)
|
|
option(WITHDUMPGEN "Enable generating DMP files on crash" ON)
|
|
option(ENABLE_AVX2 "Enable AVX2 instruction set (requires AVX2-capable CPU, Haswell/2013 or newer)" ON)
|
|
option(ADD_VERSION_SUFFIX "Add date and commit hash to the executable name" ON)
|
|
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
|
|
|
# vcpkg init. The triplet has to follow the host, or a non-Windows build looks
|
|
# for its packages (DXC, used by the betterRenderer shader compiler) in a
|
|
# directory that only ever exists on Windows.
|
|
set(VCPKG_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/ref/vcpkg")
|
|
if (WIN32)
|
|
set(VCPKG_TRIPLET "x64-windows")
|
|
elseif (APPLE)
|
|
set(VCPKG_TRIPLET "x64-osx")
|
|
else()
|
|
set(VCPKG_TRIPLET "x64-linux")
|
|
endif()
|
|
set(VCPKG_INSTALLED_PATH "${VCPKG_ROOT}/installed/${VCPKG_TRIPLET}")
|
|
list(APPEND CMAKE_PREFIX_PATH "${VCPKG_INSTALLED_PATH}")
|
|
list(APPEND CMAKE_MODULE_PATH "${VCPKG_INSTALLED_PATH}/share")
|
|
|
|
set(SOURCES
|
|
"model/Texture.cpp"
|
|
"utilities/Timer.cpp"
|
|
"world/Track.cpp"
|
|
"world/Traction.cpp"
|
|
"world/TractionPower.cpp"
|
|
"vehicle/Train.cpp"
|
|
"world/TrkFoll.cpp"
|
|
"vehicle/AirCoupler.cpp"
|
|
"model/AnimModel.cpp"
|
|
"vehicle/Button.cpp"
|
|
"vehicle/Camera.cpp"
|
|
"vehicle/Driver.cpp"
|
|
"application/driverhints.cpp"
|
|
"vehicle/DynObj.cpp"
|
|
"EU07.cpp"
|
|
"export_e3d_standalone.cpp"
|
|
"world/Event.cpp"
|
|
"world/EvLaunch.cpp"
|
|
"utilities/Float3d.cpp"
|
|
"vehicle/Gauge.cpp"
|
|
"utilities/Globals.cpp"
|
|
"utilities/Logs.cpp"
|
|
"McZapkie/friction.cpp"
|
|
"McZapkie/hamulce.cpp"
|
|
"McZapkie/Mover.cpp"
|
|
"McZapkie/Oerlikon_ESt.cpp"
|
|
"model/MdlMngr.cpp"
|
|
"world/MemCell.cpp"
|
|
"model/Model3d.cpp"
|
|
"world/mtable.cpp"
|
|
"utilities/parser.cpp"
|
|
"rendering/nullrenderer.cpp"
|
|
"rendering/renderer.cpp"
|
|
"model/ResourceManager.cpp"
|
|
"scene/sn_utils.cpp"
|
|
"world/Segment.cpp"
|
|
"environment/sky.cpp"
|
|
"environment/sun.cpp"
|
|
"environment/stars.cpp"
|
|
"rendering/lightarray.cpp"
|
|
"environment/skydome.cpp"
|
|
"audio/sound.cpp"
|
|
"world/Spring.cpp"
|
|
"rendering/frustum.cpp"
|
|
"application/uilayer.cpp"
|
|
"rendering/openglmatrixstack.cpp"
|
|
"environment/moon.cpp"
|
|
"input/command.cpp"
|
|
"input/keyboardinput.cpp"
|
|
"input/gamepadinput.cpp"
|
|
"input/drivermouseinput.cpp"
|
|
"utilities/translation.cpp"
|
|
"model/material.cpp"
|
|
"input/messaging.cpp"
|
|
"scene/scene.cpp"
|
|
"scene/logiccontainer.cpp"
|
|
"scene/prefab.cpp"
|
|
"scene/scenenode.cpp"
|
|
"simulation/simulation.cpp"
|
|
"model/vertex.cpp"
|
|
"audio/audio.cpp"
|
|
"audio/audiorenderer.cpp"
|
|
"utilities/motiontelemetry.cpp"
|
|
"utilities/utilities.cpp"
|
|
"application/uitranscripts.cpp"
|
|
"world/station.cpp"
|
|
"application/application.cpp"
|
|
"application/shotrunner.cpp"
|
|
"rendering/terrainclipmap.cpp"
|
|
"rendering/terraintileloader.cpp"
|
|
"rendering/terraintilepool.cpp"
|
|
"rendering/terrainground.cpp"
|
|
"simulation/loadprofile.cpp"
|
|
"simulation/cookdeps.cpp"
|
|
"simulation/logiccook.cpp"
|
|
"simulation/terrainbake.cpp"
|
|
"simulation/simulationtime.cpp"
|
|
"scene/sceneeditor.cpp"
|
|
"rendering/screenshot.cpp"
|
|
"input/driverkeyboardinput.cpp"
|
|
"application/drivermode.cpp"
|
|
"application/driveruilayer.cpp"
|
|
"application/driveruipanels.cpp"
|
|
"input/editorkeyboardinput.cpp"
|
|
"editor/editorSettings.cpp"
|
|
"editor/puwg1992.cpp"
|
|
"editor/polandmap.cpp"
|
|
"editor/turnouts.cpp"
|
|
"editor/orthophoto.cpp"
|
|
"editor/plan_chain.cpp"
|
|
"editor/plan_document_io.cpp"
|
|
"editor/plan_join.cpp"
|
|
"editor/plan_layout.cpp"
|
|
"editor/plan_model.cpp"
|
|
"editor/plan_rail_renderer.cpp"
|
|
"editor/plan_render.cpp"
|
|
"editor/plan_scn_export.cpp"
|
|
"editor/plan_sketch.cpp"
|
|
"editor/plan_solution.cpp"
|
|
"editor/plan_tilecache.cpp"
|
|
"editor/plan_turnout_geometry.cpp"
|
|
"editor/editorTerrain.cpp"
|
|
"editor/editorTerrainStreamer.cpp"
|
|
"application/editormode.cpp"
|
|
"input/editormouseinput.cpp"
|
|
"application/editoruilayer.cpp"
|
|
"application/editoruipanels.cpp"
|
|
"application/planpanel.cpp"
|
|
"application/scenarioloadermode.cpp"
|
|
"application/scenarioloaderuilayer.cpp"
|
|
"scene/scenenodegroups.cpp"
|
|
"simulation/simulationenvironment.cpp"
|
|
"simulation/simulationstateserializer.cpp"
|
|
"rendering/precipitation.cpp"
|
|
"scripting/pythonscreenviewer.cpp"
|
|
"utilities/dictionary.cpp"
|
|
"rendering/particles.cpp"
|
|
"utilities/headtrack.cpp"
|
|
"scripting/ladderlogic.cpp"
|
|
"rendering/geometrybank.cpp"
|
|
"rendering/openglcolor.cpp"
|
|
"simulation/simulationsounds.cpp"
|
|
"rendering/openglcamera.cpp"
|
|
|
|
"network/network.cpp"
|
|
"network/message.cpp"
|
|
"network/manager.cpp"
|
|
|
|
"widgets/vehiclelist.cpp"
|
|
"widgets/map.cpp"
|
|
"widgets/map_objects.cpp"
|
|
"widgets/popup.cpp"
|
|
"widgets/time.cpp"
|
|
"widgets/vehicleparams.cpp"
|
|
"widgets/trainingcard.cpp"
|
|
"widgets/perfgraphs.cpp"
|
|
|
|
"${DEPS_DIR}/glad/src/glad.c"
|
|
"${DEPS_DIR}/dds-ktx/src/dds-ktx.c"
|
|
|
|
"gl/shader.cpp"
|
|
"gl/vao.cpp"
|
|
"gl/ubo.cpp"
|
|
"gl/framebuffer.cpp"
|
|
"gl/renderbuffer.cpp"
|
|
"gl/postfx.cpp"
|
|
"gl/cubemap.cpp"
|
|
"gl/glsl_common.cpp"
|
|
"gl/buffer.cpp"
|
|
"gl/fence.cpp"
|
|
"gl/pbo.cpp"
|
|
"gl/query.cpp"
|
|
|
|
"imgui/imgui.cpp"
|
|
"imgui/imgui_demo.cpp"
|
|
"imgui/imgui_draw.cpp"
|
|
"imgui/imgui_widgets.cpp"
|
|
"imgui/imgui_impl_glfw.cpp"
|
|
"imgui/ImGuizmo.cpp"
|
|
|
|
"stb/stb_image.c"
|
|
|
|
"launcher/launchermode.cpp"
|
|
"launcher/scenery_list.cpp"
|
|
"launcher/launcheruilayer.cpp"
|
|
"launcher/vehicle_picker.cpp"
|
|
"launcher/keymapper.cpp"
|
|
"launcher/textures_scanner.cpp"
|
|
"launcher/scenery_scanner.cpp"
|
|
|
|
"vr/vr_interface.cpp"
|
|
)
|
|
|
|
set(DEFINITIONS)
|
|
|
|
# Definitions that used to live at the top of stdafx.h. They must be identical in
|
|
# every translation unit (glm is header-only and its GLM_FORCE_* switches change
|
|
# type layout), so they are set on the target rather than in a header that a file
|
|
# could forget to include first.
|
|
set(DEFINITIONS ${DEFINITIONS}
|
|
"_USE_MATH_DEFINES"
|
|
"NOMINMAX"
|
|
"GLFW_INCLUDE_NONE"
|
|
"GLM_FORCE_SWIZZLE"
|
|
"GLM_ENABLE_EXPERIMENTAL"
|
|
"GLM_FORCE_CTOR_INIT"
|
|
# empty value, not 1: glm/simd/platform.h defines this itself as a bare
|
|
# #define, and a differing definition would warn on every translation unit
|
|
"GLM_FORCE_INTRINSICS=")
|
|
|
|
if (WIN32)
|
|
# _WIN32_WINNT came from targetver.h, which only ever existed to be pulled in
|
|
# by stdafx.h; keep the same Windows 7 API level now that both are gone
|
|
set(DEFINITIONS ${DEFINITIONS} "WIN32_LEAN_AND_MEAN" "_WIN32_WINNT=0x0601")
|
|
endif()
|
|
|
|
if (APPLE)
|
|
# parts of the codebase gate posix-only code on __unix__, which Apple does not define
|
|
set(DEFINITIONS ${DEFINITIONS} "__unix__=1")
|
|
endif()
|
|
|
|
if (MSVC)
|
|
set(DEFINITIONS ${DEFINITIONS} "GLM_FORCE_INLINE" "_CRTDBG_MAP_ALLOC")
|
|
endif()
|
|
|
|
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64|ARM64)$")
|
|
set(DEFINITIONS ${DEFINITIONS} "GLM_FORCE_NEON")
|
|
elseif (ENABLE_AVX2)
|
|
set(DEFINITIONS ${DEFINITIONS} "GLM_FORCE_AVX2")
|
|
endif()
|
|
set(SOURCES ${SOURCES} "imgui/imgui_impl_opengl3.cpp")
|
|
set(SOURCES ${SOURCES} "imgui/imgui_impl_opengl2.cpp")
|
|
|
|
if (WITH_CRASHPAD)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_CRASHPAD")
|
|
set(SOURCES ${SOURCES} "utilities/crashreporter.cpp")
|
|
if (WIN32)
|
|
include_directories("${DEPS_DIR}/crashpad/include" "${DEPS_DIR}/crashpad/include/mini_chromium")
|
|
else()
|
|
include_directories("${DEPS_DIR}/crashpad/crashpad" "${DEPS_DIR}/crashpad/crashpad/third_party/mini_chromium/mini_chromium")
|
|
endif()
|
|
endif()
|
|
|
|
if(WITH_PYTHON)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_PYTHON")
|
|
set(SOURCES ${SOURCES} "scripting/PyInt.cpp")
|
|
else()
|
|
set(SOURCES ${SOURCES} "scripting/PyIntStub.cpp")
|
|
endif()
|
|
|
|
if (WITH_UART)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_UART")
|
|
set(SOURCES ${SOURCES} "utilities/uart.cpp")
|
|
endif()
|
|
|
|
if (WITH_ZMQ)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_ZMQ")
|
|
set(SOURCES ${SOURCES} "input/zmq_input.cpp")
|
|
endif()
|
|
|
|
if (WITH_OPENVR)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_OPENVR")
|
|
set(SOURCES ${SOURCES} "vr/openvr_imp.cpp")
|
|
endif()
|
|
|
|
if (WITH_LUA)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_LUA")
|
|
set(SOURCES ${SOURCES} "scripting/lua.cpp")
|
|
endif()
|
|
|
|
if (WITHDUMPGEN)
|
|
set(DEFINITIONS ${DEFINITIONS} "WITHDUMPGEN")
|
|
endif()
|
|
|
|
if (WITH_OPENGL_MODERN)
|
|
set(SOURCES ${SOURCES}
|
|
"rendering/opengl33geometrybank.cpp"
|
|
"rendering/opengl33light.cpp"
|
|
"rendering/opengl33skydome.cpp"
|
|
"rendering/opengl33precipitation.cpp"
|
|
"rendering/opengl33particles.cpp"
|
|
"rendering/opengl33renderer.cpp")
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_OPENGL_MODERN")
|
|
endif()
|
|
|
|
if (WITH_OPENGL_LEGACY)
|
|
set(SOURCES ${SOURCES}
|
|
"rendering/openglgeometrybank.cpp"
|
|
"rendering/opengllight.cpp"
|
|
"rendering/openglskydome.cpp"
|
|
"rendering/openglprecipitation.cpp"
|
|
"rendering/openglparticles.cpp"
|
|
"rendering/openglrenderer.cpp")
|
|
set(DEFINITIONS ${DEFINITIONS} "WITH_OPENGL_LEGACY")
|
|
endif()
|
|
|
|
add_subdirectory("${DEPS_DIR}/glfw/" EXCLUDE_FROM_ALL)
|
|
|
|
set(SOURCES ${SOURCES} "extras/piped_proc.cpp" "widgets/cameraview_extcam.cpp")
|
|
|
|
find_package(Git)
|
|
|
|
if (GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} describe --match=DUMMY --always --dirty
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
OUTPUT_VARIABLE GIT_HASH
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
OUTPUT_VARIABLE SRC_DATE
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
|
|
execute_process(
|
|
COMMAND ${GIT_EXECUTABLE} show -s --format=%cs
|
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
OUTPUT_VARIABLE SRC_SHORT_DATE
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
else()
|
|
string(TIMESTAMP SRC_SHORT_DATE %Y-%m-%d UTC)
|
|
string(TIMESTAMP SRC_DATE UTC)
|
|
set(GIT_HASH "(unknown)")
|
|
endif()
|
|
|
|
configure_file("${CMAKE_SOURCE_DIR}/version_info.h.in" "${CMAKE_BINARY_DIR}/geninc/version_info.h")
|
|
|
|
set (PREFIX "")
|
|
set (SUFFIX "")
|
|
|
|
if (ADD_VERSION_SUFFIX)
|
|
set (SUFFIX "_${SRC_SHORT_DATE}_${GIT_HASH}")
|
|
endif()
|
|
|
|
set(OPENVR_LIBRARY "openvr_api")
|
|
set(OPENVR_INCLUDE_DIR "")
|
|
|
|
if (WIN32)
|
|
set(DEFINITIONS ${DEFINITIONS} "HAVE_ROUND") # to make pymath to not redefine round
|
|
# set(DEFINITIONS ${DEFINITIONS} "GLFW_DLL")
|
|
|
|
set(SOURCES ${SOURCES} "windows.cpp" "Console.cpp" "Console/LPT.cpp" "Console/PoKeys55.cpp")
|
|
#set(GLFW3_INCLUDE_DIR ${GLFW3_INCLUDE_DIR} "${DEPS_DIR}/glfw/include/")
|
|
set(PNG_INCLUDE_DIRS ${PNG_INCLUDE_DIRS} "${DEPS_DIR}/libpng/include/")
|
|
#set(ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR} "${DEPS_DIR}/zlib/")
|
|
set(OPENAL_INCLUDE_DIR ${OPENAL_INCLUDE_DIR} "${DEPS_DIR}/openal/include")
|
|
set(LIBSNDFILE_INCLUDE_DIR ${LIBSNDFILE_INCLUDE_DIR} "${DEPS_DIR}/libsndfile/include")
|
|
set(LUAJIT_INCLUDE_DIR ${LUAJIT_INCLUDE_DIR} "${DEPS_DIR}/luajit/include")
|
|
set(libserialport_INCLUDE_DIR ${LIBSERIALPORT_INCLUDE_DIR} "${DEPS_DIR}/libserialport/include")
|
|
set(OPENVR_INCLUDE_DIR "${DEPS_DIR}/openvr/include")
|
|
|
|
#if(${CMAKE_EXE_LINKER_FLAGS} STREQUAL "/machine:x64")
|
|
# set (ARCH "x64")
|
|
#else()
|
|
# set (ARCH "x86")
|
|
#endif()
|
|
|
|
set(ARCH "x64")
|
|
set (PREFIX "-${ARCH}")
|
|
|
|
#set(GLFW3_LIBRARIES ${GLFW3_LIBRARIES} "${DEPS_DIR}/glfw/lib/${ARCH}/glfw3dll.lib")
|
|
set(PNG_LIBRARIES ${PNG_LIBRARIES} "${DEPS_DIR}/libpng/lib/${ARCH}/libpng16.lib")
|
|
set(OPENAL_LIBRARY ${OPENAL_LIBRARY} "${DEPS_DIR}/openal/lib/${ARCH}/OpenAL32.lib")
|
|
set(LIBSNDFILE_LIBRARY ${LIBSNDFILE_LIBRARY} "${DEPS_DIR}/libsndfile/lib/${ARCH}/libsndfile-1.lib")
|
|
set(LUAJIT_LIBRARIES ${LUAJIT_LIBRARIES} "${DEPS_DIR}/luajit/lib/${ARCH}/lua51.lib")
|
|
set(libserialport_LIBRARY ${LIBSERIALPORT_LIBRARY} "${DEPS_DIR}/libserialport/lib/${ARCH}/libserialport-0.lib")
|
|
set(cppzmq_LIBRARY ${cppzmq_LIBRARY} "${DEPS_DIR}/cppzmq/lib/${ARCH}/libzmq.lib")
|
|
set(OPENVR_LIBRARY "${DEPS_DIR}/openvr/lib/${ARCH}/openvr_api.lib")
|
|
endif()
|
|
|
|
set(cppzmq_INCLUDE_DIR ${cppzmq_INCLUDE_DIR} "${DEPS_DIR}/cppzmq/include")
|
|
set(GLM_INCLUDE_DIR ${GLM_INCLUDE_DIR} "${DEPS_DIR}/glm/")
|
|
|
|
# Process version.rc.in into version.rc
|
|
configure_file(${CMAKE_SOURCE_DIR}/eu07.rc.in
|
|
${CMAKE_BINARY_DIR}/eu07.rc @ONLY)
|
|
|
|
# Gated on WIN32, not MSVC: CMake only sets MSVC for the MSVC-style driver, and
|
|
# the Windows build uses clang's GNU driver, which needs the version resource
|
|
# and the icon just the same.
|
|
if (WIN32)
|
|
# the Visual Studio generators enable RC on their own; Ninja does not
|
|
enable_language(RC)
|
|
set(SOURCES ${SOURCES} ${CMAKE_BINARY_DIR}/eu07.rc)
|
|
set(SOURCES ${SOURCES} eu07.ico)
|
|
if (MSVC)
|
|
add_compile_options("/utf-8") # clang's GNU driver already reads UTF-8
|
|
endif()
|
|
endif()
|
|
|
|
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
|
|
|
|
# C++20 module interface units. They must be declared through a CXX_MODULES file
|
|
# set so CMake runs the dependency scanner and orders the build; the matching
|
|
# .cpp implementation units stay ordinary sources in ${SOURCES}.
|
|
file(GLOB MODULE_INTERFACES CONFIGURE_DEPENDS "*.cppm"
|
|
"Console/*.cppm"
|
|
"McZapkie/*.cppm"
|
|
"gl/*.cppm"
|
|
"network/*.cppm"
|
|
"vr/*.cppm"
|
|
"network/backend/*.cppm"
|
|
"widgets/*.cppm"
|
|
"launcher/*.cppm"
|
|
"extras/*.cppm"
|
|
"global_include/*.cppm"
|
|
"global_include/interfaces/*.cppm"
|
|
"simulation/*.cppm"
|
|
"scene/*.cppm"
|
|
"rendering/*.cppm"
|
|
"audio/*.cppm"
|
|
"environment/*.cppm"
|
|
"application/*.cppm"
|
|
"input/*.cppm"
|
|
"scripting/*.cppm"
|
|
"model/*.cppm"
|
|
"utilities/*.cppm"
|
|
"world/*.cppm"
|
|
"editor/*.cppm"
|
|
"vehicle/*.cppm"
|
|
"simcore/*.cppm")
|
|
|
|
# Unlike ordinary sources, every interface unit in the file set is scanned even
|
|
# when the feature that owns it is switched off, so the optional ones have to be
|
|
# dropped explicitly or the scan fails on their missing SDK headers.
|
|
list(REMOVE_ITEM MODULE_INTERFACES "${CMAKE_CURRENT_SOURCE_DIR}/world/Curve.cppm")
|
|
if (NOT WITH_ZMQ)
|
|
list(REMOVE_ITEM MODULE_INTERFACES "${CMAKE_CURRENT_SOURCE_DIR}/input/zmq_input.cppm")
|
|
endif()
|
|
if (NOT WITH_OPENVR)
|
|
list(REMOVE_ITEM MODULE_INTERFACES "${CMAKE_CURRENT_SOURCE_DIR}/vr/openvr_imp.cppm")
|
|
endif()
|
|
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF)
|
|
|
|
|
|
target_compile_definitions(${PROJECT_NAME} PRIVATE ${DEFINITIONS})
|
|
|
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
|
"."
|
|
"Console"
|
|
"McZapkie"
|
|
"gl"
|
|
"${DEPS_DIR}/glad/include"
|
|
"${DEPS_DIR}/dds-ktx/include"
|
|
"${CMAKE_BINARY_DIR}/geninc"
|
|
"${GLOBAL_INCLUDE_DIR}")
|
|
|
|
if (MSVC)
|
|
# override cmake defaults
|
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO " /MD /Zi /O2 /DNDEBUG")
|
|
set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO " /DEBUG /INCREMENTAL:NO /OPT:REF /OPT:ICF")
|
|
|
|
# /wd4996: disable "deprecation" warnings
|
|
# /wd4244: disable warnings for conversion with possible loss of data
|
|
# /wd5033: disable because it is all over Python headers
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd4996 /wd4244 /wd5033")
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE")
|
|
|
|
# /MAP is a link.exe option; lld-link, which clang-cl usually drives, spells
|
|
# it differently. The map only feeds the debug-symbols artifact, whose upload
|
|
# tolerates it being absent.
|
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
|
target_link_options(${PROJECT_NAME} PRIVATE "/MAP")
|
|
endif()
|
|
endif()
|
|
|
|
set_target_properties( ${PROJECT_NAME}
|
|
PROPERTIES
|
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
|
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
|
PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/pdb"
|
|
OUTPUT_NAME "${PROJECT_NAME}${PREFIX}${SUFFIX}"
|
|
DEBUG_POSTFIX "_d"
|
|
)
|
|
|
|
check_cxx_symbol_exists(__GNUC__ "" COMPILER_HAVE_GNUC)
|
|
if (COMPILER_HAVE_GNUC)
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
|
endif()
|
|
|
|
if (USE_LTO)
|
|
set_property(TARGET ${PROJECT_NAME} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
|
endif()
|
|
|
|
if (WITH_OPENVR)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENVR_INCLUDE_DIR})
|
|
target_link_libraries(${PROJECT_NAME} ${OPENVR_LIBRARY})
|
|
endif()
|
|
|
|
if (WITH_CRASHPAD)
|
|
if (WIN32)
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/lib_md/base.lib")
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/lib_md/client.lib")
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/lib_md/util.lib")
|
|
else()
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/crashpad/out/Default/obj/client/libclient.a")
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/crashpad/out/Default/obj/util/libutil.a")
|
|
target_link_libraries(${PROJECT_NAME} "${DEPS_DIR}/crashpad/crashpad/out/Default/obj/third_party/mini_chromium/mini_chromium/base/libbase.a")
|
|
endif()
|
|
endif()
|
|
|
|
target_link_libraries(${PROJECT_NAME} glfw)
|
|
# the cooked terrain heightfield stores its tiles compressed
|
|
target_link_libraries(${PROJECT_NAME} zstd::libzstd)
|
|
|
|
if(WITH_PYTHON)
|
|
find_package(Python3 3.14 REQUIRED COMPONENTS Development)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${Python3_INCLUDE_DIRS})
|
|
target_link_libraries(${PROJECT_NAME} ${Python3_LIBRARIES})
|
|
|
|
if(WIN32)
|
|
# Python3_ROOT_DIR is only an input hint and is not populated by
|
|
# find_package(... COMPONENTS Development). Derive the install root from
|
|
# the include dir (parent of <root>/include) when it was not provided.
|
|
if(NOT Python3_ROOT_DIR)
|
|
get_filename_component(Python3_ROOT_DIR "${Python3_INCLUDE_DIRS}" DIRECTORY)
|
|
endif()
|
|
set(EU07_PY_DLL "${Python3_ROOT_DIR}/python314.dll")
|
|
set(EU07_PY_ZLIB "${Python3_ROOT_DIR}/DLLs/zlib1.dll")
|
|
set(EU07_PY_LIBDIR "${Python3_ROOT_DIR}/Lib")
|
|
set(EU07_PY_DLLSDIR "${Python3_ROOT_DIR}/DLLs")
|
|
endif()
|
|
endif()
|
|
|
|
if (NOT WIN32)
|
|
find_package(PNG 1.6 REQUIRED)
|
|
target_link_libraries(${PROJECT_NAME} PNG::PNG)
|
|
else()
|
|
include_directories(${PNG_INCLUDE_DIRS})
|
|
target_link_libraries(${PROJECT_NAME} ${PNG_LIBRARIES})
|
|
endif()
|
|
|
|
find_package(zstd CONFIG QUIET)
|
|
if(NOT zstd_FOUND)
|
|
find_package(PkgConfig REQUIRED)
|
|
pkg_check_modules(ZSTD REQUIRED IMPORTED_TARGET libzstd)
|
|
add_library(zstd::libzstd ALIAS PkgConfig::ZSTD)
|
|
endif()
|
|
|
|
find_package(Threads REQUIRED)
|
|
target_link_libraries(${PROJECT_NAME} Threads::Threads)
|
|
|
|
# the editor's map imagery talks to a WMS over https. windows has WinHttp in the platform sdk;
|
|
# everywhere else libcurl is the transport (see editor/orthophoto.cpp). it is not required: a tree
|
|
# without it builds an editor that draws and exports as usual, only with no imagery behind the plan
|
|
if (NOT WIN32)
|
|
find_package(CURL)
|
|
if (CURL_FOUND)
|
|
target_link_libraries(${PROJECT_NAME} CURL::libcurl)
|
|
target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_CURL)
|
|
else()
|
|
message(WARNING
|
|
"libcurl not found: the editor will have no map imagery. "
|
|
"Install libcurl4-openssl-dev (Debian/Ubuntu) or libcurl-devel (Fedora) to get it back.")
|
|
endif()
|
|
endif()
|
|
|
|
find_package(GLM REQUIRED)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${GLM_INCLUDE_DIR})
|
|
|
|
# JSON lib
|
|
add_subdirectory(ref/json)
|
|
target_link_libraries(${PROJECT_NAME} nlohmann_json::nlohmann_json)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR})
|
|
|
|
# track layout domain model used by the editor; plain C++20, no dependencies of its own
|
|
|
|
|
|
|
|
if (WITH_DISCORD_RPC)
|
|
add_subdirectory(ref/discord-rpc)
|
|
set_target_properties(discord-rpc PROPERTIES FOLDER "libraries")
|
|
target_link_libraries(${PROJECT_NAME} discord-rpc)
|
|
|
|
# Add the include directory so the compiler can find discord_rpc.h
|
|
target_include_directories(${PROJECT_NAME} PUBLIC
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/ref/discord-rpc/include"
|
|
)
|
|
|
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_DISCORD_RPC=1)
|
|
else()
|
|
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_DISCORD_RPC=0)
|
|
endif()
|
|
|
|
find_package(OpenAL REQUIRED)
|
|
if (TARGET OpenAL::OpenAL)
|
|
target_link_libraries(${PROJECT_NAME} OpenAL::OpenAL)
|
|
else()
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${OPENAL_INCLUDE_DIR})
|
|
target_link_libraries(${PROJECT_NAME} ${OPENAL_LIBRARY})
|
|
endif()
|
|
|
|
find_package(SndFile REQUIRED)
|
|
target_link_libraries(${PROJECT_NAME} SndFile::sndfile)
|
|
|
|
if (WITH_LUA)
|
|
find_package(LuaJIT REQUIRED)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${LUAJIT_INCLUDE_DIR})
|
|
target_link_libraries(${PROJECT_NAME} ${LUAJIT_LIBRARIES})
|
|
endif()
|
|
|
|
if (WITH_UART)
|
|
find_package(libserialport REQUIRED)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${libserialport_INCLUDE_DIR})
|
|
target_link_libraries(${PROJECT_NAME} ${libserialport_LIBRARY})
|
|
endif()
|
|
|
|
find_package(ASIO REQUIRED)
|
|
target_link_libraries(${PROJECT_NAME} asio::asio)
|
|
|
|
if (WIN32)
|
|
target_link_libraries(${PROJECT_NAME} ws2_32)
|
|
endif()
|
|
|
|
if (WITH_ZMQ)
|
|
find_package(cppzmq REQUIRED)
|
|
target_include_directories(${PROJECT_NAME} PRIVATE ${cppzmq_INCLUDE_DIR})
|
|
target_link_libraries(${PROJECT_NAME} ${cppzmq_LIBRARY})
|
|
endif()
|
|
|
|
if (WIN32)
|
|
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy -t $<TARGET_FILE_DIR:${PROJECT_NAME}> $<TARGET_RUNTIME_DLLS:${PROJECT_NAME}>
|
|
COMMAND_EXPAND_LISTS
|
|
)
|
|
endif ()
|
|
|
|
if(WIN32 AND WITH_PYTHON)
|
|
add_custom_command(
|
|
TARGET ${PROJECT_NAME} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EU07_PY_DLL}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EU07_PY_ZLIB}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${EU07_PY_LIBDIR}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>/python64/Lib"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_directory "${EU07_PY_DLLSDIR}" "$<TARGET_FILE_DIR:${PROJECT_NAME}>/python64/DLLs"
|
|
)
|
|
endif()
|
|
|
|
# The module interface units live in their own library so that other targets --
|
|
# betterRenderer, which is a separate add_library -- can import them. A target
|
|
# can only consume C++20 modules by linking the target that owns the file set,
|
|
# and the executable's own modules are not reachable that way.
|
|
#
|
|
# The interfaces need exactly the flags the executable was given, so they are
|
|
# copied off it rather than restated; this has to happen after all the
|
|
# third-party wiring above and before betterRenderer is added, or the mirrored
|
|
# link list would point back at betterRenderer and make the dependency circular.
|
|
add_subdirectory(editor/tests)
|
|
|
|
add_library(eu07_modules STATIC)
|
|
|
|
get_target_property(EU07_INCLUDES ${PROJECT_NAME} INCLUDE_DIRECTORIES)
|
|
get_target_property(EU07_DEFINITIONS ${PROJECT_NAME} COMPILE_DEFINITIONS)
|
|
get_target_property(EU07_LINKS ${PROJECT_NAME} LINK_LIBRARIES)
|
|
|
|
target_sources(eu07_modules
|
|
PUBLIC FILE_SET CXX_MODULES
|
|
BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}
|
|
FILES ${MODULE_INTERFACES})
|
|
|
|
target_include_directories(eu07_modules PUBLIC ${EU07_INCLUDES})
|
|
target_compile_definitions(eu07_modules PUBLIC ${EU07_DEFINITIONS})
|
|
target_link_libraries(eu07_modules PUBLIC ${EU07_LINKS})
|
|
set_target_properties(eu07_modules PROPERTIES
|
|
CXX_STANDARD 20 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF
|
|
POSITION_INDEPENDENT_CODE ON)
|
|
|
|
target_link_libraries(${PROJECT_NAME} eu07_modules)
|
|
|
|
if (WITH_BETTER_RENDERER)
|
|
add_subdirectory("betterRenderer")
|
|
set_target_properties(betterRenderer betterRenderer_fsr2 betterRenderer_shaders PROPERTIES FOLDER "renderers")
|
|
target_link_libraries(${PROJECT_NAME} "betterRenderer")
|
|
endif ()
|
|
|
|
|
|
# Enable compiling with debug symbols
|
|
if(GENERATE_PDB)
|
|
if (MSVC)
|
|
# Ensure Debug and Release configurations use appropriate runtime libraries
|
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Zi /MDd")
|
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi /MD")
|
|
|
|
# Add compile options for debugging
|
|
add_compile_options(/Zi) # Always enable debug symbols
|
|
add_link_options(/DEBUG /MAP)
|
|
|
|
# Ensure that the PCH is built with the correct runtime library for each configuration
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
|
COMPILE_OPTIONS "$<$<CONFIG:Debug>:/MDd>$<$<CONFIG:Release>:/MD>")
|
|
else()
|
|
# GCC/Clang (ensure -g is set for all configurations)
|
|
add_compile_options(-g)
|
|
endif()
|
|
endif()
|
|
|
|
# /MP is an MSVC-only option; clang-cl rejects it, and under Ninja the generator
|
|
# already runs one compiler process per core.
|
|
if(ENABLE_MCC AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_GENERATOR MATCHES "Ninja")
|
|
message(STATUS "Enabling multi-processor compilation for MSVC.")
|
|
add_compile_options(/MP)
|
|
endif()
|
|
|
|
if(ENABLE_AVX2)
|
|
message(STATUS "Enabling AVX2 instruction set.")
|
|
if (MSVC)
|
|
target_compile_options(${PROJECT_NAME} PRIVATE /arch:AVX2)
|
|
else()
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -mavx2)
|
|
endif()
|
|
endif() |