From 0997e209bc049b32dbc71f3e94e6b4a54dcfc9dd Mon Sep 17 00:00:00 2001 From: Michael Fabian 'Xaymar' Dirks Date: Tue, 13 Nov 2018 19:47:33 +0100 Subject: [PATCH] cmake: Versioning, ffmpeg dependency, installer and more --- CMakeLists.txt | 61 +++++++++++-- cmake/installer.iss.in | 114 ++++++++++++++++++++++++ cmake/modules/FindFFmpeg.cmake | 155 +++++++++++++++++++++++++++++++++ 3 files changed, 324 insertions(+), 6 deletions(-) create mode 100644 cmake/installer.iss.in create mode 100644 cmake/modules/FindFFmpeg.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 60050b2..3cfa2d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,10 +19,41 @@ cmake_minimum_required(VERSION 3.1.0) include("cmake/util.cmake") +# Automatic Versioning +set(VERSION_MAJOR 0) +set(VERSION_MINOR 1) +set(VERSION_PATCH 0) +set(VERSION_TWEAK 0) +set(PROJECT_COMMIT "N/A") +if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/.git") + set(GIT_RESULT "") + set(GIT_OUTPUT "") + execute_process( + COMMAND git rev-list --count --topo-order ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}..HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE GIT_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ERROR_QUIET + ) + if(GIT_RESULT EQUAL 0) + set(VERSION_TWEAK ${GIT_OUTPUT}) + endif() + execute_process( + COMMAND git rev-parse HEAD + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + RESULT_VARIABLE GIT_RESULT + OUTPUT_VARIABLE GIT_OUTPUT + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_STRIP_TRAILING_WHITESPACE ERROR_QUIET + ) + if(GIT_RESULT EQUAL 0) + set(PROJECT_COMMIT ${GIT_OUTPUT}) + endif() +endif() + # Define Project project( enc-ffmpeg - VERSION 1.0.0.0 + VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_TWEAK} ) set(PROJECT_FULL_NAME "FFMPEG Encoder for OBS Studio") set(PROJECT_DESCRIPTION "Plugin for OBS Studio to add FFMPEG options for Recording and Streaming") @@ -30,7 +61,7 @@ set(PROJECT_AUTHORS "Michael Fabian 'Xaymar' Dirks ") set(PROJECT_COPYRIGHT_YEARS "2018") ################################################################################ -# CMake / Compiler +# Setup / Bootstrap ################################################################################ # Detect Build Type @@ -48,6 +79,13 @@ else() set(ARCH "x64") endif() +# Search Path +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") + +################################################################################ +# CMake / Compiler +################################################################################ + # Configure Version Header configure_file( "${PROJECT_SOURCE_DIR}/cmake/version.hpp.in" @@ -58,6 +96,13 @@ configure_file( "${PROJECT_BINARY_DIR}/source/module.cpp" ) +# Windows +## Installer (InnoSetup) +Configure_File( + "${PROJECT_SOURCE_DIR}/cmake/installer.iss.in" + "${PROJECT_BINARY_DIR}/installer.iss" +) + # Windows Specific Resource Definition if(WIN32) set(PROJECT_PRODUCT_NAME "${PROJECT_FULL_NAME}") @@ -86,8 +131,6 @@ elseif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic") endif() -math(EXPR BITS "8*${CMAKE_SIZEOF_VOID_P}") - ################################################################################ # Options ################################################################################ @@ -158,6 +201,14 @@ elseif(${PropertyPrefix}OBS_DOWNLOAD) UPDATE_DISCONNECTED 1 ) include("${libobs_SOURCE_DIR}/cmake/LibObs/LibObsConfig.cmake") + if(WIN32) + download_project( + PROJ libobs-deps + URL "https://obsproject.com/downloads/dependencies2017.zip" + UPDATE_DISCONNECTED 1 + ) + set(FFmpegPath "${libobs-deps_SOURCE_DIR}/win${BITS}/") + endif() else() message(CRITICAL "Impossible case reached, very system stability.") return() @@ -178,8 +229,6 @@ set(PROJECT_PRIVATE "${PROJECT_SOURCE_DIR}/source/utility.hpp" "${PROJECT_SOURCE_DIR}/source/encoders/prores_aw.hpp" "${PROJECT_SOURCE_DIR}/source/encoders/prores_aw.cpp" - "${PROJECT_SOURCE_DIR}/source/encoders/prores_ks.hpp" - "${PROJECT_SOURCE_DIR}/source/encoders/prores_ks.cpp" "${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.cpp" "${PROJECT_SOURCE_DIR}/source/ffmpeg/avframe-queue.hpp" "${PROJECT_SOURCE_DIR}/source/ffmpeg/swscale.hpp" diff --git a/cmake/installer.iss.in b/cmake/installer.iss.in new file mode 100644 index 0000000..dc3bbcd --- /dev/null +++ b/cmake/installer.iss.in @@ -0,0 +1,114 @@ +; Script generated by the Inno Setup Script Wizard. +; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! + +#define MyAppName "@PROJECT_FULL_NAME@" +#define MyAppVersion "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@.@PROJECT_VERSION_TWEAK@" +#define MyAppPublisher "Xaymars Technology Workshop" +#define MyAppURL "https://www.xaymar.com/" + +[Setup] +; NOTE: The value of AppId uniquely identifies this application. +; Do not use the same AppId value in installers for other applications. +; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) +AppId={6559B77C-0F41-4F97-AC9D-2C13DE22D236} +AppName={#MyAppName} +AppVersion={#MyAppVersion} +;AppVerName={#MyAppName} {#MyAppVersion} +AppPublisher={#MyAppPublisher} +AppPublisherURL={#MyAppURL} +AppSupportURL={#MyAppURL} +AppUpdatesURL={#MyAppURL} +DefaultDirName={code:GetDirName} +DefaultGroupName={#MyAppName} +AllowNoIcons=yes +LicenseFile="@PROJECT_SOURCE_DIR@/LICENSE" +OutputDir="@CMAKE_INSTALL_PREFIX@/../" +OutputBaseFilename=obs-ffmpeg-encoder-{#MyAppVersion} +Compression=lzma +SolidCompression=yes +VersionInfoVersion={#MyAppVersion} +VersionInfoCompany={#MyAppPublisher} +VersionInfoDescription={#MyAppName} Setup + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" + +[Files] +Source: "@CMAKE_INSTALL_PREFIX@/*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs +; NOTE: Don't use "Flags: ignoreversion" on any shared system files + +[Icons] +Name: "{group}\{cm:ProgramOnTheWeb,{#MyAppName}}"; Filename: "{#MyAppURL}" +Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}" + +[Code] +function GetDirName(Value: string): string; +var + InstallPath: string; +begin + // initialize default path, which will be returned when the following registry + // key queries fail due to missing keys or for some different reason + Result := '{pf}\obs-studio'; + // query the first registry value; if this succeeds, return the obtained value + if RegQueryStringValue(HKLM32, 'SOFTWARE\OBS Studio', '', InstallPath) then + Result := InstallPath +end; + +///////////////////////////////////////////////////////////////////// +function GetUninstallString(): String; +var + sUnInstPath: String; + sUnInstallString: String; +begin + sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); + sUnInstallString := ''; + if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then + RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); + Result := sUnInstallString; +end; + + +///////////////////////////////////////////////////////////////////// +function IsUpgrade(): Boolean; +begin + Result := (GetUninstallString() <> ''); +end; + + +///////////////////////////////////////////////////////////////////// +function UnInstallOldVersion(): Integer; +var + sUnInstallString: String; + iResultCode: Integer; +begin +// Return Values: +// 1 - uninstall string is empty +// 2 - error executing the UnInstallString +// 3 - successfully executed the UnInstallString + + // default return value + Result := 0; + + // get the uninstall string of the old app + sUnInstallString := GetUninstallString(); + if sUnInstallString <> '' then begin + sUnInstallString := RemoveQuotes(sUnInstallString); + if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then + Result := 3 + else + Result := 2; + end else + Result := 1; +end; + +///////////////////////////////////////////////////////////////////// +procedure CurStepChanged(CurStep: TSetupStep); +begin + if (CurStep=ssInstall) then + begin + if (IsUpgrade()) then + begin + UnInstallOldVersion(); + end; + end; +end; \ No newline at end of file diff --git a/cmake/modules/FindFFmpeg.cmake b/cmake/modules/FindFFmpeg.cmake new file mode 100644 index 0000000..5206695 --- /dev/null +++ b/cmake/modules/FindFFmpeg.cmake @@ -0,0 +1,155 @@ +# +# This module defines the following variables: +# +# FFMPEG_FOUND - All required components and the core library were found +# FFMPEG_INCLUDE_DIRS - Combined list of all components include dirs +# FFMPEG_LIBRARIES - Combined list of all componenets libraries +# FFMPEG_VERSION_STRING - Version of the first component requested +# +# For each requested component the following variables are defined: +# +# FFMPEG__FOUND - The component was found +# FFMPEG__INCLUDE_DIRS - The components include dirs +# FFMPEG__LIBRARIES - The components libraries +# FFMPEG__VERSION_STRING - The components version string +# FFMPEG__VERSION_MAJOR - The components major version +# FFMPEG__VERSION_MINOR - The components minor version +# FFMPEG__VERSION_MICRO - The components micro version +# +# is the uppercase name of the component + + +find_package(PkgConfig QUIET) + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_lib_suffix 64) +else() + set(_lib_suffix 32) +endif() + +function(find_ffmpeg_library component header) + string(TOUPPER "${component}" component_u) + set(FFMPEG_${component_u}_FOUND FALSE PARENT_SCOPE) + set(FFmpeg_${component}_FOUND FALSE PARENT_SCOPE) + + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_FFMPEG_${component} QUIET lib${component}) + endif() + + find_path(FFMPEG_${component}_INCLUDE_DIR + NAMES + "lib${component}/${header}" "lib${component}/version.h" + HINTS + ENV FFmpegPath${_lib_suffix} + ENV FFmpegPath + ENV DepsPath${_lib_suffix} + ENV DepsPath + ${FFmpegPath${_lib_suffix}} + ${FFmpegPath} + ${DepsPath${_lib_suffix}} + ${DepsPath} + ${PC_FFMPEG_${component}_INCLUDE_DIRS} + PATHS + /usr/include /usr/local/include /opt/local/include /sw/include + PATH_SUFFIXES ffmpeg libav include) + + find_library(FFMPEG_${component}_LIBRARY + NAMES + "${component}" "lib${component}" + HINTS + ENV FFmpegPath${_lib_suffix} + ENV FFmpegPath + ENV DepsPath${_lib_suffix} + ENV DepsPath + ${FFmpegPath${_lib_suffix}} + ${FFmpegPath} + ${DepsPath${_lib_suffix}} + ${DepsPath} + ${PC_FFMPEG_${component}_LIBRARY_DIRS} + PATHS + /usr/lib /usr/local/lib /opt/local/lib /sw/lib + PATH_SUFFIXES + lib${_lib_suffix} lib + libs${_lib_suffix} libs + bin${_lib_suffix} bin + ../lib${_lib_suffix} ../lib + ../libs${_lib_suffix} ../libs + ../bin${_lib_suffix} ../bin) + + set(FFMPEG_${component_u}_INCLUDE_DIRS ${FFMPEG_${component}_INCLUDE_DIR} PARENT_SCOPE) + set(FFMPEG_${component_u}_LIBRARIES ${FFMPEG_${component}_LIBRARY} PARENT_SCOPE) + + mark_as_advanced(FFMPEG_${component}_INCLUDE_DIR FFMPEG_${component}_LIBRARY) + + if(FFMPEG_${component}_INCLUDE_DIR AND FFMPEG_${component}_LIBRARY) + set(FFMPEG_${component_u}_FOUND TRUE PARENT_SCOPE) + set(FFmpeg_${component}_FOUND TRUE PARENT_SCOPE) + + list(APPEND FFMPEG_INCLUDE_DIRS ${FFMPEG_${component}_INCLUDE_DIR}) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) + set(FFMPEG_INCLUDE_DIRS "${FFMPEG_INCLUDE_DIRS}" PARENT_SCOPE) + + list(APPEND FFMPEG_LIBRARIES ${FFMPEG_${component}_LIBRARY}) + list(REMOVE_DUPLICATES FFMPEG_LIBRARIES) + set(FFMPEG_LIBRARIES "${FFMPEG_LIBRARIES}" PARENT_SCOPE) + + set(FFMPEG_${component_u}_VERSION_STRING "unknown" PARENT_SCOPE) + set(_vfile "${FFMPEG_${component}_INCLUDE_DIR}/lib${component}/version.h") + + if(EXISTS "${_vfile}") + file(STRINGS "${_vfile}" _version_parse REGEX "^.*VERSION_(MAJOR|MINOR|MICRO)[ \t]+[0-9]+[ \t]*$") + string(REGEX REPLACE ".*VERSION_MAJOR[ \t]+([0-9]+).*" "\\1" _major "${_version_parse}") + string(REGEX REPLACE ".*VERSION_MINOR[ \t]+([0-9]+).*" "\\1" _minor "${_version_parse}") + string(REGEX REPLACE ".*VERSION_MICRO[ \t]+([0-9]+).*" "\\1" _micro "${_version_parse}") + + set(FFMPEG_${component_u}_VERSION_MAJOR "${_major}" PARENT_SCOPE) + set(FFMPEG_${component_u}_VERSION_MINOR "${_minor}" PARENT_SCOPE) + set(FFMPEG_${component_u}_VERSION_MICRO "${_micro}" PARENT_SCOPE) + + set(FFMPEG_${component_u}_VERSION_STRING "${_major}.${_minor}.${_micro}" PARENT_SCOPE) + else() + message(STATUS "Failed parsing FFmpeg ${component} version") + endif() + endif() +endfunction() + +set(FFMPEG_INCLUDE_DIRS) +set(FFMPEG_LIBRARIES) + +if(NOT FFmpeg_FIND_COMPONENTS) + message(FATAL_ERROR "No FFmpeg components requested") +endif() + +list(GET FFmpeg_FIND_COMPONENTS 0 _first_comp) +string(TOUPPER "${_first_comp}" _first_comp) + +foreach(component ${FFmpeg_FIND_COMPONENTS}) + if(component STREQUAL "avcodec") + find_ffmpeg_library("${component}" "avcodec.h") + elseif(component STREQUAL "avdevice") + find_ffmpeg_library("${component}" "avdevice.h") + elseif(component STREQUAL "avfilter") + find_ffmpeg_library("${component}" "avfilter.h") + elseif(component STREQUAL "avformat") + find_ffmpeg_library("${component}" "avformat.h") + elseif(component STREQUAL "avresample") + find_ffmpeg_library("${component}" "avresample.h") + elseif(component STREQUAL "avutil") + find_ffmpeg_library("${component}" "avutil.h") + elseif(component STREQUAL "postproc") + find_ffmpeg_library("${component}" "postprocess.h") + elseif(component STREQUAL "swresample") + find_ffmpeg_library("${component}" "swresample.h") + elseif(component STREQUAL "swscale") + find_ffmpeg_library("${component}" "swscale.h") + else() + message(FATAL_ERROR "Unknown FFmpeg component requested: ${component}") + endif() +endforeach() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(FFmpeg + FOUND_VAR FFMPEG_FOUND + REQUIRED_VARS FFMPEG_${_first_comp}_LIBRARIES FFMPEG_${_first_comp}_INCLUDE_DIRS + VERSION_VAR FFMPEG_${_first_comp}_VERSION_STRING + HANDLE_COMPONENTS)