aboutsummaryrefslogtreecommitdiff
path: root/libs/cmake_common/mo2_cpp.cmake
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/cmake_common/mo2_cpp.cmake
Fluorine Manager: full Linux port of Mod Organizer 2
Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'libs/cmake_common/mo2_cpp.cmake')
-rw-r--r--libs/cmake_common/mo2_cpp.cmake358
1 files changed, 358 insertions, 0 deletions
diff --git a/libs/cmake_common/mo2_cpp.cmake b/libs/cmake_common/mo2_cpp.cmake
new file mode 100644
index 0000000..1ed4250
--- /dev/null
+++ b/libs/cmake_common/mo2_cpp.cmake
@@ -0,0 +1,358 @@
+cmake_minimum_required(VERSION 3.21)
+
+include(CMakeParseArguments)
+include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
+
+#! mo2_configure_warnings : configuration warning for C++ target
+#
+# \param:WARNINGS level of warnings, possible values are ON/All, OFF, or 1, 2, 3, 4
+# for corresponding /W flags (ON is All) (default ON)
+# \param:EXTERNAL enable warnings for external libraries, possible values are
+# the same as warnings, but ON is 3 (default 1)
+#
+function(mo2_configure_warnings TARGET)
+ cmake_parse_arguments(MO2 "" "WARNINGS;EXTERNAL" "" ${ARGN})
+
+ mo2_set_if_not_defined(MO2_WARNINGS ON)
+ mo2_set_if_not_defined(MO2_EXTERNAL 1)
+
+ if (${MO2_WARNINGS} STREQUAL "ON")
+ set(MO2_WARNINGS "All")
+ endif()
+
+ if (${MO2_EXTERNAL} STREQUAL "ON")
+ set(MO2_EXTERNAL "3")
+ endif()
+
+ if(NOT (${MO2_WARNINGS} STREQUAL "OFF"))
+ if(MSVC)
+ string(TOLOWER ${MO2_WARNINGS} MO2_WARNINGS)
+ target_compile_options(${TARGET} PRIVATE "/W${MO2_WARNINGS}" "/wd4464")
+
+ # external warnings
+ if (${MO2_EXTERNAL} STREQUAL "OFF")
+ target_compile_options(${TARGET}
+ PRIVATE "/external:anglebrackets" "/external:W0")
+ else()
+ string(TOLOWER ${MO2_EXTERNAL} MO2_EXTERNAL)
+ target_compile_options(${TARGET}
+ PRIVATE "/external:anglebrackets" "/external:W${MO2_EXTERNAL}")
+ endif()
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+ target_compile_options(${TARGET} PRIVATE -Wall -Wextra -Wno-unused-parameter)
+ endif()
+ endif()
+
+endfunction()
+
+#! mo2_target_sources : add sources to a given target, eventually putting them in
+# a folder
+#
+# \param: FILES list of .ui files to add
+# \param: RC_FILES list of .qrc or .rc files to add
+#
+function(mo2_target_sources TARGET)
+ cmake_parse_arguments(MO2 "" "FOLDER" "PRIVATE;PUBLIC" ${ARGN})
+
+ mo2_set_if_not_defined(MO2_PRIVATE "")
+ mo2_set_if_not_defined(MO2_PUBLIC "")
+
+ set(_sources "")
+
+ if (MO2_PRIVATE)
+ target_sources(${TARGET} PRIVATE ${MO2_PRIVATE})
+ list(APPEND _sources ${MO2_PRIVATE})
+ endif()
+
+ if (MO2_PUBLIC)
+ target_sources(${TARGET} PUBLIC ${MO2_PUBLIC})
+ list(APPEND _sources ${MO2_PUBLIC})
+ endif()
+
+ if ((DEFINED MO2_FOLDER) AND _sources)
+ source_group(${MO2_FOLDER} FILES ${_sources})
+ endif()
+
+endfunction()
+
+#! mo2_default_source_group : configure default source groups for MO2
+#
+# \param:NO_SRC if set, the src source_group will not be created, default if false
+#
+function(mo2_default_source_group)
+ cmake_parse_arguments(MO2 "SOURCE_TREE" "" "" ${ARGN})
+
+ # remove the CMake Rules autogenerated folder
+ source_group("CMake Rules" REGULAR_EXPRESSION "^$")
+ source_group(ui REGULAR_EXPRESSION ".*\\.ui")
+ source_group(cmake FILES CMakeLists.txt)
+ source_group(autogen REGULAR_EXPRESSION ".*\\cmake_pch.*|.*\\.rule")
+ source_group(resources REGULAR_EXPRESSION ".*\\.qrc|.*\\.rc")
+
+ if (NOT NO_SRC)
+ source_group(src REGULAR_EXPRESSION ".*\\.(h|cpp)$")
+ endif()
+endfunction()
+
+#! mo2_configure_sources : configure sources for the given C++ target
+#
+# \param:SOURCE_TREE if set, a source_group will be created using TREE
+#
+function(mo2_configure_sources TARGET)
+ cmake_parse_arguments(MO2 "SOURCE_TREE" "" "" ${ARGN})
+
+ # 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 ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
+ file(GLOB_RECURSE header_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.h)
+ file(GLOB_RECURSE qrc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc)
+ file(GLOB_RECURSE rc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.rc)
+ file(GLOB_RECURSE ui_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.ui)
+ file(GLOB_RECURSE ui_header_files CONFIGURE_DEPENDS ${UI_HEADERS_DIR}/*.h)
+ file(GLOB_RECURSE rule_files CONFIGURE_DEPENDS ${CMAKE_BINARY_DIR}/*.rule)
+
+
+
+ if (${MO2_SOURCE_TREE})
+ mo2_default_source_group(NO_SRC)
+ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
+ PREFIX src FILES ${source_files} ${header_files})
+ else()
+ mo2_default_source_group()
+ endif()
+
+ target_sources(${TARGET}
+ PRIVATE
+ ${source_files}
+ ${header_files}
+ ${ui_files}
+ ${ui_header_files}
+ ${qrc_files}
+ ${rc_files}
+ ${misc_files}
+ ${qm_files})
+
+endfunction()
+
+#! mo2_configure_msvc : set flags for C++ target with MSVC
+#
+# \param:PERMISSIVE permissive mode (default OFF)
+# \param:BIGOBJ enable bigobj (default OFF)
+# \param:CLI enable C++/CLR (default OFF)
+#
+function(mo2_configure_msvc TARGET)
+
+ if (NOT MSVC)
+ return()
+ endif()
+
+ cmake_parse_arguments(MO2 "" "PERMISSIVE;BIGOBJ;CLI" "" ${ARGN})
+
+ set(CXX_STANDARD 23)
+ if (${MO2_CLI})
+ set(CXX_STANDARD 17)
+ endif()
+ set_target_properties(${TARGET} PROPERTIES
+ CXX_STANDARD ${CXX_STANDARD} CXX_EXTENSIONS OFF)
+
+ if(NOT ${MO2_PERMISSIVE})
+ target_compile_options(${TARGET} PRIVATE "/permissive-")
+ endif()
+
+ if(${MO2_BIGOBJ})
+ target_compile_options(${TARGET} PRIVATE "/bigobj")
+ endif()
+
+ # multi-threaded compilation
+ target_compile_options(${TARGET} PRIVATE "/MP")
+
+ # VS emits a warning for LTCG, at least for uibase, so maybe not required?
+ target_link_options(${TARGET}
+ PRIVATE
+ $<$<CONFIG:RelWithDebInfo>:
+ # enable link-time code generation
+ /LTCG
+
+ # disable incremental linking
+ /INCREMENTAL:NO
+
+ # eliminates functions and data that are never referenced
+ /OPT:REF
+
+ # perform identical COMDAT folding
+ /OPT:ICF
+ >)
+
+ if(${MO2_CLI})
+ set_target_properties(${TARGET} PROPERTIES COMMON_LANGUAGE_RUNTIME "")
+ endif()
+
+ get_property(CURRENT_STARTUP_PROJECT
+ DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT)
+
+ if (NOT CURRENT_STARTUP_PROJECT)
+ message(STATUS "MO2: Setting startup project to " ${TARGET} ".")
+ set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${TARGET})
+ endif()
+
+endfunction()
+
+#! mo2_configure_target : do basic configuration for a MO2 C++ 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:SOURCE_TREE if set, a source_group will be created using TREE
+# \param:NO_SOURCES if set, mo2_configure_sources will not be called
+# \param:WARNINGS enable all warnings, possible values are ON/All, OFF, or 1, 2, 3, 4
+# for corresponding /W flags (ON is All) (default ON)
+# \param:EXTERNAL_WARNINGS enable warnings for external libraries, possible values are
+# the same as warnings, but ON is 3 (default 1)
+# \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:EXTRA_TRANSLATIONS extra translations to include (folder)
+#
+function(mo2_configure_target TARGET)
+ cmake_parse_arguments(MO2 "SOURCE_TREE;NO_SOURCES"
+ "WARNINGS;EXTERNAL_WARNINGS;PERMISSIVE;BIGOBJ;CLI;TRANSLATIONS;AUTOMOC"
+ "EXTRA_TRANSLATIONS"
+ ${ARGN})
+
+ # configure parameters and compiler flags
+ mo2_set_if_not_defined(MO2_NO_SOURCES OFF)
+ 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_configure_warnings(${TARGET} ${ARGN})
+ mo2_configure_msvc(${TARGET} ${ARGN})
+
+ if (NOT MO2_NO_SOURCES)
+ mo2_configure_sources(${TARGET} ${ARGN})
+ endif()
+
+ if (${MO2_AUTOMOC})
+ find_package(Qt6 COMPONENTS Widgets REQUIRED)
+ set_target_properties(${TARGET}
+ PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON)
+ endif()
+
+ if(${MO2_TRANSLATIONS})
+ mo2_add_translations(${TARGET}
+ INSTALL_RELEASE
+ SOURCES ${CMAKE_CURRENT_SOURCE_DIR} ${MO2_EXTRA_TRANSLATIONS})
+ endif()
+
+ mo2_find_git_hash(GIT_COMMIT_HASH)
+ target_compile_definitions(
+ ${TARGET} PRIVATE NOMINMAX 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()
+endfunction()
+
+#! mo2_configure_tests : configure a target as a MO2 C++ tests
+#
+# this function creates a set of tests available in the ${TARGET}_gtests variable
+#
+# extra arguments are given to mo2_configure_target, TRANSLATIONS and AUTOMOC are
+# OFF by default
+#
+function(mo2_configure_tests TARGET)
+ cmake_parse_arguments(MO2 "NO_MOCK;NO_MAIN" "" "" ${ARGN})
+ mo2_configure_target(${TARGET} TRANSLATIONS OFF AUTOMOC OFF ${MO2_UNPARSED_ARGUMENTS})
+
+ find_package(GTest REQUIRED)
+ target_link_libraries(${TARGET} PRIVATE GTest::gtest)
+
+ if (NOT MO2_NO_MOCK)
+ target_link_libraries(${TARGET} PRIVATE GTest::gmock)
+ endif()
+ if (NOT MO2_NO_MAIN)
+ target_link_libraries(${TARGET} PRIVATE GTest::gtest_main)
+ endif()
+
+ # gtest_discover_tests would be nice but it requires Qt DLL, uibase, etc., in the
+ # path, etc., and is not working right now
+ #
+ # there is an open CMake issue: https://gitlab.kitware.com/cmake/cmake/-/issues/21453
+ #
+ # gtest_discover_tests(${TARGET}
+ # WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
+ # PROPERTIES
+ # VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
+ # )
+ #
+
+ gtest_add_tests(
+ TARGET ${TARGET}
+ TEST_LIST ${TARGET}_gtests
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+ set(${TARGET}_gtests ${${TARGET}_gtests} PARENT_SCOPE)
+
+ if(WIN32)
+ mo2_deploy_qt_for_tests(
+ TARGET ${TARGET}
+ BINARIES "$<FILTER:$<TARGET_RUNTIME_DLLS:${TARGET}>,EXCLUDE,^.*[/\\]Qt[^/\\]*[.]dll>")
+
+ set_tests_properties(${${TARGET}_gtests}
+ PROPERTIES
+ ENVIRONMENT_MODIFICATION
+ "PATH=path_list_prepend:$<JOIN:$<TARGET_RUNTIME_DLL_DIRS:${TARGET}>,\;>"
+ )
+ endif()
+endfunction()
+
+#! mo2_configure_plugin : configure a target as a MO2 C++ plugin
+#
+# this function automatically set uibase as a dependency
+#
+# extra arguments are given to mo2_configure_target
+#
+function(mo2_configure_plugin TARGET)
+ mo2_configure_target(${TARGET} ${ARGN})
+ if(WIN32)
+ mo2_set_project_to_run_from_install(
+ ${TARGET} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/${MO2_INSTALL_BIN}/ModOrganizer.exe)
+ endif()
+endfunction()
+
+#! mo2_install_plugin : install the given MO2 plugin
+#
+# for this to work properly, the target must have been configured
+#
+# \param:FOLDER install the plugin as a folder, instead of a single DLL
+#
+function(mo2_install_plugin TARGET)
+ cmake_parse_arguments(MO2 "FOLDER" "" "" ${ARGN})
+
+ if (${MO2_FOLDER})
+ install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALL_BIN}/plugins/$<TARGET_FILE_BASE_NAME:${TARGET}>)
+ else()
+ install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALL_BIN}/plugins)
+ endif()
+
+ if (NOT MO2_INSTALL_IS_BIN)
+ install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
+ if(WIN32)
+ # install PDB if possible
+ install(FILES $<TARGET_PDB_FILE:${TARGET}> DESTINATION pdb OPTIONAL)
+ endif()
+ endif()
+
+endfunction()