summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkasull <qsullian@gmail.com>2026-02-24 06:45:56 -0500
committerkasull <qsullian@gmail.com>2026-02-24 06:45:56 -0500
commitd97e17b180257f3425574eb3ba4189d312eb590a (patch)
tree97c8ea7b10158d8558e50d7150989082600c3493
parent3af651e5b65f51d9296c7a1a8ffc8adae6299f28 (diff)
enforce static Windows linkage and remove runtime DLL copy step
-rw-r--r--CMakeLists.txt113
-rw-r--r--cmake/copy_runtime_deps.cmake123
2 files changed, 83 insertions, 153 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f3638cb..561d10c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,49 +20,95 @@ pkg_check_modules(FREETYPE REQUIRED freetype2)
pkg_check_modules(GLEW REQUIRED glew)
find_package(OpenGL REQUIRED)
+
# release build settings
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-nontrivial-memcall")
# debug build settings
-set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG=1 -fsanitize=address -Wno-nontrivial-memcall")
-
-target_include_directories(app PRIVATE
- ${SDL2_INCLUDE_DIRS}
- ${FREETYPE_INCLUDE_DIRS}
- ${GLEW_INCLUDE_DIRS}
- ${OPENGL_INCLUDE_DIR}
-)
+if(WIN32)
+ set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG=1 -Wno-nontrivial-memcall")
+else()
+ set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG=1 -fsanitize=address -Wno-nontrivial-memcall")
+endif()
# Platform-specific linking
if(WIN32)
+ function(resolve_static_archives OUT_VAR LIB_DIRS_VAR LIBS_VAR)
+ set(_resolved "")
+ foreach(_lib IN LISTS ${LIBS_VAR})
+ if(IS_ABSOLUTE "${_lib}")
+ set(_archive_path "${_lib}")
+ else()
+ if(_lib MATCHES "^-")
+ message(FATAL_ERROR "Unexpected link flag in static library list: ${_lib}")
+ endif()
+
+ find_file(
+ _archive_path
+ NAMES "lib${_lib}.a" "${_lib}.a"
+ PATHS ${${LIB_DIRS_VAR}}
+ NO_DEFAULT_PATH
+ )
+ if(NOT _archive_path)
+ message(FATAL_ERROR "Could not find static archive for '${_lib}' in: ${${LIB_DIRS_VAR}}")
+ endif()
+ endif()
+
+ string(TOLOWER "${_archive_path}" _archive_path_lower)
+ if(NOT _archive_path_lower MATCHES "\\.a$" OR _archive_path_lower MATCHES "\\.dll\\.a$")
+ message(FATAL_ERROR "Expected static archive (.a), got: ${_archive_path}")
+ endif()
+
+ list(APPEND _resolved "${_archive_path}")
+ unset(_archive_path CACHE)
+ endforeach()
+
+ set(${OUT_VAR} "${_resolved}" PARENT_SCOPE)
+ endfunction()
+
+ set(SDL2_INCLUDE_DIRS ${SDL2_STATIC_INCLUDE_DIRS})
+ set(FREETYPE_INCLUDE_DIRS ${FREETYPE_STATIC_INCLUDE_DIRS})
+ set(GLEW_INCLUDE_DIRS ${GLEW_STATIC_INCLUDE_DIRS})
+
+ resolve_static_archives(
+ SDL2_LIBRARIES
+ SDL2_STATIC_LIBRARY_DIRS
+ SDL2_STATIC_LIBRARIES
+ )
+ resolve_static_archives(
+ FREETYPE_LIBRARIES
+ FREETYPE_STATIC_LIBRARY_DIRS
+ FREETYPE_STATIC_LIBRARIES
+ )
+ resolve_static_archives(
+ GLEW_LIBRARIES
+ GLEW_STATIC_LIBRARY_DIRS
+ GLEW_STATIC_LIBRARIES
+ )
+ set(CXX_STDLIB_LIBRARY_DIRS
+ ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}
+ ${SDL2_STATIC_LIBRARY_DIRS}
+ )
+ set(CXX_STDLIB_LIBRARY_NAMES c++ c++abi unwind)
+ resolve_static_archives(
+ CXX_STDLIB_LIBRARIES
+ CXX_STDLIB_LIBRARY_DIRS
+ CXX_STDLIB_LIBRARY_NAMES
+ )
+ foreach(APP_LINK_OPTION IN LISTS SDL2_STATIC_LDFLAGS_OTHER FREETYPE_STATIC_LDFLAGS_OTHER GLEW_STATIC_LDFLAGS_OTHER)
+ if(NOT APP_LINK_OPTION STREQUAL "")
+ set_property(TARGET app APPEND_STRING PROPERTY LINK_FLAGS " ${APP_LINK_OPTION}")
+ endif()
+ endforeach()
+
+ target_compile_definitions(app PRIVATE GLEW_STATIC)
target_link_libraries(app PRIVATE
${SDL2_LIBRARIES}
${FREETYPE_LIBRARIES}
${GLEW_LIBRARIES}
+ ${CXX_STDLIB_LIBRARIES}
${OPENGL_LIBRARIES}
winmm # For timeGetDevCaps, timeBeginPeriod, timeEndPeriod
)
-
- set(TOOLCHAIN_BIN_DIR "")
- if(CMAKE_CXX_COMPILER)
- get_filename_component(TOOLCHAIN_BIN_DIR "${CMAKE_CXX_COMPILER}" DIRECTORY)
- endif()
- if(NOT TOOLCHAIN_BIN_DIR OR TOOLCHAIN_BIN_DIR STREQUAL ".")
- find_program(CLANGXX_PATH NAMES clang++ clang++.exe)
- if(CLANGXX_PATH)
- get_filename_component(TOOLCHAIN_BIN_DIR "${CLANGXX_PATH}" DIRECTORY)
- endif()
- endif()
-
- add_custom_command(
- TARGET app
- POST_BUILD
- COMMAND "${CMAKE_COMMAND}"
- -DAPP_EXE=$<TARGET_FILE:app>
- -DAPP_OUT_DIR=$<TARGET_FILE_DIR:app>
- -DTOOLCHAIN_BIN_DIR=${TOOLCHAIN_BIN_DIR}
- -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/copy_runtime_deps.cmake
- VERBATIM
- )
else()
target_link_libraries(app PRIVATE
${SDL2_LIBRARIES}
@@ -72,6 +118,13 @@ else()
)
endif()
+target_include_directories(app PRIVATE
+ ${SDL2_INCLUDE_DIRS}
+ ${FREETYPE_INCLUDE_DIRS}
+ ${GLEW_INCLUDE_DIRS}
+ ${OPENGL_INCLUDE_DIR}
+)
+
target_compile_options(app PRIVATE -Wall)
target_compile_options(app PRIVATE -Wno-nontrivial-memcall)
diff --git a/cmake/copy_runtime_deps.cmake b/cmake/copy_runtime_deps.cmake
deleted file mode 100644
index 9317e74..0000000
--- a/cmake/copy_runtime_deps.cmake
+++ /dev/null
@@ -1,123 +0,0 @@
-if(NOT DEFINED APP_EXE OR NOT DEFINED APP_OUT_DIR)
- message(FATAL_ERROR "APP_EXE and APP_OUT_DIR must be set")
-endif()
-
-if(NOT EXISTS "${APP_EXE}")
- message(FATAL_ERROR "Executable not found: ${APP_EXE}")
-endif()
-
-set(_search_dirs "")
-if((NOT DEFINED TOOLCHAIN_BIN_DIR OR TOOLCHAIN_BIN_DIR STREQUAL "") AND EXISTS "${APP_OUT_DIR}/CMakeCache.txt")
- file(
- STRINGS "${APP_OUT_DIR}/CMakeCache.txt"
- _compiler_line
- REGEX "^CMAKE_CXX_COMPILER:FILEPATH="
- LIMIT_COUNT 1
- )
- if(_compiler_line)
- string(REPLACE "CMAKE_CXX_COMPILER:FILEPATH=" "" TOOLCHAIN_BIN_DIR "${_compiler_line}")
- get_filename_component(TOOLCHAIN_BIN_DIR "${TOOLCHAIN_BIN_DIR}" DIRECTORY)
- endif()
-endif()
-
-if(DEFINED TOOLCHAIN_BIN_DIR AND NOT TOOLCHAIN_BIN_DIR STREQUAL "" AND EXISTS "${TOOLCHAIN_BIN_DIR}")
- list(APPEND _search_dirs "${TOOLCHAIN_BIN_DIR}")
-endif()
-
-if(NOT DEFINED TOOLCHAIN_BIN_DIR OR TOOLCHAIN_BIN_DIR STREQUAL "" OR NOT EXISTS "${TOOLCHAIN_BIN_DIR}")
- message(FATAL_ERROR "TOOLCHAIN_BIN_DIR is required and must exist")
-endif()
-
-file(TO_CMAKE_PATH "${TOOLCHAIN_BIN_DIR}" _toolchain_bin_dir_norm)
-string(TOLOWER "${_toolchain_bin_dir_norm}" _toolchain_bin_dir_norm_lower)
-
-function(_literal_to_case_insensitive_regex _literal _out_var)
- string(LENGTH "${_literal}" _len)
- if(_len EQUAL 0)
- set(${_out_var} "" PARENT_SCOPE)
- return()
- endif()
-
- set(_regex "")
- math(EXPR _last "${_len} - 1")
- foreach(_i RANGE 0 ${_last})
- string(SUBSTRING "${_literal}" ${_i} 1 _ch)
- if(_ch MATCHES "[A-Za-z]")
- string(TOUPPER "${_ch}" _up)
- string(TOLOWER "${_ch}" _lo)
- string(APPEND _regex "[${_up}${_lo}]")
- elseif(_ch STREQUAL ".")
- string(APPEND _regex "\\\\.")
- else()
- string(APPEND _regex "${_ch}")
- endif()
- endforeach()
-
- set(${_out_var} "${_regex}" PARENT_SCOPE)
-endfunction()
-
-set(_pre_exclude_regexes
- "^api-ms-win-.*"
- "^ext-ms-.*"
-)
-
-set(_windows_system_dlls
- "KERNEL32.dll"
- "USER32.dll"
- "GDI32.dll"
- "SHELL32.dll"
- "WINMM.dll"
- "OPENGL32.dll"
- "ADVAPI32.dll"
- "OLE32.dll"
- "OLEAUT32.dll"
- "COMDLG32.dll"
- "WS2_32.dll"
- "SECUR32.dll"
- "NTDLL.dll"
-)
-
-foreach(_dll IN LISTS _windows_system_dlls)
- _literal_to_case_insensitive_regex("${_dll}" _dll_regex)
- list(APPEND _pre_exclude_regexes "(^|.*[/\\\\])${_dll_regex}$")
-endforeach()
-
-file(GET_RUNTIME_DEPENDENCIES
- EXECUTABLES "${APP_EXE}"
- RESOLVED_DEPENDENCIES_VAR _resolved_deps
- UNRESOLVED_DEPENDENCIES_VAR _unresolved_deps
- CONFLICTING_DEPENDENCIES_PREFIX _conflicting_deps
- DIRECTORIES ${_search_dirs}
- PRE_EXCLUDE_REGEXES ${_pre_exclude_regexes}
- POST_EXCLUDE_REGEXES
- ".*[/\\\\]Windows[/\\\\]System32[/\\\\].*"
-)
-
-if(_unresolved_deps)
- message(STATUS "Unresolved runtime dependencies: ${_unresolved_deps}")
-endif()
-
-if(_conflicting_deps_FILENAMES)
- message(STATUS "Conflicting runtime dependency names: ${_conflicting_deps_FILENAMES}")
-endif()
-
-foreach(_dep IN LISTS _resolved_deps)
- file(TO_CMAKE_PATH "${_dep}" _dep_norm)
- string(TOLOWER "${_dep_norm}" _dep_norm_lower)
- if(NOT _dep_norm_lower MATCHES "^${_toolchain_bin_dir_norm_lower}/")
- continue()
- endif()
-
- get_filename_component(_name "${_dep}" NAME)
- if(_name STREQUAL "")
- continue()
- endif()
-
- execute_process(
- COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${_dep}" "${APP_OUT_DIR}/${_name}"
- RESULT_VARIABLE _copy_rc
- )
- if(NOT _copy_rc EQUAL 0)
- message(FATAL_ERROR "Failed to copy runtime dependency: ${_dep}")
- endif()
-endforeach()