Browse Source

Add targets for packaging DMG and InnoSetup

Fixes configure.sh

Fixes Windows code signing

Fixes an issue with conan cache on windows

Fixes build manual script

Fixes build manual

Remove unused props

Use long options

Yet another manual fix

Fixes iss
pull/2/head
Dmitry Vedenko 1 year ago
committed by Dmitry Vedenko
parent
commit
6da25e1646
  1. 19
      .github/workflows/cmake_build.yml
  2. 36
      CMakeLists.txt
  3. 36
      cmake-proxies/cmake-modules/AudacityCodeSigning.cmake
  4. 39
      cmake-proxies/cmake-modules/AudacityInnoSetup.cmake
  5. 20
      cmake-proxies/cmake-modules/Package.cmake
  6. 15
      help/CMakeLists.txt
  7. 22
      scripts/build/macOS/DMGSetup.scpt
  8. 16
      scripts/build/macOS/DMGSign.cmake
  9. 111
      scripts/build/macOS/NotarizeMacos.cmake
  10. 54
      scripts/build/macOS/SignMacos.cmake
  11. 28
      scripts/build/windows/PfxSign.cmake
  12. 108
      scripts/build/windows/PfxSign.ps1
  13. 29
      scripts/ci/configure.sh
  14. 5
      scripts/ci/environment.sh
  15. 10
      scripts/ci/package.sh
  16. 79
      win/Inno_Setup_Wizard/BuildInnoSetupInstaller.cmake
  17. 107
      win/Inno_Setup_Wizard/audacity.iss.in

19
.github/workflows/cmake_build.yml

@ -15,6 +15,13 @@ jobs:
env:
AUDACITY_CMAKE_GENERATOR: ${{ matrix.config.generator }}
AUDACITY_ARCH_LABEL: ${{ matrix.config.arch }}
# Windows codesigning
# This variables will be used by all the steps
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
# Conan home location to be used for cache action
CONAN_USER_HOME: "${{ github.workspace }}/conan-home/"
CONAN_USER_HOME_SHORT: "${{ github.workspace }}/conan-home/short"
strategy:
fail-fast: false
matrix:
@ -52,6 +59,13 @@ jobs:
- name: Environment
run: |
source "scripts/ci/environment.sh"
- name: Install Apple codesigning certificates
uses: apple-actions/import-codesign-certs@v1
if: startswith( matrix.config.os, 'macos' ) && github.event_name == 'push'
with:
p12-file-base64: ${{ secrets.APPLE_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
- name: Cache for .conan
id: cache-conan
@ -66,10 +80,15 @@ jobs:
- name: Configure
env:
# Error reporing
SENTRY_DSN_KEY: ${{ secrets.SENTRY_DSN_KEY }}
SENTRY_HOST: ${{ secrets.SENTRY_HOST }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
CRASH_REPORT_URL: ${{ secrets.CRASH_REPORT_URL }}
# Apple code signing
APPLE_CODESIGN_IDENTITY: ${{ secrets.APPLE_CODESIGN_IDENTITY }}
APPLE_NOTARIZATION_USER_NAME: ${{ secrets.APPLE_NOTARIZATION_USER_NAME }}
APPLE_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
run: |
exec bash "scripts/ci/configure.sh"

36
CMakeLists.txt

@ -534,6 +534,42 @@ file( WRITE "${CMAKE_CURRENT_BINARY_DIR}/modules.dot" "digraph {
execute_process( COMMAND
dot -O -Tsvg "${CMAKE_CURRENT_BINARY_DIR}/modules.dot" )
#
# Code signing
#
cmd_option( ${_OPT}perform_codesign
"Perform code signing during the install step. This only works on Windows and macOS."
Off
)
cmake_dependent_option(
${_OPT}perform_notarization
"Perform notarization during the install step. This only works on macOS."
Off
"${_OPT}perform_codesign;APPLE"
Off
)
if( ${_OPT}perform_codesign )
include( AudacityCodeSigning )
endif()
#
# Packaging
#
cmd_option( ${_OPT}package_manual
"Package the manual along with the DMG and InnoSetup targets"
Off
)
# Variables, that are common for all package targets
if( CMAKE_SYSTEM_NAME MATCHES "Windows" )
include( AudacityInnoSetup )
endif()
# Uncomment what follows for symbol values.
#[[
get_cmake_property( _variableNames VARIABLES )

36
cmake-proxies/cmake-modules/AudacityCodeSigning.cmake

@ -0,0 +1,36 @@
# Code signing
if( CMAKE_SYSTEM_NAME MATCHES "Windows" )
# On windows, we expect WINDOWS_CERTIFICATE to be set
# as a CMake variable or as an environment variable
if( DEFINED WINDOWS_CERTIFICATE )
install( CODE "set( WINDOWS_CERTIFICATE \"${WINDOWS_CERTIFICATE}\" )" )
endif()
if( DEFINED WINDOWS_CERTIFICATE_PASSWORD )
# To simplify the helper script - we push password to the environment
install( CODE "set( ENV{WINDOWS_CERTIFICATE_PASSWORD} \"${WINDOWS_CERTIFICATE_PASSWORD}\") " )
endif()
install( CODE "set( PFX_SIGN_PS_LOCATION \"${CMAKE_SOURCE_DIR}/scripts/build/windows/PfxSign.ps1\") " )
install( SCRIPT "scripts/build/windows/PfxSign.cmake" )
elseif( CMAKE_SYSTEM_NAME MATCHES "Darwin")
set_from_env( APPLE_CODESIGN_IDENTITY )
set_from_env( APPLE_NOTARIZATION_USER_NAME )
set_from_env( APPLE_NOTARIZATION_PASSWORD )
# Pass arguments to cmake install script
install( CODE "set( APPLE_CODESIGN_IDENTITY \"${APPLE_CODESIGN_IDENTITY}\" )" )
install( CODE "set( APPLE_NOTARIZATION_USER_NAME \"${APPLE_NOTARIZATION_USER_NAME}\" )" )
install( CODE "set( APPLE_NOTARIZATION_PASSWORD \"${APPLE_NOTARIZATION_PASSWORD}\" )" )
install( CODE "set( APP_IDENTIFIER \"org.audacityteam.audacity\" )" )
install( CODE "get_filename_component( APP_LOCATION \${CMAKE_INSTALL_PREFIX}/Audacity.app ABSOLUTE )" )
install( CODE "set( APPLE_CODESIGN_ENTITLEMENTS ${CMAKE_SOURCE_DIR}/mac/Audacity.entitlements )")
install( SCRIPT "scripts/build/macOS/SignMacos.cmake" )
if( ${_OPT}perform_notarization )
install( SCRIPT "scripts/build/macOS/NotarizeMacos.cmake" )
endif()
endif()

39
cmake-proxies/cmake-modules/AudacityInnoSetup.cmake

@ -0,0 +1,39 @@
# Defines innosetup target
# The target will be only generated if InnoSetup 6 is installed.
find_program(
INNO_SETUP_COMPILER
NAMES iscc ISCC
HINTS
"C:/Program Files (x86)/Inno Setup 6"
"C:/Program Files/Inno Setup 6"
)
if( INNO_SETUP_COMPILER )
message(STATUS "Creating target innosetup...")
set( TEMP_PACKAGE_PATH "${CMAKE_BINARY_DIR}/innosetup" )
add_custom_target(
innosetup
COMMAND
${CMAKE_COMMAND}
-DBUILD_DIR=${CMAKE_BINARY_DIR}
-DSOURCE_DIR=${CMAKE_SOURCE_DIR}
-DOUTPUT_DIR=${TEMP_PACKAGE_PATH}
-DINNO_SETUP_COMPILER=${INNO_SETUP_COMPILER}
-DEMBED_MANUAL=${${_OPT}package_manual}
-DBUILDING_64_BIT=${IS_64BIT}
-DSIGN=${${_OPT}perform_codesign}
-DWINDOWS_CERTIFICATE=${WINDOWS_CERTIFICATE}
-D WINDOWS_CERTIFICATE_PASSWORD=${WINDOWS_CERTIFICATE_PASSWORD}
-P "${CMAKE_SOURCE_DIR}/win/Inno_Setup_Wizard/BuildInnoSetupInstaller.cmake"
VERBATIM
)
if( ${_OPT}package_manual )
add_dependencies( innosetup manual )
endif()
set_target_properties( innosetup PROPERTIES FOLDER "packaging" )
endif()

20
cmake-proxies/cmake-modules/Package.cmake

@ -2,6 +2,8 @@
set(CPACK_PACKAGE_VERSION_MAJOR "${AUDACITY_VERSION}") # X
set(CPACK_PACKAGE_VERSION_MINOR "${AUDACITY_RELEASE}") # Y
set(CPACK_PACKAGE_VERSION_PATCH "${AUDACITY_REVISION}") # Z
set(CPACK_PACKAGE_VENDOR "Audacity")
set(CPACK_PACKAGE_HOMEPAGE_URL "https://audacityteam.org")
# X.Y.Z-alpha-20210615
set(CPACK_PACKAGE_VERSION "${AUDACITY_VERSION}.${AUDACITY_RELEASE}.${AUDACITY_REVISION}${AUDACITY_SUFFIX}")
@ -22,4 +24,22 @@ set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}/package")
set(CPACK_GENERATOR ZIP)
if( CMAKE_SYSTEM_NAME STREQUAL "Darwin" )
set( CPACK_GENERATOR DragNDrop )
set( CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/mac/Resources/Audacity-DMG-background.png")
set( CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_SOURCE_DIR}/scripts/build/macOS/DMGSetup.scpt")
if( ${_OPT}perform_codesign )
set( CPACK_APPLE_CODESIGN_IDENTITY ${APPLE_CODESIGN_IDENTITY} )
set( CPACK_APPLE_NOTARIZATION_USER_NAME ${APPLE_NOTARIZATION_USER_NAME} )
set( CPACK_APPLE_NOTARIZATION_PASSWORD ${APPLE_NOTARIZATION_PASSWORD} )
set( CPACK_APPLE_SIGN_SCRIPTS "${CMAKE_SOURCE_DIR}/scripts/build/macOS" )
set( CPACK_PERFORM_NOTARIZATION ${${_OPT}perform_notarization} )
# CPACK_POST_BUILD_SCRIPTS was added in 3.19, but we only need it on macOS
SET( CPACK_POST_BUILD_SCRIPTS "${CMAKE_SOURCE_DIR}/scripts/build/macOS/DMGSign.cmake" )
endif()
endif()
include(CPack) # do this last

15
help/CMakeLists.txt

@ -34,6 +34,20 @@ add_custom_command(
add_custom_target( ${TARGET} DEPENDS "${out}" )
if( ${_OPT}package_manual )
install(CODE " \
execute_process( \
COMMAND \
${CMAKE_COMMAND} \
--build ${CMAKE_BINARY_DIR} \
--config \${CMAKE_INSTALL_CONFIG_NAME} \
--target manual \
) \
")
install( DIRECTORY "${out_dir}/${host}/" DESTINATION "help/manual" )
endif()
if( NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" )
if( NOT "${CMAKE_GENERATOR}" MATCHES "Visual Studio*")
install( DIRECTORY "${dst}" OPTIONAL
@ -44,4 +58,3 @@ if( NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" )
DESTINATION "${_DATADIR}/appdata" )
endif()
endif()

22
scripts/build/macOS/DMGSetup.scpt

@ -0,0 +1,22 @@
on run argv
set diskImage to item 1 of argv
tell application "Finder"
tell disk diskImage
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {400, 100, 1000, 550}
set theViewOptions to the icon view options of container window
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to 72
set background picture of theViewOptions to file ".background:background.png"
set position of item "Audacity" of container window to {170, 350}
set position of item "Applications" of container window to {430, 350}
close
open
update without registering applications
end tell
end tell
end run

16
scripts/build/macOS/DMGSign.cmake

@ -0,0 +1,16 @@
set( APPLE_CODESIGN_IDENTITY ${CPACK_APPLE_CODESIGN_IDENTITY} )
set( APPLE_NOTARIZATION_USER_NAME ${CPACK_APPLE_NOTARIZATION_USER_NAME} )
set( APPLE_NOTARIZATION_PASSWORD ${CPACK_APPLE_NOTARIZATION_PASSWORD} )
set( PERFORM_NOTARIZATION ${CPACK_PERFORM_NOTARIZATION} )
set( APP_IDENTIFIER "org.audacityteam.audacity" )
foreach( file ${CPACK_PACKAGE_FILES} )
set( DMG_LOCATION ${CPACK_PACKAGE_FILES} )
include( "${CPACK_APPLE_SIGN_SCRIPTS}/SignMacos.cmake" )
if( PERFORM_NOTARIZATION )
include( "${CPACK_APPLE_SIGN_SCRIPTS}/NotarizeMacos.cmake" )
endif()
endforeach()

111
scripts/build/macOS/NotarizeMacos.cmake

@ -0,0 +1,111 @@
# CMake script to sign macOS build
# Arguments:
# APP_IDENTIFIER - app identifier
# APP_LOCATION - the path to Audacity.app
# DMG_LOCATION - the path to Audaicty dmg package
# APPLE_NOTARIZATION_USER_NAME - notarization user name
# APPLE_NOTARIZATION_PASSWORD - notarization password
# https://cmake.org/cmake/help/latest/policy/CMP0054.html
cmake_policy( SET CMP0054 NEW )
# https://cmake.org/cmake/help/latest/policy/CMP0011.html
cmake_policy( SET CMP0011 NEW )
function( get_plist_value output path key )
execute_process(
COMMAND /usr/libexec/PlistBuddy -c "Print ${key}" "${path}"
OUTPUT_VARIABLE result
)
string( STRIP ${result} result )
set( ${output} ${result} PARENT_SCOPE )
endfunction()
if( APP_LOCATION )
get_filename_component( temp_dir "${APP_LOCATION}/.." ABSOLUTE )
else()
get_filename_component( temp_dir "${DMG_LOCATION}" DIRECTORY )
endif()
set( temp_plist "${temp_dir}/NotarizationResult.plist" )
function( notarize path )
message( STATUS "Notarizing ${path}" )
execute_process(
COMMAND
xcrun altool
--notarize-app
--primary-bundle-id "${APP_IDENTIFIER}"
--file "${path}"
--username "${APPLE_NOTARIZATION_USER_NAME}"
--password "${APPLE_NOTARIZATION_PASSWORD}"
--output-format xml
OUTPUT_VARIABLE
result
)
file( WRITE ${temp_plist} ${result} )
get_plist_value( req_id ${temp_plist} "notarization-upload:RequestUUID" )
message( STATUS "\t Request ID: '${req_id}'" )
set( success Off )
while( NOT success )
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 15)
execute_process(
COMMAND
xcrun altool
--notarization-info ${req_id}
--username ${APPLE_NOTARIZATION_USER_NAME}
--password ${APPLE_NOTARIZATION_PASSWORD}
--output-format xml
OUTPUT_VARIABLE
result
)
file( WRITE ${temp_plist} ${result} )
get_plist_value( notarization_result ${temp_plist} "notarization-info:Status" )
message( STATUS "\t Status: ${notarization_result}" )
if( NOT "${notarization_result}" STREQUAL "in progress" )
if ( NOT "${notarization_result}" STREQUAL "success" )
message(FATAL_ERROR "Notarization failed:\n${result}\n")
else()
message(STATUS "Notarization successfull")
endif()
break()
endif()
endwhile()
endfunction()
if( DEFINED APP_LOCATION )
get_filename_component( archive "${APP_LOCATION}/../notarization.zip" ABSOLUTE )
execute_process(
COMMAND
xcrun ditto
-c -k --keepParent
${APP_LOCATION}
${archive}
)
notarize( ${archive} )
execute_process( COMMAND stapler staple "${APP_LOCATION}" )
file( REMOVE "${APP_LOCATION}/../notarization.zip" )
endif()
if( DEFINED DMG_LOCATION )
notarize( ${DMG_LOCATION} )
execute_process( COMMAND stapler staple "${DMG_LOCATION}" )
endif()
file( REMOVE ${temp_plist} )

54
scripts/build/macOS/SignMacos.cmake

@ -0,0 +1,54 @@
# CMake script to sign macOS build
# Arguments:
# APP_IDENTIFIER - app identifier
# APP_LOCATION - the path to Audacity.app
# DMG_LOCATION - the path to Audaicty dmg package
# APPLE_CODESIGN_IDENTITY - identity to use
# APPLE_CODESIGN_ENTITLEMENTS - path to the entitlements
function( codesign path deep is_dmg)
message(STATUS "Signing ${path}")
set ( args
--verbose
--timestamp
--identifier "${APP_IDENTIFIER}"
--sign "${APPLE_CODESIGN_IDENTITY}"
)
if( NOT is_dmg )
list( APPEND args
--options runtime
--entitlements "${APPLE_CODESIGN_ENTITLEMENTS}"
)
endif()
if( deep )
list( APPEND args --deep)
endif()
execute_process( COMMAND xcrun codesign ${args} ${path} )
endfunction()
function( sign_modules path )
message(STATUS "\tLooking for modules or plugins in: '${path}'")
file( GLOB_RECURSE modules
LIST_DIRECTORIES Off
"${path}/*.so" "${path}/*.dylib"
)
foreach( module ${modules} )
codesign( ${module} Off Off )
endforeach()
endfunction()
if( DEFINED APP_LOCATION )
sign_modules( "${APP_LOCATION}/Contents/modules" )
sign_modules( "${APP_LOCATION}/Contents/plug-ins" )
codesign( "${APP_LOCATION}" On Off )
endif()
if (DEFINED DMG_LOCATION )
codesign( "${DMG_LOCATION}" Off On)
endif()

28
scripts/build/windows/PfxSign.cmake

@ -0,0 +1,28 @@
# This is a CMake script that properly calls the PfxSign.ps1
if( DEFINED WINDOWS_CERTIFICATE_PASSWORD )
set( ENV{WINDOWS_CERTIFICATE_PASSWORD} "${WINDOWS_CERTIFICATE_PASSWORD}" )
endif()
if(DEFINED WINDOWS_CERTIFICATE)
execute_process(
COMMAND powershell
-ExecutionPolicy Bypass
-File ${PFX_SIGN_PS_LOCATION}
-Directory ${CMAKE_INSTALL_PREFIX}
-CertFile ${WINDOWS_CERTIFICATE}
)
elseif(DEFINED ENV{WINDOWS_CERTIFICATE})
execute_process(
COMMAND powershell
-ExecutionPolicy Bypass
-File ${PFX_SIGN_PS_LOCATION}
-Directory ${CMAKE_INSTALL_PREFIX}
)
else()
message(FATAL_ERROR [[
Code signing is skipped, as certifacte is missing.
Please, set the path to PFX file using -DWINDOWS_CERTIFICATE=...
or set the environment variable WINDOWS_CERTIFICATE to base64 encoded PFX certifacte.
]])
endif()

108
scripts/build/windows/PfxSign.ps1

@ -0,0 +1,108 @@
# This script uses Set-AuthenticodeSignature to sign a file
# or exe/dll/msi files in a directory using a pfx file.
# If PFX file is not present, script expects a base64 encode certificate
# in WINDOWS_CERTIFICATE environment variable.
# Password can be passed using WINDOWS_CERTIFICATE_PASSWORD environmnet variable.
# The script only signs previously unsigned files
[CmdletBinding()]
param (
# A path to the certificate file. If missing, env:WINDOWS_CERTIFICATE will be used.
[string]$CertFile,
# A password for the certificate. If missing, env:WINDOWS_CERTIFICATE_PASSWORD will be used.
[string]$Password,
# A file to sign.
[string]$File,
# A directory to sign.
[string]$Directory
)
# Configure the error behavior
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
# Sign a file, if it was previously unsigned
# We sign using SHA256, as we only support Windows 7+.
function Set-FileSignature {
param (
[String]$InputFile,
$pfxCert
)
if((Get-AuthenticodeSignature $InputFile).Status -ne [System.Management.Automation.SignatureStatus]::Valid) {
Write-Host "Singning file $InputFile"
Set-AuthenticodeSignature `
-FilePath $InputFile `
-Certificate $pfxCert `
-IncludeChain All `
-TimestampServer 'http://timestamp.digicert.com' `
-HashAlgorithm 'sha256' `
-Force
} else {
Write-Host "Skipping file $InputFile as it is already signed"
}
}
# Sanity checks: only allow File or Directory
if ($File -eq "" -and $Directory -eq "") {
Write-Host "-File or -Directory should be provided"
exit 1
} elseif ($File -ne "" -and $Directory -ne "") {
Write-Host "Only one of -File or -Directory should be provided"
exit 1
}
$cleanupPfx = $false
# Check, if we need to retrieve PFX from environment
if($CertFile -eq "") {
Write-Host "Trying to read certificate file from env:WINDOWS_CERTIFICATE"
if(Test-Path "env:WINDOWS_CERTIFICATE") {
$CertFile = "cert.pfx"
[IO.File]::WriteAllBytes($CertFile, [System.Convert]::FromBase64String($env:WINDOWS_CERTIFICATE))
$cleanupPfx = $true
} else {
Write-Host "No certificate is provided"
exit 1
}
}
# Check, if we need to retrieve password from environment
if($Password -eq "") {
if (Test-Path "env:WINDOWS_CERTIFICATE_PASSWORD") {
$Password = $env:WINDOWS_CERTIFICATE_PASSWORD
}
}
$pfx = $null
# Retrieve the actual certificate
if($Password -ne "") {
$securePassword = ConvertTo-SecureString -String $Password -AsPlainText -Force
$pfx = Get-PfxData -FilePath "$CertFile" -Password $securePassword
} else {
$pfx = Get-PfxData -FilePath "$CertFile"
}
$pfxCert = $pfx.EndEntityCertificates[0]
# Perform the code signing.
if ($File -ne "") {
Set-FileSignature -InputFile $File -pfxCert $pfxCert
} else {
Get-ChildItem `
-Path "$Directory" `
-Include *.dll,*.exe,*.msi `
-Recurse `
-File | ForEach-Object {
Set-FileSignature -InputFile $_.FullName -pfxCert $pfxCert
}
}
# Remove PFX file if it was created from environment.
if($cleanupPfx) {
Remove-Item "${CertFile}"
}

29
scripts/ci/configure.sh

@ -34,5 +34,34 @@ elif [[ "${AUDACITY_CMAKE_GENERATOR}" == Xcode* ]]; then
)
fi
if [[ -n "${APPLE_CODESIGN_IDENTITY}" && "${OSTYPE}" == darwin* ]]; then
cmake_args+=(
-D APPLE_CODESIGN_IDENTITY="${APPLE_CODESIGN_IDENTITY}"
-D audacity_perform_codesign=yes
)
if [[ ${GIT_BRANCH} == release* ]]; then
cmake_args+=(
-D APPLE_NOTARIZATION_USER_NAME="${APPLE_NOTARIZATION_USER_NAME}"
-D APPLE_NOTARIZATION_PASSWORD="${APPLE_NOTARIZATION_PASSWORD}"
-D audacity_perform_notarization=yes
)
fi
elif [[ -n "${WINDOWS_CERTIFICATE}" && "${OSTYPE}" == msys* ]]; then
# Windows certificate will be used from the environment
cmake_args+=(
-D audacity_perform_codesign=yes
)
fi
if [[ ${GIT_BRANCH} == release* ]]; then
cmake_args+=(
-D audacity_package_manual=yes
)
fi
# Configure Audacity
cmake "${cmake_args[@]}"
# Remove build directories and sources to reduce the cache size.
conan remove "*" --src --builds --force

5
scripts/ci/environment.sh

@ -15,11 +15,10 @@ function gh_export()
repository_root="$(cd "$(dirname "${BASH_SOURCE}")/../.."; echo "${PWD}")"
gh_export CONAN_USER_HOME="${repository_root}/conan-home/"
gh_export CONAN_USER_HOME_SHORT="${repository_root}/conan-home/short"
gh_export GIT_HASH="$(git show -s --format='%H')"
gh_export GIT_HASH_SHORT="$(git show -s --format='%h')"
gh_export AUDACITY_BUILD_TYPE="RelWithDebInfo"
gh_export AUDACITY_INSTALL_PREFIX="${repository_root}/build/install"
gh_export GIT_BRANCH=${GITHUB_REF##*/}

10
scripts/ci/package.sh

@ -5,4 +5,12 @@
set -euxo pipefail
cd build
cpack -C "${AUDACITY_BUILD_TYPE}" --verbose
if [[ "${OSTYPE}" == msys* && ${GIT_BRANCH} == release* ]]; then # Windows
cmake --build . --target innosetup --config "${AUDACITY_BUILD_TYPE}"
else
cpack -C "${AUDACITY_BUILD_TYPE}" --verbose
fi
# Remove the temporary directory
rm -Rf package/_CPack_Packages

79
win/Inno_Setup_Wizard/BuildInnoSetupInstaller.cmake

@ -0,0 +1,79 @@
# This CMake script is invoked to build the InnoSetup installer for Audacity
# Requiered parameters:
# BUILD_DIR - should be set to CMAKE_BINARY_DIR by the caller
# SOURCE_DIR - should be set to CMAKE_SOURCE_DIR by teh caller
# OUTPUT_DIR - directory, where installer will be built
# INNO_SETUP_COMPILER - InnoSetup compiler executable
# BUILDING_64_BIT - Flag, that indicates that we are building a 64-bit installer
# EMBED_MANUAL - embed a fresh copy of manual
# SIGN - sign the installer
# WINDOWS_CERTIFICATE - path to PFX file. If not present, env:WINDOWS_CERTIFICATE will be used
# WINDOWS_CERTIFICATE_PASSWORD - password for the PFX file. If not present, env:WINDOWS_CERTIFICATE_PASSWORD will be used
if( BUILDING_64_BIT )
set( INSTALLER_SUFFIX "x64" )
set( INSTALLER_X64_MODE "ArchitecturesInstallIn64BitMode=x64")
else()
set( INSTALLER_SUFFIX "x86" )
set( INSTALLER_X64_MODE "ArchitecturesInstallIn64BitMode=x64")
endif()
if( SIGN )
set( SIGN_TOOL "SignTool=byparam powershell -ExecutionPolicy Bypass -File \$q${SOURCE_DIR}/scripts/build/windows/PfxSign.ps1\$q -File $f")
if( WINDOWS_CERTIFICATE )
string(APPEND SIGN_TOOL " -CertFile \$q${WINDOWS_CERTIFICATE}\$q")
endif()
if( WINDOWS_CERTIFICATE_PASSWORD )
message("Setting env:WINDOWS_CERTIFICATE_PASSWORD...")
set( ENV{WINDOWS_CERTIFICATE_PASSWORD} "${WINDOWS_CERTIFICATE_PASSWORD}")
endif()
else()
set( SIGN_TOOL )
endif()
if( EMBED_MANUAL )
set ( MANUAL [[Source: "Package\help\manual\*"; DestDir: "{app}\help\manual\"; Flags: ignoreversion recursesubdirs]])
else()
set( MANUAL )
endif()
# Prepare the output directory
file(COPY "${SOURCE_DIR}/win/Inno_Setup_Wizard/" DESTINATION "${OUTPUT_DIR}")
configure_file("${OUTPUT_DIR}/audacity.iss.in" "${OUTPUT_DIR}/audacity.iss")
# Copy additional files
file(COPY "${SOURCE_DIR}/presets" DESTINATION "${OUTPUT_DIR}/Additional")
file(COPY
"${SOURCE_DIR}/LICENSE.txt"
"${SOURCE_DIR}/README.txt"
"${SOURCE_DIR}/win/audacity.ico"
DESTINATION
"${OUTPUT_DIR}/Additional"
)
# "Install" prebuilt package
execute_process(
COMMAND
${CMAKE_COMMAND}
--install ${BUILD_DIR}
--prefix "${OUTPUT_DIR}/Package"
)
# Build the installer
execute_process(
COMMAND
${INNO_SETUP_COMPILER} /Sbyparam=$p "audacity.iss"
WORKING_DIRECTORY
${OUTPUT_DIR}
)
# Emulate CPack behavior
file( COPY "${OUTPUT_DIR}/Output/" DESTINATION "${BUILD_DIR}/package" )

107
win/Inno_Setup_Wizard/audacity.iss → win/Inno_Setup_Wizard/audacity.iss.in

@ -1,5 +1,5 @@
; Audacity: A Digital Audio Editor
; Audacity(R) is copyright (c) 1999-2016 Audacity Team.
; Audacity(R) is copyright (c) 1999-2021 Audacity Team.
; License: GPL v2. See License.txt.
;
; audacity.iss
@ -7,7 +7,8 @@
;
; This requires that the ISS Preprocessor be installed
#define AppExe "..\release\audacity.exe"
#define AppExe "Package\audacity.exe"
#define AppMajor ""
#define AppMinor ""
#define AppRev ""
@ -22,7 +23,7 @@ Filename: "{app}\unins*.*";
[Setup]
; compiler-related directives
OutputBaseFilename=audacity-win-{#AppVersion}
OutputBaseFilename=audacity-win-{#AppVersion}-@INSTALLER_SUFFIX@
WizardImageFile=".\audacity_InnoWizardImage.bmp"
WizardSmallImageFile=".\audacity_InnoWizardSmallImage.bmp"
@ -43,8 +44,9 @@ AppPublisherURL=http://audacityteam.org
AppSupportURL=http://audacityteam.org
AppUpdatesURL=http://audacityteam.org
ChangesAssociations=yes
@INSTALLER_X64_MODE@
DefaultDirName={pf}\Audacity
DefaultDirName={commonpf}\Audacity
VersionInfoProductName={#AppName}
VersionInfoProductTextVersion={#GetFileProductVersion(AppExe)}
@ -63,7 +65,7 @@ UninstallDisplayIcon="{app}\audacity.exe"
; No longer force them to accept the license, just display it. LicenseFile=..\LICENSE.txt
InfoBeforeFile=".\audacity_InnoWizard_InfoBefore.rtf"
InfoAfterFile=..\..\README.txt
InfoAfterFile=Additional\README.txt
; We no longer produce new ANSI builds.
; As we use Inno Setup (u), the Unicode version, to build this script,
@ -72,7 +74,9 @@ InfoAfterFile=..\..\README.txt
; MinVersion=4.0,5.0
; cosmetic-related directives
SetupIconFile="..\audacity.ico"
SetupIconFile="Additional\audacity.ico"
@SIGN_TOOL@
[INI]
Filename: "{app}\FirstTime.ini"; Section: "FromInno"; Key: "ResetPrefs"; String: "1"; Tasks: resetPrefs;
@ -89,47 +93,26 @@ Name: resetPrefs; Description: "{cm:ResetPrefs}"; Flags: unchecked
Source: ".\FirstTimeModel.ini"; DestDir: "{app}"; DestName: "FirstTime.ini"; Permissions: users-modify
; Don't display in separate window, rather as InfoAfterFile. Source: "..\README.txt"; DestDir: "{app}"; Flags: ignoreversion isreadme
Source: "..\..\README.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "Additional\README.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\..\LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "Additional\LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#AppExe}"; DestDir: "{app}"; Flags: ignoreversion
; Manual, which should be got from the manual wiki using ..\scripts\mw2html_audacity\wiki2htm.bat
Source: "..\..\help\manual\*"; DestDir: "{app}\help\manual\"; Flags: ignoreversion recursesubdirs
Source: "..\..\presets\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; wxWidgets DLLs. Be specific (not *.dll) so we don't accidentally distribute avformat.dll, for example.
; Don't use the WXWIN environment variable, because...
; 1) Can't get the documented {%WXWIN|default dir} parsing to work.
; 2) Need the DLL's in the release dir for testing, anyway.
Source: "..\release\wxbase313u_xml_vc_custom.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\wxbase313u_vc_custom.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\wxmsw313u_core_vc_custom.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\wxmsw313u_html_vc_custom.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\wxmsw313u_qa_vc_custom.dll"; DestDir: "{app}"; Flags: ignoreversion
; MSVC runtime DLLs. Some users can't put these in the system dir, so just put them in the EXE dir.
; It's legal, per http://www.fsf.org/licensing/licenses/gpl-faq.html#WindowsRuntimeAndGPL .
; This is not an ideal solution, but should need the least tech support.
; We'll know we have the right version, don't step on anybody else's older version, and
; it's easy to make the zip (and they match better).
; Copy the several required DLL's from
; "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x86\Microsoft.VC120.CRT\"
; or "C:\Program Files\Microsoft Visual Studio 12.0\VC\redist\x86\Microsoft.VC120.CRT\"
; according to your system
Source: "..\release\concrt140.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\msvcp140.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\msvcp140_1.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\msvcp140_2.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\release\languages\*"; DestDir: "{app}\Languages\"; Flags: ignoreversion recursesubdirs
@MANUAL@
Source: "Additional\presets\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; We include all dll files from the Adacity root directory. This script is now executed as a part of CI build process,
; so we controll which dll files are present in the directory.
Source: "Package\*.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "Package\languages\*"; DestDir: "{app}\Languages\"; Flags: ignoreversion recursesubdirs
; We don't ship all modules, so the next line is commented out
; Source: "..\release\modules\*"; DestDir: "{app}\Modules\"; Flags: ignoreversion recursesubdirs skipifsourcedoesntexist
Source: "..\release\nyquist\*"; DestDir: "{app}\Nyquist\"; Flags: ignoreversion recursesubdirs
Source: "..\release\plug-ins\*"; DestDir: "{app}\Plug-Ins\"; Flags: ignoreversion
Source: "..\release\modules\mod-script-pipe.dll"; DestDir: "{app}\modules\"; Flags: ignoreversion
; Source: "Package\modules\*"; DestDir: "{app}\Modules\"; Flags: ignoreversion recursesubdirs skipifsourcedoesntexist
Source: "Package\nyquist\*"; DestDir: "{app}\Nyquist\"; Flags: ignoreversion recursesubdirs
Source: "Package\plug-ins\*"; DestDir: "{app}\Plug-Ins\"; Flags: ignoreversion
Source: "Package\modules\*"; DestDir: "{app}\modules\"; Flags: ignoreversion recursesubdirs
[Icons]
Name: "{commonprograms}\Audacity"; Filename: "{app}\audacity.exe"
@ -213,8 +196,8 @@ Filename: "{app}\audacity.exe"; Description: "{cm:LaunchProgram,Audacity}"; Flag
; NOTE: "0" in locale name will be translated to "@" when read by Audacity.
; Create subdirectories where we'll store the unofficial and dummy translation files
{#expr Exec("cmd", "/c mkdir """ + CompilerPath + "Languages\dummy""", , , SW_HIDE), \
Exec("cmd", "/c mkdir """ + CompilerPath + "Languages\unofficial""", , , SW_HIDE)}
{#expr Exec("cmd", "/c mkdir """ + "Languages\dummy""", '.\', , SW_HIDE), \
Exec("cmd", "/c mkdir """ + "Languages\unofficial""", '.\', , SW_HIDE)}
; Download Additional Inno Setup translations from:
;
@ -227,28 +210,28 @@ Filename: "{app}\audacity.exe"; Description: "{cm:LaunchProgram,Audacity}"; Flag
; the Inno Setup Languages folder if it hasn't already been downloaded.
; (Sorry, it's not a quick process, but it only happens once.)
#define Get(URL) \
Local[0] = "Languages\unofficial\" + Copy(URL, RPos("/", URL) + 1), \
Local[1] = (FileExists(CompilerPath + Local[0]) \
Local[0] = ".\Languages\unofficial\" + Copy(URL, RPos("/", URL) + 1), \
Local[1] = (FileExists(Local[0]) \
? "alreadyexists" \
: Exec("powershell", "echo 'Downloading: " + URL + "'; $wc = new-object System.Net.WebClient; $wc.DownloadFile('" + URLBase + URL + "', '" + Local[0] + "')", , , SW_NORMAL)), \
"compiler:" + Local[0]
: Exec("powershell", "echo 'Downloading: " + URL + "'; $wc = new-object System.Net.WebClient; $wc.DownloadFile('" + URLBase + URL + "', '" + Local[0] + "')", '.\', , SW_NORMAL)), \
Local[0]
; This macro will define a dummy translation based on the Defaults.isl
#define Dummy(NAME, ID) \
Local[0] = "Languages\dummy\", \
Local[0] = ".\Languages\dummy\", \
Local[1] = Local[0] + NAME + ".isl", \
Local[2] = CompilerPath + Local[1], \
Local[2] = SourcePath + Local[1], \
Local[3] = (FileExists(Local[2]) \
? "alreadyexists" \
: (CopyFile(CompilerPath + "Default.isl", Local[2]), \
WriteIni(Local[2], "LangOptions", "LanguageName", NAME), \
WriteIni(Local[2], "LangOptions", "LanguageID", "$" + ID))), \
"compiler:" + Local[1]
Local[1]
Name: "af"; MessagesFile: "{#Get('Afrikaans.isl')}"
Name: "ar"; MessagesFile: "{#Get('Arabic.isl')}"
Name: "be"; MessagesFile: "{#Get('Belarusian.isl')}"
Name: "bg"; MessagesFile: "{#Get('Bulgarian.isl')}"
Name: "bg"; MessagesFile: "compiler:Languages\Bulgarian.isl"
Name: "bn"; MessagesFile: "{#Get('Bengali.islu')}"
Name: "bs"; MessagesFile: "{#Get('Bosnian.isl')}"
Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl"
@ -258,7 +241,7 @@ Name: "cs"; MessagesFile: "compiler:Languages\Czech.isl"
Name: "cy"; MessagesFile: "{#Dummy('Welsh', '0452')}"
Name: "da"; MessagesFile: "compiler:Languages\Danish.isl"
Name: "de"; MessagesFile: "compiler:Languages\German.isl"
Name: "el"; MessagesFile: "compiler:Languages\Greek.isl"
Name: "el"; MessagesFile: "{#Get('Greek.isl')}"
Name: "en"; MessagesFile: "compiler:Default.isl"
Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
Name: "eu"; MessagesFile: "{#Get('Basque.isl')}"
@ -270,19 +253,19 @@ Name: "gl"; MessagesFile: "{#Get('Galician.isl')}"
Name: "he"; MessagesFile: "compiler:Languages\Hebrew.isl"
Name: "hi"; MessagesFile: "{#Get('Hindi.islu')}"
Name: "hr"; MessagesFile: "{#Get('Croatian.isl')}"
Name: "hu"; MessagesFile: "compiler:Languages\Hungarian.isl"
Name: "hy"; MessagesFile: "compiler:Languages\Armenian.islu"
Name: "hu"; MessagesFile: "{#Get('Hungarian.isl')}"
Name: "hy"; MessagesFile: "compiler:Languages\Armenian.isl"
Name: "id"; MessagesFile: "{#Get('Indonesian.isl')}"
Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl"
Name: "ka"; MessagesFile: "{#Get('Georgian.islu')}"
Name: "ka"; MessagesFile: "{#Get('Georgian.isl')}"
Name: "km"; MessagesFile: "{#Dummy('Khmer', '0409')}"
Name: "ko"; MessagesFile: "{#Dummy('Korean', '0412')}"
Name: "lt"; MessagesFile: "{#Get('Lithuanian.isl')}"
Name: "mk"; MessagesFile: "{#Get('Macedonian.isl')}"
Name: "my"; MessagesFile: "{#Dummy('Burmese', '0409')}"
Name: "nb"; MessagesFile: "compiler:Languages\Norwegian.isl"
;Name: "ne"; MessagesFile: "compiler:Languages\Nepali.islu"
Name: "ne"; MessagesFile: "{#Get('Nepali.islu')}"
Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
Name: "oc"; MessagesFile: "{#Get('Occitan.isl')}"
Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl"
@ -290,16 +273,16 @@ Name: "pt_PT"; MessagesFile: "compiler:Languages\Portuguese.isl"
Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl"
Name: "ro"; MessagesFile: "{#Get('Romanian.isl')}"
Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
Name: "sk"; MessagesFile: "{#Get('Slovak.isl')}"
Name: "sk"; MessagesFile: "compiler:Languages\Slovak.isl"
Name: "sl"; MessagesFile: "compiler:Languages\Slovenian.isl"
Name: "sr_RS"; MessagesFile: "compiler:Languages\SerbianCyrillic.isl"
Name: "sr_RS0latin"; MessagesFile: "compiler:Languages\SerbianLatin.isl"
Name: "sr_RS"; MessagesFile: "{#Get('SerbianCyrillic.isl')}"
Name: "sr_RS0latin"; MessagesFile: "{#Get('SerbianLatin.isl')}"
Name: "sv"; MessagesFile: "{#Get('Swedish.isl')}"
Name: "ta"; MessagesFile: "{#Dummy('Tamil', '0449')}"
Name: "tg"; MessagesFile: "{#Dummy('Tajik', '0428')}"
Name: "tr"; MessagesFile: "compiler:Languages\Turkish.isl"
Name: "uk"; MessagesFile: "compiler:Languages\Ukrainian.isl"
;Name: "vi"; MessagesFile: "{#Get('Vietnamese.islu')}"
Name: "vi"; MessagesFile: "{#Get('Vietnamese.isl')}"
Name: "zh_CN"; MessagesFile: "{#Get('ChineseSimplified.isl')}"
Name: "zh_TW"; MessagesFile: "{#Get('ChineseTraditional.isl')}"
@ -361,7 +344,7 @@ lt.ResetPrefs=Reset Preferences
mk.ResetPrefs=Reset Preferences
my.ResetPrefs=Reset Preferences
nb.ResetPrefs=Reset Preferences
;ne.ResetPrefs=Reset Preferences
ne.ResetPrefs=Reset Preferences
nl.ResetPrefs=Voorkeuren herstellen?
oc.ResetPrefs=Reset Preferences
pl.ResetPrefs=Zresetować ustawienia?
Loading…
Cancel
Save