From 2b46a4c5401ebec35ca3e35bd399fcef604865b1 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 14 Feb 2017 16:45:04 +0100 Subject: [PATCH] Handle packaging for Windows. --- cmake_builder/additional_steps.cmake | 27 + cmake_builder/linphone_package/CMakeLists.txt | 339 ++++++ .../linphone_package/NSIS.template.in | 982 ++++++++++++++++++ .../linphone_package/README.openh264.txt.in | 20 + .../WindowsPackaging.cmake.in | 34 + .../linphone_package/linphone-banner.bmp | Bin 0 -> 25818 bytes .../linphone_package/openh264-install.nsi.in | 7 + .../linphone_package/openh264-uninstall.nsi | 1 + .../sdk_content/antlr3c.list.in | 1 + .../sdk_content/bctoolbox.list.in | 5 + .../sdk_content/bcunit.list.in | 1 + .../sdk_content/bellesip.list.in | 5 + .../linphone_package/sdk_content/bv16.list.in | 1 + .../sdk_content/bzrtp.list.in | 2 + .../sdk_content/ffmpeg.list.in | 4 + .../linphone_package/sdk_content/gsm.list.in | 1 + .../sdk_content/linphone.list.in | 9 + .../sdk_content/mbedtls.list.in | 3 + .../linphone_package/sdk_content/ms2.list.in | 8 + .../sdk_content/ms2plugins.list.in | 1 + .../sdk_content/openh264.list.in | 1 + .../linphone_package/sdk_content/opus.list.in | 1 + .../linphone_package/sdk_content/ortp.list.in | 6 + .../sdk_content/polarssl.list.in | 1 + .../sdk_content/speex.list.in | 1 + .../sdk_content/sqlite3.list.in | 1 + .../linphone_package/sdk_content/srtp.list.in | 1 + .../sdk_content/vcard.list.in | 6 + .../linphone_package/sdk_content/xml2.list.in | 1 + .../linphone_package/sdk_content/zlib.list.in | 1 + cmake_builder/linphone_package/signtool.py | 28 + cmake_builder/linphone_package/uninstall.nsi | 7 + linphone-desktop/CMakeLists.txt | 2 +- linphone-desktop/linphone.ico | Bin 0 -> 370070 bytes linphone-desktop/linphone.rc | 2 + 35 files changed, 1509 insertions(+), 1 deletion(-) create mode 100644 cmake_builder/linphone_package/CMakeLists.txt create mode 100644 cmake_builder/linphone_package/NSIS.template.in create mode 100644 cmake_builder/linphone_package/README.openh264.txt.in create mode 100644 cmake_builder/linphone_package/WindowsPackaging.cmake.in create mode 100644 cmake_builder/linphone_package/linphone-banner.bmp create mode 100644 cmake_builder/linphone_package/openh264-install.nsi.in create mode 100644 cmake_builder/linphone_package/openh264-uninstall.nsi create mode 100644 cmake_builder/linphone_package/sdk_content/antlr3c.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/bctoolbox.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/bcunit.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/bellesip.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/bv16.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/bzrtp.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/ffmpeg.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/gsm.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/linphone.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/mbedtls.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/ms2.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/ms2plugins.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/openh264.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/opus.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/ortp.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/polarssl.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/speex.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/sqlite3.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/srtp.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/vcard.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/xml2.list.in create mode 100644 cmake_builder/linphone_package/sdk_content/zlib.list.in create mode 100644 cmake_builder/linphone_package/signtool.py create mode 100644 cmake_builder/linphone_package/uninstall.nsi create mode 100644 linphone-desktop/linphone.ico create mode 100644 linphone-desktop/linphone.rc diff --git a/cmake_builder/additional_steps.cmake b/cmake_builder/additional_steps.cmake index 4db83c31d..c85fa0167 100644 --- a/cmake_builder/additional_steps.cmake +++ b/cmake_builder/additional_steps.cmake @@ -29,3 +29,30 @@ if(LINPHONE_BUILDER_TARGET STREQUAL linphoneqt AND WIN32) add_custom_command(OUTPUT "${SHORTCUT_PATH}" COMMAND "cscript" "${CMAKE_CURRENT_BINARY_DIR}/winshortcut.vbs") add_custom_target(linphoneqt_winshortcut ALL DEPENDS "${SHORTCUT_PATH}" TARGET_linphone_builder) endif() + +# Packaging +if(ENABLE_PACKAGING) + get_cmake_property(_varnames VARIABLES) + set(ENABLE_VARIABLES ) + foreach(_varname ${_varnames}) + if(_varname MATCHES "^ENABLE_.*") + list(APPEND ENABLE_VARIABLES -D${_varname}=${${_varname}}) + endif() + endforeach() + + if(LINPHONE_BUILDER_TARGET STREQUAL linphoneqt) + # Linphone and linphone SDK packages + linphone_builder_apply_flags() + linphone_builder_set_ep_directories(linphone_package) + linphone_builder_expand_external_project_vars() + ExternalProject_Add(TARGET_linphone_package + DEPENDS TARGET_linphone_builder + TMP_DIR ${ep_tmp} + BINARY_DIR ${ep_build} + SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/linphone_package" + DOWNLOAD_COMMAND "" + CMAKE_GENERATOR ${CMAKE_GENERATOR} + CMAKE_ARGS ${LINPHONE_BUILDER_EP_ARGS} -DCMAKE_INSTALL_PREFIX=${LINPHONE_BUILDER_WORK_DIR}/PACKAGE -DTOOLS_DIR=${CMAKE_BINARY_DIR}/programs -DLINPHONE_OUTPUT_DIR=${CMAKE_INSTALL_PREFIX} -DLINPHONE_DESKTOP_DIR=${CMAKE_CURRENT_LIST_DIR}/../linphone-desktop -DLINPHONE_SOURCE_DIR=${EP_linphone_SOURCE_DIR} ${ENABLE_VARIABLES} -DOPENH264_VERSION=${OPENH264_VERSION} + ) + endif() +endif() diff --git a/cmake_builder/linphone_package/CMakeLists.txt b/cmake_builder/linphone_package/CMakeLists.txt new file mode 100644 index 000000000..170578ac0 --- /dev/null +++ b/cmake_builder/linphone_package/CMakeLists.txt @@ -0,0 +1,339 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2017 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################ + +cmake_minimum_required(VERSION 3.0) +project(LINPHONE_PACKAGE) # Dummy project + +find_package(Linphone REQUIRED) +find_package(Git) + +set(LINPHONE_QML_DIR "${LINPHONE_DESKTOP_DIR}/ui") + +if(WIN32) + set(WINDEPLOYQT_PROGRAM windeployqt) +endif() + +if(GIT_EXECUTABLE) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --always + OUTPUT_VARIABLE LINPHONE_GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + WORKING_DIRECTORY ${LINPHONE_SOURCE_DIR} + ) +else() + set(LINPHONE_GIT_REVISION "0.0.0") +endif() +string(REGEX REPLACE "([0-9.]+)-?.*" "\\1" LINPHONE_VERSION "${LINPHONE_GIT_REVISION}") +string(REPLACE "." ";" SPLITTED_LINPHONE_VERSION ${LINPHONE_VERSION}) +list(GET SPLITTED_LINPHONE_VERSION 0 LINPHONE_MAJOR_VERSION) +list(GET SPLITTED_LINPHONE_VERSION 1 LINPHONE_MINOR_VERSION) +list(GET SPLITTED_LINPHONE_VERSION 2 LINPHONE_MICRO_VERSION) +set(PACKAGE_VERSION "${LINPHONE_VERSION}") + +# Preparing the Linphone SDK bundle +set(LINPHONE_SDK_TMP "${CMAKE_CURRENT_BINARY_DIR}/linphone-sdk-tmp") +file(REMOVE_RECURSE "${LINPHONE_SDK_TMP}") +file(COPY "${LINPHONE_OUTPUT_DIR}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +file(RENAME "${CMAKE_CURRENT_BINARY_DIR}/desktop" "${LINPHONE_SDK_TMP}") +if(APPLE) + set(RPATH_CHANGE_CMDS + -change /opt/local/lib/libintl.8.dylib @rpath/libintl.8.dylib + -change /opt/local/lib/libiconv.2.dylib @rpath/libiconv.2.dylib + ) + file(COPY + /opt/local/lib/libintl.8.dylib + /opt/local/lib/libintl.dylib + /opt/local/lib/libiconv.dylib + /opt/local/lib/libiconv.2.dylib + DESTINATION ${LINPHONE_SDK_TMP}/lib + ) + execute_process(COMMAND install_name_tool + -id @rpath/libintl.8.dylib + -change /opt/local/lib/libiconv.2.dylib @rpath/libiconv.2.dylib + ${LINPHONE_SDK_TMP}/lib/libintl.8.dylib + ) + execute_process(COMMAND install_name_tool + -id @rpath/libiconv.2.dylib + ${LINPHONE_SDK_TMP}/lib/libiconv.2.dylib + ) + execute_process(COMMAND install_name_tool + -change /opt/local/lib/libintl.8.dylib @rpath/libintl.8.dylib + -change /opt/local/lib/libiconv.2.dylib @rpath/libiconv.2.dylib + ${LINPHONE_SDK_TMP}/lib/liblinphone.dylib + ) +endif() + +# Generates a zip archive containing the development files of liblinphone +macro(add_list_file NAME) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sdk_content/${NAME}.list.in" "${LINPHONE_SDK_TMP}/${NAME}.list" @ONLY) + list(APPEND LIST_FILES "${LINPHONE_SDK_TMP}/${NAME}.list") +endmacro() +if(WIN32) + set(LIBDIR "bin") + set(LIBPREFIX "") + set(LIBEXT "dll") + set(PLUGINEXT "dll") +elseif(APPLE) + set(LIBDIR "lib") + set(LIBPREFIX "lib") + set(LIBEXT "dylib") + set(PLUGINEXT "so") +endif() +set(LIST_FILES ) +add_list_file(bctoolbox) +add_list_file(antlr3c) +add_list_file(bellesip) +add_list_file(ortp) +add_list_file(ms2) +add_list_file(ms2plugins) +add_list_file(linphone) +if(WIN32) + add_list_file(sqlite3) + add_list_file(xml2) + add_list_file(zlib) +endif() +if(ENABLE_UNIT_TESTS) + add_list_file(bcunit) +endif() +if(ENABLE_VCARD) + add_list_file(vcard) +endif() +if(ENABLE_BV16) + add_list_file(bv16) +endif() +if(ENABLE_GSM) + add_list_file(gsm) +endif() +if(ENABLE_OPUS) + add_list_file(opus) +endif() +if(ENABLE_SPEEX) + add_list_file(speex) +endif() +if(ENABLE_MBEDTLS) + add_list_file(mbedtls) +endif() +if(ENABLE_POLARSSL) + add_list_file(polarssl) +endif() +if(ENABLE_SRTP) + add_list_file(srtp) +endif() +if(ENABLE_ZRTP) + add_list_file(bzrtp) +endif() +if(ENABLE_FFMPEG) + add_list_file(ffmpeg) +endif() +if(ENABLE_OPENH264) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/README.openh264.txt.in" "${LINPHONE_SDK_TMP}/README.openh264.txt" @ONLY) + add_list_file(openh264) +endif() +file(WRITE "${LINPHONE_SDK_TMP}/linphone-sdk.list" "") +foreach(_file ${LIST_FILES}) + file(READ "${_file}" _content) + file(APPEND "${LINPHONE_SDK_TMP}/linphone-sdk.list" "${_content}\n") +endforeach() +if(WIN32) + find_program(7Z_PROGRAM 7z.exe) + if(7Z_PROGRAM) + execute_process( + COMMAND ${7Z_PROGRAM} a -tzip ${CMAKE_BINARY_DIR}/linphone-sdk-${LINPHONE_GIT_REVISION}-win32.zip @linphone-sdk.list + WORKING_DIRECTORY ${LINPHONE_SDK_TMP} + ) + else() + message(WARNING "7z has not been found, cannot generate the SDK!") + endif() +elseif(APPLE) + execute_process( + COMMAND rm -rf "${CMAKE_BINARY_DIR}/linphone-sdk-${LINPHONE_GIT_REVISION}-mac.zip" + COMMAND zip -ry "${CMAKE_BINARY_DIR}/linphone-sdk-${LINPHONE_GIT_REVISION}-mac.zip" . -i "@linphone-sdk.list" + WORKING_DIRECTORY ${LINPHONE_SDK_TMP} + ) +endif() + +if(WIN32) + execute_process( + COMMAND ${WINDEPLOYQT_PROGRAM} "${LINPHONE_OUTPUT_DIR}/bin/linphone.exe" "--qmldir" "${LINPHONE_QML_DIR}" + ) + + install(DIRECTORY "${LINPHONE_OUTPUT_DIR}/" + DESTINATION "." + COMPONENT "linphone_base" + PATTERN "doc" EXCLUDE + PATTERN "etc" EXCLUDE + PATTERN "include" EXCLUDE + PATTERN "lib/cmake" EXCLUDE + PATTERN "lib/mediastreamer" EXCLUDE + PATTERN "lib/pkgconfig" EXCLUDE + PATTERN "lib/*.a" EXCLUDE + PATTERN "lib/*.def" EXCLUDE + PATTERN "lib/*.exp" EXCLUDE + PATTERN "lib/*.la" EXCLUDE + PATTERN "lib/*.lib" EXCLUDE + PATTERN "man" EXCLUDE + PATTERN "manifest" EXCLUDE + PATTERN "share/aclocal" EXCLUDE + PATTERN "share/BCUnit" EXCLUDE + PATTERN "share/java" EXCLUDE + PATTERN "src" EXCLUDE + PATTERN "linphone.lnk" EXCLUDE + PATTERN "bin/openh264.dll" EXCLUDE + PATTERN "share/*/cmake" EXCLUDE + ) + + if(ENABLE_OPENH264) + # Include bunzip2.exe and bzip2.dll to be able to extract the openh264 file downloaded from Cisco + install(DIRECTORY "${TOOLS_DIR}/" + DESTINATION "bin" + COMPONENT "msopenh264" + FILES_MATCHING PATTERN "b*zip2.*" + ) + install(DIRECTORY "${LINPHONE_OUTPUT_DIR}/lib/mediastreamer/plugins/" + DESTINATION "lib/mediastreamer/plugins" + COMPONENT "msopenh264" + FILES_MATCHING PATTERN "libmsopenh264.*" + ) + endif() + + install(DIRECTORY "${LINPHONE_OUTPUT_DIR}/lib/mediastreamer/plugins/" + DESTINATION "lib/mediastreamer/plugins" + FILES_MATCHING PATTERN "libmssilk.*" + ) +elseif(APPLE) + find_program(MAC_BUNDLER gtk-mac-bundler) + if(NOT MAC_BUNDLER) + message(FATAL_ERROR "Could not find gtk-mac-bundler executable!") + endif() + find_program(PATCH_PROGRAM patch) + if(NOT PATCH_PROGRAM) + message(FATAL_ERROR "Could not find patch executable!") + endif() + configure_file("${LINPHONE_SOURCE_DIR}/build/macos/Info-linphone.plist.in" "mac-bundler/Info-linphone.plist" @ONLY) + configure_file("${LINPHONE_SOURCE_DIR}/build/macos/environment.sh" "mac-bundler/environment.sh" COPYONLY) + configure_file("${LINPHONE_SOURCE_DIR}/gtk/gtkrc.mac" "mac-bundler/gtkrc" COPYONLY) + configure_file("${LINPHONE_SOURCE_DIR}/pixmaps/linphone.icns" "mac-bundler/linphone.icns" COPYONLY) + configure_file("mac-bundler/linphone.bundle" "mac-bundler/linphone.bundle" COPYONLY) # This file has to be different than the one in the linphone source code because of different file access paths + configure_file("mac-bundler/pkg-scripts/postinstall.in" "mac-bundler/pkg-scripts/postinstall" @ONLY) + configure_file("mac-bundler/call-bundler.cmake.in" "mac-bundler/call-bundler.cmake") + install(SCRIPT "${CMAKE_BINARY_DIR}/mac-bundler/call-bundler.cmake") +endif() + +if(MSVC) + install(DIRECTORY "${LINPHONE_OUTPUT_DIR}/lib/mediastreamer/plugins/" + DESTINATION "lib/mediastreamer/plugins" + FILES_MATCHING PATTERN "libmswasapi.dll" + ) + string(REGEX REPLACE "Visual Studio ([0-9]+).*" "\\1" MSVC_VERSION "${CMAKE_GENERATOR}") + find_file(MSVCP_LIB "msvcp${MSVC_VERSION}0.dll" PATHS "C:/Windows/System32") + find_file(UCRTBASE_LIB "ucrtbase.dll" PATHS "C:/Windows/System32") + # Starting with Visual Studio 2015 (MSVC_VERSION==14) the msvcr dll has been renamed to vcruntime + find_file(VCRUNTIME_LIB "vcruntime${MSVC_VERSION}0.dll" PATHS "C:/Windows/System32") + if(NOT VCRUNTIME_LIB) + find_file(VCRUNTIME_LIB "msvcr${MSVC_VERSION}0.dll" PATHS "C:/Windows/System32") + endif() + install(FILES ${MSVCP_LIB} ${UCRTBASE_LIB} ${VCRUNTIME_LIB} DESTINATION "bin") + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + find_file(MSVCPD_LIB "msvcp${MSVC_VERSION}0d.dll" PATHS "C:/Windows/System32") + find_file(UCRTBASED_LIB "ucrtbased.dll" PATHS "C:/Windows/System32") + find_file(VCRUNTIMED_LIB "vcruntime${MSVC_VERSION}0d.dll" PATHS "C:/Windows/System32") + if(NOT VCRUNTIMED_LIB) + find_file(VCRUNTIMED_LIB "msvcr${MSVC_VERSION}0d.dll" PATHS "C:/Windows/System32") + endif() + install(FILES ${MSVCPD_LIB} ${UCRTBASED_LIB} ${VCRUNTIMED_LIB} DESTINATION "bin") + endif() +endif() + +set(CPACK_PACKAGE_NAME "Linphone") +set(CPACK_PACKAGE_VENDOR "Belledonne communications") +set(CPACK_PACKAGE_VERSION_MAJOR ${LINPHONE_MAJOR_VERSION}) +set(CPACK_PACKAGE_VERSION_MINOR ${LINPHONE_MINOR_VERSION}) +set(CPACK_PACKAGE_VERSION_PATCH ${LINPHONE_MICRO_VERSION}) +set(CPACK_PACKAGE_EXECUTABLES "linphone;Linphone") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "Linphone") +set(CPACK_RESOURCE_FILE_LICENSE "${LINPHONE_SOURCE_DIR}/COPYING") + +if(WIN32) + set(CPACK_COMPONENT_LINPHONE_BASE_DISPLAY_NAME "Linphone") + set(CPACK_COMPONENT_LINPHONE_BASE_DESCRIPTION "Minimal installation of Linphone") + set(CPACK_COMPONENT_LINPHONE_BASE_REQUIRED True) + if(ENABLE_OPENH264) + set(CPACK_COMPONENT_MSOPENH264_DISPLAY_NAME "Cisco's OpenH264 codec") + set(CPACK_COMPONENT_MSOPENH264_DESCRIPTION "Download OpenH264 Video Codec provided by Cisco Systems, Inc.") + set(CPACK_COMPONENT_MSOPENH264_DISABLED True) + endif() +endif() + +if(WIN32) + # Use template from the current source directory to force uninstallation and ensure that linphone is not running before installation + set(CPACK_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}") + set(CPACK_GENERATOR "NSIS") + set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\linphone-banner.bmp") + set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${LINPHONE_GIT_REVISION}-win32") + set(CPACK_NSIS_MUI_ICON "${LINPHONE_DESKTOP_DIR}/linphone.ico") + set(CPACK_NSIS_MUI_UNIICON "${LINPHONE_DESKTOP_DIR}/linphone.ico") + set(CPACK_NSIS_DISPLAY_NAME "Linphone") + set(CPACK_NSIS_PACKAGE_NAME "Linphone ${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}") + set(CPACK_NSIS_URL_INFO_ABOUT "http://www.linphone.org/") + + file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" DOS_STYLE_SOURCE_DIR) + string(REPLACE "\\" "\\\\" ESCAPED_DOS_STYLE_SOURCE_DIR "${DOS_STYLE_SOURCE_DIR}") + file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}" DOS_STYLE_BINARY_DIR) + string(REPLACE "\\" "\\\\" ESCAPED_DOS_STYLE_BINARY_DIR "${DOS_STYLE_BINARY_DIR}") + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/uninstall.nsi" "${CMAKE_CURRENT_BINARY_DIR}/uninstall.nsi" COPYONLY) + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\uninstall.nsi\\\"") + if(ENABLE_OPENH264) + # Add NSI instructions to download the openh264 codec from Cisco's servers whether msopenh264 has been installed + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/openh264-install.nsi.in" "${CMAKE_CURRENT_BINARY_DIR}/openh264-install.nsi" @ONLY) + set(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "!include \\\"${ESCAPED_DOS_STYLE_BINARY_DIR}\\\\openh264-install.nsi\\\"") + + # Add NSI instructions to delete the openh264 codecs while uninstalling Linphone + set(CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS "${CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS}\n!include \\\"${ESCAPED_DOS_STYLE_SOURCE_DIR}\\\\openh264-uninstall.nsi\\\"") + endif() + + # Sign the installer + set(TIMESTAMP_URL "http://timestamp.verisign.com/scripts/timestamp.dll") + set(PFX_FILE "${CMAKE_CURRENT_SOURCE_DIR}/sign/linphone.pfx") + set(PASSPHRASE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/sign/passphrase.txt") + get_filename_component(WINSDK_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows;CurrentInstallFolder]" REALPATH CACHE) + find_package(PythonInterp) + find_program(SIGNTOOL signtool PATHS ${WINSDK_DIR}/bin) + set(SIGNTOOL_COMMAND "${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/signtool.py") + set(PERFORM_SIGNING 0) + if(EXISTS ${PFX_FILE}) + if(SIGNTOOL) + set(SIGNTOOL_COMMAND "${SIGNTOOL_COMMAND} signtool sign /f ${PFX_FILE}") + set(SIGNTOOL_COMMAND "${SIGNTOOL_COMMAND} /p ${PASSPHRASE_FILE}") + set(SIGNTOOL_COMMAND "${SIGNTOOL_COMMAND} /t ${TIMESTAMP_URL}") + message("Found signtool and certificate ${PFX_FILE}") + set(PERFORM_SIGNING 1) + else() + message(STATUS "Could not find signtool! Code signing disabled (${SIGNTOOL})") + endif() + else() + message(STATUS "No signtool certificate found; assuming development machine (${PFX_FILE})") + endif() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/WindowsPackaging.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/WindowsPackaging.cmake" @ONLY) + install(SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/WindowsPackaging.cmake") +endif() +include(CPack) diff --git a/cmake_builder/linphone_package/NSIS.template.in b/cmake_builder/linphone_package/NSIS.template.in new file mode 100644 index 000000000..138acd94c --- /dev/null +++ b/cmake_builder/linphone_package/NSIS.template.in @@ -0,0 +1,982 @@ +; CPack install script designed for a nmake build + +;-------------------------------- +; You must define these values + + !define VERSION "@CPACK_PACKAGE_VERSION@" + !define PATCH "@CPACK_PACKAGE_VERSION_PATCH@" + !define INST_DIR "@CPACK_TEMPORARY_DIRECTORY@" + +;-------------------------------- +;Variables + + Var MUI_TEMP + Var STARTMENU_FOLDER + Var SV_ALLUSERS + Var START_MENU + Var DO_NOT_ADD_TO_PATH + Var ADD_TO_PATH_ALL_USERS + Var ADD_TO_PATH_CURRENT_USER + Var INSTALL_DESKTOP + Var IS_DEFAULT_INSTALLDIR +;-------------------------------- +;Include Modern UI + + !include "MUI.nsh" + + ;Default installation folder + InstallDir "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + +;-------------------------------- +;General + + ;Name and file + Name "@CPACK_NSIS_PACKAGE_NAME@" + OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@" + + ;Set compression + SetCompressor @CPACK_NSIS_COMPRESSOR@ + + ;Require administrator access + RequestExecutionLevel admin + +@CPACK_NSIS_DEFINES@ + + !include Sections.nsh + +;--- Component support macros: --- +; The code for the add/remove functionality is from: +; http://nsis.sourceforge.net/Add/Remove_Functionality +; It has been modified slightly and extended to provide +; inter-component dependencies. +Var AR_SecFlags +Var AR_RegFlags +@CPACK_NSIS_SECTION_SELECTED_VARS@ + +; Loads the "selected" flag for the section named SecName into the +; variable VarName. +!macro LoadSectionSelectedIntoVar SecName VarName + SectionGetFlags ${${SecName}} $${VarName} + IntOp $${VarName} $${VarName} & ${SF_SELECTED} ;Turn off all other bits +!macroend + +; Loads the value of a variable... can we get around this? +!macro LoadVar VarName + IntOp $R0 0 + $${VarName} +!macroend + +; Sets the value of a variable +!macro StoreVar VarName IntValue + IntOp $${VarName} 0 + ${IntValue} +!macroend + +!macro InitSection SecName + ; This macro reads component installed flag from the registry and + ;changes checked state of the section on the components page. + ;Input: section index constant name specified in Section command. + + ClearErrors + ;Reading component status from registry + ReadRegDWORD $AR_RegFlags HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" "Installed" + IfErrors "default_${SecName}" + ;Status will stay default if registry value not found + ;(component was never installed) + IntOp $AR_RegFlags $AR_RegFlags & ${SF_SELECTED} ;Turn off all other bits + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading default section flags + IntOp $AR_SecFlags $AR_SecFlags & 0xFFFE ;Turn lowest (enabled) bit off + IntOp $AR_SecFlags $AR_RegFlags | $AR_SecFlags ;Change lowest bit + + ; Note whether this component was installed before + !insertmacro StoreVar ${SecName}_was_installed $AR_RegFlags + IntOp $R0 $AR_RegFlags & $AR_RegFlags + + ;Writing modified flags + SectionSetFlags ${${SecName}} $AR_SecFlags + + "default_${SecName}:" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected +!macroend + +!macro FinishSection SecName + ; This macro reads section flag set by user and removes the section + ;if it is not selected. + ;Then it writes component installed flag to registry + ;Input: section index constant name specified in Section command. + + SectionGetFlags ${${SecName}} $AR_SecFlags ;Reading section flags + ;Checking lowest bit: + IntOp $AR_SecFlags $AR_SecFlags & ${SF_SELECTED} + IntCmp $AR_SecFlags 1 "leave_${SecName}" + ;Section is not selected: + ;Calling Section uninstall macro and writing zero installed flag + !insertmacro "Remove_${${SecName}}" + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 0 + Goto "exit_${SecName}" + + "leave_${SecName}:" + ;Section is selected: + WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@\Components\${SecName}" \ + "Installed" 1 + + "exit_${SecName}:" +!macroend + +!macro RemoveSection_CPack SecName + ; This macro is used to call section's Remove_... macro + ;from the uninstaller. + ;Input: section index constant name specified in Section command. + + !insertmacro "Remove_${${SecName}}" +!macroend + +; Determine whether the selection of SecName changed +!macro MaybeSelectionChanged SecName + !insertmacro LoadVar ${SecName}_selected + SectionGetFlags ${${SecName}} $R1 + IntOp $R1 $R1 & ${SF_SELECTED} ;Turn off all other bits + + ; See if the status has changed: + IntCmp $R0 $R1 "${SecName}_unchanged" + !insertmacro LoadSectionSelectedIntoVar ${SecName} ${SecName}_selected + + IntCmp $R1 ${SF_SELECTED} "${SecName}_was_selected" + !insertmacro "Deselect_required_by_${SecName}" + goto "${SecName}_unchanged" + + "${SecName}_was_selected:" + !insertmacro "Select_${SecName}_depends" + + "${SecName}_unchanged:" +!macroend +;--- End of Add/Remove macros --- + +;-------------------------------- +;Interface Settings + + !define MUI_HEADERIMAGE + !define MUI_ABORTWARNING + +;-------------------------------- +; path functions + +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 + +;---------------------------------------- +; based upon a script of "Written by KiCHiK 2003-01-18 05:57:02" +;---------------------------------------- +!verbose 3 +!include "WinMessages.NSH" +!verbose 4 +;==================================================== +; get_NT_environment +; Returns: the selected environment +; Output : head of the stack +;==================================================== +!macro select_NT_profile UN +Function ${UN}select_NT_profile + StrCmp $ADD_TO_PATH_ALL_USERS "1" 0 environment_single + DetailPrint "Selected environment for all users" + Push "all" + Return + environment_single: + DetailPrint "Selected environment for current user only." + Push "current" + Return +FunctionEnd +!macroend +!insertmacro select_NT_profile "" +!insertmacro select_NT_profile "un." +;---------------------------------------------------- +!define NT_current_env 'HKCU "Environment"' +!define NT_all_env 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + +!ifndef WriteEnvStr_RegKey + !ifdef ALL_USERS + !define WriteEnvStr_RegKey \ + 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' + !else + !define WriteEnvStr_RegKey 'HKCU "Environment"' + !endif +!endif + +; AddToPath - Adds the given dir to the search path. +; Input - head of the stack +; Note - Win9x systems requires reboot + +Function AddToPath + Exch $0 + Push $1 + Push $2 + Push $3 + + # don't add if the path doesn't exist + IfFileExists "$0\*.*" "" AddToPath_done + + ReadEnvStr $1 PATH + ; if the path is too long for a NSIS variable NSIS will return a 0 + ; length string. If we find that, then warn and skip any path + ; modification as it will trash the existing path. + StrLen $2 $1 + IntCmp $2 0 CheckPathLength_ShowPathWarning CheckPathLength_Done CheckPathLength_Done + CheckPathLength_ShowPathWarning: + Messagebox MB_OK|MB_ICONEXCLAMATION "Warning! PATH too long installer unable to modify PATH!" + Goto AddToPath_done + CheckPathLength_Done: + Push "$1;" + Push "$0;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$0\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + GetFullPathName /SHORT $3 $0 + Push "$1;" + Push "$3;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + Push "$1;" + Push "$3\;" + Call StrStr + Pop $2 + StrCmp $2 "" "" AddToPath_done + + Call IsNT + Pop $1 + StrCmp $1 1 AddToPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" a + FileSeek $1 -1 END + FileReadByte $1 $2 + IntCmp $2 26 0 +2 +2 # DOS EOF + FileSeek $1 -1 END # write over EOF + FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" + FileClose $1 + SetRebootFlag true + Goto AddToPath_done + + AddToPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" ReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto DoTrim + ReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + DoTrim: + StrCmp $1 "" AddToPath_NTdoIt + Push $1 + Call Trim + Pop $1 + StrCpy $0 "$1;$0" + AddToPath_NTdoIt: + StrCmp $ADD_TO_PATH_ALL_USERS "1" WriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $0 + Goto DoSend + WriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $0 + DoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + AddToPath_done: + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + + +; RemoveFromPath - Remove a given dir from the path +; Input: head of the stack + +Function un.RemoveFromPath + Exch $0 + Push $1 + Push $2 + Push $3 + Push $4 + Push $5 + Push $6 + + IntFmt $6 "%c" 26 # DOS EOF + + Call un.IsNT + Pop $1 + StrCmp $1 1 unRemoveFromPath_NT + ; Not on NT + StrCpy $1 $WINDIR 2 + FileOpen $1 "$1\autoexec.bat" r + GetTempFileName $4 + FileOpen $2 $4 w + GetFullPathName /SHORT $0 $0 + StrCpy $0 "SET PATH=%PATH%;$0" + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoop: + FileRead $1 $3 + StrCpy $5 $3 1 -1 # read last char + StrCmp $5 $6 0 +2 # if DOS EOF + StrCpy $3 $3 -1 # remove DOS EOF so we can compare + StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine + StrCmp $3 "" unRemoveFromPath_dosLoopEnd + FileWrite $2 $3 + Goto unRemoveFromPath_dosLoop + unRemoveFromPath_dosLoopRemoveLine: + SetRebootFlag true + Goto unRemoveFromPath_dosLoop + + unRemoveFromPath_dosLoopEnd: + FileClose $2 + FileClose $1 + StrCpy $1 $WINDIR 2 + Delete "$1\autoexec.bat" + CopyFiles /SILENT $4 "$1\autoexec.bat" + Delete $4 + Goto unRemoveFromPath_done + + unRemoveFromPath_NT: + StrCmp $ADD_TO_PATH_ALL_USERS "1" unReadAllKey + ReadRegStr $1 ${NT_current_env} "PATH" + Goto unDoTrim + unReadAllKey: + ReadRegStr $1 ${NT_all_env} "PATH" + unDoTrim: + StrCpy $5 $1 1 -1 # copy last char + StrCmp $5 ";" +2 # if last char != ; + StrCpy $1 "$1;" # append ; + Push $1 + Push "$0;" + Call un.StrStr ; Find `$0;` in $1 + Pop $2 ; pos of our dir + StrCmp $2 "" unRemoveFromPath_done + ; else, it is in path + # $0 - path to add + # $1 - path var + StrLen $3 "$0;" + StrLen $4 $2 + StrCpy $5 $1 -$4 # $5 is now the part before the path to remove + StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove + StrCpy $3 $5$6 + + StrCpy $5 $3 1 -1 # copy last char + StrCmp $5 ";" 0 +2 # if last char == ; + StrCpy $3 $3 -1 # remove last char + + StrCmp $ADD_TO_PATH_ALL_USERS "1" unWriteAllKey + WriteRegExpandStr ${NT_current_env} "PATH" $3 + Goto unDoSend + unWriteAllKey: + WriteRegExpandStr ${NT_all_env} "PATH" $3 + unDoSend: + SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 + + unRemoveFromPath_done: + Pop $6 + Pop $5 + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Uninstall sutff +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +########################################### +# Utility Functions # +########################################### + +;==================================================== +; IsNT - Returns 1 if the current system is NT, 0 +; otherwise. +; Output: head of the stack +;==================================================== +; IsNT +; no input +; output, top of the stack = 1 if NT or 0 if not +; +; Usage: +; Call IsNT +; Pop $R0 +; ($R0 at this point is 1 or 0) + +!macro IsNT un +Function ${un}IsNT + Push $0 + ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + StrCmp $0 "" 0 IsNT_yes + ; we are not NT. + Pop $0 + Push 0 + Return + + IsNT_yes: + ; NT!!! + Pop $0 + Push 1 +FunctionEnd +!macroend +!insertmacro IsNT "" +!insertmacro IsNT "un." + +; StrStr +; input, top of stack = string to search for +; top of stack-1 = string to search in +; output, top of stack (replaces with the portion of the string remaining) +; modifies no other variables. +; +; Usage: +; Push "this is a long ass string" +; Push "ass" +; Call StrStr +; Pop $R0 +; ($R0 at this point is "ass string") + +!macro StrStr un +Function ${un}StrStr +Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + loop: + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 done + StrCmp $R5 "" done + IntOp $R4 $R4 + 1 + Goto loop +done: + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +FunctionEnd +!macroend +!insertmacro StrStr "" +!insertmacro StrStr "un." + +Function Trim ; Added by Pelaca + Exch $R1 + Push $R2 +Loop: + StrCpy $R2 "$R1" 1 -1 + StrCmp "$R2" " " RTrim + StrCmp "$R2" "$\n" RTrim + StrCmp "$R2" "$\r" RTrim + StrCmp "$R2" ";" RTrim + GoTo Done +RTrim: + StrCpy $R1 "$R1" -1 + Goto Loop +Done: + Pop $R2 + Exch $R1 +FunctionEnd + +Function ConditionalAddToRegisty + Pop $0 + Pop $1 + StrCmp "$0" "" ConditionalAddToRegisty_EmptyString + WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" \ + "$1" "$0" + ;MessageBox MB_OK "Set Registry: '$1' to '$0'" + DetailPrint "Set install registry entry: '$1' to '$0'" + ConditionalAddToRegisty_EmptyString: +FunctionEnd + +;-------------------------------- + +!ifdef CPACK_USES_DOWNLOAD +Function DownloadFile + IfFileExists $INSTDIR\* +2 + CreateDirectory $INSTDIR + Pop $0 + + ; Skip if already downloaded + IfFileExists $INSTDIR\$0 0 +2 + Return + + StrCpy $1 "@CPACK_DOWNLOAD_SITE@" + + try_again: + NSISdl::download "$1/$0" "$INSTDIR\$0" + + Pop $1 + StrCmp $1 "success" success + StrCmp $1 "Cancelled" cancel + MessageBox MB_OK "Download failed: $1" + cancel: + Return + success: +FunctionEnd +!endif + +;-------------------------------- +; Installation types +@CPACK_NSIS_INSTALLATION_TYPES@ + +;-------------------------------- +; Component sections +@CPACK_NSIS_COMPONENT_SECTIONS@ + +;-------------------------------- +; Define some macro setting for the gui +@CPACK_NSIS_INSTALLER_MUI_ICON_CODE@ +@CPACK_NSIS_INSTALLER_ICON_CODE@ +@CPACK_NSIS_INSTALLER_MUI_COMPONENTS_DESC@ +@CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE@ + +;-------------------------------- +;Pages + !insertmacro MUI_PAGE_WELCOME + + !insertmacro MUI_PAGE_LICENSE "@CPACK_RESOURCE_FILE_LICENSE@" + Page custom InstallOptionsPage + !insertmacro MUI_PAGE_DIRECTORY + + ;Start Menu Folder Page Configuration + !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" + !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start Menu Folder" + !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER + + @CPACK_NSIS_PAGE_COMPONENTS@ + + !insertmacro MUI_PAGE_INSTFILES + !insertmacro MUI_PAGE_FINISH + + !insertmacro MUI_UNPAGE_CONFIRM + !insertmacro MUI_UNPAGE_INSTFILES + +;-------------------------------- +;Languages + + !insertmacro MUI_LANGUAGE "English" ;first language is the default language + !insertmacro MUI_LANGUAGE "Albanian" + !insertmacro MUI_LANGUAGE "Arabic" + !insertmacro MUI_LANGUAGE "Basque" + !insertmacro MUI_LANGUAGE "Belarusian" + !insertmacro MUI_LANGUAGE "Bosnian" + !insertmacro MUI_LANGUAGE "Breton" + !insertmacro MUI_LANGUAGE "Bulgarian" + !insertmacro MUI_LANGUAGE "Croatian" + !insertmacro MUI_LANGUAGE "Czech" + !insertmacro MUI_LANGUAGE "Danish" + !insertmacro MUI_LANGUAGE "Dutch" + !insertmacro MUI_LANGUAGE "Estonian" + !insertmacro MUI_LANGUAGE "Farsi" + !insertmacro MUI_LANGUAGE "Finnish" + !insertmacro MUI_LANGUAGE "French" + !insertmacro MUI_LANGUAGE "German" + !insertmacro MUI_LANGUAGE "Greek" + !insertmacro MUI_LANGUAGE "Hebrew" + !insertmacro MUI_LANGUAGE "Hungarian" + !insertmacro MUI_LANGUAGE "Icelandic" + !insertmacro MUI_LANGUAGE "Indonesian" + !insertmacro MUI_LANGUAGE "Irish" + !insertmacro MUI_LANGUAGE "Italian" + !insertmacro MUI_LANGUAGE "Japanese" + !insertmacro MUI_LANGUAGE "Korean" + !insertmacro MUI_LANGUAGE "Kurdish" + !insertmacro MUI_LANGUAGE "Latvian" + !insertmacro MUI_LANGUAGE "Lithuanian" + !insertmacro MUI_LANGUAGE "Luxembourgish" + !insertmacro MUI_LANGUAGE "Macedonian" + !insertmacro MUI_LANGUAGE "Malay" + !insertmacro MUI_LANGUAGE "Mongolian" + !insertmacro MUI_LANGUAGE "Norwegian" + !insertmacro MUI_LANGUAGE "Polish" + !insertmacro MUI_LANGUAGE "Portuguese" + !insertmacro MUI_LANGUAGE "PortugueseBR" + !insertmacro MUI_LANGUAGE "Romanian" + !insertmacro MUI_LANGUAGE "Russian" + !insertmacro MUI_LANGUAGE "Serbian" + !insertmacro MUI_LANGUAGE "SerbianLatin" + !insertmacro MUI_LANGUAGE "SimpChinese" + !insertmacro MUI_LANGUAGE "Slovak" + !insertmacro MUI_LANGUAGE "Slovenian" + !insertmacro MUI_LANGUAGE "Spanish" + !insertmacro MUI_LANGUAGE "Swedish" + !insertmacro MUI_LANGUAGE "Thai" + !insertmacro MUI_LANGUAGE "TradChinese" + !insertmacro MUI_LANGUAGE "Turkish" + !insertmacro MUI_LANGUAGE "Ukrainian" + !insertmacro MUI_LANGUAGE "Welsh" + + +;-------------------------------- +;Reserve Files + + ;These files should be inserted before other files in the data block + ;Keep these lines before any File command + ;Only for solid compression (by default, solid compression is enabled for BZIP2 and LZMA) + + ReserveFile "NSIS.InstallOptions.ini" + !insertmacro MUI_RESERVEFILE_INSTALLOPTIONS + +;-------------------------------- +;Installer Sections + +Section "-Core installation" + ;Use the entire tree produced by the INSTALL target. Keep the + ;list of directories here in sync with the RMDir commands below. + SetOutPath "$INSTDIR" + @CPACK_NSIS_EXTRA_PREINSTALL_COMMANDS@ + @CPACK_NSIS_FULL_INSTALL@ + + ;Store installation folder + WriteRegStr SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "" $INSTDIR + + ;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall.exe" + Push "DisplayName" + Push "@CPACK_NSIS_DISPLAY_NAME@" + Call ConditionalAddToRegisty + Push "DisplayVersion" + Push "@CPACK_PACKAGE_VERSION@" + Call ConditionalAddToRegisty + Push "Publisher" + Push "@CPACK_PACKAGE_VENDOR@" + Call ConditionalAddToRegisty + Push "UninstallString" + Push "$INSTDIR\Uninstall.exe" + Call ConditionalAddToRegisty + Push "NoRepair" + Push "1" + Call ConditionalAddToRegisty + + !ifdef CPACK_NSIS_ADD_REMOVE + ;Create add/remove functionality + Push "ModifyPath" + Push "$INSTDIR\AddRemove.exe" + Call ConditionalAddToRegisty + !else + Push "NoModify" + Push "1" + Call ConditionalAddToRegisty + !endif + + ; Optional registration + Push "DisplayIcon" + Push "$INSTDIR\@CPACK_NSIS_INSTALLED_ICON_NAME@" + Call ConditionalAddToRegisty + Push "HelpLink" + Push "@CPACK_NSIS_HELP_LINK@" + Call ConditionalAddToRegisty + Push "URLInfoAbout" + Push "@CPACK_NSIS_URL_INFO_ABOUT@" + Call ConditionalAddToRegisty + Push "Contact" + Push "@CPACK_NSIS_CONTACT@" + Call ConditionalAddToRegisty + !insertmacro MUI_INSTALLOPTIONS_READ $INSTALL_DESKTOP "NSIS.InstallOptions.ini" "Field 5" "State" + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + + ;Create shortcuts + CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" +@CPACK_NSIS_CREATE_ICONS@ +@CPACK_NSIS_CREATE_ICONS_EXTRA@ + CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\Uninstall.exe" + + ;Read a value from an InstallOptions INI file + !insertmacro MUI_INSTALLOPTIONS_READ $DO_NOT_ADD_TO_PATH "NSIS.InstallOptions.ini" "Field 2" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_ALL_USERS "NSIS.InstallOptions.ini" "Field 3" "State" + !insertmacro MUI_INSTALLOPTIONS_READ $ADD_TO_PATH_CURRENT_USER "NSIS.InstallOptions.ini" "Field 4" "State" + + ; Write special uninstall registry entries + Push "StartMenu" + Push "$STARTMENU_FOLDER" + Call ConditionalAddToRegisty + Push "DoNotAddToPath" + Push "$DO_NOT_ADD_TO_PATH" + Call ConditionalAddToRegisty + Push "AddToPathAllUsers" + Push "$ADD_TO_PATH_ALL_USERS" + Call ConditionalAddToRegisty + Push "AddToPathCurrentUser" + Push "$ADD_TO_PATH_CURRENT_USER" + Call ConditionalAddToRegisty + Push "InstallToDesktop" + Push "$INSTALL_DESKTOP" + Call ConditionalAddToRegisty + + !insertmacro MUI_STARTMENU_WRITE_END + +@CPACK_NSIS_EXTRA_INSTALL_COMMANDS@ + +SectionEnd + +Section "-Add to path" + Push $INSTDIR\bin + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 doNotAddToPath + StrCmp $DO_NOT_ADD_TO_PATH "1" doNotAddToPath 0 + Call AddToPath + doNotAddToPath: +SectionEnd + +;-------------------------------- +; Create custom pages +Function InstallOptionsPage + !insertmacro MUI_HEADER_TEXT "Install Options" "Choose options for installing @CPACK_NSIS_PACKAGE_NAME@" + !insertmacro MUI_INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini" + +FunctionEnd + +;-------------------------------- +; determine admin versus local install +Function un.onInit + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + Goto done + StrCmp $1 "Power" 0 +3 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + Goto done + + noLM: + ;Get installation folder from registry if available + + done: + +FunctionEnd + +;--- Add/Remove callback functions: --- +!macro SectionList MacroName + ;This macro used to perform operation on multiple sections. + ;List all of your components in following manner here. +@CPACK_NSIS_COMPONENT_SECTION_LIST@ +!macroend + +Section -FinishComponents + ;Removes unselected components and writes component status to registry + !insertmacro SectionList "FinishSection" + +!ifdef CPACK_NSIS_ADD_REMOVE + ; Get the name of the installer executable + System::Call 'kernel32::GetModuleFileNameA(i 0, t .R0, i 1024) i r1' + StrCpy $R3 $R0 + + ; Strip off the last 13 characters, to see if we have AddRemove.exe + StrLen $R1 $R0 + IntOp $R1 $R0 - 13 + StrCpy $R2 $R0 13 $R1 + StrCmp $R2 "AddRemove.exe" addremove_installed + + ; We're not running AddRemove.exe, so install it + CopyFiles $R3 $INSTDIR\AddRemove.exe + + addremove_installed: +!endif +SectionEnd +;--- End of Add/Remove callback functions --- + +;-------------------------------- +; Component dependencies +Function .onSelChange + !insertmacro SectionList MaybeSelectionChanged +FunctionEnd + +;-------------------------------- +;Uninstaller Section + +Section "Uninstall" + ReadRegStr $START_MENU SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "StartMenu" + ;MessageBox MB_OK "Start menu is in: $START_MENU" + ReadRegStr $DO_NOT_ADD_TO_PATH SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "DoNotAddToPath" + ReadRegStr $ADD_TO_PATH_ALL_USERS SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathAllUsers" + ReadRegStr $ADD_TO_PATH_CURRENT_USER SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "AddToPathCurrentUser" + ;MessageBox MB_OK "Add to path: $DO_NOT_ADD_TO_PATH all users: $ADD_TO_PATH_ALL_USERS" + ReadRegStr $INSTALL_DESKTOP SHCTX \ + "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "InstallToDesktop" + ;MessageBox MB_OK "Install to desktop: $INSTALL_DESKTOP " + +@CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS@ + + ;Remove files we installed. + ;Keep the list of directories here in sync with the File commands above. +@CPACK_NSIS_DELETE_FILES@ +@CPACK_NSIS_DELETE_DIRECTORIES@ + +!ifdef CPACK_NSIS_ADD_REMOVE + ;Remove the add/remove program + Delete "$INSTDIR\AddRemove.exe" +!endif + + ;Remove the uninstaller itself. + Delete "$INSTDIR\Uninstall.exe" + DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ;Remove the installation directory if it is empty. + RMDir "$INSTDIR" + + ; Remove the registry entries. + DeleteRegKey SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + ; Removes all optional components + !insertmacro SectionList "RemoveSection_CPack" + + !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP + + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS@ +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + startMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors startMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" startMenuDeleteLoopDone startMenuDeleteLoop + startMenuDeleteLoopDone: + + ; If the user changed the shortcut, then untinstall may not work. This should + ; try to fix it. + StrCpy $MUI_TEMP "$START_MENU" + Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" +@CPACK_NSIS_DELETE_ICONS_EXTRA@ + + ;Delete empty start menu parent diretories + StrCpy $MUI_TEMP "$SMPROGRAMS\$MUI_TEMP" + + secondStartMenuDeleteLoop: + ClearErrors + RMDir $MUI_TEMP + GetFullPathName $MUI_TEMP "$MUI_TEMP\.." + + IfErrors secondStartMenuDeleteLoopDone + + StrCmp "$MUI_TEMP" "$SMPROGRAMS" secondStartMenuDeleteLoopDone secondStartMenuDeleteLoop + secondStartMenuDeleteLoopDone: + + DeleteRegKey /ifempty SHCTX "Software\@CPACK_PACKAGE_VENDOR@\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" + + Push $INSTDIR\bin + StrCmp $DO_NOT_ADD_TO_PATH_ "1" doNotRemoveFromPath 0 + Call un.RemoveFromPath + doNotRemoveFromPath: +SectionEnd + +;-------------------------------- +; determine admin versus local install +; Is install for "AllUsers" or "JustMe"? +; Default to "JustMe" - set to "AllUsers" if admin or on Win9x +; This function is used for the very first "custom page" of the installer. +; This custom page does not show up visibly, but it executes prior to the +; first visible page and sets up $INSTDIR properly... +; Choose different default installation folder based on SV_ALLUSERS... +; "Program Files" for AllUsers, "My Documents" for JustMe... + +Function .onInit + FindWindow $0 "gdkWindowToplevel" "Linphone" + StrCmp $0 0 notRunning + MessageBox MB_OK|MB_ICONEXCLAMATION "Linphone is running. Please close it first and restart the installation." /SD IDOK + Abort + +notRunning: + + ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\@CPACK_PACKAGE_INSTALL_REGISTRY_KEY@" "UninstallString" + StrCmp $0 "" inst + + MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ + "Linphone is already installed. $\n$\nDo you want to continue and uninstall the old version before installing the new one?" \ + IDOK uninst + Abort + +;Run the uninstaller +uninst: + ClearErrors + StrLen $2 "\Uninstall.exe" + StrCpy $3 $0 -$2 # remove "\Uninstall.exe" from UninstallString to get path + ExecWait '$0 _?=$3' ;Do not copy the uninstaller to a temp file + + IfErrors uninst_failed inst +uninst_failed: + MessageBox MB_OK|MB_ICONSTOP "Uninstall failed." + Abort + + +inst: + ; Reads components status for registry + !insertmacro SectionList "InitSection" + + ; check to see if /D has been used to change + ; the install directory by comparing it to the + ; install directory that is expected to be the + ; default + StrCpy $IS_DEFAULT_INSTALLDIR 0 + StrCmp "$INSTDIR" "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" 0 +2 + StrCpy $IS_DEFAULT_INSTALLDIR 1 + + StrCpy $SV_ALLUSERS "JustMe" + ; if default install dir then change the default + ; if it is installed for JustMe + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "$DOCUMENTS\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + ClearErrors + UserInfo::GetName + IfErrors noLM + Pop $0 + UserInfo::GetAccountType + Pop $1 + StrCmp $1 "Admin" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Admin group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + StrCmp $1 "Power" 0 +4 + SetShellVarContext all + ;MessageBox MB_OK 'User "$0" is in the Power Users group' + StrCpy $SV_ALLUSERS "AllUsers" + Goto done + + noLM: + StrCpy $SV_ALLUSERS "AllUsers" + ;Get installation folder from registry if available + + done: + StrCmp $SV_ALLUSERS "AllUsers" 0 +3 + StrCmp "$IS_DEFAULT_INSTALLDIR" "1" 0 +2 + StrCpy $INSTDIR "@CPACK_NSIS_INSTALL_ROOT@\@CPACK_PACKAGE_INSTALL_DIRECTORY@" + + StrCmp "@CPACK_NSIS_MODIFY_PATH@" "ON" 0 noOptionsPage + !insertmacro MUI_INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini" + + noOptionsPage: +FunctionEnd diff --git a/cmake_builder/linphone_package/README.openh264.txt.in b/cmake_builder/linphone_package/README.openh264.txt.in new file mode 100644 index 000000000..4f88bbedf --- /dev/null +++ b/cmake_builder/linphone_package/README.openh264.txt.in @@ -0,0 +1,20 @@ +H264 codec +---------- +Mediastreamer 2 uses Cisco's OpenH264 library as H264 codec. OpenH264 is an +open source library but H264 is a coding format protected by a patent from +MPEG-LA. That's why that bundle does not embed any OpenH264 library and so you +will not able to use H264 out-the-box. + +Fortunatly, Cisco Systems Inc. distribute OpenH264 in its binary form that you +can use in Mediastreamer without paying much royalties to MPEG-LA. However, +that binary file as a restrictive licence. See http://www.openh264.org/BINARY_LICENSE.txt form more information. + + +Installation procedure +---------------------- +The Cisco's provided OpenH264 library is available at this address: +http://ciscobinary.openh264.org/libopenh264-@OPENH264_VERSION@-osx64.dylib.bz2 for MacOS +http://ciscobinary.openh264.org/openh264-@OPENH264_VERSION@-win32msvc.dll.bz2 for Windows (32 bit) + +Once you get the library, uncompress it into /lib/libopenh264.1.dylib +On Windows, the library must be installed into \bin\openh264.dll diff --git a/cmake_builder/linphone_package/WindowsPackaging.cmake.in b/cmake_builder/linphone_package/WindowsPackaging.cmake.in new file mode 100644 index 000000000..5abcf7495 --- /dev/null +++ b/cmake_builder/linphone_package/WindowsPackaging.cmake.in @@ -0,0 +1,34 @@ +############################################################################ +# WindowsPackaging.cmake +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################ + +if(NOT "${CMAKE_INSTALL_PREFIX}" MATCHES .*/_CPack_Packages/.*) + execute_process( + COMMAND ${CMAKE_CPACK_COMMAND} -G NSIS + RESULT_VARIABLE CPACK_COMMAND_SUCCESS + ) + + if(@PERFORM_SIGNING@) + execute_process( + COMMAND @SIGNTOOL_COMMAND@ @CMAKE_CURRENT_BINARY_DIR@/@CPACK_PACKAGE_FILE_NAME@.exe + ) + endif() +endif() diff --git a/cmake_builder/linphone_package/linphone-banner.bmp b/cmake_builder/linphone_package/linphone-banner.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fffb5660cf418ded618544cac2c59c52a1c73ee2 GIT binary patch literal 25818 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

T2`Mqy9_g=#bn7$`zO|fbQQjCLo^Ga~^jwnj3iz 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