diff --git a/.gitmodules b/.gitmodules index 36425b7..87f91db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,6 +4,9 @@ [submodule "cmake/codesign"] path = cmake/codesign url = https://github.com/Xaymar/cmake-codesign.git +[submodule "cmake/version"] + path = cmake/version + url = https://github.com/Xaymar/cmake-version.git [submodule "third-party/nlohmann-json"] path = third-party/nlohmann-json url = https://github.com/nlohmann/json.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 25ae4ec..911f61c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,25 @@ else() set(LOGPREFIX "") endif() +################################################################################ +# Modules +################################################################################ + +# Search Paths +set(CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/clang" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/codesign" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/version" + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" +) + +# Include +include("util") # CacheClear, CacheSet +include("version") # version() +include("DownloadProject") # DownloadProject +include("CheckIPOSupported") # check_ipo_supported + ################################################################################ # Detect if we are building with OBS Studio (different from Grouped builds) ################################################################################ @@ -50,116 +69,51 @@ endif() # Versioning ################################################################################ -# Variables for Versioning -set(VERSION_MAJOR 0) # Major -set(VERSION_MINOR 0) # Minor -set(VERSION_PATCH 0) # Patch -set(VERSION_STAGE "") # Prefix for Tweak, if left empty will assume '.'. -set(VERSION_TWEAK 0) # Tweak -set(VERSION_COMMIT "00000000") -# Final format will be [MAJOR].[MINOR].[PATCH]([TYPE][TWEAK])(-[COMMIT]) +# For automatic versioning, which version is the "root" of the current changes? +set(PROJECT_VERSION_GIT_BASE "0.11.0") -function(parse_version_string) - # Parses a version in the format A.B.C[.|a|b|rc]D-E - cmake_parse_arguments( - PARSE_ARGV 0 - _ARGS - "" - "INPUT;OUTPUT" - "" - ) - - set(_tmp_MAJOR 0) - set(_tmp_MINOR 0) - set(_tmp_PATCH 0) - set(_tmp_STAGE "") - set(_tmp_TWEAK "") - set(_tmp_COMMIT "") +# What is our version goal? +set(PROJECT_VERSION "0.12.0") +version(PARSE PROJECT_VERSION "${PROJECT_VERSION}") - # Replace separators with list separators - string(REPLACE "-" "." _tmp "${_ARGS_INPUT}") - string(REPLACE "." ";" _tmp "${_tmp}") - - # Parse version differently depending on total string length. - list(LENGTH _tmp _tmp_len) - if(_tmp_len GREATER_EQUAL 1) # A[...] - list(GET _tmp 0 _tmp_MAJOR) - endif() - if(_tmp_len GREATER_EQUAL 2) # A.B[...] - list(GET _tmp 1 _tmp_MINOR) - endif() - if(_tmp_len GREATER_EQUAL 3) # A.B.C[...] - list(GET _tmp 2 _tmp_PATCH) - endif() - if(_tmp_len EQUAL 4) # A.B.C.D or A.B.C-gEEEEEEEE - list(GET _tmp 3 _tmp2) - # No support for '{N,M}' in CMake-Regex! - if(_tmp2 MATCHES "^g[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]") - # A.B.C-gEEEEEEEE - set(_tmp_COMMIT "${_tmp2}") - else() - # It is A.B.C.D - set(_tmp_TWEAK "${_tmp2}") - set(_tmp_STAGE "a") - endif() - elseif(_tmp_len EQUAL 5) # A.B.C.D-gEEEEEEEE - set(_tmp_STAGE "a") - list(GET _tmp 3 _tmp_TWEAK) - list(GET _tmp 4 _tmp_COMMIT) - endif() - if(_tmp_TWEAK STREQUAL "") # Is A.B.C-gEEEEEEEE actually A.B.CxD-gEEEEEEEE? - string(REGEX MATCHALL "^([0-9]+)([_a-c]+)([0-9]+)" T_MATCHES "${_tmp_PATCH}") - if(T_MATCHES) - set(_tmp_PATCH ${CMAKE_MATCH_1}) - set(_tmp_STAGE ${CMAKE_MATCH_2}) - set(_tmp_TWEAK ${CMAKE_MATCH_3}) - endif() - endif() - - set(${_ARGS_OUTPUT}_MAJOR ${_tmp_MAJOR} PARENT_SCOPE) - set(${_ARGS_OUTPUT}_MINOR ${_tmp_MINOR} PARENT_SCOPE) - set(${_ARGS_OUTPUT}_PATCH ${_tmp_PATCH} PARENT_SCOPE) - set(${_ARGS_OUTPUT}_STAGE ${_tmp_STAGE} PARENT_SCOPE) - set(${_ARGS_OUTPUT}_TWEAK ${_tmp_TWEAK} PARENT_SCOPE) - set(${_ARGS_OUTPUT}_COMMIT ${_tmp_COMMIT} PARENT_SCOPE) -endfunction() - -# Check if we are in a git repository. +# If possible, automatically generate versions from git. if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/.git") - set(VERSION_BASE "0.11.0") # Automatic versioning base - set(VERSION_TARGET "0.12.0") # Automatic versioning target - - # Parse target version as it is for output. - parse_version_string(OUTPUT "VERSION" INPUT "${VERSION_TARGET}") - - # Try and figure out where git is. - find_program(GIT git - PATHS - /bin - /sbin - /usr/bin - /usr/local/bin + find_program(GIT + NAMES + git + git.exe ) - if(GIT) - # Tweak + if(EXISTS "${GIT}") + # Calculate the Tweak version component from the given base version. execute_process( - COMMAND "${GIT}" describe --tags --long --match "${VERSION_BASE}" --abbrev=8 HEAD + COMMAND "${GIT}" describe --tags --long --match "${PROJECT_VERSION_GIT_BASE}" --abbrev=8 HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} RESULT_VARIABLE GIT_RESULT - OUTPUT_VARIABLE GIT_OUTPUT + OUTPUT_VARIABLE PROJECT_VERSION_GIT ERROR_VARIABLE GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) - if(NOT GIT_RESULT EQUAL 0) - message(WARNING "${LOGPREFIX}Failed to detect version, using default instead.") + if(GIT_RESULT EQUAL 0) + # Some minor string editing so the output conforms to SemVer 2.0.0. + string(REPLACE "-" ";" PROJECT_VERSION_GIT "${PROJECT_VERSION_GIT}") + + # Parse as SemVer 2.0.0 + list(GET PROJECT_VERSION_GIT 1 PROJECT_VERSION_GIT_TWEAK) + list(GET PROJECT_VERSION_GIT 2 PROJECT_VERSION_GIT_BUILD) + + # Update our global version. + version(MODIFY PROJECT_VERSION "${PROJECT_VERSION}" COMPRESS + TWEAK "${PROJECT_VERSION_GIT_TWEAK}" + BUILD "${PROJECT_VERSION_GIT_BUILD}" + PRERELEASE "a" + REQUIRE "PATCH;TWEAK" + ) + version(PARSE PROJECT_VERSION "${PROJECT_VERSION}" REQUIRE "PATCH;TWEAK") else() - parse_version_string(OUTPUT "GIT_VERSION" INPUT "${GIT_OUTPUT}") - set(VERSION_STAGE ${GIT_VERSION_STAGE}) - set(VERSION_TWEAK ${GIT_VERSION_TWEAK}) - set(VERSION_COMMIT ${GIT_VERSION_COMMIT}) + message(WARNING "${LOGPREFIX}Unable to detect Tweak and Build component with 'git'.") endif() # Is there a tag on the current commit? @@ -167,79 +121,81 @@ if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/.git") COMMAND "${GIT}" tag "--sort=-v:refname" "--points-at" HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} RESULT_VARIABLE GIT_RESULT - OUTPUT_VARIABLE TAG_OUTPUT + OUTPUT_VARIABLE PROJECT_VERSION_TAG ERROR_VARIABLE GIT_ERROR OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) - if((GIT_RESULT EQUAL 0) AND (NOT "${TAG_OUTPUT}" STREQUAL "")) - string(REGEX REPLACE "[\r\n]+.*" "" T_MATCHES "${TAG_OUTPUT}") - parse_version_string(OUTPUT "TAG_VERSION" INPUT "${T_MATCHES}") - set(VERSION_MAJOR "${TAG_VERSION_MAJOR}") - set(VERSION_MINOR "${TAG_VERSION_MINOR}") - set(VERSION_PATCH "${TAG_VERSION_PATCH}") - set(VERSION_STAGE "${TAG_VERSION_STAGE}") - set(VERSION_TWEAK "${TAG_VERSION_TWEAK}") + if((GIT_RESULT EQUAL 0) AND (NOT "${PROJECT_VERSION_TAG}" STREQUAL "")) + # Some minor string editing so the output conforms to SemVer 2.0.0. + string(REGEX REPLACE "[\r\n]+.*" "" PROJECT_VERSION_TAG "${PROJECT_VERSION_TAG}") + + # Parse as SemVer 2.0.0 + version(PARSE PROJECT_VERSION_TAG "${PROJECT_VERSION_TAG}" REQUIRE "PATCH;TWEAK") + if(PROJECT_VERSION_TAG_PRERELEASE) + string(SUBSTRING "${PROJECT_VERSION_TAG_PRERELEASE}" 1 -1 PROJECT_VERSION_TAG_TWEAK) + string(SUBSTRING "${PROJECT_VERSION_TAG_PRERELEASE}" 0 1 PROJECT_VERSION_TAG_PRERELEASE) + + if(NOT PROJECT_VERSION_TAG_TWEAK STREQUAL PROJECT_VERSION_GIT_TWEAK) + message(WARNING "${LOGPREFIX}'git' tag mismatches detected version: '${PROJECT_VERSION_TAG_TWEAK}' != '${PROJECT_VERSION_GIT_TWEAK}'.") + endif() + endif() + + # Update our global version. + version(GENERATE PROJECT_VERSION COMPRESS + MAJOR "${PROJECT_VERSION_TAG_MAJOR}" + MINOR "${PROJECT_VERSION_TAG_MINOR}" + PATCH "${PROJECT_VERSION_TAG_PATCH}" + TWEAK "${PROJECT_VERSION_TAG_TWEAK}" + PRERELEASE "${PROJECT_VERSION_TAG_PRERELEASE}" + BUILD "${PROJECT_VERSION_BUILD}" + ) + version(PARSE PROJECT_VERSION "${PROJECT_VERSION}" REQUIRE "PATCH;TWEAK") endif() + else() + message(STATUS "${LOGPREFIX}'git' not found, automatic version detection disabled.") endif() else() message(STATUS "${LOGPREFIX}Not a git repository, automatic version detection disabled.") endif() # Allow manual overrides of the detected version. -set(${PREFIX}VERSION "" CACHE STRING "Override StreamFX version with this string. Format: Major.Minor.Patch[Stage][Tweak[-Commit8c]]") -if(NOT (${PREFIX}VERSION STREQUAL "")) - parse_version_string(OUTPUT "VERSION" INPUT "${${PREFIX}VERSION}") +set(${PREFIX}VERSION "" CACHE STRING "Override detected or pre-configured version with this string. Accepts strings in CMake and SemVer 2.0.0 format.") +if(NOT ("${${PREFIX}VERSION}" STREQUAL "")) + version(PARSE PROJECT_VERSION_CFG "${${PREFIX}VERSION}" REQUIRE "PATCH;TWEAK") + if("${PROJECT_VERSION_CFG_BUILD}" STREQUAL "") + set(PROJECT_VERSION_CFG_BUILD "${PROJECT_VERSION_BUILD}") + endif() + version(GENERATE PROJECT_VERSION COMPRESS + MAJOR "${PROJECT_VERSION_CFG_MAJOR}" + MINOR "${PROJECT_VERSION_CFG_MINOR}" + PATCH "${PROJECT_VERSION_CFG_PATCH}" + TWEAK "${PROJECT_VERSION_CFG_TWEAK}" + PRERELEASE "${PROJECT_VERSION_CFG_PRERELEASE}" + BUILD "${PROJECT_VERSION_CFG_BUILD}" + ) endif() -# Generate Version String -if(VERSION_COMMIT) - set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_STAGE}${VERSION_TWEAK}-${VERSION_COMMIT}") -else() - set(VERSION_STRING "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_STAGE}${VERSION_TWEAK}") -endif() - -# Log the detected version. -message(STATUS "${LOGPREFIX}Version ${VERSION_STRING}") +# Parse & Log the detected version. +message(STATUS "${LOGPREFIX}Version ${PROJECT_VERSION}") ################################################################################ # Project ################################################################################ -set(_VERSION_TWEAK "0${VERSION_TWEAK}") +version(GENERATE PROJECT_VERSION_CMAKE + MAJOR "${PROJECT_VERSION_MAJOR}" + MINOR "${PROJECT_VERSION_MINOR}" + PATCH "${PROJECT_VERSION_PATCH}" + TWEAK "${PROJECT_VERSION_TWEAK}" +) project( StreamFX - VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${_VERSION_TWEAK} + VERSION ${PROJECT_VERSION_CMAKE} DESCRIPTION "Additional sources, filters, transitions and encoders for OBS Studio." HOMEPAGE_URL "https://streamfx.xaymar.com/" ) -# Helpers for CI -if(VERSION_STAGE STREQUAL "") - file( - GENERATE - OUTPUT "$/tag_name" - CONTENT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}" - TARGET ${PROJECT_NAME} - FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE - ) -else() - file( - GENERATE - OUTPUT "$/tag_name" - CONTENT "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${VERSION_STAGE}${VERSION_TWEAK}" - TARGET ${PROJECT_NAME} - FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE - ) -endif() -file( - GENERATE - OUTPUT "$/version" - CONTENT "${VERSION_STRING}" - TARGET ${PROJECT_NAME} - FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE -) - # Full Project Name set(PROJECT_FULL_NAME "StreamFX (for OBS Studio)") @@ -252,23 +208,6 @@ set(PROJECT_AUTHORS "Michael Fabian 'Xaymar' Dirks ") # Copyright Years (TODO: Update every year) set(PROJECT_COPYRIGHT_YEARS "2018 - 2020") -# Versioning -set(PROJECT_VERSION_STRING ${VERSION_STRING}) - -################################################################################ -# Modules -################################################################################ - -# Search Paths -set(CMAKE_MODULE_PATH - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" - "${CMAKE_CURRENT_SOURCE_DIR}/cmake" -) - -# Include -include("util") # CacheClear, CacheSet -include("DownloadProject") # DownloadProject -include("CheckIPOSupported") # check_ipo_supported ################################################################################ # Platform Setup @@ -2241,6 +2180,8 @@ set_target_properties(${PROJECT_NAME} PROPERTIES # Set file version (on anything but MacOS) if(NOT D_PLATFORM_MAC) set_target_properties(${PROJECT_NAME} PROPERTIES + MACHO_COMPATIBILITY_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} + MACHO_CURRENT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK} SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.${PROJECT_VERSION_TWEAK} ) @@ -2520,7 +2461,7 @@ endif() if(STANDALONE) # Packaging if(NOT PACKAGE_SUFFIX) - set(_PACKAGE_SUFFIX_OVERRIDE "${VERSION_STRING}") + set(_PACKAGE_SUFFIX_OVERRIDE "${PROJECT_VERSION}") else() set(_PACKAGE_SUFFIX_OVERRIDE "${PACKAGE_SUFFIX}") endif() diff --git a/cmake/version b/cmake/version new file mode 160000 index 0000000..2494a2b --- /dev/null +++ b/cmake/version @@ -0,0 +1 @@ +Subproject commit 2494a2b6c894380ced96307ae833afc0be37a143 diff --git a/source/obs/obs-encoder-factory.hpp b/source/obs/obs-encoder-factory.hpp index 3b55282..66d5868 100644 --- a/source/obs/obs-encoder-factory.hpp +++ b/source/obs/obs-encoder-factory.hpp @@ -169,7 +169,7 @@ namespace streamfx::obs { instance->migrate(settings, version); } obs_data_set_int(settings, S_VERSION, static_cast(STREAMFX_VERSION)); - obs_data_set_string(settings, S_COMMIT, STREAMFX_COMMIT); + obs_data_set_string(settings, S_COMMIT, STREAMFX_VERSION_BUILD); } private /* Factory */: diff --git a/source/obs/obs-source-factory.hpp b/source/obs/obs-source-factory.hpp index 736d761..ad64229 100644 --- a/source/obs/obs-source-factory.hpp +++ b/source/obs/obs-source-factory.hpp @@ -444,7 +444,7 @@ namespace streamfx::obs { uint64_t version = static_cast(obs_data_get_int(settings, S_VERSION)); priv->migrate(settings, version); obs_data_set_int(settings, S_VERSION, static_cast(STREAMFX_VERSION)); - obs_data_set_string(settings, S_COMMIT, STREAMFX_COMMIT); + obs_data_set_string(settings, S_COMMIT, STREAMFX_VERSION_BUILD); priv->load(settings); } } catch (const std::exception& ex) { @@ -472,7 +472,7 @@ namespace streamfx::obs { if (data) { reinterpret_cast<_instance*>(data)->save(settings); obs_data_set_int(settings, S_VERSION, static_cast(STREAMFX_VERSION)); - obs_data_set_string(settings, S_COMMIT, STREAMFX_COMMIT); + obs_data_set_string(settings, S_COMMIT, STREAMFX_VERSION_BUILD); } } catch (const std::exception& ex) { DLOG_ERROR("Unexpected exception in function '%s': %s.", __FUNCTION_NAME__, ex.what()); diff --git a/templates/version.hpp.in b/templates/version.hpp.in index 68b7bad..02eab08 100644 --- a/templates/version.hpp.in +++ b/templates/version.hpp.in @@ -30,16 +30,13 @@ #define STREAMFX_MASK_COMPAT 0xFFFFFFFF00000000ull #define STREAMFX_MASK_UPDATE 0xFFFFFFFFFFFF0000ull -#define STREAMFX_COMMIT "@VERSION_COMMIT@" +#define STREAMFX_VERSION_MAJOR @PROJECT_VERSION_MAJOR@u +#define STREAMFX_VERSION_MINOR @PROJECT_VERSION_MINOR@u +#define STREAMFX_VERSION_PATCH @PROJECT_VERSION_PATCH@u +#define STREAMFX_VERSION_TWEAK @PROJECT_VERSION_TWEAK@u +#define STREAMFX_VERSION_PRERELEASE "@PROJECT_VERSION_PRERELEASE@" +#define STREAMFX_VERSION_BUILD "@PROJECT_VERSION_BUILD@" #define STREAMFX_VERSION \ STREAMFX_MAKE_VERSION(STREAMFX_VERSION_MAJOR, STREAMFX_VERSION_MINOR, STREAMFX_VERSION_PATCH, \ - STREAMFX_VERSION_BUILD) -#define STREAMFX_VERSION_MAJOR @PROJECT_VERSION_MAJOR@ -#define STREAMFX_VERSION_MINOR @PROJECT_VERSION_MINOR@ -#define STREAMFX_VERSION_PATCH @PROJECT_VERSION_PATCH@ -#define STREAMFX_VERSION_BUILD @PROJECT_VERSION_TWEAK@ -#define STREAMFX_VERSION_TWEAK @PROJECT_VERSION_TWEAK@ -#define STREAMFX_VERSION_SUFFIX "@VERSION_STAGE@" -#define STREAMFX_VERSION_STAGE "@VERSION_STAGE@" -#define STREAMFX_VERSION_COMMIT "@VERSION_COMMIT@" -#define STREAMFX_VERSION_STRING "@VERSION_STRING@" + STREAMFX_VERSION_TWEAK) +#define STREAMFX_VERSION_STRING "@PROJECT_VERSION@"