mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-12-04 15:39:34 +01:00
Integrate macOS code signing into CMake
Moves code signing from the release-tool to CMake and unifies the Windows-equivalent code.
This commit is contained in:
committed by
Jonathan White
parent
c09ba0113b
commit
4e59c1c579
@@ -36,7 +36,7 @@ find_library(
|
||||
NAMES ${BOTAN_NAMES}
|
||||
PATH_SUFFIXES release/lib lib
|
||||
DOC "The Botan (release) library")
|
||||
if(MSVC)
|
||||
if(WIN32 AND NOT MINGW)
|
||||
find_library(
|
||||
BOTAN_LIBRARY_DEBUG
|
||||
NAMES ${BOTAN_NAMES_DEBUG}
|
||||
@@ -55,7 +55,7 @@ endif()
|
||||
|
||||
if(BOTAN_FOUND)
|
||||
set(BOTAN_INCLUDE_DIRS ${BOTAN_INCLUDE_DIR})
|
||||
if(MSVC)
|
||||
if(WIN32 AND NOT MINGW)
|
||||
set(BOTAN_LIBRARIES optimized ${BOTAN_LIBRARY} debug ${BOTAN_LIBRARY_DEBUG})
|
||||
else()
|
||||
set(BOTAN_LIBRARIES ${BOTAN_LIBRARY})
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
find_path(QRENCODE_INCLUDE_DIR NAMES qrencode.h)
|
||||
|
||||
if(WIN32 AND MSVC)
|
||||
if(WIN32 AND NOT MINGW)
|
||||
find_library(QRENCODE_LIBRARY_RELEASE qrencode)
|
||||
find_library(QRENCODE_LIBRARY_DEBUG qrencoded)
|
||||
set(QRENCODE_LIBRARY optimized ${QRENCODE_LIBRARY_RELEASE} debug ${QRENCODE_LIBRARY_DEBUG})
|
||||
|
||||
102
cmake/MacOSCodesign.cmake.in
Normal file
102
cmake/MacOSCodesign.cmake.in
Normal file
@@ -0,0 +1,102 @@
|
||||
# Copyright (C) 2025 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# 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 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# CPACK_PACKAGE_FILES is set only during POST_BUILD
|
||||
if(NOT CPACK_PACKAGE_FILES) # PRE_BUILD: Sign binaries
|
||||
|
||||
set(PROGNAME "@PROGNAME@")
|
||||
set(CODESIGN_IDENTITY "@WITH_XC_CODESIGN_IDENTITY@")
|
||||
set(ENTITLEMENTS @MACOSX_BUNDLE_APPLE_ENTITLEMENTS@)
|
||||
set(APP_DIR "${CPACK_TEMPORARY_INSTALL_DIRECTORY}/ALL_IN_ONE/${PROGNAME}.app")
|
||||
|
||||
if(NOT CODESIGN_IDENTITY)
|
||||
message(FATAL_ERROR "No codesign identity specified.")
|
||||
endif()
|
||||
|
||||
message(STATUS "Codesign identity used: ${CODESIGN_IDENTITY}")
|
||||
message(STATUS "Signing ${PROGNAME}.app, this may take while...")
|
||||
|
||||
# Sign all binaries
|
||||
execute_process(
|
||||
COMMAND xcrun codesign --sign=${CODESIGN_IDENTITY} --force --options=runtime --deep ${APP_DIR}
|
||||
RESULT_VARIABLE SIGN_RESULT
|
||||
OUTPUT_VARIABLE SIGN_OUTPUT
|
||||
ERROR_VARIABLE SIGN_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if (NOT SIGN_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Signing binaries failed: ${SIGN_ERROR}")
|
||||
endif()
|
||||
|
||||
# (Re-)Sign main executable with --entitlements
|
||||
execute_process(
|
||||
COMMAND xcrun codesign --sign=${CODESIGN_IDENTITY} --force --options=runtime --deep --entitlements=${ENTITLEMENTS} ${APP_DIR}
|
||||
RESULT_VARIABLE SIGN_RESULT
|
||||
OUTPUT_VARIABLE SIGN_OUTPUT
|
||||
ERROR_VARIABLE SIGN_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if (NOT SIGN_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Signing main binary failed: ${SIGN_ERROR}")
|
||||
endif()
|
||||
|
||||
message(STATUS "${PROGNAME}.app signed successfully.")
|
||||
|
||||
else() # POST_BUILD: Notarize DMG
|
||||
set(KEYCHAIN_PROFILE "@WITH_XC_NOTARY_KEYCHAIN_PROFILE@")
|
||||
file(GLOB_RECURSE DMG_FILE "${CPACK_PACKAGE_DIRECTORY}/${CPACK_PACKAGE_FILE_NAME}.dmg")
|
||||
|
||||
if(NOT KEYCHAIN_PROFILE)
|
||||
message(FATAL_ERROR "No notarization credentials keychain profile specified.")
|
||||
endif()
|
||||
|
||||
# Submit for notarization
|
||||
message(STATUS "Submitting DMG bundle for notarization, this may take while...")
|
||||
execute_process(
|
||||
COMMAND xcrun notarytool submit --keychain-profile=${KEYCHAIN_PROFILE} --wait ${DMG_FILE}
|
||||
RESULT_VARIABLE NOTARIZE_RESULT
|
||||
OUTPUT_VARIABLE NOTARIZE_OUTPUT
|
||||
ERROR_VARIABLE NOTARIZE_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if (NOT NOTARIZE_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Notarization failed: ${NOTARIZE_ERROR}")
|
||||
endif()
|
||||
message(STATUS "DMG bundle notarized successfully.")
|
||||
|
||||
# Staple tickets
|
||||
message(STATUS "Stapling notarization ticket...")
|
||||
execute_process(
|
||||
COMMAND xcrun stapler staple ${DMG_FILE} && xcrun stapler validate ${DMG_FILE}
|
||||
RESULT_VARIABLE STAPLE_RESULT
|
||||
OUTPUT_VARIABLE STAPLE_OUTPUT
|
||||
ERROR_VARIABLE STAPLE_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if (NOT STAPLE_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Stapling failed: ${STAPLE_ERROR}")
|
||||
endif()
|
||||
message(STATUS "DMG bundle notarization ticket stapled successfully.")
|
||||
|
||||
endif()
|
||||
79
cmake/WindowsCodesign.cmake.in
Normal file
79
cmake/WindowsCodesign.cmake.in
Normal file
@@ -0,0 +1,79 @@
|
||||
# Copyright (C) 2025 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# 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 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(INSTALL_DIR ${CPACK_TEMPORARY_INSTALL_DIRECTORY})
|
||||
set(CODESIGN_IDENTITY @WITH_XC_CODESIGN_IDENTITY@)
|
||||
set(TIMESTAMP_URL @WITH_XC_CODESIGN_TIMESTAMP_URL@)
|
||||
|
||||
if(CPACK_PACKAGE_FILES)
|
||||
# This variable is set only during POST_BUILD, reset SIGN_FILES first
|
||||
set(SIGN_FILES "")
|
||||
foreach(PACKAGE_FILE ${CPACK_PACKAGE_FILES})
|
||||
# Check each package file to see if it can be signed
|
||||
if(PACKAGE_FILE MATCHES "\\.msix?$" OR PACKAGE_FILE MATCHES "\\.exe$")
|
||||
message(STATUS "Adding ${PACKAGE_FILE} for signature")
|
||||
list(APPEND SIGN_FILES "${PACKAGE_FILE}")
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
# Setup portable zip file if building one
|
||||
if(INSTALL_DIR MATCHES "/ZIP/")
|
||||
file(TOUCH "${INSTALL_DIR}/.portable")
|
||||
message(STATUS "Injected portable marker into ZIP file.")
|
||||
endif()
|
||||
|
||||
# Find all dll and exe files in the install directory
|
||||
file(GLOB_RECURSE SIGN_FILES
|
||||
RELATIVE "${INSTALL_DIR}"
|
||||
"${INSTALL_DIR}/*.dll"
|
||||
"${INSTALL_DIR}/*.exe"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Sign relevant binaries if requested
|
||||
if(CODESIGN_IDENTITY AND SIGN_FILES)
|
||||
# Find signtool in PATH or error out
|
||||
find_program(SIGNTOOL signtool.exe QUIET)
|
||||
if(NOT SIGNTOOL)
|
||||
message(FATAL_ERROR "signtool.exe not found in PATH, correct or unset WITH_XC_CODESIGN_IDENTITY")
|
||||
endif()
|
||||
|
||||
# Check that a certificate thumbprint was provided or error out
|
||||
if(CODESIGN_IDENTITY STREQUAL "auto")
|
||||
message(STATUS "Signing using best available certificate.")
|
||||
set(CERT_OPTS /a)
|
||||
else ()
|
||||
message(STATUS "Signing using certificate with fingerprint ${CODESIGN_IDENTITY}.")
|
||||
set(CERT_OPTS /sha1 ${CODESIGN_IDENTITY})
|
||||
endif()
|
||||
|
||||
message(STATUS "Signing binary files, this may take a while...")
|
||||
# Use cmd /c to enable pop-up for pin entry if needed
|
||||
execute_process(
|
||||
COMMAND cmd /c ${SIGNTOOL} sign /fd SHA256 ${CERT_OPTS} /tr ${TIMESTAMP_URL} /td SHA256 /d ${CPACK_PACKAGE_FILE_NAME} ${SIGN_FILES}
|
||||
WORKING_DIRECTORY "${INSTALL_DIR}"
|
||||
RESULT_VARIABLE SIGN_RESULT
|
||||
OUTPUT_VARIABLE SIGN_OUTPUT
|
||||
ERROR_VARIABLE SIGN_ERROR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if(NOT SIGN_RESULT EQUAL 0)
|
||||
message(FATAL_ERROR "Signing binary files failed: ${SIGN_ERROR}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Binary files signed successfully.")
|
||||
endif()
|
||||
@@ -1,71 +0,0 @@
|
||||
# Copyright (C) 2025 KeePassXC Team <team@keepassxc.org>
|
||||
#
|
||||
# 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 or (at your option)
|
||||
# version 3 of the License.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(_installdir ${CPACK_TEMPORARY_INSTALL_DIRECTORY})
|
||||
set(_sign @WITH_XC_SIGNINSTALL@)
|
||||
set(_cert_thumbprint @WITH_XC_SIGNINSTALL_CERT@)
|
||||
set(_timestamp_url @WITH_XC_SIGNINSTALL_TIMESTAMP_URL@)
|
||||
|
||||
# Setup portable zip file if building one
|
||||
if(_installdir MATCHES "/ZIP/")
|
||||
file(TOUCH "${_installdir}/.portable")
|
||||
message(STATUS "Injected portable zip file.")
|
||||
endif()
|
||||
|
||||
# Find all dll and exe files in the install directory
|
||||
file(GLOB_RECURSE _sign_files
|
||||
RELATIVE "${_installdir}"
|
||||
"${_installdir}/*.dll"
|
||||
"${_installdir}/*.exe"
|
||||
)
|
||||
|
||||
# Sign relevant binaries if requested
|
||||
if(_sign AND _sign_files)
|
||||
# Find signtool in PATH or error out
|
||||
find_program(_signtool signtool.exe QUIET)
|
||||
if(NOT _signtool)
|
||||
message(FATAL_ERROR "signtool.exe not found in PATH, correct or unset WITH_XC_SIGNINSTALL")
|
||||
endif()
|
||||
|
||||
# Set a default timestamp URL if none was provided
|
||||
if (NOT _timestamp_url)
|
||||
set(_timestamp_url "http://timestamp.sectigo.com")
|
||||
endif()
|
||||
|
||||
# Check that a certificate thumbprint was provided or error out
|
||||
if (NOT _cert_thumbprint)
|
||||
message(STATUS "Signing using best available certificate.")
|
||||
set(_certopt /a)
|
||||
else()
|
||||
message(STATUS "Signing using certificate with thumbprint ${_cert_thumbprint}.")
|
||||
set(_certopt /sha1 ${_cert_thumbprint})
|
||||
endif()
|
||||
|
||||
message(STATUS "Signing binary files with signtool, this may take a while...")
|
||||
# Use cmd /c to enable pop-up for pin entry if needed
|
||||
execute_process(
|
||||
COMMAND cmd /c ${_signtool} sign /fd SHA256 ${_certopt} /tr ${_timestamp_url} /td SHA256 ${_sign_files}
|
||||
WORKING_DIRECTORY "${_installdir}"
|
||||
RESULT_VARIABLE sign_result
|
||||
OUTPUT_VARIABLE sign_output
|
||||
ERROR_VARIABLE sign_error
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_STRIP_TRAILING_WHITESPACE
|
||||
ECHO_OUTPUT_VARIABLE
|
||||
)
|
||||
if (NOT sign_result EQUAL 0)
|
||||
message(FATAL_ERROR "signtool failed: ${sign_error}")
|
||||
endif()
|
||||
endif()
|
||||
Reference in New Issue
Block a user