mirror of
https://github.com/ModOrganizer2/cmake_common.git
synced 2026-07-27 14:06:46 -07:00
330 lines
11 KiB
CMake
330 lines
11 KiB
CMake
cmake_minimum_required(VERSION 3.16)
|
|
|
|
include(CMakeParseArguments)
|
|
include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
|
|
include(${CMAKE_CURRENT_LIST_DIR}/mo2_targets.cmake)
|
|
|
|
#! mo2_configure_target : do basic configuration for a MO2 target
|
|
#
|
|
# this functions does many things:
|
|
# - glob relevant files and add them to the target
|
|
# - set many compile flags, definitions, etc.
|
|
# - add step to create translations (if not turned OFF)
|
|
#
|
|
# \param:WARNINGS enable all warnings (default ON)
|
|
# \param:PERMISSIVE permissive mode (default OFF)
|
|
# \param:BIGOBJ enable bigobj (default OFF)
|
|
# \param:CLI enable C++/CLR (default OFF)
|
|
# \param:TRANSLATIONS generate translations (default ON)
|
|
# \param:AUTOMOC automoc (and autouic, autoqrc), (default ON)
|
|
# \param:BOOST add boost includes or library (OFF, INC, LIB), (default OFF)
|
|
# \param:EXTRA_TRANSLATIONS extra translations to include
|
|
#
|
|
function(mo2_configure_target MO2_TARGET)
|
|
cmake_parse_arguments(MO2 ""
|
|
"WARNINGS;PERMISSIVE;BIGOBJ;CLI;TRANSLATIONS;AUTOMOC"
|
|
"EXTRA_TRANSLATIONS;PUBLIC_DEPENDS;PRIVATE_DEPENDS"
|
|
${ARGN})
|
|
|
|
# configure parameters and compiler flags
|
|
mo2_set_if_not_defined(MO2_WARNINGS ON)
|
|
mo2_set_if_not_defined(MO2_PERMISSIVE OFF)
|
|
mo2_set_if_not_defined(MO2_BIGOBJ OFF)
|
|
mo2_set_if_not_defined(MO2_CLI OFF)
|
|
mo2_set_if_not_defined(MO2_TRANSLATIONS ON)
|
|
mo2_set_if_not_defined(MO2_AUTOMOC ON)
|
|
mo2_set_if_not_defined(MO2_EXTRA_TRANSLATIONS "")
|
|
mo2_set_if_not_defined(MO2_PUBLIC_DEPENDS "")
|
|
mo2_set_if_not_defined(MO2_PRIVATE_DEPENDS "")
|
|
|
|
if (${MO2_AUTOMOC})
|
|
find_package(Qt6 COMPONENTS Widgets REQUIRED)
|
|
set_target_properties(${MO2_TARGET}
|
|
PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON)
|
|
endif()
|
|
|
|
target_compile_options(${MO2_TARGET}
|
|
PRIVATE "/MP"
|
|
$<$<CONFIG:RelWithDebInfo>:/O2>
|
|
)
|
|
|
|
set(CXX_STANDARD 20)
|
|
if (${MO2_CLI})
|
|
set(CXX_STANDARD 17)
|
|
endif()
|
|
set_target_properties(${MO2_TARGET} PROPERTIES
|
|
CXX_STANDARD ${CXX_STANDARD}
|
|
CXX_EXTENSIONS OFF)
|
|
|
|
# VS emits a warning for LTCG, at least for uibase, so maybe not required?
|
|
target_link_options(${MO2_TARGET}
|
|
PRIVATE
|
|
$<$<CONFIG:RelWithDebInfo>:/LTCG /INCREMENTAL:NO /OPT:REF /OPT:ICF>)
|
|
|
|
if(${MO2_WARNINGS})
|
|
target_compile_options(${MO2_TARGET} PRIVATE "/Wall" "/wd4464")
|
|
endif()
|
|
|
|
if(NOT ${MO2_PERMISSIVE})
|
|
target_compile_options(${MO2_TARGET} PRIVATE "/permissive-")
|
|
endif()
|
|
|
|
if(${MO2_BIGOBJ})
|
|
target_compile_options(${MO2_TARGET} PRIVATE "/bigobj")
|
|
endif()
|
|
|
|
# find source files
|
|
if(DEFINED AUTOGEN_BUILD_DIR)
|
|
set(UI_HEADERS_DIR ${AUTOGEN_BUILD_DIR})
|
|
else()
|
|
set(UI_HEADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_autogen/include_RelWithDebInfo)
|
|
endif()
|
|
|
|
file(GLOB_RECURSE source_files CONFIGURE_DEPENDS *.cpp)
|
|
file(GLOB_RECURSE header_files CONFIGURE_DEPENDS *.h)
|
|
file(GLOB_RECURSE qrc_files CONFIGURE_DEPENDS *.qrc)
|
|
file(GLOB_RECURSE rc_files CONFIGURE_DEPENDS *.rc)
|
|
file(GLOB_RECURSE ui_files CONFIGURE_DEPENDS *.ui)
|
|
file(GLOB_RECURSE ui_header_files CONFIGURE_DEPENDS ${UI_HEADERS_DIR}/*.h)
|
|
file(GLOB_RECURSE rule_files CONFIGURE_DEPENDS ${CMAKE_BINARY_DIR}/*.rule)
|
|
file(GLOB_RECURSE misc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../*.natvis)
|
|
|
|
source_group(src REGULAR_EXPRESSION ".*\\.(h|cpp)")
|
|
source_group(ui REGULAR_EXPRESSION ".*\\.ui")
|
|
source_group(cmake FILES CMakeLists.txt)
|
|
source_group(autogen FILES ${rule_files} ${qm_files} ${ui_header_files})
|
|
source_group(autogen REGULAR_EXPRESSION ".*\\cmake_pch.*")
|
|
source_group(resources FILES ${rc_files} ${qrc_files})
|
|
|
|
|
|
if(${MO2_TRANSLATIONS})
|
|
find_package(Qt6LinguistTools)
|
|
|
|
if (MO2_EXTRA_TRANSLATIONS)
|
|
file(GLOB_RECURSE MO2_EXTRA_TRANSLATIONS CONFIGURE_DEPENDS
|
|
${MO2_EXTRA_TRANSLATIONS}/*.cpp
|
|
${MO2_EXTRA_TRANSLATIONS}/*.h
|
|
${MO2_EXTRA_TRANSLATIONS}/*.ui)
|
|
endif()
|
|
|
|
set(translation_files ${source_files} ${header_files} ${ui_files} ${MO2_EXTRA_TRANSLATIONS})
|
|
|
|
qt_add_translations(
|
|
${MO2_TARGET} TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}_en.ts
|
|
QM_FILES_OUTPUT_VARIABLE qm_files
|
|
SOURCES ${translation_files}
|
|
LUPDATE_OPTIONS -silent
|
|
)
|
|
|
|
# we need to set this property otherwise there is an issue with C# projects
|
|
# requiring nuget packages (e.g., installer_omod) that tries to resolve Nuget
|
|
# packages on these target but fails because there are obviously none
|
|
set_target_properties(${MO2_TARGET}_lrelease PROPERTIES
|
|
VS_GLOBAL_ResolveNugetPackages False)
|
|
set_target_properties(${MO2_TARGET}_lupdate PROPERTIES
|
|
VS_GLOBAL_ResolveNugetPackages False)
|
|
|
|
add_dependencies(${MO2_TARGET}_lrelease ${MO2_TARGET}_lupdate)
|
|
add_dependencies(${MO2_TARGET} ${MO2_TARGET}_lrelease)
|
|
|
|
install(FILES ${qm_files} DESTINATION bin/translations)
|
|
endif()
|
|
|
|
target_sources(${MO2_TARGET}
|
|
PRIVATE
|
|
${source_files}
|
|
${header_files}
|
|
${ui_files}
|
|
${ui_header_files}
|
|
${qrc_files}
|
|
${rc_files}
|
|
${misc_files}
|
|
${qm_files})
|
|
|
|
execute_process(
|
|
COMMAND git log -1 --format=%h
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
|
|
target_compile_definitions(
|
|
${MO2_TARGET}
|
|
PRIVATE
|
|
_UNICODE
|
|
UNICODE
|
|
NOMINMAX
|
|
_CRT_SECURE_NO_WARNINGS
|
|
BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE
|
|
_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING
|
|
QT_MESSAGELOGCONTEXT
|
|
GITID="${GIT_COMMIT_HASH}")
|
|
|
|
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
|
|
target_precompile_headers(${PROJECT_NAME}
|
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/pch.h)
|
|
endif()
|
|
|
|
if(${MO2_CLI})
|
|
if (CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
set_target_properties(${MO2_TARGET} PROPERTIES COMMON_LANGUAGE_RUNTIME "")
|
|
else()
|
|
# can this really happen?
|
|
set(COMPILE_FLAGS "${COMPILE_FLAGS} /clr")
|
|
string(REPLACE "/EHs" "/EHa" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
|
endif()
|
|
endif()
|
|
|
|
set_target_properties(${MO2_TARGET} PROPERTIES VS_STARTUP_PROJECT ${MO2_TARGET})
|
|
|
|
target_link_libraries(${MO2_TARGET} PRIVATE Version Dbghelp)
|
|
|
|
if (MO2_PUBLIC_DEPENDS)
|
|
mo2_add_dependencies(${MO2_TARGET} PUBLIC ${MO2_PUBLIC_DEPENDS})
|
|
endif()
|
|
|
|
if (MO2_PRIVATE_DEPENDS)
|
|
mo2_add_dependencies(${MO2_TARGET} PRIVATE ${MO2_PRIVATE_DEPENDS})
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
#! mo2_configure_tests : configure a target as a MO2 C++ tests
|
|
#
|
|
# extra arguments are given to mo2_configure_target
|
|
#
|
|
function(mo2_configure_tests MO2_TARGET)
|
|
mo2_find_uibase()
|
|
|
|
mo2_configure_target(${MO2_TARGET} TRANSLATIONS OFF AUTOMOC OFF ${ARGN})
|
|
set_target_properties(${MO2_TARGET} PROPERTIES MO2_TARGET_TYPE "tests")
|
|
|
|
find_package(GTest REQUIRED)
|
|
set_property(TARGET ${MO2_TARGET} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded")
|
|
target_link_libraries(${MO2_TARGET}
|
|
PRIVATE mo2::uibase GTest::gtest GTest::gmock GTest::gtest_main)
|
|
|
|
# this would be nice but it requires Qt DLL in the path, etc., which is kind of
|
|
# a PITA, and not working right now
|
|
# gtest_discover_tests(${MO2_TARGET} WORKING_DIRECTORY ${MO2_INSTALL_PATH}/bin)
|
|
endfunction()
|
|
|
|
#! mo2_configure_uibase : configure the uibase target for MO2
|
|
#
|
|
# this function does mostly nothing except calling mo2_configure_target, but is useful
|
|
# to be consistent with other mo2_configure_XXX
|
|
#
|
|
function(mo2_configure_uibase MO2_TARGET)
|
|
if (NOT (${MO2_TARGET} STREQUAL "uibase"))
|
|
message(WARNING "mo2_configure_uibase() should only be used on the uibase target")
|
|
endif()
|
|
|
|
mo2_configure_target(${MO2_TARGET} ${ARGN})
|
|
set_target_properties(${MO2_TARGET} PROPERTIES MO2_TARGET_TYPE "uibase")
|
|
|
|
target_include_directories(${MO2_TARGET} PUBLIC
|
|
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/game_features)
|
|
endfunction()
|
|
|
|
#! mo2_configure_plugin : configure a target as a MO2 C++ plugin
|
|
#
|
|
# extra arguments are given to mo2_configure_target
|
|
#
|
|
function(mo2_configure_plugin MO2_TARGET)
|
|
mo2_configure_target(${MO2_TARGET} ${ARGN})
|
|
mo2_add_dependencies(${MO2_TARGET} PRIVATE uibase)
|
|
|
|
set_target_properties(${MO2_TARGET} PROPERTIES MO2_TARGET_TYPE "plugin")
|
|
endfunction()
|
|
|
|
#! mo2_configure_library : configure a C++ library (NOT a plugin)
|
|
#
|
|
# extra arguments are given to mo2_configure_target
|
|
#
|
|
function(mo2_configure_library MO2_TARGET)
|
|
mo2_configure_target(${MO2_TARGET} AUTOMOC OFF TRANSLATIONS OFF ${ARGN})
|
|
|
|
get_target_property(TARGET_TYPE ${MO2_TARGET} TYPE)
|
|
|
|
target_include_directories(${MO2_TARGET}
|
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
|
|
|
if (${TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
|
|
set_target_properties(${MO2_TARGET} PROPERTIES MO2_TARGET_TYPE "library-static")
|
|
else()
|
|
set_target_properties(${MO2_TARGET} PROPERTIES MO2_TARGET_TYPE "library-shared")
|
|
endif()
|
|
endfunction()
|
|
|
|
#! mo2_configure_executable : configure a target as MO2 C++ executable
|
|
#
|
|
# extra arguments are given to mo2_configure_target
|
|
#
|
|
function(mo2_configure_executable MO2_TARGET)
|
|
cmake_parse_arguments(MO2 "ELEVATED" "" "" ${ARGN})
|
|
|
|
mo2_configure_target(${MO2_TARGET} ${ARGN})
|
|
set_target_properties(${MO2_TARGET}
|
|
PROPERTIES
|
|
WIN32_EXECUTABLE TRUE
|
|
MO2_TARGET_TYPE "executable")
|
|
|
|
if (${MO2_ELEVATED})
|
|
# does not work with target_link_options, so keeping it that way for now... this
|
|
# is not a very used option anyway
|
|
set_target_properties(${MO2_TARGET} PROPERTIES LINK_FLAGS
|
|
"/MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\"")
|
|
endif()
|
|
endfunction()
|
|
|
|
#! mo2_install_target : set install for a MO2 target
|
|
#
|
|
# for this to work properly, the target must have been configured
|
|
#
|
|
function(mo2_install_target MO2_TARGET)
|
|
cmake_parse_arguments(MO2 "" "INSTALLDIR" "" ${ARGN})
|
|
|
|
|
|
get_target_property(MO2_TARGET_TYPE ${MO2_TARGET} MO2_TARGET_TYPE)
|
|
|
|
# core install: .lib, .dll or .exe, to the right folder
|
|
if (${MO2_TARGET_TYPE} STREQUAL "uibase")
|
|
install(TARGETS ${MO2_TARGET} RUNTIME DESTINATION bin)
|
|
install(TARGETS ${MO2_TARGET} ARCHIVE DESTINATION libs)
|
|
elseif (${MO2_TARGET_TYPE} STREQUAL "plugin")
|
|
install(TARGETS ${MO2_TARGET} RUNTIME DESTINATION bin/plugins)
|
|
install(TARGETS ${MO2_TARGET} ARCHIVE DESTINATION libs)
|
|
elseif (${MO2_TARGET_TYPE} STREQUAL "library-static")
|
|
install(TARGETS ${MO2_TARGET} ARCHIVE DESTINATION libs)
|
|
elseif (${MO2_TARGET_TYPE} STREQUAL "library-shared")
|
|
mo2_set_if_not_defined(MO2_INSTALLDIR "bin/dlls")
|
|
install(TARGETS ${MO2_TARGET} RUNTIME DESTINATION ${MO2_INSTALLDIR})
|
|
install(TARGETS ${MO2_TARGET} ARCHIVE DESTINATION libs)
|
|
elseif (${MO2_TARGET_TYPE} STREQUAL "executable")
|
|
mo2_set_if_not_defined(MO2_INSTALLDIR "bin")
|
|
install(TARGETS ${MO2_TARGET} RUNTIME DESTINATION ${MO2_INSTALLDIR})
|
|
else()
|
|
message(ERROR "unknown MO2 target type for target '${MO2_TARGET}', did you forget using mo2_configure_XXX?")
|
|
endif()
|
|
|
|
# install PDB if possible
|
|
if (NOT (${MO2_TARGET_TYPE} STREQUAL "library-static"))
|
|
install(FILES $<TARGET_PDB_FILE:${MO2_TARGET}> DESTINATION pdb)
|
|
endif()
|
|
|
|
# set project to run from main MO2 executable or from themselves for executable
|
|
if (${MO2_TARGET_TYPE} STREQUAL "executable")
|
|
get_target_property(output_name ${MO2_TARGET} OUTPUT_NAME)
|
|
if("${output_name}" STREQUAL "output_name-NOTFOUND")
|
|
set(output_name ${MO2_TARGET})
|
|
|
|
mo2_set_project_to_run_from_install(
|
|
PROJECT ${PROJECT_NAME} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/bin/${output_name})
|
|
endif()
|
|
elseif(NOT (${MO2_TARGET_TYPE} STREQUAL "library-static"))
|
|
mo2_set_project_to_run_from_install(
|
|
PROJECT ${PROJECT_NAME} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/bin/ModOrganizer.exe)
|
|
endif()
|
|
|
|
endfunction()
|