Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions .github/workflows/macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,40 +82,43 @@ jobs:
modules: qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors
cache: true

- name: Import Code Signing Certificate
if: github.event_name != 'pull_request'
uses: apple-actions/import-codesign-certs@v5
with:
p12-file-base64: ${{ secrets.MACOS_SIGNING_CERTS_P12 }}
p12-password: ${{ secrets.MACOS_SIGNING_CERTS_PASS }}

- name: Configure
- name: CMake configure
working-directory: ${{ runner.temp }}/shadow_build_dir
run: ${{ env.QT_ROOT_DIR }}/bin/qt-cmake -S ${{ github.workspace }} -B . -G Ninja
-DCMAKE_BUILD_TYPE=${{ matrix.BuildType }}
-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
-DQGC_STABLE_BUILD=${{ github.ref_type == 'tag' || contains(github.ref, 'Stable') && 'ON' || 'OFF' }}
-DQGC_MACOS_SIGN_WITH_IDENTITY=${{ github.event_name != 'pull_request' && 'ON' || 'OFF' }}

- name: Build
working-directory: ${{ runner.temp }}/shadow_build_dir
run: cmake --build . --target all --config ${{ matrix.BuildType }}

- name: Sanity check dev build excecutable
if: matrix.BuildType == 'Release'
- name: Sanity check dev build executable
working-directory: ${{ runner.temp }}/shadow_build_dir/Release/QGroundControl.app/Contents/MacOS
run: ./QGroundControl --simple-boot-test

- name: Create DMG
- name: Import Code Signing Certificate
if: github.event_name != 'pull_request'
uses: apple-actions/import-codesign-certs@v5
with:
p12-file-base64: ${{ secrets.MACOS_CERT_P12_BASE64 }}
p12-password: ${{ secrets.MACOS_CERT_P12_PASSWORD }}

- name: Create signed/notarized/stapled app bundle
working-directory: ${{ runner.temp }}/shadow_build_dir
run: cmake --install . --config ${{ matrix.BuildType }}
env:
QGC_MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }}
QGC_MACOS_NOTARIZATION_USERNAME: ${{ secrets.MACOS_NOTARIZATION_USERNAME }}
QGC_MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
QGC_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }}

- name: Mount DMG
if: matrix.BuildType == 'Release'
working-directory: ${{ runner.temp }}/shadow_build_dir
run: hdiutil attach QGroundControl.dmg

- name: Sanity check DMG exectuable
if: matrix.BuildType == 'Release'
- name: Sanity check DMG executable
working-directory: /Volumes/QGroundControl/QGroundControl.app/Contents/MacOS
run: ./QGroundControl --simple-boot-test

Expand Down
6 changes: 0 additions & 6 deletions cmake/CreateMacDMG.cmake
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@

set(STAGING_BUNDLE_PATH ${CMAKE_BINARY_DIR}/staging/${TARGET_APP_NAME}.app)

message(STATUS "Signing bundle: ${STAGING_BUNDLE_PATH}")
execute_process(
COMMAND codesign --force --deep -s - "${STAGING_BUNDLE_PATH}"
COMMAND_ERROR_IS_FATAL ANY
)

file(REMOVE_RECURSE ${CMAKE_BINARY_DIR}/package)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/package)
file(COPY ${STAGING_BUNDLE_PATH} DESTINATION ${CMAKE_BINARY_DIR}/package)
Expand Down
20 changes: 17 additions & 3 deletions cmake/Install.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ install(
set(deploy_tool_options_arg "")
if(MACOS OR WIN32)
set(deploy_tool_options_arg "-qmldir=${CMAKE_SOURCE_DIR}")
if(MACOS_SIGNING_IDENTITY)
message(STATUS "Signing MacOS Bundle")
set(deploy_tool_options_arg "${deplay_tool_options_arg} -sign-for-notarization=${MACOS_SIGNING_IDENTITY}")
if(MACOS)
list(APPEND deploy_tool_options_arg "-appstore-compliant")
endif()
endif()

Expand Down Expand Up @@ -75,6 +74,21 @@ elseif(WIN32)
install(CODE "set(QGC_WINDOWS_INSTALLER_SCRIPT ${CMAKE_SOURCE_DIR}/deploy/windows/nullsoft_installer.nsi)")
install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/CreateWinInstaller.cmake")
elseif(MACOS)
install(CODE "set(QGC_STAGING_BUNDLE_PATH \"${CMAKE_BINARY_DIR}/staging/${CMAKE_PROJECT_NAME}.app\")")
if(QGC_MACOS_SIGN_WITH_IDENTITY)
message(STATUS "QGC: Signing Bundle using signing identity")
install(SCRIPT "${CMAKE_SOURCE_DIR}/cmake/SignMacBundle.cmake")
else()
message(STATUS "QGC: Signing Bundle using Ad-Hoc signing")
install(CODE "
message(STATUS \"QGC: Signing Bundle using Ad-Hoc signing\")
execute_process(
COMMAND codesign --force --deep -s - \"\${QGC_STAGING_BUNDLE_PATH}\"
COMMAND_ERROR_IS_FATAL ANY
)
")
endif()

install(CODE "set(TARGET_APP_NAME ${QGC_APP_NAME})")
find_program(CREATE_DMG_PROGRAM create-dmg)
if(NOT CREATE_DMG_PROGRAM)
Expand Down
70 changes: 70 additions & 0 deletions cmake/SignMacBundle.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
message(STATUS "QGC: Signing Bundle using signing identity")
if(NOT DEFINED ENV{QGC_MACOS_SIGNING_IDENTITY} OR "$ENV{QGC_MACOS_SIGNING_IDENTITY}" STREQUAL "")
message(FATAL_ERROR "QGC: QGC_MACOS_SIGNING_IDENTITY environment variable must be set to sign MacOS bundle")
endif()
if(NOT DEFINED ENV{QGC_MACOS_NOTARIZATION_USERNAME} OR "$ENV{QGC_MACOS_NOTARIZATION_USERNAME}" STREQUAL "")
message(FATAL_ERROR "QGC: QGC_MACOS_NOTARIZATION_USERNAME environment variable must be set to notarize MacOS bundle")
endif()
if(NOT DEFINED ENV{QGC_MACOS_NOTARIZATION_TEAM_ID} OR "$ENV{QGC_MACOS_NOTARIZATION_TEAM_ID}" STREQUAL "")
message(FATAL_ERROR "QGC: QGC_MACOS_NOTARIZATION_TEAM_ID environment variable must be set to notarize MacOS bundle")
endif()
if(NOT DEFINED ENV{QGC_MACOS_NOTARIZATION_PASSWORD} OR "$ENV{QGC_MACOS_NOTARIZATION_PASSWORD}" STREQUAL "")
message(FATAL_ERROR "QGC: QGC_MACOS_NOTARIZATION_PASSWORD environment variable must be set to notarize MacOS bundle")
endif()
file(REMOVE ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/GStreamer.framework/Commands)
file(REMOVE ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/GStreamer.framework/Versions/1.0/Commands)
execute_process(
COMMAND find ${QGC_STAGING_BUNDLE_PATH}/Contents -type f -name "*.dylib" -exec codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" "{}" \\;
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND find ${QGC_STAGING_BUNDLE_PATH}/Contents -type f -name "*.so" -exec codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" "{}" \\;
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND find ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/GStreamer.framework/Versions/1.0/libexec/gstreamer-1.0 -type f -name "*" -exec codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" "{}" \\;
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/GStreamer.framework/Versions/1.0/lib/GStreamer
COMMAND_ERROR_IS_FATAL ANY
)
execute_process(
COMMAND codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/GStreamer.framework/Versions/1.0/GStreamer
COMMAND_ERROR_IS_FATAL ANY
)
file(GLOB FRAMEWORK_DIRS ${QGC_STAGING_BUNDLE_PATH}/Contents/Frameworks/*.framework)
foreach(FRAMEWORK_DIR ${FRAMEWORK_DIRS})
if (EXISTS "${FRAMEWORK_DIR}/Versions/1.0")
execute_process(
COMMAND find ${FRAMEWORK_DIR}/Versions/1.0 -type f -exec codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" "{}" \\;
COMMAND_ERROR_IS_FATAL ANY
)
endif()
if (EXISTS "${FRAMEWORK_DIR}/Versions/A")
execute_process(
COMMAND find ${FRAMEWORK_DIR}/Versions/A -type f -exec codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" "{}" \\;
COMMAND_ERROR_IS_FATAL ANY
)
endif()
endforeach()
execute_process(
COMMAND codesign --timestamp --options=runtime --force -s "$ENV{QGC_MACOS_SIGNING_IDENTITY}" ${QGC_STAGING_BUNDLE_PATH}
COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "QGC: Archiving Bundle for Notarization upload")
file(REMOVE qgc_notarization_upload.zip)
execute_process(
COMMAND ditto -c -k --keepParent ${QGC_STAGING_BUNDLE_PATH} qgc_notarization_upload.zip
COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "QGC: Notarizing app bundle. This may take a while...")
execute_process(
COMMAND xcrun notarytool submit qgc_notarization_upload.zip --apple-id "$ENV{QGC_MACOS_NOTARIZATION_USERNAME}" --team-id "$ENV{QGC_MACOS_NOTARIZATION_TEAM_ID}" --password "$ENV{QGC_MACOS_NOTARIZATION_PASSWORD}" --wait
COMMAND_ERROR_IS_FATAL ANY
)
message(STATUS "QGC: Stapling notarization ticket to app bundle")
execute_process(
COMMAND xcrun stapler staple ${QGC_STAGING_BUNDLE_PATH}
COMMAND_ERROR_IS_FATAL ANY
)
7 changes: 7 additions & 0 deletions docs/en/qgc-dev-guide/getting_started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ Example commands to build a default QGC and run it afterwards:
```

Change the directory for qt-cmake to match your install location for Qt and the kit you want to use.

**Mac**: To Sign/Notarize/Staple the QGC app bundle, add `-DQGC_MACOS_SIGN_WITH_IDENTITY=ON` to the configure command line. During the `install` phase the following environment variables will need to be available:

* `QGC_MACOS_SIGNING_IDENTITY` - Signing identity for your Developer ID certificate which must be in the keychain
* `QGC_MACOS_NOTARIZATION_USERNAME` - Username for your Apple Developer Account
* `QGC_MACOS_NOTARIZATION_PASSWORD` - App specific password for Notarization from your Apple Developer Account
* `QGC_MACOS_NOTARIZATION_TEAM_ID` - Apple Developer Account Team ID

1. Build

Expand Down
Loading