Import stuff from registry and update README.

This commit is contained in:
Mikaël Capelle
2024-07-10 20:48:35 +02:00
parent 16fef181f8
commit 44457dc6dd
6 changed files with 316 additions and 906 deletions
+72 -70
View File
@@ -1,94 +1,96 @@
# MO2 CMake Common
This repository contains CMake macro and functions that are used in most MO2
repository to build uibase, modorganizer itself and plugins (C++/Python).
This repository contains useful CMake macro and functions that are used to ease creating
CMake configuration for most of MO2 repositories (e.g.,
[uibase](https://github.com/ModOrganizer2/modorganizer-uibase),
[plugin_python](https://github.com/ModOrganizer2/modorganizer-plugin_python) or
[ModOrganizer2](https://github.com/ModOrganizer2/modorganizer) itself).
## Getting Started
To get started, simply include the `mo2.cmake` file in your project:
### 1. With VCPKG
```cmake
# this can safely be included multiple time
include(path_to_cmake_common/mo2.cmake)
Add [MO2 VCPKG registry](https://github.com/ModOrganizer2/vcpkg-registry) to your
`vcpkg-configuration.json`:
```json
{
"default-registry": {
"kind": "git",
"repository": "https://github.com/Microsoft/vcpkg",
"baseline": "f61a294e765b257926ae9e9d85f96468a0af74e7"
},
"registries": [
{
"kind": "git",
"repository": "https://github.com/ModOrganizer2/vcpkg-registry",
"baseline": "27d8adbfe9e4ce88a875be3a45fadab69869eb60",
"packages": ["mo2-cmake"]
}
]
}
```
This will set some (not too intrusive) variables and define many useful functions,
all prefixed with `mo2_`.
The basic MO2 plugin/executable CMake will then look like this:
Add `mo2-cmake` to your VCPKG dependencies (`vcpkg.json`) and then import the utilities
with `find_package` in your CMake configuration:
```cmake
# this is for a C++ plugin
add_library(my_plugin SHARED)
# configure the plugin - this will also set the sources of the plugin
# based on the file in the current directory (and subdirectory)
mo2_configure_plugin(my_plugin)
# install the target to MO2 installation path, typically in the
# plugins/ folder
mo2_install_target(my_plugin)
find_package(mo2-cmake CONFIG REQUIRED)
```
## Configuring
### 2. Manually
The main entry-points are the the configure functions:
Clone this repository somewhere and then `include(mo2.cmake)` in your CMake
configuration files.
- C++
- `mo2_configure_target` - this is the "base" configuration,
which should not be used most of the time (this one is called by
other functions),
- `mo2_configure_uibase` - specific for uibase, should not be used
elsewhere,
- `mo2_configure_plugin` - configuration for a C++ plugin,
- `mo2_configure_library` - configuration for static or shared libraries,
- `mo2_configure_executable` - configuration for executables, including the main
MO2 executable,
- `mo2_configure_tests` - configuration for tests.
- Python
- `mo2_configure_python`.
## Usage
The function are documented so you can look at the documentation to see what arguments
are available.
Be aware that using these utilities will automatically some (not too intrusive) global
variable on your project.
You will need to have `Qt` in your CMake module path otherwise the import will fail
due to a broken `find_package(Qt6)`.
### Dependencies
For some functions to work properly, you should set `CMAKE_INSTALL_PREFIX` to a
directory where `${CMAKE_INSTALL_PREFIX}/bin/ModOrganizer.exe` can be found.
You can add dependencies to the target by using the standard `target_link_libraries`,
but this might be difficult when looking for MO2 dependencies, such as other libraries
or Qt.
All functions are prefixed by `mo2_` and should not conflict with other existing
functions.
The `mo2_configure_XXX` accept `PRIVATE_DEPENDS` and `PUBLIC_DEPENDS` parameters that
can be used to add dependencies to the target in an easier way.
These parameters accept 3 types of dependencies:
### Generic Utilities
- Qt dependencies, that should be specified as `Qt::COMPONENTS`, e.g., `Qt::Core` or
`Qt::Widgets`. Note that the `Qt::` is version-independent, MO2 will add the proper
version for you.
- Boost dependencies - For header only libraries, you can simply pass `boost`, for
non-header only libraries, you can pass `boost::COMPONENT`, e.g., `boost::threads`.
- MO2 dependencies - Those are either components available via the MO2 build system,
such as `zlib` or `libbsarch`, or other MO2 components such as `game_gamebryo`.
- `mo2_set_if_not_defined` - Set a variable to a given value if the variable is not
defined.
- `mo2_add_subdirectories` -
- `mo2_find_python_executable` - Find Python executable.
- `mo2_find_git_hash` - Find the hash of the current git HEAD.
- `mo2_find_qt_executable` - Find a given Qt executable.
- `mo2_set_project_to_run_from_install` - Configure the debug executable for a VS project.
- `mo2_add_filter` - Add a source group filter.
- `mo2_deploy_qt_for_tests` - Deploy Qt DLLs, etc., for tests.
- `mo2_deploy_qt` - Deploy Qt DLLs for ModOrganizer2.
- `mo2_add_lupdate` - Create a target to run Qt `lupdate`.
- `mo2_add_lrelease` - Create a target to Qt `lrelease`.
- `mo2_add_translations` - Add targets to generate translations for the given target.
## Installing
### C++ Utilities
For C++ plugin, you need to call `mo2_install_target` to install the plugins or
executable in MO2 installation directory.
Where the target should be installed is defined in the `mo2_configure_XXX` function
(which should be called before `mo2_install_target`).
TODO:
Installing Python plugins does not require extra call apart from `mo2_configure_python`.
- `mo2_configure_warnings` - Utility function configure warnings for a target.
- `mo2_configure_sources` - Glob and configure sources, including Qt-related files
(.ui, etc.) for a target.
- `mo2_configure_msvc` - Set some MSVC-specific flag for a target.
- (Deprecated) `mo2_configure_target` - Combine the above function + Extra stuff.
- (Deprecated) `mo2_configure_plugin`
- `mo2_configure_tests` - TO BE CHANGED
- `mo2_install_plugin` - Install a plugin.
## Examples
### Python Utilities
All MO2 repositories use these functions, so you can look at any repository to get
details on how to use them.
Here are entry points for the various type of plugins:
- [`game_skyrimse`](https://github.com/ModOrganizer2/modorganizer-game_skyrimSE/)
for a plugin that depends on a static library built by MO2.
- [`game_gamebryo`](https://github.com/ModOrganizer2/modorganizer-game_gamebryo/)
for a static library example.
- [`installer_wizard`](https://github.com/ModOrganizer2/modorganizer-installer_wizard)
for a Python plugin (module).
- [`fnistool`](https://github.com/ModOrganizer2/modorganizer-fnistool/) for a Python
plugin (simple file).
- `mo2_python_uifiles` - Add a target to generate `.py` files from `.ui` files.
- `mo2_python_pip_install` - Install Python packages.
- `mo2_python_requirements` - Install plugin requirements from a `plugin-requirements.txt`
file, ready to ship.
- `mo2_configure_python_module` - Configure a Python module plugin.
- (Deprecated) `mo2_configure_python_simple` - Configure a Python single file plugin.
- `mo2_configure_python` - Wrapper for the two above functions.
+13 -34
View File
@@ -4,42 +4,21 @@ if (DEFINED MO2_INCLUDED)
return()
endif()
set(MO2_QT_MAJOR_VERSION 6)
set(MO2_QT_MINOR_VERSION 7)
set(MO2_QT_PATCH_VERSION 0)
set(MO2_QT_VERSION "${MO2_QT_MAJOR_VERSION}.${MO2_QT_MINOR_VERSION}.${MO2_QT_PATCH_VERSION}")
set(MO2_PYTHON_VERSION "3.12")
find_package(Qt6 ${MO2_QT_VERSION} REQUIRED COMPONENTS Core)
# version-major independent variables
set(Qt_VERSION ${Qt6_VERSION})
set(Qt_VERSION_MAJOR ${Qt6_VERSION_MAJOR})
include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
# setup path for find_package(), etc.
mo2_required_variable(NAME BOOST_ROOT TYPE PATH)
mo2_required_variable(NAME QT_ROOT TYPE PATH)
mo2_required_variable(NAME PYTHON_ROOT TYPE PATH)
mo2_required_variable(NAME CMAKE_INSTALL_PREFIX TYPE PATH)
get_filename_component(MO2_BUILD_PATH "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH)
get_filename_component(MO2_SUPER_PATH "${MO2_BUILD_PATH}/modorganizer_super" REALPATH)
get_filename_component(MO2_UIBASE_PATH "${MO2_SUPER_PATH}/uibase" REALPATH)
get_filename_component(MO2_INSTALL_PATH "${MO2_SUPER_PATH}/../../install" REALPATH)
get_filename_component(MO2_INSTALL_LIBS_PATH "${MO2_INSTALL_PATH}/libs" REALPATH)
list(APPEND CMAKE_PREFIX_PATH
${QT_ROOT}/lib/cmake
${BOOST_ROOT}/build
${MO2_BUILD_PATH}/googletest/build/lib/cmake/GTest)
# find Qt major version and set QT_DEFAULT_MAJOR_VERSION to avoid issues
# when including LinguistTools without a QtCore
mo2_find_qt_version(QT_VERSION)
string(REPLACE "." ";" QT_VERSION_LIST ${QT_VERSION})
list(GET QT_VERSION_LIST 0 QT_MAJOR_VERSION)
# we add the Qt DLL to the paths for some tools
set(ENV{PATH} "${QT_ROOT}/bin;$ENV{PATH}")
# custom property, used to keep track of the type of target
define_property(
TARGET PROPERTY MO2_TARGET_TYPE INHERITED
BRIEF_DOCS "Target type for MO2 C++ target."
FULL_DOCS "Automatically set when using mo2_configure_XXX functions.")
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_USE_STATIC_LIBS ON)
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+161 -246
View File
@@ -1,12 +1,150 @@
cmake_minimum_required(VERSION 3.21)
if (POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
endif()
include(CMakeParseArguments)
include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/mo2_targets.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"))
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()
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})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
PREFIX src FILES ${source_files} ${header_files})
else()
source_group(src REGULAR_EXPRESSION ".*\\.(h|cpp)")
endif()
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})
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 20)
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()
set_target_properties(${TARGET} PROPERTIES VS_STARTUP_PROJECT ${TARGET})
endfunction()
#! mo2_configure_target : do basic configuration for a MO2 C++ target
#
@@ -26,27 +164,24 @@ include(${CMAKE_CURRENT_LIST_DIR}/mo2_targets.cmake)
# \param:TRANSLATIONS generate translations (default ON)
# \param:AUTOMOC automoc (and autouic, autoqrc), (default ON)
# \param:EXTRA_TRANSLATIONS extra translations to include (folder)
# \param:PUBLIC_DEPENDS adds PUBLIC dependencies to the target, see
# mo2_add_dependencies for information on what is available
# \param:PRIVATE_DEPENDS same a PUBLIC_DEPENDS, but link is PRIVATE instead of PUBLIC
#
function(mo2_configure_target TARGET)
cmake_parse_arguments(MO2 "SOURCE_TREE"
"WARNINGS;EXTERNAL_WARNINGS;PERMISSIVE;BIGOBJ;CLI;TRANSLATIONS;AUTOMOC"
"EXTRA_TRANSLATIONS;PUBLIC_DEPENDS;PRIVATE_DEPENDS"
"EXTRA_TRANSLATIONS"
${ARGN})
# configure parameters and compiler flags
mo2_set_if_not_defined(MO2_WARNINGS ON)
mo2_set_if_not_defined(MO2_EXTERNAL_WARNINGS 1)
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 "")
mo2_configure_warnings(${TARGET} ${ARGN})
mo2_configure_sources(${TARGET} ${ARGN})
mo2_configure_msvc(${TARGET} ${ARGN})
if (${MO2_AUTOMOC})
find_package(Qt6 COMPONENTS Widgets REQUIRED)
@@ -54,176 +189,34 @@ function(mo2_configure_target TARGET)
PROPERTIES AUTOMOC ON AUTOUIC ON AUTORCC ON)
endif()
target_compile_options(${TARGET}
PRIVATE "/MP"
$<$<CONFIG:RelWithDebInfo>:/O2>
)
set(CXX_STANDARD 20)
if (${MO2_CLI})
set(CXX_STANDARD 17)
endif()
set_target_properties(${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(${TARGET}
PRIVATE
$<$<CONFIG:RelWithDebInfo>:/LTCG /INCREMENTAL:NO /OPT:REF /OPT:ICF>)
if (${MO2_WARNINGS} STREQUAL "ON")
set(MO2_WARNINGS "All")
endif()
if (${MO2_EXTERNAL_WARNINGS} STREQUAL "ON")
set(MO2_EXTERNAL_WARNINGS "3")
endif()
if(NOT (${MO2_WARNINGS} STREQUAL "OFF"))
string(TOLOWER ${MO2_WARNINGS} MO2_WARNINGS)
target_compile_options(${TARGET} PRIVATE "/W${MO2_WARNINGS}" "/wd4464")
# external warnings
if (${MO2_EXTERNAL_WARNINGS} STREQUAL "OFF")
target_compile_options(${TARGET}
PRIVATE "/external:anglebrackets" "/external:W0")
else()
string(TOLOWER ${MO2_EXTERNAL_WARNINGS} MO2_EXTERNAL_WARNINGS)
target_compile_options(${TARGET}
PRIVATE "/external:anglebrackets" "/external:W${MO2_EXTERNAL_WARNINGS}")
endif()
endif()
if(NOT ${MO2_PERMISSIVE})
target_compile_options(${TARGET} PRIVATE "/permissive-")
endif()
if(${MO2_BIGOBJ})
target_compile_options(${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 ${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)
file(GLOB_RECURSE misc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../*.natvis)
if (${MO2_SOURCE_TREE})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
PREFIX src
FILES ${source_files} ${header_files})
else()
source_group(src REGULAR_EXPRESSION ".*\\.(h|cpp)")
endif()
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})
mo2_add_translations(${TARGET}
INSTALL_RELEASE
SOURCES ${CMAKE_CURRENT_SOURCE_DIR} ${MO2_EXTRA_TRANSLATIONS})
endif()
target_sources(${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
)
mo2_find_git_hash(GIT_COMMIT_HASH)
target_compile_definitions(
${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}")
${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()
if(${MO2_CLI})
if (CMAKE_GENERATOR MATCHES "Visual Studio")
set_target_properties(${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(${TARGET} PROPERTIES VS_STARTUP_PROJECT ${TARGET})
target_link_libraries(${TARGET} PRIVATE Version Dbghelp)
if (MO2_PUBLIC_DEPENDS)
mo2_add_dependencies(${TARGET} PUBLIC ${MO2_PUBLIC_DEPENDS})
endif()
if (MO2_PRIVATE_DEPENDS)
mo2_add_dependencies(${TARGET} PRIVATE ${MO2_PRIVATE_DEPENDS})
endif()
# set the VS startup project if not already set
get_property(startup_project DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT)
if (NOT startup_project)
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${TARGET})
endif()
endfunction()
#! mo2_configure_tests : configure a target as a MO2 C++ tests
#
# this function creates a set of tests available in the ${TARET}_gtests variable
#
# \param:DEPENDS dependencies to link to AND add folder for ctest to look for DLLs,
# typically the library being tests
#
# extra arguments are given to mo2_configure_target, TRANSLATIONS and AUTOMOC are
# OFF by default
#
function(mo2_configure_tests TARGET)
mo2_configure_target(${TARGET} TRANSLATIONS OFF AUTOMOC OFF ${ARGN})
cmake_parse_arguments(MO2 "" "" "DEPENDS" ${ARGN})
set_target_properties(${TARGET} PROPERTIES MO2_TARGET_TYPE "tests")
find_package(GTest REQUIRED)
target_link_libraries(${TARGET} PRIVATE GTest::gtest GTest::gmock GTest::gtest_main)
mo2_add_dependencies(${TARGET} PRIVATE ${MO2_DEPENDS})
# gtest_discover_tests would be nice but it requires Qt DLL, uibase, etc., in the
# path, etc., and is not working right now
@@ -231,9 +224,9 @@ function(mo2_configure_tests TARGET)
# there is an open CMake issue: https://gitlab.kitware.com/cmake/cmake/-/issues/21453
#
# gtest_discover_tests(${TARGET}
# WORKING_DIRECTORY ${MO2_INSTALL_PATH}/bin
# WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
# PROPERTIES
# VS_DEBUGGER_WORKING_DIRECTORY ${MO2_INSTALL_PATH}/bin
# VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin
# )
#
@@ -259,105 +252,27 @@ endfunction()
#
function(mo2_configure_plugin TARGET)
mo2_configure_target(${TARGET} ${ARGN})
mo2_add_dependencies(${TARGET} PUBLIC uibase)
set_target_properties(${TARGET} PROPERTIES MO2_TARGET_TYPE "plugin")
mo2_set_project_to_run_from_install(
${TARGET} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/bin/ModOrganizer.exe)
endfunction()
#! mo2_configure_library : configure a C++ library (NOT a plugin), can be a STATIC
# or SHARED library
#
# extra arguments are given to mo2_configure_target, TRANSLATIONS and AUTOMOC are
# OFF by default
#
function(mo2_configure_library TARGET)
mo2_configure_target(${TARGET} AUTOMOC OFF TRANSLATIONS OFF ${ARGN})
get_target_property(TARGET_TYPE ${TARGET} TYPE)
target_include_directories(${TARGET}
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
if (${TARGET_TYPE} STREQUAL "STATIC_LIBRARY")
set_target_properties(${TARGET} PROPERTIES MO2_TARGET_TYPE "library-static")
else()
mo2_set_project_to_run_from_install(
${TARGET} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/bin/ModOrganizer.exe)
set_target_properties(${TARGET} PROPERTIES MO2_TARGET_TYPE "library-shared")
endif()
endfunction()
#! mo2_configure_executable : configure a target as MO2 C++ executable
#
# \param:ELEVATED set flag on the executable to run as elevated by default
#
# extra arguments are given to mo2_configure_target
#
function(mo2_configure_executable TARGET)
cmake_parse_arguments(MO2 "ELEVATED" "" "" ${ARGN})
mo2_configure_target(${TARGET} ${ARGN})
set_target_properties(${TARGET}
PROPERTIES WIN32_EXECUTABLE TRUE MO2_TARGET_TYPE "executable")
get_target_property(output_name ${TARGET} OUTPUT_NAME)
if("${output_name}" STREQUAL "output_name-NOTFOUND")
set(output_name ${TARGET})
endif()
mo2_set_project_to_run_from_install(
${TARGET} EXECUTABLE ${CMAKE_INSTALL_PREFIX}/bin/${output_name})
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(${TARGET} PROPERTIES LINK_FLAGS
"/MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\"")
endif()
endfunction()
#! mo2_install_target : set install for a MO2 target
#! 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, ignore for
# other target types
# \param:INSTALLDIR installation directory, default is automatically deduced based on
# the target type, this parameter is ignored for plugins and static libraries
# \param:FOLDER install the plugin as a folder, instead of a single DLL
#
function(mo2_install_target TARGET)
cmake_parse_arguments(MO2 "FOLDER" "INSTALLDIR" "" ${ARGN})
function(mo2_install_plugin TARGET)
cmake_parse_arguments(MO2 "FOLDER" "" "" ${ARGN})
get_target_property(MO2_TARGET_TYPE ${TARGET} MO2_TARGET_TYPE)
# core install: .lib, .dll or .exe, to the right folder
if (${MO2_TARGET_TYPE} STREQUAL "plugin")
if (${MO2_FOLDER})
install(TARGETS ${TARGET} RUNTIME DESTINATION bin/plugins/$<TARGET_FILE_BASE_NAME:${TARGET}>)
else()
install(TARGETS ${TARGET} RUNTIME DESTINATION bin/plugins)
endif()
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
elseif (${MO2_TARGET_TYPE} STREQUAL "library-static")
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
elseif (${MO2_TARGET_TYPE} STREQUAL "library-shared")
mo2_set_if_not_defined(MO2_INSTALLDIR "bin/dlls")
install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALLDIR})
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
elseif (${MO2_TARGET_TYPE} STREQUAL "executable")
mo2_set_if_not_defined(MO2_INSTALLDIR "bin")
install(TARGETS ${TARGET} RUNTIME DESTINATION ${MO2_INSTALLDIR})
if (${MO2_FOLDER})
install(TARGETS ${TARGET} RUNTIME DESTINATION bin/plugins/$<TARGET_FILE_BASE_NAME:${TARGET}>)
else()
message(FATAL_ERROR "unknown MO2 target type for target '${TARGET}', did you forget using mo2_configure_XXX?")
install(TARGETS ${TARGET} RUNTIME DESTINATION bin/plugins)
endif()
install(TARGETS ${TARGET} ARCHIVE DESTINATION lib)
# install PDB if possible
if (NOT (${MO2_TARGET_TYPE} STREQUAL "library-static"))
install(FILES $<TARGET_PDB_FILE:${TARGET}> DESTINATION pdb)
endif()
install(FILES $<TARGET_PDB_FILE:${TARGET}> DESTINATION pdb OPTIONAL)
endfunction()
+6 -72
View File
@@ -32,12 +32,10 @@ function(mo2_python_uifiles TARGET)
set(output "${folder}/${name}.py")
add_custom_command(
OUTPUT "${output}"
COMMAND ${PYTHON_EXE}
-I
-m PyQt${QT_MAJOR_VERSION}.uic.pyuic
COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}/pylibs
${CMAKE_BINARY_DIR}/pylibs/bin/pyuic${Qt_VERSION_MAJOR}.exe
-o "${output}"
"${UI_FILE}"
WORKING_DIRECTORY ${PYTHON_ROOT}
DEPENDS "${UI_FILE}"
)
@@ -53,61 +51,7 @@ function(mo2_python_uifiles TARGET)
set_target_properties("${TARGET}_uic" PROPERTIES FOLDER autogen)
add_dependencies(${TARGET} "${TARGET}_uic")
endfunction()
#! mo2_python_rcfiles : create .py files from .qrc files for a python target
#
# \param:TARGET target to generate .py files for
# \param:INPLACE if specified, .py files are generated next to the .qrc files, useful
# for Python modules, otherwise files are generated in the binary directory
# \param:FILES list of .qrc files to generate .py files from
#
function(mo2_python_rcfiles TARGET)
cmake_parse_arguments(MO2 "" "INPLACE" "FILES" ${ARGN})
if (NOT MO2_FILES)
return()
endif()
mo2_find_python_executable(PYTHON_EXE)
message(DEBUG "generating .py from qrc files: ${MO2_FILES}")
set(pyrc_files "")
foreach (RC_FILE ${MO2_FILES})
get_filename_component(name "${RC_FILE}" NAME_WLE)
get_filename_component(folder "${RC_FILE}" DIRECTORY)
if (${MO2_INPLACE})
get_filename_component(folder "${RC_FILE}" DIRECTORY)
else()
set(folder "${CMAKE_CURRENT_BINARY_DIR}")
endif()
set(output "${folder}/${name}_rc.py")
add_custom_command(
OUTPUT "${output}"
COMMAND ${PYTHON_EXE}
-I
-m PyQt5.pyrcc_main
-o "${output}"
"${RC_FILE}"
WORKING_DIRECTORY ${PYTHON_ROOT}
DEPENDS "${RC_FILE}"
)
list(APPEND pyrc_files "${output}")
endforeach()
if (${MO2_INPLACE})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}
PREFIX autogen FILES ${pyrc_files})
endif()
add_custom_target("${TARGET}_qrc" DEPENDS ${pyrc_files})
set_target_properties("${TARGET}_qrc" PROPERTIES FOLDER autogen)
add_dependencies(${TARGET} "${TARGET}_qrc")
add_dependencies("${TARGET}_uic" PyQt6)
endfunction()
@@ -139,7 +83,6 @@ function(mo2_python_pip_install TARGET)
--target="${MO2_DIRECTORY}"
--log="${pip_log_file}"
${MO2_PACKAGES}
WORKING_DIRECTORY ${PYTHON_ROOT}
)
set(pip_target_name "${TARGET}_pip_${PIP_FILE_LOG}")
@@ -169,7 +112,6 @@ function(mo2_python_requirements TARGET)
--target="${MO2_LIBDIR}"
--log="${CMAKE_CURRENT_BINARY_DIR}/pip.log"
-r "${PROJECT_SOURCE_DIR}/plugin-requirements.txt"
WORKING_DIRECTORY ${PYTHON_ROOT}
DEPENDS "${PROJECT_SOURCE_DIR}/plugin-requirements.txt"
)
add_custom_target("${TARGET}_libs"
@@ -182,7 +124,7 @@ function(mo2_python_requirements TARGET)
install(
DIRECTORY "${MO2_LIBDIR}"
DESTINATION "${MO2_INSTALL_PATH}/bin/plugins/${TARGET}/"
DESTINATION "bin/plugins/${TARGET}/"
PATTERN "__pycache__" EXCLUDE
)
@@ -227,10 +169,6 @@ function(mo2_configure_python_module TARGET)
file(GLOB_RECURSE ui_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.ui)
mo2_python_uifiles(${TARGET} INPLACE FILES ${ui_files})
# qrc file
file(GLOB_RECURSE qrc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc)
mo2_python_rcfiles(${TARGET} INPLACE FILES ${qrc_files})
# install requirements if there are any
if(EXISTS "${PROJECT_SOURCE_DIR}/plugin-requirements.txt")
mo2_python_requirements(${TARGET} LIBDIR "${lib_dir}")
@@ -241,7 +179,7 @@ function(mo2_configure_python_module TARGET)
FILES "${PROJECT_SOURCE_DIR}/plugin-requirements.txt")
endif()
set(install_dir "${MO2_INSTALL_PATH}/bin/plugins/${TARGET}")
set(install_dir "bin/plugins/${TARGET}")
# directories that go in bin/plugins/${name}
install(
@@ -281,10 +219,6 @@ function(mo2_configure_python_simple TARGET)
file(GLOB ui_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.ui)
mo2_python_uifiles(${TARGET} FILES ${ui_files})
# qrc file
file(GLOB qrc_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.qrc)
mo2_python_rcfiles(${TARGET} FILES ${qrc_files})
# .py files directly in the directory
file(GLOB py_files CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.py)
@@ -305,7 +239,7 @@ function(mo2_configure_python_simple TARGET)
PREFIX data
FILES ${json_files})
set(install_dir "${MO2_INSTALL_PATH}/bin/plugins")
set(install_dir "bin/plugins")
# .py files directly in src/ go to plugins/
install(FILES ${py_files} DESTINATION ${install_dir})
-448
View File
@@ -1,448 +0,0 @@
cmake_minimum_required(VERSION 3.16)
if (POLICY CMP0144)
cmake_policy(SET CMP0144 NEW)
endif()
include(FetchContent)
include(${CMAKE_CURRENT_LIST_DIR}/mo2_utils.cmake)
#! mo2_add_dependencies : add dependencies to the given target
#
# the name of the dependencies should be:
# - valid mo2 "libraries", as per mo2_find_libraries,
# - boost (for header-only Boost libraries) or "boost::XXX" for specific Boost
# components
# - or Qt::XXX for Qt components
#
function(mo2_add_dependencies TARGET PRIVATE_OR_PUBLIC)
# remove everything boost related
set(standard_deps ${ARGN})
list(FILTER standard_deps EXCLUDE REGEX "^boost.*")
list(FILTER standard_deps EXCLUDE REGEX "^Qt::.*")
# keep everything boost related
set(boost_deps ${ARGN})
list(FILTER boost_deps INCLUDE REGEX "^boost.*")
# keep everything Qt related
set(qt_deps ${ARGN})
list(FILTER qt_deps INCLUDE REGEX "^Qt::.*")
message(DEBUG "deps: standards[ ${standard_deps} ], boost_deps[ ${boost_deps} ], qt_deps[ ${qt_deps} ]")
# handle "standard" dependencies
mo2_find_libraries(${standard_deps})
list(TRANSFORM standard_deps REPLACE "^(.+)$" "mo2::\\1")
message(DEBUG "standard: ${standard_deps}")
target_link_libraries(${TARGET} ${PRIVATE_OR_PUBLIC} ${standard_deps})
# handle Qt dependencies
if (qt_deps)
# remove Qt:: for find_package
list(TRANSFORM qt_deps REPLACE "Qt::" "")
find_package(Qt${QT_MAJOR_VERSION} COMPONENTS ${qt_deps} REQUIRED)
set(qt_include_dirs "")
foreach(qt_dep ${qt_deps})
list(APPEND qt_include_dirs ${Qt${qt_dep}_INCLUDE_DIRS})
endforeach()
target_include_directories(${TARGET} SYSTEM ${PRIVATE_OR_PUBLIC} ${qt_include_dirs})
# add QtX:: for target ink
list(TRANSFORM qt_deps REPLACE "^(.+)$" "Qt${QT_MAJOR_VERSION}::\\1")
target_link_libraries(${TARGET} ${PRIVATE_OR_PUBLIC} ${qt_deps})
endif()
# handle boost dependencies
if (boost_deps)
find_package(Boost REQUIRED)
target_include_directories(
${TARGET} SYSTEM ${PRIVATE_OR_PUBLIC} ${Boost_INCLUDE_DIRS})
list(TRANSFORM boost_deps REPLACE "boost(::)?" "")
list(FILTER boost_deps EXCLUDE REGEX "^$")
message(DEBUG "boost: ${boost_deps}")
if (boost_deps)
find_package(Boost COMPONENTS ${boost_deps} REQUIRED)
message(DEBUG "boost: ${Boost_LIBRARIES}")
target_link_libraries(${TARGET} ${PRIVATE_OR_PUBLIC} ${Boost_LIBRARIES})
endif()
endif()
endfunction()
#! mo2_find_uibase : find and create a mo2::uibase target
#
# if a 'uibase' target already exists, makes an alias as 'mo2::uibase', otherwise
# creates an imported target
#
function(mo2_find_uibase)
# target was already created
if (TARGET mo2-uibase)
return()
endif()
# if the uibase target exists, we use it
if (TARGET uibase)
add_library(mo2-uibase ALIAS uibase)
add_library(mo2::uibase ALIAS uibase)
else()
if (NOT DEFINED MO2_UIBASE_INCLUDE)
set(MO2_UIBASE_INCLUDE ${MO2_UIBASE_PATH}/src)
endif()
add_library(mo2-uibase IMPORTED SHARED)
set_target_properties(mo2-uibase PROPERTIES
IMPORTED_IMPLIB ${MO2_INSTALL_LIBS_PATH}/uibase.lib
IMPORTED_LOCATION ${MO2_INSTALL_PATH}/bin/uibase.dll)
mo2_add_dependencies(mo2-uibase
INTERFACE Qt::Widgets Qt::Network Qt::QuickWidgets)
target_include_directories(mo2-uibase
INTERFACE ${MO2_UIBASE_INCLUDE} ${MO2_UIBASE_INCLUDE}/game_features)
add_library(mo2::uibase ALIAS mo2-uibase)
endif()
endfunction()
#! mo2_find_corelib : find a static core library, e.g., bsatk or esptk, and create
# an appropriate target
#
function(mo2_find_corelib LIBRARY)
cmake_parse_arguments(MO2 "" "" "DEPENDS" ${ARGN})
mo2_set_if_not_defined(MO2_DEPENDS "")
# target was already created
if (TARGET mo2-${LIBRARY})
return()
endif()
# if the target exists, we use it
if (TARGET ${LIBRARY})
message(STATUS "Found existing ${LIBRARY} target, using it.")
add_library(mo2-${LIBRARY} ALIAS ${LIBRARY})
add_library(mo2::${LIBRARY} ALIAS ${LIBRARY})
else()
message(STATUS "Existing ${LIBRARY} target not found, creating it.")
add_library(mo2-${LIBRARY} IMPORTED STATIC)
set_target_properties(mo2-${LIBRARY} PROPERTIES
IMPORTED_LOCATION ${MO2_INSTALL_LIBS_PATH}/${LIBRARY}.lib)
target_include_directories(mo2-${LIBRARY}
INTERFACE ${MO2_SUPER_PATH}/${LIBRARY}/src)
if (MO2_DEPENDS)
mo2_add_dependencies(mo2-${LIBRARY} INTERFACE ${MO2_DEPENDS})
endif()
add_library(mo2::${LIBRARY} ALIAS mo2-${LIBRARY})
endif()
endfunction()
#! mo2_find_bsatk : find and create a mo2::bsatk target
#
function(mo2_find_bsatk)
mo2_find_corelib(bsatk DEPENDS boost::thread zlib lz4)
endfunction()
#! mo2_find_esptk : find and create a mo2::esptk target
#
function(mo2_find_esptk)
mo2_find_corelib(esptk)
endfunction()
#! mo2_find_archive : find and create a mo2::archive target
#
function(mo2_find_archive)
mo2_find_corelib(archive)
endfunction()
#! mo2_find_githubpp : find and create a mo2::githubpp target
#
function(mo2_find_githubpp)
mo2_find_corelib(githubpp DEPENDS Qt::Core Qt::Network)
endfunction()
#! mo2_find_lootcli : find and create a mo2::lootcli target
#
function(mo2_find_lootcli)
if (TARGET mo2-lootcli)
return()
endif()
add_library(mo2-lootcli IMPORTED INTERFACE)
target_include_directories(mo2-lootcli INTERFACE
${MO2_SUPER_PATH}/lootcli/include)
add_library(mo2::lootcli ALIAS mo2-lootcli)
endfunction()
#! mo2_find_gamebryo : find and create a mo2::gamebryo target
#
function(mo2_find_gamebryo)
# this does not use mo2_find_corelib because the target name do not match (we
# want gamebryo, the target is game_gamebryo), and the src folder is not the same
# other lib (src/gamebryo instead of src/)
# target was already created
if (TARGET mo2-gamebryo)
return()
endif()
# if the target exists, we use it
if (TARGET game_gamebryo)
message(STATUS "Found existing game_gamebryo target, using it.")
add_library(mo2-gamebryo ALIAS game_gamebryo)
add_library(mo2::gamebryo ALIAS game_gamebryo)
else()
message(STATUS "Existing game_gamebryo target not found, creating it.")
add_library(mo2-gamebryo IMPORTED STATIC)
set_target_properties(mo2-gamebryo PROPERTIES
IMPORTED_LOCATION ${MO2_INSTALL_LIBS_PATH}/game_gamebryo.lib)
target_include_directories(mo2-gamebryo
INTERFACE ${MO2_SUPER_PATH}/game_gamebryo/src/gamebryo)
mo2_add_dependencies(mo2-gamebryo INTERFACE zlib lz4)
add_library(mo2::gamebryo ALIAS mo2-gamebryo)
endif()
endfunction()
#! mo2_find_creation : find and create a mo2::creation target
#
function(mo2_find_creation)
# same as mo2_find_gamebryo, we do not use mo2_find_corelib (see mo2_find_gamebryo
# comment for why)
# target was already created
if (TARGET mo2-creation)
return()
endif()
# if the target exists, we use it
if (TARGET game_creation)
message(STATUS "Found existing game_creation target, using it.")
add_library(mo2-creation ALIAS game_creation)
add_library(mo2::creation ALIAS game_creation)
else()
message(STATUS "Existing game_creation target not found, creating it.")
add_library(mo2-creation IMPORTED STATIC)
set_target_properties(mo2-creation PROPERTIES
IMPORTED_LOCATION ${MO2_INSTALL_LIBS_PATH}/game_creation.lib)
target_include_directories(mo2-creation
INTERFACE ${MO2_SUPER_PATH}/game_gamebryo/src/creation)
add_library(mo2::creation ALIAS mo2-creation)
mo2_add_dependencies(mo2-creation INTERFACE gamebryo lz4)
endif()
endfunction()
#! mo2_find_loot : find and create a mo2::loot target
#
function(mo2_find_loot)
if (TARGET mo2-loot)
return()
endif()
mo2_required_variable(NAME LOOT_PATH TYPE PATH)
find_package(Boost COMPONENTS locale REQUIRED)
add_library(mo2-loot IMPORTED SHARED)
set_target_properties(mo2-loot PROPERTIES IMPORTED_LOCATION ${LOOT_PATH}/bin/loot.dll)
set_target_properties(mo2-loot PROPERTIES IMPORTED_IMPLIB ${LOOT_PATH}/lib/loot.lib)
target_include_directories(mo2-loot INTERFACE ${LOOT_PATH}/include)
target_link_libraries(mo2-loot INTERFACE ${Boost_LIBRARIES})
add_library(mo2::loot ALIAS mo2-loot)
endfunction()
#! mo2_find_spdlog : find and carete a mo2::spdlog target
#
function(mo2_find_spdlog)
if (TARGET mo2-spdlog)
return()
endif()
mo2_required_variable(NAME SPDLOG_ROOT TYPE PATH)
add_library(mo2-spdlog INTERFACE)
target_compile_definitions(mo2-spdlog INTERFACE SPDLOG_USE_STD_FORMAT)
target_include_directories(mo2-spdlog SYSTEM INTERFACE ${SPDLOG_ROOT}/include)
add_library(mo2::spdlog ALIAS mo2-spdlog)
endfunction()
#! mo2_find_directxtex : find and create a mo2::directxtex target
#
function(mo2_find_directxtex)
if (TARGET mo2-directxtex)
return()
endif()
mo2_required_variable(NAME DIRECTXTEX_ROOT TYPE PATH)
add_library(mo2-directxtex IMPORTED STATIC)
set_target_properties(mo2-directxtex PROPERTIES
IMPORTED_LOCATION_DEBUG ${DIRECTXTEX_ROOT}/Lib/Debug/DirectXTex.lib
IMPORTED_LOCATION_MINSIZEREL ${DIRECTXTEX_ROOT}/Lib/Release/DirectXTex.lib
IMPORTED_LOCATION_RELEASE ${DIRECTXTEX_ROOT}/Lib/Release/DirectXTex.lib
IMPORTED_LOCATION_RELWITHDEBINFO ${DIRECTXTEX_ROOT}/Lib/Release/DirectXTex.lib
)
target_include_directories(mo2-directxtex INTERFACE ${DIRECTXTEX_ROOT}/Include)
add_library(mo2::DirectXTex ALIAS mo2-directxtex)
endfunction()
#! mo2_find_libbsarch : find and create a mo2::libbsarch target
#
function(mo2_find_libbsarch)
if (TARGET mo2-libbsarch)
return()
endif()
mo2_find_directxtex()
mo2_required_variable(NAME LIBBSARCH_ROOT TYPE PATH)
add_library(mo2-libbsarch IMPORTED SHARED)
set_target_properties(mo2-libbsarch PROPERTIES
IMPORTED_IMPLIB ${LIBBSARCH_ROOT}/libbsarch.lib
IMPORTED_LOCATION ${LIBBSARCH_ROOT}/libbsarch.dll
)
target_include_directories(mo2-libbsarch INTERFACE ${LIBBSARCH_ROOT})
target_link_libraries(mo2-libbsarch INTERFACE ${LIBBSARCH_ROOT}/libbsarch_OOP.lib mo2::DirectXTex)
add_library(mo2::libbsarch ALIAS mo2-libbsarch)
endfunction()
#! mo2_find_zlib : find and carete a mo2::zlib target
#
function(mo2_find_zlib)
if (TARGET mo2-zlib)
return()
endif()
mo2_required_variable(NAME ZLIB_ROOT TYPE PATH)
# not using find_package(ZLIB) because we want the static version
add_library(mo2-zlib IMPORTED STATIC)
set_target_properties(mo2-zlib PROPERTIES
IMPORTED_LOCATION ${ZLIB_ROOT}/lib/zlibstatic.lib)
target_include_directories(mo2-zlib INTERFACE ${ZLIB_ROOT}/include)
add_library(mo2::zlib ALIAS mo2-zlib)
endfunction()
#! mo2_find_lz4 : find and carete a mo2::lz4 target
#
function(mo2_find_lz4)
if (TARGET mo2-lz4)
return()
endif()
mo2_required_variable(NAME LZ4_ROOT TYPE PATH)
add_library(mo2-lz4 IMPORTED SHARED)
set_target_properties(mo2-lz4 PROPERTIES
IMPORTED_LOCATION ${LZ4_ROOT}/bin/liblz4.dll
IMPORTED_IMPLIB ${LZ4_ROOT}/bin/liblz4.lib
)
target_include_directories(mo2-lz4 INTERFACE ${LZ4_ROOT}/lib)
add_library(mo2::lz4 ALIAS mo2-lz4)
endfunction()
#! mo2_find_7z : find and carete a mo2::7z target
#
function(mo2_find_7z)
if (TARGET mo2-7z)
return()
endif()
mo2_required_variable(NAME SEVENZ_ROOT TYPE PATH)
add_library(mo2-7z INTERFACE)
target_include_directories(mo2-7z INTERFACE ${SEVENZ_ROOT}/CPP)
add_library(mo2::7z ALIAS mo2-7z)
endfunction()
#! mo2_find_tomlplusplus : find and create a mo2::tomlplusplus target
#
function(mo2_find_tomlplusplus)
if (TARGET mo2-tomlplusplus)
return()
endif()
FetchContent_Declare(
tomlplusplus
URL "https://github.com/marzer/tomlplusplus/archive/v3.2.0.tar.gz"
URL_HASH "SHA256=aeba776441df4ac32e4d4db9d835532db3f90fd530a28b74e4751a2915a55565"
)
FetchContent_MakeAvailable(tomlplusplus)
add_library(mo2-tomlplusplus INTERFACE)
target_include_directories(mo2-tomlplusplus INTERFACE "${tomlplusplus_SOURCE_DIR}/include")
add_dependencies(mo2-tomlplusplus tomlplusplus)
add_library(mo2::tomlplusplus ALIAS mo2-tomlplusplus)
endfunction()
#! mo2_find_usvfs : find and create a mo2::usvfs target
#
function(mo2_find_usvfs)
if (TARGET mo2-usvfs)
return()
endif()
set(USVFS_PATH "${MO2_BUILD_PATH}/usvfs")
set(USVFS_INC_PATH "${USVFS_PATH}/include")
set(USVFS_LIB_PATH "${USVFS_PATH}/lib")
add_library(mo2-usvfs IMPORTED SHARED)
set_target_properties(mo2-usvfs PROPERTIES
IMPORTED_LOCATION "${USVFS_LIB_PATH}/usvfs_x64.dll"
)
set_target_properties(mo2-usvfs PROPERTIES
IMPORTED_IMPLIB "${USVFS_LIB_PATH}/usvfs_x64.lib"
)
target_include_directories(mo2-usvfs INTERFACE ${USVFS_INC_PATH})
add_library(mo2::usvfs ALIAS mo2-usvfs)
endfunction()
#! mo2_find_libraries : find and create libraries to link to
#
# this function tries to find the given libraries and generates (if the libraries are
# found) targets mo2::LIBRARY_NAME for each library found
#
# example: mo2_find_libraries(uibase loot) will create mo2::uibase and mo2::loot
#
# available libraries are the ones with mo2_find_XXX functions
#
function(mo2_find_libraries)
foreach(target ${ARGN})
cmake_language(CALL "mo2_find_${target}")
endforeach()
endfunction()
+64 -36
View File
@@ -18,24 +18,71 @@ function (mo2_set_if_not_defined NAME VALUE)
endif()
endfunction()
#! mo2_add_subdirectories : add all repositories matching the given list of patterns
#
# \param:FOLDER Folder (layout) to add the subdirectories to
# \param:GLOB List of glob patterns to find repositories
#
function (mo2_add_subdirectories)
cmake_parse_arguments(MO2 "" "FOLDER" "GLOB" ${ARGN})
if (NOT DEFINED MO2_FOLDER)
message(FATAL_ERROR "missing FOLDER in add_subdirectories")
endif()
if (NOT DEFINED MO2_GLOB)
message(FATAL_ERROR "missing GLOB in add_subdirectories")
endif()
file(GLOB directories RELATIVE ${CMAKE_CURRENT_LIST_DIR} LIST_DIRECTORIES TRUE ${MO2_GLOB})
set(CMAKE_FOLDER ${MO2_FOLDER})
foreach(directory ${directories})
add_subdirectory(${directory})
endforeach()
unset(CMAKE_FOLDER)
endfunction()
#! mo2_find_python_executable : find the full path to the Python executable
#
# \param:VARNAME name of the variable that will contain the path to Python
function(mo2_find_python_executable VARNAME)
if (EXISTS "${PYTHON_ROOT}/PCbuild/amd64/python_d.exe")
set(${VARNAME} "${PYTHON_ROOT}/PCbuild/amd64/python_d.exe" PARENT_SCOPE)
else()
set(${VARNAME} "${PYTHON_ROOT}/PCbuild/amd64/python.exe" PARENT_SCOPE)
if (NOT DEFINED Python_EXECUTABLE)
find_package(Python ${MO2_PYTHON_VERSION} COMPONENTS Interpreter REQUIRED)
endif()
set(${VARNAME} ${Python_EXECUTABLE} PARENT_SCOPE)
endfunction()
#! mo2_find_windeployqt_executable : find the full path to the windeployqt executable
#! mo2_find_git_hash : find the git hash of HEAD on the current source project
#
# \param:VARNAME name of the variable that will contain the path to Python
function(mo2_find_windeployqt_executable VARNAME)
# find_program() does not work for whatever reason, just going for the whole
# name
set(${VARNAME} ${QT_ROOT}/bin/windeployqt.exe PARENT_SCOPE)
# \param:VARNAME variable to store the git hash
function(mo2_find_git_hash VARNAME)
execute_process(
COMMAND git log -1 --format=%h
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(${VARNAME} ${GIT_COMMIT_HASH} PARENT_SCOPE)
endfunction()
#! mo2_find_qt_executable : find the path to the executable from Qt
#
function(mo2_find_qt_executable VARNAME EXECUTABLE)
# retrieve the absolute path to qmake and then use that path to find
# the windeployqt and macdeployqt binaries
get_target_property(_qmake_executable Qt6::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
# need to use a custom varname per executable to use the cache
find_program(QT_${EXECUTABLE} ${EXECUTABLE} HINTS "${_qt_bin_dir}")
if(WIN32 AND NOT QT_${EXECUTABLE})
message(FATAL_ERROR "${EXECUTABLE} not found")
endif()
set(${VARNAME} ${QT_${EXECUTABLE}} PARENT_SCOPE)
endfunction()
#! mo2_set_project_to_run_from_install : set a target to run from a given executable
@@ -101,27 +148,6 @@ function(mo2_add_filter)
source_group(${filter_name} FILES ${files})
endfunction()
#! mo2_find_qt_version : try to deduce Qt version from QT_ROOT variable
#
# this function caches the given variable
#
# \param:VAR name of the variable to store the version into
#
function(mo2_find_qt_version VAR)
if (DEFINED CACHE{${VAR}})
return()
endif()
# TODO: deduce version from the QT_ROOT folder
get_filename_component(VFOLDER ${QT_ROOT} DIRECTORY)
get_filename_component(${VAR} ${VFOLDER} NAME)
message(STATUS "deduced Qt version to ${${VAR}}")
set(${VAR} ${${VAR}} CACHE STRING "Qt Version}")
endfunction()
#! mo2_deploy_qt_for_tests : add comments to deploy Qt for tests
#
# unlike mo2_deploy_qt(), this function does not perform any cleaning
@@ -132,7 +158,7 @@ endfunction()
function(mo2_deploy_qt_for_tests)
cmake_parse_arguments(DEPLOY "" "TARGET" "BINARIES" ${ARGN})
mo2_find_windeployqt_executable(windeployqt)
mo2_find_qt_executable(windeployqt windeployqt)
add_custom_command(TARGET "${DEPLOY_TARGET}"
POST_BUILD
@@ -160,7 +186,7 @@ endfunction()
function(mo2_deploy_qt)
cmake_parse_arguments(DEPLOY "NOPLUGINS" "" "BINARIES" ${ARGN})
mo2_find_windeployqt_executable(windeployqt)
mo2_find_qt_executable(windeployqt windeployqt)
set(args
"--no-translations \
@@ -287,12 +313,12 @@ function(mo2_add_lupdate TARGET)
message(TRACE "TS_FILE: ${MO2_TS_FILE}, SOURCES: ${MO2_SOURCES}, FILES: ${translation_files}")
if (${is_cpp})
set(lupdate_command ${QT_ROOT}/bin/lupdate)
mo2_find_qt_executable(lupdate_command lupdate)
set(lupdate_args ${MO2_SOURCES} -ts ${MO2_TS_FILE})
else()
mo2_find_python_executable(PYTHON_EXE)
set(lupdate_command ${PYTHON_EXE})
set(lupdate_args -I -m PyQt${QT_MAJOR_VERSION}.lupdate.pylupdate --ts "${MO2_TS_FILE}" ${translation_files})
set(lupdate_args -I -m PyQt${Qt_VERSION_MAJOR}.lupdate.pylupdate --ts "${MO2_TS_FILE}" ${translation_files})
endif()
add_custom_command(OUTPUT ${MO2_TS_FILE}
@@ -325,8 +351,10 @@ endfunction()
function(mo2_add_lrelease TARGET)
cmake_parse_arguments(MO2 "INSTALL" "QM_FILE" "TS_FILES" ${ARGN})
mo2_find_qt_executable(lrelease_command lrelease)
add_custom_command(OUTPUT ${MO2_QM_FILE}
COMMAND ${QT_ROOT}/bin/lrelease
COMMAND ${lrelease_command}
ARGS ${MO2_TS_FILES} -qm ${MO2_QM_FILE}
DEPENDS "${MO2_TS_FILES}"
VERBATIM)