diff --git a/.appveyor.yml b/.appveyor.yml index 3b632d1f30e..7ca7d58c4ce 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -19,5 +19,9 @@ build_script: - cmake -DUSE_COMPILE_CACHE=ON -DCACHE_TOOL=%APPVEYOR_BUILD_FOLDER%/clcache.4.1.0/clcache-4.1.0/clcache.exe -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_PREFIX_PATH=c:/Qt/5.12/msvc2017%QT_SUFFIX%;c:/tools/vcpkg/installed/%PLATFORM%-windows -DCMAKE_GENERATOR_PLATFORM="%CMAKE_PLATFORM%" .. - cmake --build . -- /maxcpucount:4 - cmake --build . --target tests + - cmake --build . --target package +artifacts: + - path: 'build\lmms-*.exe' + name: Installer cache: - c:/tools/vcpkg/installed diff --git a/.circleci/config.yml b/.circleci/config.yml index 4174ba1effb..99b987f8675 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -59,6 +59,15 @@ jobs: - run: name: Build tests command: cd build && make tests + - run: + name: Build installer + command: | + cd build + make package + cp ./lmms-*.exe /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / - *ccache_stats - *save_cache mingw64: @@ -79,6 +88,15 @@ jobs: - run: name: Build tests command: cd build && make tests + - run: + name: Build installer + command: | + cd build + make package + cp ./lmms-*.exe /tmp/artifacts/ + - store_artifacts: + path: /tmp/artifacts/ + destination: / - *ccache_stats - *save_cache linux.gcc: diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9d376e286..a08a9c8f76f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.3) PROJECT(lmms) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH}) +SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) +SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0005 NEW) @@ -13,6 +15,7 @@ IF(COMMAND CMAKE_POLICY) CMAKE_POLICY(SET CMP0050 OLD) ENDIF() CMAKE_POLICY(SET CMP0020 NEW) + CMAKE_POLICY(SET CMP0057 NEW) ENDIF(COMMAND CMAKE_POLICY) INCLUDE(CheckSubmodules) @@ -565,8 +568,8 @@ ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(data) ADD_SUBDIRECTORY(doc) -# post-install tasks -ADD_SUBDIRECTORY(cmake/postinstall) +# install tasks +ADD_SUBDIRECTORY(cmake/install) ADD_CUSTOM_COMMAND(OUTPUT "${CMAKE_BINARY_DIR}/lmms.1.gz" COMMAND gzip -c ${CMAKE_SOURCE_DIR}/doc/lmms.1 > ${CMAKE_BINARY_DIR}/lmms.1.gz @@ -706,4 +709,9 @@ MESSAGE( "\n\n") SET(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION "${BIN_DIR}") +if(MSVC) + # We can't set this on the install time according to the configuration + SET(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE) + SET(CMAKE_INSTALL_UCRT_LIBRARIES TRUE) +endif() INCLUDE(InstallRequiredSystemLibraries) diff --git a/cmake/install/CMakeLists.txt b/cmake/install/CMakeLists.txt new file mode 100644 index 00000000000..a3a81beebda --- /dev/null +++ b/cmake/install/CMakeLists.txt @@ -0,0 +1,41 @@ +SET(PLUGIN_FILES "") +IF(LMMS_BUILD_WIN32) + INSTALL(FILES $ DESTINATION platforms) +ENDIF() + +IF(LMMS_BUILD_WIN32 OR LMMS_INSTALL_DEPENDENCIES) + include(InstallTargetDependencies) + + # Collect directories to search for DLLs + GET_FILENAME_COMPONENT(QTBIN_DIR "${QT_QMAKE_EXECUTABLE}" PATH) + set(LIB_DIRS "${QTBIN_DIR}") + + GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) + + IF(LMMS_BUILD_WIN32) + SET(LMMS_DEP_DESTINATION ${BIN_DIR}) + SET(PLUGIN_DEP_DESTINATION ${BIN_DIR}) + ELSE() + SET(LMMS_DEP_DESTINATION ${LIB_DIR}) + SET(PLUGIN_DEP_DESTINATION ${LIB_DIR}) + ENDIF() + + INSTALL_TARGET_DEPENDENCIES( + NAME "main_binary" + TARGETS lmms + DESTINATION "${LMMS_DEP_DESTINATION}" + LIB_DIRS ${LIB_DIRS} + ) + + INSTALL_TARGET_DEPENDENCIES( + NAME "plugins" + TARGETS ${PLUGINS_BUILT} + DESTINATION ${PLUGIN_DEP_DESTINATION} + LIB_DIRS ${LIB_DIRS} "${PLUGIN_DIR}" + ) +ENDIF() + +IF(LMMS_BUILD_APPLE) + INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") +ENDIF() diff --git a/cmake/install/excludelist-win b/cmake/install/excludelist-win new file mode 100644 index 00000000000..17793a113d9 --- /dev/null +++ b/cmake/install/excludelist-win @@ -0,0 +1,23 @@ +# List of DLLs considered to be system libraries. +# This is needed when cross-compiling for Windows. +ADVAPI32.dll +COMCTL32.dll +comdlg32.dll +dwmapi.dll +GDI32.dll +IMM32.dll +KERNEL32.dll +MPR.DLL +msvcrt.dll +ole32.dll +OLEAUT32.dll +OPENGL32.DLL +SHELL32.dll +USER32.dll +UxTheme.dll +VERSION.dll +WINMM.DLL +WS2_32.dll +RPCRT4.dll +dsound.dll +SETUPAPI.dll diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index efa3e5b468e..675433e631b 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -62,7 +62,10 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms) ENDIF(LMMS_BUILD_WIN32) - INSTALL(TARGETS ${PLUGIN_NAME} DESTINATION "${PLUGIN_DIR}") + INSTALL(TARGETS ${PLUGIN_NAME} + LIBRARY DESTINATION "${PLUGIN_DIR}" + RUNTIME DESTINATION "${PLUGIN_DIR}" + ) IF(LMMS_BUILD_APPLE) IF ("${PLUGIN_LINK}" STREQUAL "SHARED") @@ -72,9 +75,11 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) ENDIF() ADD_DEPENDENCIES(${PLUGIN_NAME} lmms) ENDIF(LMMS_BUILD_APPLE) - IF(LMMS_BUILD_WIN32 AND STRIP) + IF(LMMS_BUILD_WIN32) + IF(STRIP) + ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") + ENDIF() SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES PREFIX "") - ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") ENDIF() SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${RCC_OUT} ${plugin_MOC_out}") @@ -89,5 +94,8 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_INCLUDE_DIRECTORIES(${PLUGIN_NAME} PUBLIC $ ) + + SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT ${PLUGIN_NAME}) + GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) ENDMACRO(BUILD_PLUGIN) diff --git a/cmake/modules/CreateTempFile.cmake b/cmake/modules/CreateTempFile.cmake new file mode 100644 index 00000000000..5210342ac0d --- /dev/null +++ b/cmake/modules/CreateTempFile.cmake @@ -0,0 +1,21 @@ +function(CreateTempFilePath) + set(options CONFIG_SUFFIX) + set(oneValueArgs OUTPUT_VAR TAG) + set(multiValueArgs CONTENT) + cmake_parse_arguments(TEMP "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # Use hash to create a unique identifier + # for this file. + string(SHA1 hashed_content "${TEMP_CONTENT}") + + set(file_name "${CMAKE_BINARY_DIR}/${TEMP_TAG}_${hashed_content}") + set(${TEMP_OUTPUT_VAR} "${file_name}" PARENT_SCOPE) + if(CONFIG_SUFFIX) + set(file_name "${file_name}_$") + endif() + + file(GENERATE OUTPUT "${file_name}" + CONTENT "${TEMP_CONTENT}") + +endfunction() diff --git a/cmake/modules/DefineInstallVar.cmake b/cmake/modules/DefineInstallVar.cmake new file mode 100644 index 00000000000..b13cb1d52b3 --- /dev/null +++ b/cmake/modules/DefineInstallVar.cmake @@ -0,0 +1,31 @@ +# This functions forwards a variable to +# the install stage. +# Parameters: +# CONTENT: Variable content. +# NAME: Variable name. +# Options: +# GENERATOR_EXPRESSION: Support generator expression for CONTENT. +function(DEFINE_INSTALL_VAR) + set(options GENERATOR_EXPRESSION) + set(oneValueArgs NAME ) + set(multiValueArgs CONTENT) + cmake_parse_arguments(VAR "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + # install(CODE) does not support generator expression in ver<3.14 + if(VAR_GENERATOR_EXPRESSION AND ${CMAKE_VERSION} VERSION_LESS "3.14.0") + include(CreateTempFile) + if(CMAKE_CONFIGURATION_TYPES) # in case of multi-config generators like MSVC generators + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}" CONFIG_SUFFIX) + install(CODE "file(READ \"${file_path}_\${CMAKE_INSTALL_CONFIG_NAME}\" \"${VAR_NAME}\")") + else() + CreateTempFilePath(OUTPUT_VAR file_path TAG "${VAR_NAME}" CONTENT "${VAR_CONTENT}") + install(CODE "file(READ \"${file_path}\" \"${VAR_NAME}\")") + endif() + else() + if(VAR_GENERATOR_EXPRESSION) + cmake_policy(SET CMP0087 NEW) + endif() + install(CODE "set(\"${VAR_NAME}\" \"${VAR_CONTENT}\")") + endif() +endfunction() diff --git a/cmake/modules/InstallDependencies.cmake b/cmake/modules/InstallDependencies.cmake new file mode 100644 index 00000000000..791041bb24a --- /dev/null +++ b/cmake/modules/InstallDependencies.cmake @@ -0,0 +1,184 @@ +include(GetPrerequisites) +include(CMakeParseArguments) + +CMAKE_POLICY(SET CMP0011 NEW) +CMAKE_POLICY(SET CMP0057 NEW) + +function(make_absolute var) + get_filename_component(abs "${${var}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}") + set(${var} ${abs} PARENT_SCOPE) +endfunction() + +# Reads lines of a file into a list, skipping '#' comment lines +function(READ_LIST_FILE FILE VAR) + file(STRINGS "${FILE}" list) + + set(result "") + foreach(item ${list}) + string(STRIP "${item}" item) + if(item STREQUAL "" OR item MATCHES "^\#") + continue() + endif() + list(APPEND result "${item}") + endforeach() + + set(${VAR} ${result} PARENT_SCOPE) +endfunction() + +function(make_all_absolute list_var) + set(result "") + foreach(file ${${list_var}}) + make_absolute(file) + list(APPEND result ${file}) + endforeach() + set(${list_var} ${result} PARENT_SCOPE) +endfunction() + +if(CMAKE_BINARY_DIR) + set(tmp_lib_dir "${CMAKE_BINARY_DIR}/bundled-libraries") +elseif(CMAKE_HOST_UNIX) + set(tmp_lib_dir "/tmp/bundled-libraries") +elseif(DEFINED ENV{TEMP}) + set(tmp_lib_dir "$ENV{TMP}/bundled-libraries") +else() + message(FATAL_ERROR "Can't find a temp dir for libraries") +endif() + +# Like file(INSTALL), but resolves symlinks +function(install_file_resolved file destination) + + get_filename_component(file_name "${file}" NAME) + if(IS_SYMLINK "${file}") + get_filename_component(real_path "${file}" REALPATH) + get_filename_component(real_name "${real_path}" NAME) + file(COPY "${real_path}" DESTINATION "${tmp_lib_dir}") + file(RENAME "${tmp_lib_dir}/${real_name}" "${tmp_lib_dir}/${file_name}") + set(file_path "${tmp_lib_dir}/${file_name}") + else() + set(file_path "${file}") + endif() + + file(INSTALL "${file_path}" DESTINATION "${destination}") +endfunction() + +function(install_resolved) + cmake_parse_arguments("" "" "DESTINATION" "FILES" ${ARGN}) + foreach(file ${_FILES}) + install_file_resolved("${file}" "${_DESTINATION}") + endforeach() +endfunction() + +if(CMAKE_CROSSCOMPILING) + # If we're cross-compiling, GetPrerequisites may not be able to find system libraries such as kernel32.dll because + # they're supplied by the toolchain. To suppress thousands of lines of warnings being printed to the console, we + # override gp_resolved_file_type to return "system" for any library in ${IGNORE_LIBS} without trying to resolve the + # file first. + # GetPrerequisites supports using an override function called gp_resolved_file_type_override, but it's not suited + # for our purpose because it's only called by gp_resolved_file_type *after* trying to resolve the file. + function(gp_resolved_file_type original_file file exepath dirs type_var) + set(file_find "${file}") + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${file_find}" file_find) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + if(IGNORE_LIBS AND ${file_find} IN_LIST IGNORE_LIBS) + set(${type_var} system PARENT_SCOPE) + else() + #_gp_resolved_file_type(${ARGV}) + _gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "${dirs}" "${type_var}" ${ARGN}) + endif() + endfunction() +endif() + +function(INSTALL_DEPENDENCIES) + cmake_parse_arguments("" "INCLUDE_SYSTEM;IGNORE_CASE" "GP_TOOL;DESTINATION;IGNORE_LIBS_FILE" "FILES;LIB_DIRS;SEARCH_PATHS;IGNORE_LIBS" ${ARGN}) + + # Make paths absolute + make_absolute(_DESTINATION) + make_all_absolute(_FILES) + make_all_absolute(_LIB_DIRS) + make_all_absolute(_SEARCH_PATHS) + + if(_INCLUDE_SYSTEM) + set(EXCLUDE_SYSTEM 0) + else() + set(EXCLUDE_SYSTEM 1) + endif() + + if(_IGNORE_LIBS_FILE) + READ_LIST_FILE("${_IGNORE_LIBS_FILE}" _IGNORE_LIBS) + if(_IGNORE_CASE) + # On case-insensitive systems, convert to upper characters to respect it + string(TOUPPER "${_IGNORE_LIBS}" _IGNORE_LIBS) + endif() + SET(IGNORE_LIBS ${_IGNORE_LIBS} CACHE INTERNAL "Ignored library names" FORCE) + endif() + + if(_GP_TOOL) + set(gp_tool "${_GP_TOOL}") + endif() + + set(prereqs "") + foreach(file ${_FILES}) + get_filename_component(file_name "${file}" NAME) + message("-- Finding prerequisites of ${file_name}") + find_prerequisites("${file}" _prereqs + ${EXCLUDE_SYSTEM} # exclude system files + 1 # recurse + "" + "${_LIB_DIRS}" + "${_SEARCH_PATHS}" + "${_IGNORE_LIBS}" + ) + + list(APPEND prereqs ${_prereqs}) + endforeach() + + list(REMOVE_DUPLICATES prereqs) + + foreach(prereq ${prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + + foreach(rpath ${_SEARCH_PATHS}) + if(EXISTS "${rpath}/${prereq_name}") + list(REMOVE_ITEM prereqs "${prereq}") + break() + endif() + endforeach() + endforeach() + + #file(INSTALL ${prereqs} DESTINATION ${_DESTINATION}) + install_resolved(FILES ${prereqs} DESTINATION "${_DESTINATION}") +endfunction() + +# Like get_prerequisites, but returns full paths +function(FIND_PREREQUISITES target RESULT_VAR exclude_system recurse + exepath dirs rpaths) + set(RESULTS) + + get_prerequisites("${target}" _prereqs ${exclude_system} ${recurse} + "" "${dirs}" "${rpaths}") + + foreach(prereq ${_prereqs}) + get_filename_component(prereq_name "${prereq}" NAME) + if(_IGNORE_CASE) + # Windows is case insensitive. + # Use upper characters to respect it. + string(TOUPPER "${prereq_name}" prereq_name) + endif() + if("${prereq_name}" IN_LIST IGNORE_LIBS) + continue() + endif() + + gp_resolve_item("${LIB_DLL}" "${prereq}" "" "${dirs}" RESOLVED_PREREQ "${rpaths}") + + if(RESOLVED_PREREQ AND IS_ABSOLUTE ${RESOLVED_PREREQ} AND EXISTS ${RESOLVED_PREREQ}) + list(APPEND RESULTS ${RESOLVED_PREREQ}) + else() + message(FATAL_ERROR "Can't resolve dependency ${prereq}.") + endif() + endforeach() + + set(${RESULT_VAR} ${RESULTS} PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/InstallTargetDependencies.cmake b/cmake/modules/InstallTargetDependencies.cmake new file mode 100644 index 00000000000..9665a0b8715 --- /dev/null +++ b/cmake/modules/InstallTargetDependencies.cmake @@ -0,0 +1,89 @@ +include(DefineInstallVar) + +SET(DEFAULT_SEARCH_DIRECTORIES "${BIN_DIR}" "${LIB_DIR}" "${CMAKE_FIND_ROOT_PATH}" "${CMAKE_PREFIX_PATH}") +SET(DEFAULT_SEARCH_SUFFIXES "bin" "lib" "../bin") + +# Like INSTALL_DEPENDENCIES but can be called from regular cmake code +# (instead of install(CODE)), takes targets instead of files, +# takes care of configuring search paths, and other platform-specific tweaks. +# Arguments: +# TARGETS: list of cmake targets to install. +# NAME: unique string for this install. +# DESTINATION: directory path to install the binaries to. +# LIB_DIRS: list of paths for looking up dependencies. +# LIB_DIRS_SUFFIXES: list of possible suffixes for LIB_DIRS entries. +# NO_DEFAULT_PATHS: supply this value to avoid adding DEFAULT_SEARCH_DIRECTORIES +# to LIB_DIRS and DEFAULT_SEARCH_SUFFIXES to LIB_DIRS_SUFFIXES. +FUNCTION(INSTALL_TARGET_DEPENDENCIES) + set(options NO_DEFAULT_PATHS) + set(oneValueArgs NAME) + set(multiValueArgs TARGETS DESTINATION LIB_DIRS_SUFFIXES LIB_DIRS) + cmake_parse_arguments(DEPS "${options}" "${oneValueArgs}" + "${multiValueArgs}" ${ARGN} ) + + if(NOT DEPS_LIB_DIRS) + set(DEPS_LIB_DIRS "") + endif() + + # Set default values. + if(NOT DEPS_NO_DEFAULT_PATHS) + list(APPEND DEPS_LIB_DIRS ${DEFAULT_SEARCH_DIRECTORIES}) + set(DEPS_LIB_DIRS_SUFFIXES "${DEPS_LIB_DIRS_SUFFIXES}" ${DEFAULT_SEARCH_SUFFIXES}) + endif() + + FOREACH(TARGET ${DEPS_TARGETS}) + IF(NOT TARGET ${TARGET}) + message(FATAL_ERROR "Not a target: ${TARGET}") + ENDIF() + + # Collect target output files. + LIST(APPEND DEPLOY_TARGETS "$") + + # Collect target link directories + get_target_property(target_libs ${TARGET} LINK_LIBRARIES) + + foreach(lib ${target_libs}) + if(TARGET ${lib} OR NOT IS_ABSOLUTE ${lib}) + continue() + endif() + + get_filename_component(lib_dir ${lib} PATH) + list(APPEND DEPS_LIB_DIRS ${lib_dir}) + endforeach() + ENDFOREACH() + + LIST(APPEND DEPS_LIB_DIRS ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) + + FOREACH(LIB_PATH ${DEPS_LIB_DIRS}) + FOREACH(suffix ${DEPS_LIB_DIRS_SUFFIXES}) + list(APPEND DEPS_LIB_DIRS "${LIB_PATH}/${suffix}") + ENDFOREACH() + ENDFOREACH() + + DEFINE_INSTALL_VAR(NAME "DEPLOY_FILES" CONTENT "${DEPLOY_TARGETS}" GENERATOR_EXPRESSION) + + LIST(REMOVE_DUPLICATES DEPS_LIB_DIRS) + + IF(LMMS_BUILD_LINUX) + FILE(DOWNLOAD "https://raw.githubusercontent.com/AppImage/AppImages/master/excludelist" + "${CMAKE_BINARY_DIR}/excludelist") + SET(additional_args INCLUDE_SYSTEM IGNORE_LIBS_FILE ${CMAKE_BINARY_DIR}/excludelist) + ELSEIF(LMMS_BUILD_WIN32) + SET(additional_args IGNORE_CASE IGNORE_LIBS_FILE "${LMMS_SOURCE_DIR}/cmake/install/excludelist-win") + IF(CMAKE_CROSSCOMPILING) + SET(additional_args "${additional_args}" GP_TOOL objdump) + ENDIF() + ENDIF() + + INSTALL(CODE " + INCLUDE(\"${LMMS_SOURCE_DIR}/cmake/modules/InstallDependencies.cmake\") + + INSTALL_DEPENDENCIES( + FILES \"\${DEPLOY_FILES}\" + DESTINATION \"${DEPS_DESTINATION}\" + LIB_DIRS \"${DEPS_LIB_DIRS}\" + SEARCH_PATHS \"${DEPS_SEARCH_PATHS}\" + ${additional_args} + ) + ") +ENDFUNCTION() diff --git a/cmake/postinstall/CMakeLists.txt b/cmake/postinstall/CMakeLists.txt deleted file mode 100644 index 434d1c54e79..00000000000 --- a/cmake/postinstall/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -IF(LMMS_BUILD_APPLE) - INSTALL(CODE "EXECUTE_PROCESS(COMMAND chmod u+x ${CMAKE_BINARY_DIR}/install_apple.sh)") - INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_BINARY_DIR}/install_apple.sh)") -ENDIF() \ No newline at end of file diff --git a/plugins/vst_base/CMakeLists.txt b/plugins/vst_base/CMakeLists.txt index 44ed0dcb3be..873ed5f8e81 100644 --- a/plugins/vst_base/CMakeLists.txt +++ b/plugins/vst_base/CMakeLists.txt @@ -11,23 +11,35 @@ SET(REMOTE_VST_PLUGIN_FILEPATH_64 "RemoteVstPlugin64" CACHE STRING "Relative fil ADD_SUBDIRECTORY(vstbase) -SET(LMMS_BINARY_DIR ${CMAKE_BINARY_DIR}) -SET(LMMS_SOURCE_DIR ${CMAKE_SOURCE_DIR}) - SET(EXTERNALPROJECT_ARGS SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin" - INSTALL_COMMAND "" + #INSTALL_COMMAND "" BUILD_ALWAYS ON + # Skip the install step. + INSTALL_COMMAND "" ) +set(export_variables + "LMMS_SOURCE_DIR" + "LMMS_BINARY_DIR" + "CMAKE_MODULE_PATH" + "CMAKE_RUNTIME_OUTPUT_DIRECTORY" + "CMAKE_BUILD_TYPE" + "LMMS_BUILD_LINUX" + "LMMS_BUILD_WIN32" + "PLUGIN_DIR") + SET(EXTERNALPROJECT_CMAKE_ARGS - "-DLMMS_SOURCE_DIR=${CMAKE_SOURCE_DIR}" - "-DLMMS_BINARY_DIR=${CMAKE_BINARY_DIR}" - "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" - "-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}" - "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" + "-DBUILD_WITH_EXTERNALPROJECT=ON" ) +macro(_export_var_to_external var_name) + list(APPEND EXTERNALPROJECT_CMAKE_ARGS "-D${var_name}=${${var_name}}") +endmacro() +foreach(var ${export_variables}) + _export_var_to_external(${var}) +endforeach() + # build 32 bit version of RemoteVstPlugin IF(WANT_VST_32) INCLUDE("${CMAKE_CURRENT_LIST_DIR}/RemoteVstPlugin32.cmake") diff --git a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt index 59dd19a0aa6..f4023fd426c 100644 --- a/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt +++ b/plugins/vst_base/RemoteVstPlugin/CMakeLists.txt @@ -76,3 +76,18 @@ endif() IF(STRIP) ADD_CUSTOM_COMMAND(TARGET ${EXE_NAME} POST_BUILD COMMAND "${STRIP}" "$") ENDIF() + +if(BITNESS EQUAL 32) + INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}/32") +else() + INSTALL(TARGETS ${EXE_NAME} RUNTIME DESTINATION "${PLUGIN_DIR}") +endif() + +if(BUILD_WITH_EXTERNALPROJECT) + include(InstallTargetDependencies) + INSTALL_TARGET_DEPENDENCIES(TARGETS ${EXE_NAME} + DESTINATION "${PLUGIN_DIR}/32") +else() + # Needed to deploy dependencies of RemoteVstPlugin + SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "${EXE_NAME}") +endif() diff --git a/plugins/vst_base/RemoteVstPlugin32.cmake b/plugins/vst_base/RemoteVstPlugin32.cmake index 9a8f0452948..efbd00ee9ec 100644 --- a/plugins/vst_base/RemoteVstPlugin32.cmake +++ b/plugins/vst_base/RemoteVstPlugin32.cmake @@ -1,14 +1,21 @@ +# INSTALL_EXTERNAL_PROJECT: install a project created with ExternalProject_Add in the +# parent project's install time. +# +# Description: +# In a regular scenario, cmake will install external projects +# BEFORE actually building the parent project. Since the building +# process may use installed components from the project. +# We want to give the external project the ability to install +# files directly to the parent's install. Therefore, we have to +# manually trigger the install stage with the parent's INSTALL_PREFIX. +MACRO(INSTALL_EXTERNAL_PROJECT name) + ExternalProject_Get_Property(${name} BINARY_DIR) + + install(CODE "include(\"${BINARY_DIR}/cmake_install.cmake\")") +ENDMACRO() + IF(LMMS_BUILD_WIN32 AND NOT LMMS_BUILD_WIN64) ADD_SUBDIRECTORY(RemoteVstPlugin) - IF(MSVC) - SET(VCPKG_ROOT "${CMAKE_FIND_ROOT_PATH}") - INSTALL(FILES "${VCPKG_ROOT}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - ELSE(MSVC) - INSTALL(FILES "${MINGW_PREFIX}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${MINGW_PREFIX}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - ENDIF(MSVC) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") ELSEIF(LMMS_BUILD_WIN64 AND MSVC) SET(MSVC_VER ${CMAKE_CXX_COMPILER_VERSION}) @@ -46,16 +53,7 @@ ELSEIF(LMMS_BUILD_WIN64 AND MSVC) "-DCMAKE_PREFIX_PATH=${QT_32_PREFIX}" ) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") - - #TODO: find a solution when not using vcpkg for qt - SET(VCPKG_ROOT_32 "${CMAKE_FIND_ROOT_PATH}/../x86-windows") - - INSTALL(FILES "${VCPKG_ROOT_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/pcre2-16.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/double-conversion.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${VCPKG_ROOT_32}/bin/qt5core.dll" DESTINATION "${PLUGIN_DIR}/32") - + INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) ELSEIF(LMMS_BUILD_LINUX) # Use winegcc INCLUDE(CheckWineGcc) @@ -82,9 +80,7 @@ ELSEIF(CMAKE_TOOLCHAIN_FILE_32) "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH_32}" "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE_32}" ) - INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/Qt5Core.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(FILES "${CMAKE_PREFIX_PATH_32}/bin/zlib1.dll" DESTINATION "${PLUGIN_DIR}/32") - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../32/RemoteVstPlugin32.exe" DESTINATION "${PLUGIN_DIR}/32") + INSTALL_EXTERNAL_PROJECT(RemoteVstPlugin32) ELSE() MESSAGE(WARNING "Can't build RemoteVstPlugin32, unknown environment. Please supply CMAKE_TOOLCHAIN_FILE_32 and optionally CMAKE_PREFIX_PATH_32") RETURN() diff --git a/plugins/vst_base/RemoteVstPlugin64.cmake b/plugins/vst_base/RemoteVstPlugin64.cmake index 4b02bf8abf4..65b33a16251 100644 --- a/plugins/vst_base/RemoteVstPlugin64.cmake +++ b/plugins/vst_base/RemoteVstPlugin64.cmake @@ -1,6 +1,5 @@ IF(LMMS_BUILD_WIN64) ADD_SUBDIRECTORY(RemoteVstPlugin) - INSTALL(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/../RemoteVstPlugin64.exe" DESTINATION "${PLUGIN_DIR}") ELSEIF(LMMS_BUILD_LINUX) INCLUDE(CheckWineGcc) CheckWineGcc(64 "${WINEGCC}" WINEGCC_WORKING) diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index f1d37fa3eb6..d6fa9c727a8 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -162,6 +162,8 @@ SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) ADD_EXECUTABLE(RemoteZynAddSubFx RemoteZynAddSubFx.cpp "${WINRC}") INSTALL(TARGETS RemoteZynAddSubFx RUNTIME DESTINATION "${PLUGIN_DIR}") +# Needed to deploy dependencies of RemoteZynAddSubFx +SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT "RemoteZynAddSubFx") IF(LMMS_BUILD_WIN32) SET_TARGET_PROPERTIES(RemoteZynAddSubFx PROPERTIES LINK_FLAGS "${LINK_FLAGS} -mwindows") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ac6bf1332f..10ce72ae6c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -186,210 +186,20 @@ FOREACH(LIB ${LMMS_REQUIRED_LIBS}) ENDIF() ENDFOREACH() - -# Install -IF(NOT MSVC) - IF(LMMS_BUILD_WIN32) - SET_TARGET_PROPERTIES(lmms PROPERTIES - LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON - ) - - IF(LMMS_BUILD_MSYS) - # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. - # Add the linker flag manually to create liblmms.dll.a import library - SET_PROPERTY(TARGET lmms - APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" - ) - ENDIF() - - IF(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") - ADD_CUSTOM_COMMAND(TARGET lmms POST_BUILD COMMAND "${STRIP}" "$") - ENDIF() - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - INSTALL(FILES - "${MINGW_PREFIX}/bin/Qt5Core.dll" - "${MINGW_PREFIX}/bin/Qt5Gui.dll" - "${MINGW_PREFIX}/bin/Qt5Widgets.dll" - "${MINGW_PREFIX}/bin/Qt5Xml.dll" - DESTINATION .) - INSTALL(FILES - "${MINGW_PREFIX}/lib/qt5/plugins/platforms/qwindows.dll" - DESTINATION ./platforms) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libsamplerate-0.dll" - "${MINGW_PREFIX}/bin/libsndfile-1.dll" - "${MINGW_PREFIX}/bin/libvorbis-0.dll" - "${MINGW_PREFIX}/bin/libvorbisenc-2.dll" - "${MINGW_PREFIX}/bin/libvorbisfile-3.dll" - "${MINGW_PREFIX}/bin/libjpeg-9.dll" - "${MINGW_PREFIX}/bin/libogg-0.dll" - "${MINGW_PREFIX}/bin/libmp3lame-0.dll" - "${MINGW_PREFIX}/bin/libfftw3f-3.dll" - "${MINGW_PREFIX}/bin/libFLAC-8.dll" - "${MINGW_PREFIX}/bin/libpng16-16.dll" - "${MINGW_PREFIX}/bin/SDL.dll" - "${MINGW_PREFIX}/bin/libglib-2.0-0.dll" - "${MINGW_PREFIX}/bin/libgthread-2.0-0.dll" - "${MINGW_PREFIX}/bin/zlib1.dll" - "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll" - DESTINATION .) - IF(LMMS_BUILD_MSYS) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libwinpthread-1.dll" - "${MINGW_PREFIX}/bin/libgcc_s_seh-1.dll" - "${MINGW_PREFIX}/bin/libstdc++-6.dll" - DESTINATION .) - ELSE() - INSTALL(FILES - "${MINGW_PREFIX}/${CMAKE_SYSTEM_PROCESSOR}-w64-mingw32/bin/libwinpthread-1.dll" - DESTINATION .) - ENDIF() - IF(FLTK_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libfltk.dll" - DESTINATION .) - ENDIF() - IF(FLUIDSYNTH_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libfluidsynth.dll" - DESTINATION .) - ENDIF() - IF(GIG_FOUND) - # Handle libgig-*.dll - FILE(GLOB GIG_LIBRARY "${MINGW_PREFIX}/bin/libgig-*.dll") - INSTALL(FILES - ${GIG_LIBRARY} - DESTINATION .) - ENDIF() - IF(PORTAUDIO_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/bin/libportaudio-2.dll" - DESTINATION .) - ENDIF() - IF(SOUNDIO_FOUND) - INSTALL(FILES - "${MINGW_PREFIX}/lib/libsoundio.dll" - DESTINATION .) - ENDIF() - - ELSE(LMMS_BUILD_WIN32) - IF(NOT LMMS_BUILD_APPLE) - SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") - ENDIF(NOT LMMS_BUILD_APPLE) - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) - - ENDIF(LMMS_BUILD_WIN32) -ELSE(NOT MSVC) - SET_TARGET_PROPERTIES(lmms PROPERTIES - ENABLE_EXPORTS ON - ) - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - - SET_TARGET_PROPERTIES(lmms PROPERTIES - LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON +IF(LMMS_BUILD_WIN32) + SET_TARGET_PROPERTIES(lmms PROPERTIES + ENABLE_EXPORTS ON + ) + IF(LMMS_BUILD_MSYS) + # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. + # Add the linker flag manually to create liblmms.dll.a import library + SET_PROPERTY(TARGET lmms + APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" ) + ENDIF() +ELSE() + INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" + PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) +ENDIF() - #CMAKE_FIND_ROOT_PATH - SET(VCPKG_ROOT ${CMAKE_FIND_ROOT_PATH}) - - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") - - INSTALL(FILES - "${VCPKG_ROOT}/bin/Qt5Core.dll" - "${VCPKG_ROOT}/bin/Qt5Gui.dll" - "${VCPKG_ROOT}/bin/Qt5Widgets.dll" - "${VCPKG_ROOT}/bin/Qt5Xml.dll" - - "${VCPKG_ROOT}/bin/zlib1.dll" - "${VCPKG_ROOT}/bin/jpeg62.dll" - "${VCPKG_ROOT}/bin/libpng16.dll" - "${VCPKG_ROOT}/bin/gthread-2.dll" - "${VCPKG_ROOT}/bin/glib-2.dll" - "${VCPKG_ROOT}/bin/harfbuzz.dll" - "${VCPKG_ROOT}/bin/pcre2-16.dll" - "${VCPKG_ROOT}/bin/double-conversion.dll" - "${VCPKG_ROOT}/bin/freetype.dll" - "${VCPKG_ROOT}/bin/libbz2.dll" - "${VCPKG_ROOT}/bin/pcre.dll" - "${VCPKG_ROOT}/bin/libiconv.dll" - "${VCPKG_ROOT}/bin/libcharset.dll" - "${VCPKG_ROOT}/bin/libintl.dll" - DESTINATION .) - - INSTALL(FILES - "${VCPKG_ROOT}/plugins/platforms/qwindows.dll" - DESTINATION ./platforms) - - INSTALL(FILES - "${VCPKG_ROOT}/bin/libsndfile-1.dll" - "${VCPKG_ROOT}/bin/ogg.dll" - "${VCPKG_ROOT}/bin/vorbis.dll" - "${VCPKG_ROOT}/bin/vorbisenc.dll" - "${VCPKG_ROOT}/bin/FLAC.dll" - "${VCPKG_ROOT}/bin/vorbisfile.dll" - - "${VCPKG_ROOT}/bin/libsamplerate-0.dll" - "${VCPKG_ROOT}/bin/SDL2.dll" - "${VCPKG_ROOT}/bin/fftw3f.dll" - DESTINATION .) - - #not yet in vcpkg - #IF(LAME_FOUND) - # INSTALL(FILES - # "${VCPKG_ROOT}/bin/libmp3lame-0.dll" - # DESTINATION .) - #ENDIF(LAME_FOUND) - - IF(FLTK_FOUND) - INSTALL(FILES - "${VCPKG_ROOT}/bin/libfltk_SHARED.dll" - - "${VCPKG_ROOT}/bin/zlib1.dll" - "${VCPKG_ROOT}/bin/jpeg62.dll" - DESTINATION .) - ENDIF() - - IF(FLUIDSYNTH_FOUND) - INSTALL(FILES - "${VCPKG_ROOT}/bin/libfluidsynth-1.dll" - "${VCPKG_ROOT}/bin/glib-2.dll" - "${VCPKG_ROOT}/bin/pcre.dll" - "${VCPKG_ROOT}/bin/libiconv.dll" - "${VCPKG_ROOT}/bin/libcharset.dll" - "${VCPKG_ROOT}/bin/libintl.dll" - DESTINATION .) - ENDIF() - - #not yet included in vcpkg - #IF(GIG_FOUND) - # # Handle libgig-*.dll - # FILE(GLOB GIG_LIBRARY "${VCPKG_ROOT}/bin/libgig-*.dll") - # INSTALL(FILES - # ${GIG_LIBRARY} - # DESTINATION .) - #ENDIF() - - IF(PORTAUDIO_FOUND) - IF(LMMS_BUILD_WIN64) - INSTALL(FILES - "${VCPKG_ROOT}/bin/portaudio-x64.dll" - DESTINATION .) - ELSE(LMMS_BUILD_WIN64) - INSTALL(FILES - "${VCPKG_ROOT}/bin/portaudio-x86.dll" - DESTINATION .) - ENDIF(LMMS_BUILD_WIN64) - ENDIF() - - #not yet in vcpkg - #IF(SOUNDIO_FOUND) - # INSTALL(FILES - # "${VCPKG_ROOT}/bin/libsoundio.dll" - # DESTINATION .) - #ENDIF() -ENDIF(NOT MSVC) +INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") \ No newline at end of file