CMake build system

This commit is contained in:
Tim Angus 2025-08-03 17:36:01 +01:00
parent 4fed624cff
commit 4c6f3f81eb
40 changed files with 1641 additions and 0 deletions

71
CMakeLists.txt Normal file
View File

@ -0,0 +1,71 @@
cmake_minimum_required(VERSION 3.18)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
include(identity)
project(${PROJECT_NAME} VERSION ${PROJECT_VERSION} LANGUAGES C ASM)
option(BUILD_SERVER "Build dedicated server" ON)
option(BUILD_CLIENT "Build client" ON)
option(BUILD_RENDERER_GL1 "Build GL1 renderer" ON)
option(BUILD_RENDERER_GL2 "Build GL2 renderer" ON)
option(BUILD_GAME_LIBRARIES "Build game module libraries" ON)
option(BUILD_GAME_QVMS "Build game module qvms" ON)
option(BUILD_STANDALONE "Build binaries for standalone games" OFF)
option(USE_ARCHLESS_FILENAMES "Don't include the architecture in binary filenames" OFF)
option(USE_RENDERER_DLOPEN "Dynamically load the renderer(s)" ON)
option(USE_OPENAL "OpenAL audio" ON)
option(USE_OPENAL_DLOPEN "Dynamically load OpenAL" ON)
option(USE_HTTP "HTTP download support" ON)
option(USE_CODEC_VORBIS "Ogg Vorbis support" ON)
option(USE_CODEC_OPUS "Ogg Opus support" ON)
option(USE_VOIP "Voice chat" ON)
option(USE_MUMBLE "Mumble support" ON)
option(USE_FREETYPE "Freetype font rendering" OFF)
option(USE_INTERNAL_LIBS "Use internally packaged libraries" ON)
option(USE_INTERNAL_ZLIB "Use internal copy of zlib" ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_JPEG "Use internal copy of libjpeg" ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_OGG "Use internal copy of ogg" ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_VORBIS "Use internal copy of vorbis" ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_OPUS "Use internal copy of opus" ${USE_INTERNAL_LIBS})
# Release build by default, set externally if you want something else
if(NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_SHARED_LIBRARY_PREFIX "")
set(PRODUCT_VERSION "${CMAKE_PROJECT_VERSION}")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
execute_process(
COMMAND git show -s --pretty=format:%h
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_REV
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
if(GIT_REV)
set(PRODUCT_VERSION "${PRODUCT_VERSION}_g${GIT_REV}")
endif()
endif()
add_compile_definitions(PRODUCT_VERSION="${PRODUCT_VERSION}")
set(SOURCE_DIR ${CMAKE_SOURCE_DIR}/code)
include(compilers/all)
include(platforms/all)
include(libraries/all)
include(server)
include(renderer_gl1)
include(renderer_gl2)
include(client)
include(basegame)
include(missionpack)

34
cmake/Info.plist.in Normal file
View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>@MACOS_APP_EXECUTABLE_NAME@</string>
<key>CFBundleIconFile</key>
<string>@MACOS_APP_ICON_FILE@</string>
<key>CFBundleIdentifier</key>
<string>@MACOS_APP_GUI_IDENTIFIER@</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>@MACOS_APP_BUNDLE_NAME@</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>@MACOS_APP_SHORT_VERSION_STRING@</string>
<key>CFBundleVersion</key>
<string>@MACOS_APP_BUNDLE_VERSION@</string>
<key>NSHumanReadableCopyright</key>
<string>@MACOS_APP_COPYRIGHT@</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSMinimumSystemVersion</key>
<string>@MACOS_APP_DEPLOYMENT_TARGET@</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
@MACOS_APP_PLIST_URL_TYPES@
</dict>
</plist>

184
cmake/basegame.cmake Normal file
View File

@ -0,0 +1,184 @@
if(NOT BUILD_GAME_LIBRARIES AND NOT BUILD_GAME_QVMS)
return()
endif()
include(utils/arch)
include(utils/qvm_tools)
include(utils/set_output_dirs)
set(CGAME_SOURCES
${SOURCE_DIR}/cgame/cg_main.c
${SOURCE_DIR}/game/bg_misc.c
${SOURCE_DIR}/game/bg_pmove.c
${SOURCE_DIR}/game/bg_slidemove.c
${SOURCE_DIR}/game/bg_lib.c
${SOURCE_DIR}/cgame/cg_consolecmds.c
${SOURCE_DIR}/cgame/cg_draw.c
${SOURCE_DIR}/cgame/cg_drawtools.c
${SOURCE_DIR}/cgame/cg_effects.c
${SOURCE_DIR}/cgame/cg_ents.c
${SOURCE_DIR}/cgame/cg_event.c
${SOURCE_DIR}/cgame/cg_info.c
${SOURCE_DIR}/cgame/cg_localents.c
${SOURCE_DIR}/cgame/cg_marks.c
${SOURCE_DIR}/cgame/cg_particles.c
${SOURCE_DIR}/cgame/cg_players.c
${SOURCE_DIR}/cgame/cg_playerstate.c
${SOURCE_DIR}/cgame/cg_predict.c
${SOURCE_DIR}/cgame/cg_scoreboard.c
${SOURCE_DIR}/cgame/cg_servercmds.c
${SOURCE_DIR}/cgame/cg_snapshot.c
${SOURCE_DIR}/cgame/cg_view.c
${SOURCE_DIR}/cgame/cg_weapons.c
)
set(CGAME_BINARY_SOURCES ${SOURCE_DIR}/cgame/cg_syscalls.c)
set(CGAME_QVM_SOURCES ${SOURCE_DIR}/cgame/cg_syscalls.asm)
set(GAME_SOURCES
${SOURCE_DIR}/game/g_main.c
${SOURCE_DIR}/game/ai_chat.c
${SOURCE_DIR}/game/ai_cmd.c
${SOURCE_DIR}/game/ai_dmnet.c
${SOURCE_DIR}/game/ai_dmq3.c
${SOURCE_DIR}/game/ai_main.c
${SOURCE_DIR}/game/ai_team.c
${SOURCE_DIR}/game/ai_vcmd.c
${SOURCE_DIR}/game/bg_misc.c
${SOURCE_DIR}/game/bg_pmove.c
${SOURCE_DIR}/game/bg_slidemove.c
${SOURCE_DIR}/game/bg_lib.c
${SOURCE_DIR}/game/g_active.c
${SOURCE_DIR}/game/g_arenas.c
${SOURCE_DIR}/game/g_bot.c
${SOURCE_DIR}/game/g_client.c
${SOURCE_DIR}/game/g_cmds.c
${SOURCE_DIR}/game/g_combat.c
${SOURCE_DIR}/game/g_items.c
${SOURCE_DIR}/game/g_mem.c
${SOURCE_DIR}/game/g_misc.c
${SOURCE_DIR}/game/g_missile.c
${SOURCE_DIR}/game/g_mover.c
${SOURCE_DIR}/game/g_session.c
${SOURCE_DIR}/game/g_spawn.c
${SOURCE_DIR}/game/g_svcmds.c
${SOURCE_DIR}/game/g_target.c
${SOURCE_DIR}/game/g_team.c
${SOURCE_DIR}/game/g_trigger.c
${SOURCE_DIR}/game/g_utils.c
${SOURCE_DIR}/game/g_weapon.c
)
set(GAME_BINARY_SOURCES ${SOURCE_DIR}/game/g_syscalls.c)
set(GAME_QVM_SOURCES ${SOURCE_DIR}/game/g_syscalls.asm)
set(UI_SOURCES
${SOURCE_DIR}/q3_ui/ui_main.c
${SOURCE_DIR}/game/bg_misc.c
${SOURCE_DIR}/game/bg_lib.c
${SOURCE_DIR}/q3_ui/ui_addbots.c
${SOURCE_DIR}/q3_ui/ui_atoms.c
${SOURCE_DIR}/q3_ui/ui_cdkey.c
${SOURCE_DIR}/q3_ui/ui_cinematics.c
${SOURCE_DIR}/q3_ui/ui_confirm.c
${SOURCE_DIR}/q3_ui/ui_connect.c
${SOURCE_DIR}/q3_ui/ui_controls2.c
${SOURCE_DIR}/q3_ui/ui_credits.c
${SOURCE_DIR}/q3_ui/ui_demo2.c
${SOURCE_DIR}/q3_ui/ui_display.c
${SOURCE_DIR}/q3_ui/ui_gameinfo.c
${SOURCE_DIR}/q3_ui/ui_ingame.c
${SOURCE_DIR}/q3_ui/ui_loadconfig.c
${SOURCE_DIR}/q3_ui/ui_menu.c
${SOURCE_DIR}/q3_ui/ui_mfield.c
${SOURCE_DIR}/q3_ui/ui_mods.c
${SOURCE_DIR}/q3_ui/ui_network.c
${SOURCE_DIR}/q3_ui/ui_options.c
${SOURCE_DIR}/q3_ui/ui_playermodel.c
${SOURCE_DIR}/q3_ui/ui_players.c
${SOURCE_DIR}/q3_ui/ui_playersettings.c
${SOURCE_DIR}/q3_ui/ui_preferences.c
${SOURCE_DIR}/q3_ui/ui_qmenu.c
${SOURCE_DIR}/q3_ui/ui_removebots.c
${SOURCE_DIR}/q3_ui/ui_saveconfig.c
${SOURCE_DIR}/q3_ui/ui_serverinfo.c
${SOURCE_DIR}/q3_ui/ui_servers2.c
${SOURCE_DIR}/q3_ui/ui_setup.c
${SOURCE_DIR}/q3_ui/ui_sound.c
${SOURCE_DIR}/q3_ui/ui_sparena.c
${SOURCE_DIR}/q3_ui/ui_specifyserver.c
${SOURCE_DIR}/q3_ui/ui_splevel.c
${SOURCE_DIR}/q3_ui/ui_sppostgame.c
${SOURCE_DIR}/q3_ui/ui_spskill.c
${SOURCE_DIR}/q3_ui/ui_startserver.c
${SOURCE_DIR}/q3_ui/ui_team.c
${SOURCE_DIR}/q3_ui/ui_teamorders.c
${SOURCE_DIR}/q3_ui/ui_video.c
)
set(UI_BINARY_SOURCES ${SOURCE_DIR}/ui/ui_syscalls.c)
set(UI_QVM_SOURCES ${SOURCE_DIR}/ui/ui_syscalls.asm)
set(GAME_MODULE_SHARED_SOURCES
${SOURCE_DIR}/qcommon/q_math.c
${SOURCE_DIR}/qcommon/q_shared.c
)
set(CGAME_SOURCES_BASEGAME ${CGAME_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
set(GAME_SOURCES_BASEGAME ${GAME_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
set(UI_SOURCES_BASEGAME ${UI_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
if(BUILD_GAME_LIBRARIES)
if(USE_ARCHLESS_FILENAMES)
set(CGAME_MODULE_BINARY ${CGAME_MODULE})
set(GAME_MODULE_BINARY ${GAME_MODULE})
set(UI_MODULE_BINARY ${UI_MODULE})
else()
set(CGAME_MODULE_BINARY ${CGAME_MODULE}${ARCH})
set(GAME_MODULE_BINARY ${GAME_MODULE}${ARCH})
set(UI_MODULE_BINARY ${UI_MODULE}${ARCH})
endif()
set(CGAME_MODULE_BINARY_BASEGAME ${CGAME_MODULE_BINARY}_${BASEGAME})
set(GAME_MODULE_BINARY_BASEGAME ${GAME_MODULE_BINARY}_${BASEGAME})
set(UI_MODULE_BINARY_BASEGAME ${UI_MODULE_BINARY}_${BASEGAME})
add_library( ${CGAME_MODULE_BINARY_BASEGAME} SHARED ${CGAME_SOURCES_BASEGAME} ${CGAME_BINARY_SOURCES})
target_compile_definitions( ${CGAME_MODULE_BINARY_BASEGAME} PRIVATE CGAME)
set_target_properties( ${CGAME_MODULE_BINARY_BASEGAME} PROPERTIES OUTPUT_NAME ${CGAME_MODULE_BINARY})
set_output_dirs( ${CGAME_MODULE_BINARY_BASEGAME} SUBDIRECTORY ${BASEGAME})
add_library( ${GAME_MODULE_BINARY_BASEGAME} SHARED ${GAME_SOURCES_BASEGAME} ${GAME_BINARY_SOURCES})
target_compile_definitions( ${GAME_MODULE_BINARY_BASEGAME} PRIVATE QAGAME)
set_target_properties( ${GAME_MODULE_BINARY_BASEGAME} PROPERTIES OUTPUT_NAME ${GAME_MODULE_BINARY})
set_output_dirs( ${GAME_MODULE_BINARY_BASEGAME} SUBDIRECTORY ${BASEGAME})
add_library( ${UI_MODULE_BINARY_BASEGAME} SHARED ${UI_SOURCES_BASEGAME} ${UI_BINARY_SOURCES})
target_compile_definitions( ${UI_MODULE_BINARY_BASEGAME} PRIVATE UI)
set_target_properties( ${UI_MODULE_BINARY_BASEGAME} PROPERTIES OUTPUT_NAME ${UI_MODULE_BINARY})
set_output_dirs( ${UI_MODULE_BINARY_BASEGAME} SUBDIRECTORY ${BASEGAME})
endif()
if(BUILD_GAME_QVMS)
set(CGAME_MODULE_QVM_BASEGAME ${CGAME_MODULE}qvm_${BASEGAME})
set(GAME_MODULE_QVM_BASEGAME ${GAME_MODULE}qvm_${BASEGAME})
set(UI_MODULE_QVM_BASEGAME ${UI_MODULE}qvm_${BASEGAME})
add_qvm(${CGAME_MODULE_QVM_BASEGAME}
DEFINITIONS CGAME
OUTPUT_NAME ${CGAME_MODULE}
OUTPUT_DIRECTORY ${BASEGAME}/vm
SOURCES ${CGAME_SOURCES_BASEGAME} ${CGAME_QVM_SOURCES})
add_qvm(${GAME_MODULE_QVM_BASEGAME}
DEFINITIONS QAGAME
OUTPUT_NAME ${GAME_MODULE}
OUTPUT_DIRECTORY ${BASEGAME}/vm
SOURCES ${GAME_SOURCES_BASEGAME} ${GAME_QVM_SOURCES})
add_qvm(${UI_MODULE_QVM_BASEGAME}
DEFINITIONS UI
OUTPUT_NAME ${UI_MODULE}
OUTPUT_DIRECTORY ${BASEGAME}/vm
SOURCES ${UI_SOURCES_BASEGAME} ${UI_QVM_SOURCES})
endif()

115
cmake/client.cmake Normal file
View File

@ -0,0 +1,115 @@
if(NOT BUILD_CLIENT)
return()
endif()
include(utils/add_git_dependency)
include(utils/arch)
include(utils/set_output_dirs)
include(shared_sources)
include(renderer_common)
set(CLIENT_SOURCES
${SOURCE_DIR}/client/cl_cgame.c
${SOURCE_DIR}/client/cl_cin.c
${SOURCE_DIR}/client/cl_console.c
${SOURCE_DIR}/client/cl_input.c
${SOURCE_DIR}/client/cl_keys.c
${SOURCE_DIR}/client/cl_main.c
${SOURCE_DIR}/client/cl_net_chan.c
${SOURCE_DIR}/client/cl_parse.c
${SOURCE_DIR}/client/cl_scrn.c
${SOURCE_DIR}/client/cl_ui.c
${SOURCE_DIR}/client/cl_avi.c
${SOURCE_DIR}/client/libmumblelink.c
${SOURCE_DIR}/client/snd_altivec.c
${SOURCE_DIR}/client/snd_adpcm.c
${SOURCE_DIR}/client/snd_dma.c
${SOURCE_DIR}/client/snd_mem.c
${SOURCE_DIR}/client/snd_mix.c
${SOURCE_DIR}/client/snd_wavelet.c
${SOURCE_DIR}/client/snd_main.c
${SOURCE_DIR}/client/snd_codec.c
${SOURCE_DIR}/client/snd_codec_wav.c
${SOURCE_DIR}/client/snd_codec_ogg.c
${SOURCE_DIR}/client/snd_codec_opus.c
${SOURCE_DIR}/client/qal.c
${SOURCE_DIR}/client/snd_openal.c
${SOURCE_DIR}/sdl/sdl_input.c
${SOURCE_DIR}/sdl/sdl_snd.c
${CLIENT_PLATFORM_SOURCES}
)
add_git_dependency(${SOURCE_DIR}/client/cl_console.c)
if(USE_ARCHLESS_FILENAMES)
set(CLIENT_BINARY ${CLIENT_NAME})
list(APPEND CLIENT_DEFINITIONS USE_ARCHLESS_FILENAMES)
else()
set(CLIENT_BINARY ${CLIENT_NAME}.${ARCH})
endif()
list(APPEND CLIENT_DEFINITIONS BOTLIB)
if(BUILD_STANDALONE)
list(APPEND CLIENT_DEFINITIONS STANDALONE)
endif()
if(USE_RENDERER_DLOPEN)
list(APPEND CLIENT_DEFINITIONS USE_RENDERER_DLOPEN)
endif()
if(USE_HTTP)
list(APPEND CLIENT_DEFINITIONS USE_HTTP)
endif()
if(USE_VOIP)
list(APPEND CLIENT_DEFINITIONS USE_VOIP)
endif()
if(USE_MUMBLE)
list(APPEND CLIENT_DEFINITIONS USE_MUMBLE)
list(APPEND CLIENT_LIBRARY_SOURCES ${SOURCE_DIR}/client/libmumblelink.c)
endif()
list(APPEND CLIENT_BINARY_SOURCES
${SERVER_SOURCES}
${CLIENT_SOURCES}
${COMMON_SOURCES}
${BOTLIB_SOURCES}
${SYSTEM_SOURCES}
${ASM_SOURCES}
${CLIENT_LIBRARY_SOURCES})
add_executable(${CLIENT_BINARY} ${CLIENT_EXECUTABLE_OPTIONS} ${CLIENT_BINARY_SOURCES})
target_include_directories( ${CLIENT_BINARY} PRIVATE ${CLIENT_INCLUDE_DIRS})
target_compile_definitions( ${CLIENT_BINARY} PRIVATE ${CLIENT_DEFINITIONS})
target_compile_options( ${CLIENT_BINARY} PRIVATE ${CLIENT_COMPILE_OPTIONS})
target_link_libraries( ${CLIENT_BINARY} PRIVATE ${COMMON_LIBRARIES} ${CLIENT_LIBRARIES})
target_link_options( ${CLIENT_BINARY} PRIVATE ${CLIENT_LINK_OPTIONS})
set_output_dirs(${CLIENT_BINARY})
if(NOT USE_RENDERER_DLOPEN)
target_sources(${CLIENT_BINARY} PRIVATE
# These are never simultaneously populated
${RENDERER_GL1_BINARY_SOURCES}
${RENDERER_GL2_BINARY_SOURCES})
target_include_directories( ${CLIENT_BINARY} PRIVATE ${RENDERER_INCLUDE_DIRS})
target_compile_definitions( ${CLIENT_BINARY} PRIVATE ${RENDERER_DEFINITIONS})
target_compile_options( ${CLIENT_BINARY} PRIVATE ${RENDERER_COMPILE_OPTIONS})
target_link_libraries( ${CLIENT_BINARY} PRIVATE ${RENDERER_LIBRARIES})
endif()
foreach(LIBRARY IN LISTS CLIENT_DEPLOY_LIBRARIES)
add_custom_command(TARGET ${CLIENT_BINARY} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${LIBRARY}
$<TARGET_FILE_DIR:${CLIENT_BINARY}>)
endforeach()
if(POST_CLIENT_CONFIGURE_FUNCTION)
cmake_language(CALL ${POST_CLIENT_CONFIGURE_FUNCTION})
endif()

View File

@ -0,0 +1,5 @@
include(compilers/appleclang)
include(compilers/clang)
include(compilers/gcc)
include(compilers/gnu)
include(compilers/msvc)

View File

@ -0,0 +1,5 @@
# Apple Clang compiler specific settings
if(NOT CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
return()
endif()

View File

@ -0,0 +1,5 @@
# Clang compiler specific settings
if(NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
return()
endif()

View File

@ -0,0 +1,5 @@
# GCC compiler specific settings
if(NOT CMAKE_C_COMPILER_ID STREQUAL "GNU")
return()
endif()

18
cmake/compilers/gnu.cmake Normal file
View File

@ -0,0 +1,18 @@
# GNU style (GCC/Clang) compiler specific settings
if(NOT CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_ID MATCHES "^(Apple)?Clang$")
return()
endif()
set(ASM_SOURCES
${SOURCE_DIR}/asm/snapvector.c
${SOURCE_DIR}/asm/ftola.c
)
add_compile_options(-Wall -Wimplicit
-Wstrict-prototypes -Wformat=2 -Wformat-security
-Wstrict-aliasing=2 -Wmissing-format-attribute
-Wdisabled-optimization -Werror-implicit-function-declaration)
add_compile_options(-Wno-strict-aliasing
-Wno-format-zero-length -Wno-format-nonliteral)

View File

@ -0,0 +1,37 @@
# MSVC compiler specific settings
if(NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC")
return()
endif()
include(utils/arch)
enable_language(ASM_MASM)
set(ASM_SOURCES
${SOURCE_DIR}/asm/snapvector.asm
${SOURCE_DIR}/asm/ftola.asm
)
if(ARCH MATCHES "x86_64")
list(APPEND ASM_SOURCES ${SOURCE_DIR}/asm/vm_x86_64.asm)
set_source_files_properties(
${ASM_SOURCES}
PROPERTIES COMPILE_DEFINITIONS "idx64")
endif()
# Baseline warnings
add_compile_options("$<$<COMPILE_LANGUAGE:C>:/W4>")
# C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data
# There are way too many of these to realistically deal with them
add_compile_options("$<$<COMPILE_LANGUAGE:C>:/wd4267>")
# MSVC doesn't understand __inline__, which libjpeg uses
add_compile_definitions(__inline__=inline)
# It's unlikely that we'll move to the _s variants, so stop the warning
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
# The sockets platform abstraction layer necessarily uses deprecated APIs
add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS)

20
cmake/identity.cmake Normal file
View File

@ -0,0 +1,20 @@
set(PROJECT_NAME ioq3)
set(PROJECT_VERSION 1.36)
set(SERVER_NAME ioq3ded)
set(CLIENT_NAME ioquake3)
set(BASEGAME baseq3)
set(CGAME_MODULE cgame)
set(GAME_MODULE qagame)
set(UI_MODULE ui)
set(WINDOWS_ICON_PATH ${CMAKE_SOURCE_DIR}/misc/quake3.ico)
set(MACOS_ICON_PATH ${CMAKE_SOURCE_DIR}/misc/quake3_flat.icns)
set(MACOS_BUNDLE_ID org.ioquake.${CLIENT_NAME})
set(COPYRIGHT "QUAKE III ARENA Copyright © 1999-2000 id Software, Inc. All rights reserved.")
set(PROTOCOL_HANDLER_SCHEME quake3)

View File

@ -0,0 +1,9 @@
include(libraries/curl)
include(libraries/freetype)
include(libraries/jpeg)
include(libraries/ogg)
include(libraries/opus)
include(libraries/openal)
include(libraries/sdl)
include(libraries/vorbis)
include(libraries/zlib)

View File

@ -0,0 +1,15 @@
if(NOT USE_HTTP OR WIN32)
return()
endif()
set(INTERNAL_CURL_DIR ${SOURCE_DIR}/thirdparty/curl-8.15.0)
find_package(CURL QUIET)
if(NOT CURL_FOUND)
set(CURL_DEFINITIONS USE_INTERNAL_CURL_HEADERS)
set(CURL_INCLUDE_DIR ${INTERNAL_CURL_DIR}/include)
endif()
list(APPEND CLIENT_DEFINITIONS ${CURL_DEFINITIONS})
list(APPEND CLIENT_INCLUDE_DIRS ${CURL_INCLUDE_DIR})

View File

@ -0,0 +1,8 @@
if(NOT USE_FREETYPE)
return()
endif()
find_package(Freetype REQUIRED)
list(APPEND RENDERER_INCLUDE_DIRS ${FREETYPE_INCLUDE_DIRS})
list(APPEND RENDERER_LIBRARIES ${FREETYPE_LIBRARIES})

View File

@ -0,0 +1,18 @@
include(utils/disable_warnings)
include(utils/find_include_dirs)
set(INTERNAL_JPEG_DIR ${SOURCE_DIR}/thirdparty/jpeg-9f)
if(USE_INTERNAL_JPEG)
file(GLOB_RECURSE JPEG_SOURCES ${INTERNAL_JPEG_DIR}/j*.c)
disable_warnings(${JPEG_SOURCES})
find_include_dirs(JPEG_INCLUDE_DIRS ${JPEG_SOURCES})
set(JPEG_DEFINITIONS USE_INTERNAL_JPEG)
list(APPEND RENDERER_LIBRARY_SOURCES ${JPEG_SOURCES})
else()
find_package(JPEG REQUIRED)
endif()
list(APPEND RENDERER_LIBRARIES ${JPEG_LIBRARIES})
list(APPEND RENDERER_INCLUDE_DIRS ${JPEG_INCLUDE_DIRS})
list(APPEND RENDERER_DEFINITIONS ${JPEG_DEFINTIONS})

21
cmake/libraries/ogg.cmake Normal file
View File

@ -0,0 +1,21 @@
if(NOT USE_CODEC_VORBIS)
return()
endif()
include(utils/disable_warnings)
set(INTERNAL_OGG_DIR ${SOURCE_DIR}/thirdparty/libogg-1.3.6)
if(USE_INTERNAL_OGG)
file(GLOB_RECURSE OGG_SOURCES ${INTERNAL_OGG_DIR}/*.c)
disable_warnings(${OGG_SOURCES})
set(OGG_INCLUDE_DIRS ${INTERNAL_OGG_DIR}/include)
list(APPEND CLIENT_LIBRARY_SOURCES ${OGG_SOURCES})
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(OGG REQUIRED ogg)
endif()
list(APPEND CLIENT_LIBRARIES ${OGG_LIBRARIES})
list(APPEND CLIENT_INCLUDE_DIRS ${OGG_INCLUDE_DIRS})
list(APPEND CLIENT_DEFINITIONS ${OGG_DEFINITIONS})

View File

@ -0,0 +1,23 @@
if(NOT USE_OPENAL)
return()
endif()
set(INTERNAL_OPENAL_DIR ${SOURCE_DIR}/thirdparty/openal-soft-1.24.3)
find_package(OpenAL QUIET)
if(NOT OpenAL_FOUND)
set(OPENAL_DEFINITIONS USE_INTERNAL_OPENAL_HEADERS)
set(OPENAL_INCLUDE_DIR ${INTERNAL_OPENAL_DIR}/include)
set(OPENAL_LIBRARY openal)
endif()
list(APPEND CLIENT_DEFINITIONS ${OPENAL_DEFINITIONS} USE_OPENAL)
list(APPEND CLIENT_INCLUDE_DIRS ${OPENAL_INCLUDE_DIR})
if(USE_OPENAL_DLOPEN)
list(APPEND CLIENT_DEFINITIONS USE_OPENAL_DLOPEN)
else()
find_package(Threads REQUIRED)
list(APPEND CLIENT_LIBRARIES Threads::Threads ${OPENAL_LIBRARY})
endif()

View File

@ -0,0 +1,27 @@
if(NOT USE_CODEC_OPUS)
return()
endif()
include(utils/disable_warnings)
include(utils/find_include_dirs)
set(INTERNAL_OPUS_DIR ${SOURCE_DIR}/thirdparty/opus-1.5.2)
set(INTERNAL_OPUSFILE_DIR ${SOURCE_DIR}/thirdparty/opusfile-0.12)
if(USE_INTERNAL_OPUS)
file(GLOB_RECURSE OPUS_SOURCES ${INTERNAL_OPUS_DIR}/*.c)
file(GLOB_RECURSE OPUSFILE_SOURCES ${INTERNAL_OPUSFILE_DIR}/*.c)
disable_warnings(${OPUS_SOURCES} ${OPUSFILE_SOURCES})
find_include_dirs(OPUS_INCLUDE_DIRS ${OPUS_SOURCES})
find_include_dirs(OPUSFILE_INCLUDE_DIRS ${OPUSFILE_SOURCES})
set(OPUS_INCLUDE_DIRS ${OPUS_INCLUDE_DIRS} ${OPUSFILE_INCLUDE_DIRS} ${INTERNAL_OPUSFILE_DIR}/include)
set(OPUS_DEFINITIONS USE_CODEC_OPUS OPUS_BUILD HAVE_LRINTF FLOATING_POINT FLOAT_APPROX USE_ALLOCA)
list(APPEND CLIENT_LIBRARY_SOURCES ${OPUS_SOURCES} ${OPUSFILE_SOURCES})
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(OPUS REQUIRED opus)
endif()
list(APPEND CLIENT_LIBRARIES ${OPUS_LIBRARIES})
list(APPEND CLIENT_INCLUDE_DIRS ${OPUS_INCLUDE_DIRS})
list(APPEND CLIENT_DEFINITIONS ${OPUS_DEFINITIONS})

51
cmake/libraries/sdl.cmake Normal file
View File

@ -0,0 +1,51 @@
set(INTERNAL_SDL_DIR ${SOURCE_DIR}/thirdparty/SDL2-2.32.8)
include(utils/arch)
if(NOT WIN32 AND NOT APPLE)
set(SYSTEM_SDL_REQUIRED REQUIRED)
endif()
find_package(SDL2 QUIET ${SYSTEM_SDL_REQUIRED})
if(NOT SDL2_FOUND)
set(SDL2_INCLUDE_DIRS ${INTERNAL_SDL_DIR}/include)
# On Windows and macOS we have internal SDL binaries we can use
if(WIN32)
if(ARCH STREQUAL "x86_64")
set(LIB_DIR ${SOURCE_DIR}/thirdparty/libs/win64)
elseif(ARCH STREQUAL "x86")
set(LIB_DIR ${SOURCE_DIR}/thirdparty/libs/win32)
else()
message(FATAL_ERROR "Unknown ARCH")
endif()
if(MINGW)
set(SDL2_LIBRARIES
${LIB_DIR}/libSDL2main.a
${LIB_DIR}/libSDL2.dll.a)
elseif(MSVC)
set(SDL2_LIBRARIES
${LIB_DIR}/SDL2main.lib
${LIB_DIR}/SDL2.lib)
endif()
list(APPEND CLIENT_DEPLOY_LIBRARIES ${LIB_DIR}/SDL2.dll)
elseif(APPLE)
set(SDL2_LIBRARIES
${SOURCE_DIR}/thirdparty/libs/macos/libSDL2main.a
${SOURCE_DIR}/thirdparty/libs/macos/libSDL2-2.0.0.dylib)
list(APPEND CLIENT_DEPLOY_LIBRARIES
${SOURCE_DIR}/thirdparty/libs/macos/libSDL2-2.0.0.dylib)
else()
message(FATAL_ERROR "SDL2 not found and no internal binaries available")
endif()
endif()
list(APPEND CLIENT_LIBRARIES ${SDL2_LIBRARIES})
list(APPEND CLIENT_INCLUDE_DIRS ${SDL2_INCLUDE_DIRS})
list(APPEND CLIENT_COMPILE_OPTIONS ${SDL2_CFLAGS_OTHER})
list(APPEND RENDERER_LIBRARIES ${SDL2_LIBRARIES})
list(APPEND RENDERER_INCLUDE_DIRS ${SDL2_INCLUDE_DIRS})
list(APPEND RENDERER_COMPILE_OPTIONS ${SDL2_CFLAGS_OTHER})

View File

@ -0,0 +1,22 @@
if(NOT USE_CODEC_VORBIS)
return()
endif()
include(utils/disable_warnings)
set(INTERNAL_VORBIS_DIR ${SOURCE_DIR}/thirdparty/libvorbis-1.3.7)
if(USE_INTERNAL_VORBIS)
file(GLOB_RECURSE VORBIS_SOURCES ${INTERNAL_VORBIS_DIR}/*.c)
disable_warnings(${VORBIS_SOURCES})
set(VORBIS_INCLUDE_DIRS ${INTERNAL_VORBIS_DIR}/include ${INTERNAL_VORBIS_DIR}/lib)
set(VORBIS_DEFINITIONS USE_CODEC_VORBIS)
list(APPEND CLIENT_LIBRARY_SOURCES ${VORBIS_SOURCES})
else()
find_package(PkgConfig REQUIRED)
pkg_check_modules(VORBIS REQUIRED vorbis)
endif()
list(APPEND CLIENT_LIBRARIES ${VORBIS_LIBRARIES})
list(APPEND CLIENT_INCLUDE_DIRS ${VORBIS_INCLUDE_DIRS})
list(APPEND CLIENT_DEFINITIONS ${VORBIS_DEFINITIONS})

View File

@ -0,0 +1,22 @@
include(utils/disable_warnings)
include(utils/find_include_dirs)
set(INTERNAL_ZLIB_DIR ${SOURCE_DIR}/thirdparty/zlib-1.3.1)
if(USE_INTERNAL_ZLIB)
file(GLOB_RECURSE ZLIB_SOURCES ${INTERNAL_ZLIB_DIR}/*.c)
disable_warnings(ZLIB_SOURCES)
find_include_dirs(ZLIB_INCLUDE_DIRS ${ZLIB_SOURCES})
set(ZLIB_DEFINITIONS NO_GZIP)
list(APPEND SERVER_LIBRARY_SOURCES ${ZLIB_SOURCES})
list(APPEND CLIENT_LIBRARY_SOURCES ${ZLIB_SOURCES})
else()
find_package(ZLIB REQUIRED)
endif()
list(APPEND SERVER_LIBRARIES ${ZLIB_LIBRARIES})
list(APPEND SERVER_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS})
list(APPEND SERVER_DEFINITIONS ${ZLIB_DEFINITIONS})
list(APPEND CLIENT_LIBRARIES ${ZLIB_LIBRARIES})
list(APPEND CLIENT_INCLUDE_DIRS ${ZLIB_INCLUDE_DIRS})
list(APPEND CLIENT_DEFINITIONS ${ZLIB_DEFINITIONS})

72
cmake/missionpack.cmake Normal file
View File

@ -0,0 +1,72 @@
if(NOT BUILD_GAME_LIBRARIES AND NOT BUILD_GAME_QVMS)
return()
endif()
include(utils/qvm_tools)
include(utils/set_output_dirs)
set(MPCGAME_SOURCES
${SOURCE_DIR}/cgame/cg_newdraw.c
${SOURCE_DIR}/ui/ui_shared.c
)
set(MPUI_SOURCES
${SOURCE_DIR}/ui/ui_main.c
${SOURCE_DIR}/ui/ui_atoms.c
${SOURCE_DIR}/ui/ui_gameinfo.c
${SOURCE_DIR}/ui/ui_players.c
${SOURCE_DIR}/ui/ui_shared.c
${SOURCE_DIR}/game/bg_misc.c
${SOURCE_DIR}/game/bg_lib.c
)
set(MISSIONPACK "missionpack")
set(CGAME_SOURCES_MISSIONPACK ${CGAME_SOURCES} ${MPCGAME_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
set(GAME_SOURCES_MISSIONPACK ${GAME_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
set(UI_SOURCES_MISSIONPACK ${MPUI_SOURCES} ${GAME_MODULE_SHARED_SOURCES})
if(BUILD_GAME_LIBRARIES)
set(CGAME_MODULE_BINARY_MISSIONPACK ${CGAME_MODULE_BINARY}_${MISSIONPACK})
set(GAME_MODULE_BINARY_MISSIONPACK ${GAME_MODULE_BINARY}_${MISSIONPACK})
set(UI_MODULE_BINARY_MISSIONPACK ${UI_MODULE_BINARY}_${MISSIONPACK})
add_library( ${CGAME_MODULE_BINARY_MISSIONPACK} SHARED ${CGAME_SOURCES_MISSIONPACK} ${CGAME_BINARY_SOURCES})
target_compile_definitions( ${CGAME_MODULE_BINARY_MISSIONPACK} PRIVATE CGAME MISSIONPACK)
set_target_properties( ${CGAME_MODULE_BINARY_MISSIONPACK} PROPERTIES OUTPUT_NAME ${CGAME_MODULE_BINARY})
set_output_dirs( ${CGAME_MODULE_BINARY_MISSIONPACK} SUBDIRECTORY ${MISSIONPACK})
add_library( ${GAME_MODULE_BINARY_MISSIONPACK} SHARED ${GAME_SOURCES_MISSIONPACK} ${GAME_BINARY_SOURCES})
target_compile_definitions( ${GAME_MODULE_BINARY_MISSIONPACK} PRIVATE QAGAME MISSIONPACK)
set_target_properties( ${GAME_MODULE_BINARY_MISSIONPACK} PROPERTIES OUTPUT_NAME ${GAME_MODULE_BINARY})
set_output_dirs( ${GAME_MODULE_BINARY_MISSIONPACK} SUBDIRECTORY ${MISSIONPACK})
add_library( ${UI_MODULE_BINARY_MISSIONPACK} SHARED ${UI_SOURCES_MISSIONPACK} ${UI_BINARY_SOURCES})
target_compile_definitions( ${UI_MODULE_BINARY_MISSIONPACK} PRIVATE UI MISSIONPACK)
set_target_properties( ${UI_MODULE_BINARY_MISSIONPACK} PROPERTIES OUTPUT_NAME ${UI_MODULE_BINARY})
set_output_dirs( ${UI_MODULE_BINARY_MISSIONPACK} SUBDIRECTORY ${MISSIONPACK})
endif()
if(BUILD_GAME_QVMS)
set(CGAME_MODULE_QVM_MISSIONPACK ${CGAME_MODULE}qvm_${MISSIONPACK})
set(GAME_MODULE_QVM_MISSIONPACK ${GAME_MODULE}qvm_${MISSIONPACK})
set(UI_MODULE_QVM_MISSIONPACK ${UI_MODULE}qvm_${MISSIONPACK})
add_qvm(${CGAME_MODULE_QVM_MISSIONPACK}
DEFINITIONS CGAME MISSIONPACK
OUTPUT_NAME ${CGAME_MODULE}
OUTPUT_DIRECTORY ${MISSIONPACK}/vm
SOURCES ${CGAME_SOURCES_MISSIONPACK} ${CGAME_QVM_SOURCES})
add_qvm(${GAME_MODULE_QVM_MISSIONPACK}
DEFINITIONS QAGAME MISSIONPACK
OUTPUT_NAME ${GAME_MODULE}
OUTPUT_DIRECTORY ${MISSIONPACK}/vm
SOURCES ${GAME_SOURCES_MISSIONPACK} ${GAME_QVM_SOURCES})
add_qvm(${UI_MODULE_QVM_MISSIONPACK}
DEFINITIONS UI MISSIONPACK
OUTPUT_NAME ${UI_MODULE}
OUTPUT_DIRECTORY ${MISSIONPACK}/vm
SOURCES ${UI_SOURCES_MISSIONPACK} ${UI_QVM_SOURCES})
endif()

View File

@ -0,0 +1,4 @@
include(platforms/emscripten)
include(platforms/macos)
include(platforms/unix)
include(platforms/windows)

View File

@ -0,0 +1,50 @@
# Emscripten specific settings
if(NOT EMSCRIPTEN)
return()
endif()
set(CMAKE_EXECUTABLE_SUFFIX ".js")
set(CMAKE_SHARED_LIBRARY_SUFFIX ".wasm")
# Disable options that don't make sense for emscripten
set(BUILD_SERVER OFF CACHE INTERNAL "")
set(BUILD_RENDERER_GL1 OFF CACHE INTERNAL "")
set(USE_RENDERER_DLOPEN OFF CACHE INTERNAL "")
set(USE_OPENAL_DLOPEN OFF CACHE INTERNAL "")
set(BUILD_GAME_LIBRARIES OFF CACHE INTERNAL "")
set(USE_HTTP OFF CACHE INTERNAL "")
list(APPEND CLIENT_COMPILE_OPTIONS -sUSE_SDL=2)
list(APPEND CLIENT_LINK_OPTIONS
-sTOTAL_MEMORY=256MB
-sSTACK_SIZE=5MB
-sMIN_WEBGL_VERSION=1
-sMAX_WEBGL_VERSION=2
-sEXPORTED_RUNTIME_METHODS=FS,addRunDependency,removeRunDependency
-sEXIT_RUNTIME=1
-sEXPORT_ES6
-sEXPORT_NAME=${CLIENT_NAME}
)
option(EMSCRIPTEN_PRELOAD_FILE "Preload game files into .data file" OFF)
if(EMSCRIPTEN_PRELOAD_FILE)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/${BASEGAME}")
message(FATAL_ERROR "No files in '${BASEGAME}' directory for emscripten to preload.")
endif()
list(APPEND CLIENT_LINK_OPTIONS "--preload-file ${BASEGAME}")
endif()
set(POST_CLIENT_CONFIGURE_FUNCTION deploy_shell_files)
function(deploy_shell_files)
configure_file(${SOURCE_DIR}/web/client.html.in
${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${CLIENT_NAME}.html @ONLY)
if(NOT EMSCRIPTEN_PRELOAD_FILE)
configure_file(${SOURCE_DIR}/web/client-config.json
${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}/${CLIENT_NAME}-config.json COPYONLY)
endif()
endfunction()

View File

@ -0,0 +1,80 @@
# macOS specific settings
if(NOT APPLE)
return()
endif()
# Including the arch in the filename doesn't really make sense
# on macOS where we're building Universal Binaries
set(USE_ARCHLESS_FILENAMES ON CACHE INTERNAL "")
option(BUILD_MACOS_APP "Deploy as a macOS .app" ON)
enable_language(OBJC)
list(APPEND SYSTEM_PLATFORM_SOURCES ${SOURCE_DIR}/sys/sys_osx.m)
list(APPEND COMMON_LIBRARIES "-framework Cocoa")
list(APPEND CLIENT_LIBRARIES "-framework IOKit")
list(APPEND RENDERER_LIBRARIES "-framework OpenGL")
set(CMAKE_OSX_DEPLOYMENT_TARGET 11.0)
set(CMAKE_OSX_ARCHITECTURES arm64;x86_64)
if(BUILD_MACOS_APP)
set(CLIENT_EXECUTABLE_OPTIONS MACOSX_BUNDLE)
set(POST_CLIENT_CONFIGURE_FUNCTION finish_macos_app)
endif()
function(finish_macos_app)
get_filename_component(MACOS_ICON_FILE ${MACOS_ICON_PATH} NAME)
set(MACOS_APP_BUNDLE_NAME ${CLIENT_NAME})
set(MACOS_APP_EXECUTABLE_NAME ${CLIENT_BINARY})
set(MACOS_APP_GUI_IDENTIFIER ${MACOS_BUNDLE_ID})
set(MACOS_APP_ICON_FILE ${MACOS_ICON_FILE})
set(MACOS_APP_SHORT_VERSION_STRING ${PRODUCT_VERSION})
set(MACOS_APP_BUNDLE_VERSION ${PRODUCT_VERSION})
set(MACOS_APP_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET})
set(MACOS_APP_COPYRIGHT ${COPYRIGHT})
if(PROTOCOL_HANDLER_SCHEME)
set(MACOS_APP_PLIST_URL_TYPES
"<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>${MACOS_APP_BUNDLE_NAME}</string>
<key>CFBundleURLSchemes</key>
<array>
<string>${PROTOCOL_HANDLER_SCHEME}</string>
</array>
</dict>
</array>")
else()
set(MACOS_APP_PLIST_URL_TYPES "")
endif()
configure_file(${CMAKE_SOURCE_DIR}/cmake/Info.plist.in
${CMAKE_BINARY_DIR}/Info.plist @ONLY)
set_target_properties(${CLIENT_BINARY} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_BINARY_DIR}/Info.plist)
set(RESOURCES_DIR $<TARGET_FILE_DIR:${CLIENT_BINARY}>/../Resources)
add_custom_command(TARGET ${CLIENT_BINARY} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${RESOURCES_DIR}
COMMAND ${CMAKE_COMMAND} -E copy ${MACOS_ICON_PATH} ${RESOURCES_DIR})
if(USE_RENDERER_DLOPEN)
set(MACOS_APP_BINARY_DIR ${CLIENT_BINARY}.app/Contents/MacOS)
if(BUILD_RENDERER_GL1)
set_output_dirs(${RENDERER_GL1_BINARY} SUBDIRECTORY ${MACOS_APP_BINARY_DIR})
endif()
if(BUILD_RENDERER_GL2)
set_output_dirs(${RENDERER_GL2_BINARY} SUBDIRECTORY ${MACOS_APP_BINARY_DIR})
endif()
endif()
endfunction()

View File

@ -0,0 +1,21 @@
# Unix specific settings (this includes macOS and emscripten)
if(NOT UNIX)
return()
endif()
list(APPEND SYSTEM_PLATFORM_SOURCES ${SOURCE_DIR}/sys/sys_unix.c)
if(EMSCRIPTEN)
list(APPEND SYSTEM_PLATFORM_SOURCES ${SOURCE_DIR}/sys/con_passive.c)
else()
list(APPEND SYSTEM_PLATFORM_SOURCES ${SOURCE_DIR}/sys/con_tty.c)
endif()
if(USE_HTTP)
list(APPEND CLIENT_PLATFORM_SOURCES ${SOURCE_DIR}/client/cl_http_curl.c)
endif()
list(APPEND COMMON_LIBRARIES dl m)
list(APPEND CLIENT_DEFINITIONS USE_ICON)

View File

@ -0,0 +1,35 @@
# Windows specific settings
if(NOT WIN32)
return()
endif()
list(APPEND SYSTEM_PLATFORM_SOURCES
${SOURCE_DIR}/sys/sys_win32.c
${SOURCE_DIR}/sys/con_passive.c
${SOURCE_DIR}/sys/win_resource.rc
)
if(USE_HTTP)
list(APPEND CLIENT_PLATFORM_SOURCES ${SOURCE_DIR}/client/cl_http_windows.c)
list(APPEND CLIENT_LIBRARIES wininet)
endif()
list(APPEND COMMON_LIBRARIES ws2_32 winmm psapi)
if(MINGW)
list(APPEND COMMON_LIBRARIES mingw32)
endif()
list(APPEND CLIENT_DEFINITIONS USE_ICON)
set_source_files_properties(${SOURCE_DIR}/sys/win_resource.rc
PROPERTIES COMPILE_DEFINITIONS WINDOWS_ICON_PATH=${WINDOWS_ICON_PATH})
if(MSVC)
# We have our own manifest, disable auto creation
list(APPEND SERVER_LINK_OPTIONS "/MANIFEST:NO")
list(APPEND CLIENT_LINK_OPTIONS "/MANIFEST:NO")
endif()
set(CLIENT_EXECUTABLE_OPTIONS WIN32)

View File

@ -0,0 +1,37 @@
include_guard(GLOBAL)
set(RENDERER_COMMON_SOURCES
${SOURCE_DIR}/renderercommon/tr_font.c
${SOURCE_DIR}/renderercommon/tr_image_bmp.c
${SOURCE_DIR}/renderercommon/tr_image_jpg.c
${SOURCE_DIR}/renderercommon/tr_image_pcx.c
${SOURCE_DIR}/renderercommon/tr_image_png.c
${SOURCE_DIR}/renderercommon/tr_image_tga.c
${SOURCE_DIR}/renderercommon/tr_noise.c
${SOURCE_DIR}/renderercommon/puff.c
)
set(SDL_RENDERER_SOURCES
${SOURCE_DIR}/sdl/sdl_gamma.c
${SOURCE_DIR}/sdl/sdl_glimp.c
)
set(DYNAMIC_RENDERER_SOURCES
${SOURCE_DIR}/renderercommon/tr_subs.c
${SOURCE_DIR}/qcommon/q_shared.c
${SOURCE_DIR}/qcommon/q_math.c
)
if(USE_FREETYPE)
list(APPEND RENDERER_DEFINITIONS BUILD_FREETYPE)
endif()
if(USE_RENDERER_DLOPEN)
list(APPEND RENDERER_DEFINITIONS USE_RENDERER_DLOPEN)
elseif(BUILD_RENDERER_GL1 AND BUILD_RENDERER_GL2)
message(FATAL_ERROR "Multiple static renderers enabled; choose one")
elseif(NOT BUILD_RENDERER_GL1 AND NOT BUILD_RENDERER_GL2)
message(FATAL_ERROR "Zero static renderers enabled; choose one")
endif()
list(APPEND RENDERER_LIBRARIES ${COMMON_LIBRARIES})

62
cmake/renderer_gl1.cmake Normal file
View File

@ -0,0 +1,62 @@
if(NOT BUILD_RENDERER_GL1)
return()
endif()
include(utils/arch)
include(utils/set_output_dirs)
include(renderer_common)
set(RENDERER_GL1_SOURCES
${SOURCE_DIR}/renderergl1/tr_altivec.c
${SOURCE_DIR}/renderergl1/tr_animation.c
${SOURCE_DIR}/renderergl1/tr_backend.c
${SOURCE_DIR}/renderergl1/tr_bsp.c
${SOURCE_DIR}/renderergl1/tr_cmds.c
${SOURCE_DIR}/renderergl1/tr_curve.c
${SOURCE_DIR}/renderergl1/tr_flares.c
${SOURCE_DIR}/renderergl1/tr_image.c
${SOURCE_DIR}/renderergl1/tr_init.c
${SOURCE_DIR}/renderergl1/tr_light.c
${SOURCE_DIR}/renderergl1/tr_main.c
${SOURCE_DIR}/renderergl1/tr_marks.c
${SOURCE_DIR}/renderergl1/tr_mesh.c
${SOURCE_DIR}/renderergl1/tr_model.c
${SOURCE_DIR}/renderergl1/tr_model_iqm.c
${SOURCE_DIR}/renderergl1/tr_scene.c
${SOURCE_DIR}/renderergl1/tr_shade.c
${SOURCE_DIR}/renderergl1/tr_shade_calc.c
${SOURCE_DIR}/renderergl1/tr_shader.c
${SOURCE_DIR}/renderergl1/tr_shadows.c
${SOURCE_DIR}/renderergl1/tr_sky.c
${SOURCE_DIR}/renderergl1/tr_surface.c
${SOURCE_DIR}/renderergl1/tr_world.c
)
set(RENDERER_GL1_BASENAME renderer_opengl1)
if(USE_ARCHLESS_FILENAMES)
set(RENDERER_GL1_BINARY ${RENDERER_GL1_BASENAME})
list(APPEND RENDERER_DEFINITIONS USE_ARCHLESS_FILENAMES)
else()
set(RENDERER_GL1_BINARY ${RENDERER_GL1_BASENAME}_${ARCH})
endif()
list(APPEND RENDERER_GL1_BINARY_SOURCES
${RENDERER_COMMON_SOURCES}
${RENDERER_GL1_SOURCES}
${SDL_RENDERER_SOURCES}
${RENDERER_LIBRARY_SOURCES})
if(USE_RENDERER_DLOPEN)
list(APPEND RENDERER_GL1_BINARY_SOURCES ${DYNAMIC_RENDERER_SOURCES})
add_library(${RENDERER_GL1_BINARY} SHARED ${RENDERER_GL1_BINARY_SOURCES})
target_link_libraries( ${RENDERER_GL1_BINARY} PRIVATE ${RENDERER_LIBRARIES})
target_include_directories( ${RENDERER_GL1_BINARY} PRIVATE ${RENDERER_INCLUDE_DIRS})
target_compile_definitions( ${RENDERER_GL1_BINARY} PRIVATE ${RENDERER_DEFINITIONS})
target_compile_options( ${RENDERER_GL1_BINARY} PRIVATE ${RENDERER_COMPILE_OPTIONS})
target_link_options( ${RENDERER_GL1_BINARY} PRIVATE ${RENDERER_LINK_OPTIONS})
set_output_dirs(${RENDERER_GL1_BINARY})
endif()

94
cmake/renderer_gl2.cmake Normal file
View File

@ -0,0 +1,94 @@
if(NOT BUILD_RENDERER_GL2)
return()
endif()
include(utils/arch)
include(utils/set_output_dirs)
include(renderer_common)
set(RENDERER_GL2_SOURCES
${SOURCE_DIR}/renderergl2/tr_animation.c
${SOURCE_DIR}/renderergl2/tr_backend.c
${SOURCE_DIR}/renderergl2/tr_bsp.c
${SOURCE_DIR}/renderergl2/tr_cmds.c
${SOURCE_DIR}/renderergl2/tr_curve.c
${SOURCE_DIR}/renderergl2/tr_dsa.c
${SOURCE_DIR}/renderergl2/tr_extramath.c
${SOURCE_DIR}/renderergl2/tr_extensions.c
${SOURCE_DIR}/renderergl2/tr_fbo.c
${SOURCE_DIR}/renderergl2/tr_flares.c
${SOURCE_DIR}/renderergl2/tr_glsl.c
${SOURCE_DIR}/renderergl2/tr_image.c
${SOURCE_DIR}/renderergl2/tr_image_dds.c
${SOURCE_DIR}/renderergl2/tr_init.c
${SOURCE_DIR}/renderergl2/tr_light.c
${SOURCE_DIR}/renderergl2/tr_main.c
${SOURCE_DIR}/renderergl2/tr_marks.c
${SOURCE_DIR}/renderergl2/tr_mesh.c
${SOURCE_DIR}/renderergl2/tr_model.c
${SOURCE_DIR}/renderergl2/tr_model_iqm.c
${SOURCE_DIR}/renderergl2/tr_postprocess.c
${SOURCE_DIR}/renderergl2/tr_scene.c
${SOURCE_DIR}/renderergl2/tr_shade.c
${SOURCE_DIR}/renderergl2/tr_shade_calc.c
${SOURCE_DIR}/renderergl2/tr_shader.c
${SOURCE_DIR}/renderergl2/tr_shadows.c
${SOURCE_DIR}/renderergl2/tr_sky.c
${SOURCE_DIR}/renderergl2/tr_surface.c
${SOURCE_DIR}/renderergl2/tr_vbo.c
${SOURCE_DIR}/renderergl2/tr_world.c
)
file(GLOB RENDERER_GL2_SHADER_SOURCES ${SOURCE_DIR}/renderergl2/glsl/*.glsl)
set(SHADERS_DIR ${CMAKE_BINARY_DIR}/shaders.dir)
file(MAKE_DIRECTORY ${SHADERS_DIR})
foreach(SHADER_FILE IN LISTS RENDERER_GL2_SHADER_SOURCES)
get_filename_component(SHADER_NAME ${SHADER_FILE} NAME_WE)
set(SHADER_C_FILE ${SHADERS_DIR}/${SHADER_NAME}.c)
string(REPLACE "${CMAKE_BINARY_DIR}/" "" SHADER_C_FILE_COMMENT ${SHADER_C_FILE})
add_custom_command(
OUTPUT ${SHADER_C_FILE}
COMMAND ${CMAKE_COMMAND}
-DINPUT_FILE=${SHADER_FILE}
-DOUTPUT_FILE=${SHADER_C_FILE}
-DSHADER_NAME=${SHADER_NAME}
-P ${CMAKE_SOURCE_DIR}/cmake/utils/stringify_shader.cmake
DEPENDS ${SHADER_FILE}
COMMENT "Stringify shader ${SHADER_C_FILE_COMMENT}")
list(APPEND RENDERER_GL2_SHADER_C_SOURCES ${SHADER_C_FILE})
endforeach()
set(RENDERER_GL2_BASENAME renderer_opengl2)
if(USE_ARCHLESS_FILENAMES)
set(RENDERER_GL2_BINARY ${RENDERER_GL2_BASENAME})
list(APPEND RENDERER_DEFINITIONS USE_ARCHLESS_FILENAMES)
else()
set(RENDERER_GL2_BINARY ${RENDERER_GL2_BASENAME}_${ARCH})
endif()
list(APPEND RENDERER_GL2_BINARY_SOURCES
${RENDERER_COMMON_SOURCES}
${RENDERER_GL2_SOURCES}
${RENDERER_GL2_SHADER_C_SOURCES}
${SDL_RENDERER_SOURCES}
${RENDERER_LIBRARY_SOURCES})
if(USE_RENDERER_DLOPEN)
list(APPEND RENDERER_GL2_BINARY_SOURCES ${DYNAMIC_RENDERER_SOURCES})
add_library(${RENDERER_GL2_BINARY} SHARED ${RENDERER_GL2_BINARY_SOURCES})
target_link_libraries( ${RENDERER_GL2_BINARY} PRIVATE ${RENDERER_LIBRARIES})
target_include_directories( ${RENDERER_GL2_BINARY} PRIVATE ${RENDERER_INCLUDE_DIRS})
target_compile_definitions( ${RENDERER_GL2_BINARY} PRIVATE ${RENDERER_DEFINITIONS})
target_compile_options( ${RENDERER_GL2_BINARY} PRIVATE ${RENDERER_COMPILE_OPTIONS})
target_link_options( ${RENDERER_GL2_BINARY} PRIVATE ${RENDERER_LINK_OPTIONS})
set_output_dirs(${RENDERER_GL2_BINARY})
endif()

54
cmake/server.cmake Normal file
View File

@ -0,0 +1,54 @@
if(NOT BUILD_SERVER)
return()
endif()
include(utils/set_output_dirs)
include(shared_sources)
set(NULL_SOURCES
${SOURCE_DIR}/null/null_client.c
${SOURCE_DIR}/null/null_input.c
${SOURCE_DIR}/null/null_snddma.c
)
if(USE_ARCHLESS_FILENAMES)
set(SERVER_BINARY ${SERVER_NAME})
list(APPEND SERVER_DEFINITIONS USE_ARCHLESS_FILENAMES)
else()
set(SERVER_BINARY ${SERVER_NAME}.${ARCH})
endif()
list(APPEND SERVER_DEFINITIONS DEDICATED)
list(APPEND SERVER_DEFINITIONS BOTLIB)
if(BUILD_STANDALONE)
list(APPEND SERVER_DEFINITIONS STANDALONE)
endif()
if(USE_VOIP)
list(APPEND SERVER_DEFINITIONS USE_VOIP)
endif()
list(APPEND SERVER_BINARY_SOURCES
${SERVER_SOURCES}
${NULL_SOURCES}
${COMMON_SOURCES}
${BOTLIB_SOURCES}
${SYSTEM_SOURCES}
${ASM_SOURCES}
${SERVER_LIBRARY_SOURCES})
add_executable(${SERVER_BINARY} ${SERVER_EXECUTABLE_OPTIONS} ${SERVER_BINARY_SOURCES})
target_include_directories( ${SERVER_BINARY} PRIVATE ${SERVER_INCLUDE_DIRS})
target_compile_definitions( ${SERVER_BINARY} PRIVATE ${SERVER_DEFINITIONS})
target_compile_options( ${SERVER_BINARY} PRIVATE ${SERVER_COMPILE_OPTIONS})
target_link_libraries( ${SERVER_BINARY} PRIVATE ${COMMON_LIBRARIES} ${SERVER_LIBRARIES})
target_link_options( ${SERVER_BINARY} PRIVATE ${SERVER_LINK_OPTIONS})
set_output_dirs(${SERVER_BINARY})
if(POST_SERVER_CONFIGURE_FUNCTION)
cmake_language(CALL ${POST_SERVER_CONFIGURE_FUNCTION})
endif()

104
cmake/shared_sources.cmake Normal file
View File

@ -0,0 +1,104 @@
include_guard(GLOBAL)
include(utils/add_git_dependency)
include(utils/arch)
include(utils/disable_warnings)
set(COMMON_SOURCES
${SOURCE_DIR}/qcommon/cm_load.c
${SOURCE_DIR}/qcommon/cm_patch.c
${SOURCE_DIR}/qcommon/cm_polylib.c
${SOURCE_DIR}/qcommon/cm_test.c
${SOURCE_DIR}/qcommon/cm_trace.c
${SOURCE_DIR}/qcommon/cmd.c
${SOURCE_DIR}/qcommon/common.c
${SOURCE_DIR}/qcommon/cvar.c
${SOURCE_DIR}/qcommon/files.c
${SOURCE_DIR}/qcommon/md4.c
${SOURCE_DIR}/qcommon/md5.c
${SOURCE_DIR}/qcommon/msg.c
${SOURCE_DIR}/qcommon/net_chan.c
${SOURCE_DIR}/qcommon/net_ip.c
${SOURCE_DIR}/qcommon/huffman.c
${SOURCE_DIR}/qcommon/q_math.c
${SOURCE_DIR}/qcommon/q_shared.c
${SOURCE_DIR}/qcommon/unzip.c
${SOURCE_DIR}/qcommon/ioapi.c
${SOURCE_DIR}/qcommon/vm.c
${SOURCE_DIR}/qcommon/vm_interpreted.c
)
disable_warnings(
${SOURCE_DIR}/qcommon/unzip.c
${SOURCE_DIR}/qcommon/ioapi.c
)
add_git_dependency(${SOURCE_DIR}/qcommon/common.c)
if(ARCH MATCHES "x86" OR ARCH MATCHES "x86_64")
list(APPEND COMMON_SOURCES
${SOURCE_DIR}/qcommon/vm_x86.c
)
elseif(ARCH MATCHES "ppc" OR ARCH MATCHES "ppc64")
list(APPEND COMMON_SOURCES
${SOURCE_DIR}/qcommon/vm_powerpc.c
${SOURCE_DIR}/qcommon/vm_powerpc_asm.c
)
elseif(ARCH MATCHES "arm")
list(APPEND COMMON_SOURCES
${SOURCE_DIR}/qcommon/vm_armv71.c
)
else()
list(APPEND SERVER_DEFINITIONS NO_VM_COMPILED)
list(APPEND CLIENT_DEFINITIONS NO_VM_COMPILED)
endif()
set(SYSTEM_SOURCES
${SOURCE_DIR}/sys/con_log.c
${SOURCE_DIR}/sys/sys_autoupdater.c
${SOURCE_DIR}/sys/sys_main.c
${SYSTEM_PLATFORM_SOURCES}
)
set(SERVER_SOURCES
${SOURCE_DIR}/server/sv_bot.c
${SOURCE_DIR}/server/sv_client.c
${SOURCE_DIR}/server/sv_ccmds.c
${SOURCE_DIR}/server/sv_game.c
${SOURCE_DIR}/server/sv_init.c
${SOURCE_DIR}/server/sv_main.c
${SOURCE_DIR}/server/sv_net_chan.c
${SOURCE_DIR}/server/sv_snapshot.c
${SOURCE_DIR}/server/sv_world.c
)
set(BOTLIB_SOURCES
${SOURCE_DIR}/botlib/be_aas_bspq3.c
${SOURCE_DIR}/botlib/be_aas_cluster.c
${SOURCE_DIR}/botlib/be_aas_debug.c
${SOURCE_DIR}/botlib/be_aas_entity.c
${SOURCE_DIR}/botlib/be_aas_file.c
${SOURCE_DIR}/botlib/be_aas_main.c
${SOURCE_DIR}/botlib/be_aas_move.c
${SOURCE_DIR}/botlib/be_aas_optimize.c
${SOURCE_DIR}/botlib/be_aas_reach.c
${SOURCE_DIR}/botlib/be_aas_route.c
${SOURCE_DIR}/botlib/be_aas_routealt.c
${SOURCE_DIR}/botlib/be_aas_sample.c
${SOURCE_DIR}/botlib/be_ai_char.c
${SOURCE_DIR}/botlib/be_ai_chat.c
${SOURCE_DIR}/botlib/be_ai_gen.c
${SOURCE_DIR}/botlib/be_ai_goal.c
${SOURCE_DIR}/botlib/be_ai_move.c
${SOURCE_DIR}/botlib/be_ai_weap.c
${SOURCE_DIR}/botlib/be_ai_weight.c
${SOURCE_DIR}/botlib/be_ea.c
${SOURCE_DIR}/botlib/be_interface.c
${SOURCE_DIR}/botlib/l_crc.c
${SOURCE_DIR}/botlib/l_libvar.c
${SOURCE_DIR}/botlib/l_log.c
${SOURCE_DIR}/botlib/l_memory.c
${SOURCE_DIR}/botlib/l_precomp.c
${SOURCE_DIR}/botlib/l_script.c
${SOURCE_DIR}/botlib/l_struct.c
)

View File

@ -0,0 +1,86 @@
cmake_minimum_required(VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
project(qvm_tools LANGUAGES C)
include(utils/set_output_dirs)
set(Q3ASM_SOURCES
${SOURCE_DIR}/tools/asm/q3asm.c
${SOURCE_DIR}/tools/asm/cmdlib.c
)
set(Q3LCC_SOURCES
${SOURCE_DIR}/tools/lcc/etc/lcc.c
${SOURCE_DIR}/tools/lcc/etc/bytecode.c
)
set(Q3RCC_SOURCES
${SOURCE_DIR}/tools/lcc/src/alloc.c
${SOURCE_DIR}/tools/lcc/src/bind.c
${SOURCE_DIR}/tools/lcc/src/bytecode.c
${SOURCE_DIR}/tools/lcc/src/dag.c
${SOURCE_DIR}/tools/lcc/src/decl.c
${SOURCE_DIR}/tools/lcc/src/enode.c
${SOURCE_DIR}/tools/lcc/src/error.c
${SOURCE_DIR}/tools/lcc/src/event.c
${SOURCE_DIR}/tools/lcc/src/expr.c
${SOURCE_DIR}/tools/lcc/src/gen.c
${SOURCE_DIR}/tools/lcc/src/init.c
${SOURCE_DIR}/tools/lcc/src/inits.c
${SOURCE_DIR}/tools/lcc/src/input.c
${SOURCE_DIR}/tools/lcc/src/lex.c
${SOURCE_DIR}/tools/lcc/src/list.c
${SOURCE_DIR}/tools/lcc/src/main.c
${SOURCE_DIR}/tools/lcc/src/null.c
${SOURCE_DIR}/tools/lcc/src/output.c
${SOURCE_DIR}/tools/lcc/src/prof.c
${SOURCE_DIR}/tools/lcc/src/profio.c
${SOURCE_DIR}/tools/lcc/src/simp.c
${SOURCE_DIR}/tools/lcc/src/stmt.c
${SOURCE_DIR}/tools/lcc/src/string.c
${SOURCE_DIR}/tools/lcc/src/sym.c
${SOURCE_DIR}/tools/lcc/src/symbolic.c
${SOURCE_DIR}/tools/lcc/src/trace.c
${SOURCE_DIR}/tools/lcc/src/tree.c
${SOURCE_DIR}/tools/lcc/src/types.c
)
set(Q3RCC_DAGCHECK_SOURCE ${SOURCE_DIR}/tools/lcc/src/dagcheck.md)
set(Q3CPP_SOURCES
${SOURCE_DIR}/tools/lcc/cpp/cpp.c
${SOURCE_DIR}/tools/lcc/cpp/lex.c
${SOURCE_DIR}/tools/lcc/cpp/nlist.c
${SOURCE_DIR}/tools/lcc/cpp/tokens.c
${SOURCE_DIR}/tools/lcc/cpp/macro.c
${SOURCE_DIR}/tools/lcc/cpp/eval.c
${SOURCE_DIR}/tools/lcc/cpp/include.c
${SOURCE_DIR}/tools/lcc/cpp/hideset.c
${SOURCE_DIR}/tools/lcc/cpp/getopt.c
${SOURCE_DIR}/tools/lcc/cpp/unix.c
)
set(LBURG_SOURCES
${SOURCE_DIR}/tools/lcc/lburg/lburg.c
${SOURCE_DIR}/tools/lcc/lburg/gram.c
)
add_executable(q3asm ${Q3ASM_SOURCES})
set_output_dirs(q3asm)
add_executable(q3lcc ${Q3LCC_SOURCES})
set_output_dirs(q3lcc)
add_dependencies(q3lcc q3rcc q3cpp)
add_executable(lburg ${LBURG_SOURCES})
set_output_dirs(lburg)
set(DAGCHECK_C ${CMAKE_BINARY_DIR}/dagcheck.c)
add_custom_command(
OUTPUT ${DAGCHECK_C}
COMMAND lburg ${Q3RCC_DAGCHECK_SOURCE} ${DAGCHECK_C}
DEPENDS lburg ${Q3RCC_DAGCHECK_SOURCE})
add_executable(q3rcc ${Q3RCC_SOURCES} ${DAGCHECK_C})
set_output_dirs(q3rcc)
target_include_directories(q3rcc PRIVATE ${SOURCE_DIR}/tools/lcc/src)
add_executable(q3cpp ${Q3CPP_SOURCES})
set_output_dirs(q3cpp)

View File

@ -0,0 +1,27 @@
include_guard(GLOBAL)
function(add_git_dependency SOURCE_FILE)
set(GIT_DIR ${CMAKE_SOURCE_DIR}/.git)
if(NOT EXISTS ${GIT_DIR})
return()
endif()
set(GIT_FILES)
list(APPEND GIT_FILES ${GIT_DIR}/HEAD)
list(APPEND GIT_FILES ${GIT_DIR}/packed-refs)
file(READ ${GIT_DIR}/HEAD GIT_HEAD)
string(REGEX MATCH "^ref: (.+)$" HAVE_REF ${GIT_HEAD})
if(HAVE_REF)
set(GIT_REF_PATH ${CMAKE_MATCH_1})
string(STRIP ${GIT_REF_PATH} GIT_REF_PATH)
list(APPEND GIT_FILES ${GIT_DIR}/${GIT_REF_PATH})
endif()
foreach(GIT_FILE IN LISTS GIT_FILES)
if(EXISTS ${GIT_FILE})
set_source_files_properties(${SOURCE_FILE}
PROPERTIES OBJECT_DEPENDS ${GIT_FILE})
endif()
endforeach()
endfunction()

23
cmake/utils/arch.cmake Normal file
View File

@ -0,0 +1,23 @@
include_guard(GLOBAL)
set(DETECT_ARCH_C ${CMAKE_BINARY_DIR}/detect_arch.c)
file(WRITE ${DETECT_ARCH_C}
"#include \"${SOURCE_DIR}/qcommon/q_platform.h\"
#include <stdio.h>
int main()
{
puts(ARCH_STRING);
return 0;
}
")
try_run(RUN_EXITCODE COMPILE_SUCCESS
${CMAKE_BINARY_DIR} ${DETECT_ARCH_C}
RUN_OUTPUT_VARIABLE ARCH)
string(STRIP ${ARCH} ARCH)
if(NOT COMPILE_SUCCESS OR RUN_EXITCODE OR NOT ARCH)
message(FATAL_ERROR "Architecture detection failed")
endif()

View File

@ -0,0 +1,17 @@
include_guard(GLOBAL)
function(disable_warnings)
set(SOURCES ${ARGN})
foreach(FILE IN LISTS SOURCES)
if(MSVC)
# Annoyingly if you disable all warnings (/w) in combination with enabling
# some warnings, which we and/or CMake inevitably do, this causes a
# meta-warning D9025, so instead we have to individually disable them:
set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS
"/wd4131 /wd4245 /wd4100 /wd4127 /wd4244 /wd4310 /wd4457 /wd4456 /wd4701 /wd4305 /wd4189 /wd4232")
else()
set_source_files_properties(${FILE} PROPERTIES COMPILE_FLAGS -w)
endif()
endforeach()
endfunction()

View File

@ -0,0 +1,37 @@
include_guard(GLOBAL)
function(find_include_dirs OUT_VAR)
set(SOURCES ${ARGN})
# Get top most common directory prefix for all source files
set(COMMON_PATH "")
foreach(FILE IN LISTS SOURCES)
get_filename_component(DIR ${FILE} DIRECTORY)
file(REAL_PATH ${DIR} DIR)
if(COMMON_PATH STREQUAL "")
set(COMMON_PATH ${DIR})
else()
string(LENGTH ${COMMON_PATH} PREFIX_LEN)
while(NOT ${DIR} MATCHES "^${COMMON_PATH}(/|$)" AND PREFIX_LEN GREATER 0)
string(SUBSTRING ${COMMON_PATH} 0 ${PREFIX_LEN} COMMON_PATH)
math(EXPR PREFIX_LEN "${PREFIX_LEN} - 1")
endwhile()
endif()
endforeach()
if(NOT IS_DIRECTORY ${COMMON_PATH})
message(FATAL_ERROR "Could not determine common directory for source files")
endif()
# Recursively find directories that contain .h files under common directory
file(GLOB_RECURSE HEADER_FILES ${COMMON_PATH}/*.h)
set(INCLUDE_DIRS "")
foreach(HEADER_FILE IN LISTS HEADER_FILES)
get_filename_component(HEADER_DIR ${HEADER_FILE} DIRECTORY)
list(APPEND INCLUDE_DIRS ${HEADER_DIR})
endforeach()
list(REMOVE_DUPLICATES INCLUDE_DIRS)
set(${OUT_VAR} ${INCLUDE_DIRS} PARENT_SCOPE)
endfunction()

View File

@ -0,0 +1,83 @@
include_guard(GLOBAL)
if(NOT BUILD_GAME_QVMS)
return()
endif()
include(ExternalProject)
set(TOOLS_DIR ${CMAKE_BINARY_DIR}/tools)
if(CMAKE_BUILD_TYPE)
set(BUILD_TYPE_ARG -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
endif()
ExternalProject_Add(qvm_tools
SOURCE_DIR ${CMAKE_SOURCE_DIR}/cmake/tools
BINARY_DIR ${TOOLS_DIR}
CMAKE_ARGS
-DSOURCE_DIR=${SOURCE_DIR}
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}
-DCMAKE_MINIMUM_REQUIRED_VERSION=${CMAKE_MINIMUM_REQUIRED_VERSION}
${BUILD_TYPE_ARG}
INSTALL_COMMAND "")
set(Q3LCC ${TOOLS_DIR}/$<CONFIG>/q3lcc)
set(Q3ASM ${TOOLS_DIR}/$<CONFIG>/q3asm)
function(add_qvm MODULE_NAME)
list(REMOVE_AT ARGV 0)
cmake_parse_arguments(ARG "" "" "DEFINITIONS;OUTPUT_NAME;OUTPUT_DIRECTORY;SOURCES" ${ARGV})
set(QVM_OUTPUT_DIR ${CMAKE_BINARY_DIR}/$<CONFIG>)
if(ARG_OUTPUT_DIRECTORY)
set(QVM_OUTPUT_DIR ${QVM_OUTPUT_DIR}/${ARG_OUTPUT_DIRECTORY})
endif()
add_custom_command(
OUTPUT ${QVM_OUTPUT_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${QVM_OUTPUT_DIR})
if(ARG_OUTPUT_NAME)
set(QVM_FILE ${QVM_OUTPUT_DIR}/${ARG_OUTPUT_NAME}.qvm)
else()
set(QVM_FILE ${QVM_OUTPUT_DIR}/${MODULE_NAME}.qvm)
endif()
set(QVM_ASM_DIR ${CMAKE_BINARY_DIR}/qvm.dir/${MODULE_NAME})
file(MAKE_DIRECTORY ${QVM_ASM_DIR})
set(LCC_FLAGS "")
foreach(DEFINITION IN LISTS ARG_DEFINITIONS)
list(APPEND LCC_FLAGS "-D${DEFINITION}")
endforeach()
set(ASM_FILES "")
foreach(SOURCE ${ARG_SOURCES})
if(${SOURCE} MATCHES "\\.asm$")
list(APPEND ASM_FILES ${SOURCE})
continue()
endif()
get_filename_component(BASE_FILE ${SOURCE} NAME_WE)
set(ASM_FILE ${QVM_ASM_DIR}/${BASE_FILE}.asm)
string(REPLACE "${CMAKE_BINARY_DIR}/" "" ASM_FILE_COMMENT ${ASM_FILE})
add_custom_command(
OUTPUT ${ASM_FILE}
COMMAND ${Q3LCC} ${LCC_FLAGS} -o ${ASM_FILE} ${SOURCE}
DEPENDS ${SOURCE} qvm_tools
COMMENT "Building C object ${ASM_FILE_COMMENT}")
list(APPEND ASM_FILES ${ASM_FILE})
endforeach()
string(REPLACE "${CMAKE_BINARY_DIR}/" "" QVM_FILE_COMMENT ${QVM_FILE})
add_custom_command(
OUTPUT ${QVM_FILE}
COMMAND ${Q3ASM} -o ${QVM_FILE} ${ASM_FILES}
DEPENDS ${ASM_FILES} qvm_tools
COMMENT "Linking C QVM library ${QVM_FILE_COMMENT}")
string(REGEX REPLACE "[^A-Za-z0-9]" "_" TARGET_NAME ${MODULE_NAME})
add_custom_target(${TARGET_NAME} ALL DEPENDS ${QVM_FILE})
endfunction()

View File

@ -0,0 +1,27 @@
include_guard(GLOBAL)
function(set_output_dirs TARGET)
list(REMOVE_AT ARGV 0)
cmake_parse_arguments(ARG "" "" "SUBDIRECTORY" ${ARGV})
if(CMAKE_CONFIGURATION_TYPES) # Multi-config
set(CONFIGS ${CMAKE_CONFIGURATION_TYPES})
else() # Single-config
set(CONFIGS ${CMAKE_BUILD_TYPE})
endif()
foreach(CONFIG ${CONFIGS})
string(TOUPPER ${CONFIG} CONFIG_UPPER)
if(ARG_SUBDIRECTORY)
set(OUT_DIR ${CMAKE_BINARY_DIR}/${CONFIG}/${ARG_SUBDIRECTORY})
else()
set(OUT_DIR ${CMAKE_BINARY_DIR}/${CONFIG})
endif()
set_target_properties(${TARGET} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY_${CONFIG_UPPER} ${OUT_DIR}
RUNTIME_OUTPUT_DIRECTORY_${CONFIG_UPPER} ${OUT_DIR}
ARCHIVE_OUTPUT_DIRECTORY_${CONFIG_UPPER} ${OUT_DIR})
endforeach()
endfunction()

View File

@ -0,0 +1,13 @@
# Convert a shader file to a compilable C file
# INPUT_FILE, OUTPUT_FILE, SHADER_NAME must be set via -D
file(READ ${INPUT_FILE} CONTENTS)
string(REPLACE "\\" "\\\\" CONTENTS "${CONTENTS}") # Escape backslashes
string(REPLACE "\"" "\\\"" CONTENTS "${CONTENTS}") # Escape double quotes
string(REPLACE "\n" "\\n\"\n\"" CONTENTS "${CONTENTS}") # Escape newlines
set(OUTPUT_CONTENT "const char *fallbackShader_${SHADER_NAME} =\n\"${CONTENTS}\";\n")
file(WRITE ${OUTPUT_FILE} "${OUTPUT_CONTENT}")