shithub: m8c

Download patch

ref: 7d592e540aac1269cf52d458f807caf8e7484bf5
parent: 015637c0756837916374968c491df411ee5ddb9a
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Sat Apr 19 20:21:21 EDT 2025

Refactor CMakelists, automate MacOS code signing & notarization (#194)


--- a/.github/workflows/build-macos-arm.yml
+++ b/.github/workflows/build-macos-arm.yml
@@ -9,6 +9,9 @@
      
   build-macos:
     runs-on: macos-latest
+    name: m8c MacOS build (Apple Silicon)
+    env:
+      BUILD_DIR: build-arm64
     
     steps:
       - name: 'Environment info'
@@ -16,7 +19,7 @@
           uname -m
     
       - name: 'Install dependencies'
-        run: brew update && brew install cmake pkg-config sdl3 libserialport
+        run: brew install cmake pkg-config sdl3 libserialport
           
       - name: 'Checkout'
         uses: actions/checkout@v4
@@ -23,21 +26,86 @@
 
       - name: Set current date as env variable
         run: echo "NOW=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
-        
-      - name: 'Build m8c'
+
+      - name: Create Custom Keychain
+        id: createCustomKeychain
+        env:
+          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
+        run: |
+          security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+          security list-keychains -s build.keychain
+          security default-keychain -s build.keychain
+          security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+          security set-keychain-settings build.keychain      
+
+      - name: Import Apple Developer Certificate
+        env:
+          CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
+          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
+        run: |
+          echo "${{ secrets.MACOS_CERTIFICATE }}" | base64 --decode > developer_cert.p12
+          security import developer_cert.p12 -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
+          security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain
+
+      - name: 'Configure m8c'
+        id: configureApplication
+        run: |
+          mkdir -p ${{ env.BUILD_DIR }}
+          pushd ${{ env.BUILD_DIR }}
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DCODESIGN_CERT_NAME="$CODESIGN_CERT_NAME"
+          popd
+        env:
+          CODESIGN_CERT_NAME: ${{ secrets.MACOS_CODE_SIGN_IDENTITY }}
+
+      - name: 'Build and package m8c'
         id: buildApplication
         continue-on-error: true
         run: |
-          mkdir -p build_arm64 && cd build_arm64 && cmake .. -DCMAKE_BUILD_TYPE=Release && cpack -V
+          pushd ${{ env.BUILD_DIR }}
+          cpack -V .
+          popd
+        env:
+          CMAKE_INSTALL_PREFIX: build_output
 
       - name: 'View debug log if compilation fails'
         if: failure() && steps.buildApplication.outcome == 'failure'
-        run: cat /Users/runner/work/m8c/m8c/build_arm64/_CPack_Packages/Darwin/DragNDrop/PreinstallOutput.log
+        run: cat /Users/runner/work/m8c/m8c/${{ env.BUILD_DIR }}/_CPack_Packages/Darwin/DragNDrop/PreinstallOutput.log
 
-      - name: 'Build package'
+      - name: 'Notarize the App'
         run: |
-          mv build_arm64/m8c-0.1.1-Darwin.dmg m8c-${{ env.NOW }}-macos-applesilicon.dmg
-      - name: 'Upload artifact'
+          pushd ${{ env.BUILD_DIR }}
+          APP_PATH=$(find package-output -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          xcrun notarytool submit \
+            --apple-id "$APPLE_ID" \
+            --team-id "$TEAM_ID" \
+            --password "$APPLE_PASSWORD" \
+            --wait \
+            $APP_PATH
+          xcrun stapler staple "$APP_PATH"
+          popd
+        env:
+          APPLE_ID: ${{ secrets.APPLE_ID }}
+          APPLE_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
+          TEAM_ID: ${{ secrets.TEAM_ID }}
+
+
+      - name: 'Verify Stapling'
+        run: |
+          APP_PATH=$(find "${{ env.BUILD_DIR }}/package-output" -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          echo "Verifying stapling on $APP_PATH"
+          xcrun stapler validate "$APP_PATH"        
+
+      - name: 'Delete Custom Keychain'
+        if: steps.createCustomKeychain.outcome == 'success'
+        run: |
+          security delete-keychain build.keychain        
+
+      - name: 'Copy package'
+        run: |
+          APP_PATH=$(find "${{ env.BUILD_DIR }}/package-output" -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          mv "$APP_PATH" m8c-${{ env.NOW }}-macos-applesilicon.dmg
+
+      - name: 'Upload DMG package'
         uses: actions/upload-artifact@v4
         with:
           name: m8c-${{ env.NOW }}-macos-applesilicon
--- a/.github/workflows/build-macos-intel.yml
+++ b/.github/workflows/build-macos-intel.yml
@@ -1,4 +1,4 @@
-name: m8c macos intel build 
+name: m8c macos intel build
 
 on:
   push:
@@ -8,12 +8,19 @@
 jobs:
      
   build-macos:
-    runs-on: macos-13
-
+    runs-on: macos-latest
+    name: m8c MacOS build (Intel)
+    env:
+      BUILD_DIR: build-intel
+    
     steps:
+      - name: 'Environment info'
+        run: |
+          uname -m
+    
       - name: 'Install dependencies'
-        run: brew update && brew install cmake pkg-config sdl3 libserialport
-
+        run: brew install cmake pkg-config sdl3 libserialport
+          
       - name: 'Checkout'
         uses: actions/checkout@v4
 
@@ -20,20 +27,85 @@
       - name: Set current date as env variable
         run: echo "NOW=$(date +'%Y-%m-%d')" >> $GITHUB_ENV
 
-      - name: 'Build m8c'
+      - name: Create Custom Keychain
+        id: createCustomKeychain
+        env:
+          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
+        run: |
+          security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+          security list-keychains -s build.keychain
+          security default-keychain -s build.keychain
+          security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
+          security set-keychain-settings build.keychain      
+
+      - name: Import Apple Developer Certificate
+        env:
+          CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
+          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
+        run: |
+          echo "${{ secrets.MACOS_CERTIFICATE }}" | base64 --decode > developer_cert.p12
+          security import developer_cert.p12 -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign
+          security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain
+
+      - name: 'Configure m8c'
+        id: configureApplication
+        run: |
+          mkdir -p ${{ env.BUILD_DIR }}
+          pushd ${{ env.BUILD_DIR }}
+          cmake .. -DCMAKE_BUILD_TYPE=Release -DCODESIGN_CERT_NAME="$CODESIGN_CERT_NAME"
+          popd
+        env:
+          CODESIGN_CERT_NAME: ${{ secrets.MACOS_CODE_SIGN_IDENTITY }}
+
+      - name: 'Build and package m8c'
         id: buildApplication
         continue-on-error: true
         run: |
-          mkdir -p build_x86_64 && cd build_x86_64 && cmake .. -DCMAKE_BUILD_TYPE=Release && cpack -V
+          pushd ${{ env.BUILD_DIR }}
+          cpack -V .
+          popd
+        env:
+          CMAKE_INSTALL_PREFIX: build_output
 
       - name: 'View debug log if compilation fails'
         if: failure() && steps.buildApplication.outcome == 'failure'
-        run: cat /Users/runner/work/m8c/m8c/build_x86_64/_CPack_Packages/Darwin/DragNDrop/PreinstallOutput.log
+        run: cat /Users/runner/work/m8c/m8c/${{ env.BUILD_DIR }}/_CPack_Packages/Darwin/DragNDrop/PreinstallOutput.log
 
-      - name: 'Build package'
+      - name: 'Notarize the App'
         run: |
-          mv build_x86_64/m8c-0.1.1-Darwin.dmg m8c-${{ env.NOW }}-macos-intel.dmg
-      - name: 'Upload artifact'
+          pushd ${{ env.BUILD_DIR }}
+          APP_PATH=$(find package-output -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          xcrun notarytool submit \
+            --apple-id "$APPLE_ID" \
+            --team-id "$TEAM_ID" \
+            --password "$APPLE_PASSWORD" \
+            --wait \
+            $APP_PATH
+          xcrun stapler staple "$APP_PATH"
+          popd
+        env:
+          APPLE_ID: ${{ secrets.APPLE_ID }}
+          APPLE_PASSWORD: ${{ secrets.APP_SPECIFIC_PASSWORD }}
+          TEAM_ID: ${{ secrets.TEAM_ID }}
+
+
+      - name: 'Verify Stapling'
+        run: |
+          APP_PATH=$(find "${{ env.BUILD_DIR }}/package-output" -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          echo "Verifying stapling on $APP_PATH"
+          xcrun stapler validate "$APP_PATH"        
+
+      - name: 'Delete Custom Keychain'
+        if: steps.createCustomKeychain.outcome == 'success'
+        run: |
+          security delete-keychain build.keychain        
+
+      - name: 'Copy package'
+        run: |
+          APP_PATH=$(find "${{ env.BUILD_DIR }}/package-output" -maxdepth 1 -name "m8c*.dmg" | head -n 1)
+          mv "$APP_PATH" m8c-${{ env.NOW }}-macos-intel.dmg
+
+      - name: 'Upload DMG package'
         uses: actions/upload-artifact@v4
         with:
           name: m8c-${{ env.NOW }}-macos-intel
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,62 +1,64 @@
-cmake_minimum_required(VERSION 3.15)
+cmake_minimum_required(VERSION 3.20)
 
-project(m8c LANGUAGES C)
+project(m8c LANGUAGES C VERSION 2.0.0)
 
 set(APP_NAME m8c)
 
-if (NOT DEFINED USE_LIBSERIALPORT AND NOT DEFINED USE_LIBUSB AND NOT DEFINED USE_RTMIDI)
-    set(USE_LIBSERIALPORT 1)
-endif ()
+option(USE_LIBSERIALPORT "Use libserialport as a backend" ON)
+option(USE_LIBUSB "Use libusb as a backend" OFF)
+option(USE_RTMIDI "Use RtMidi as a backend" OFF)
 
-find_package(PkgConfig REQUIRED)
-find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
-
-pkg_check_modules(SDL3 REQUIRED sdl3)
-if (USE_LIBSERIALPORT)
-    pkg_check_modules(LIBSERIALPORT REQUIRED libserialport)
-    link_directories(${SDL3_LIBRARY_DIRS} ${LIBSERIALPORT_LIBRARY_DIRS})
-    add_compile_definitions(USE_LIBSERIALPORT)
-endif (USE_LIBSERIALPORT)
-if (USE_LIBUSB)
-    pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
-    link_directories(${SDL3_LIBRARY_DIRS} ${LIBUSB_LIBRARY_DIRS})
-    add_compile_definitions(USE_LIBUSB)
-endif (USE_LIBUSB)
-if (USE_RTMIDI)
-    pkg_check_modules(RTMIDI REQUIRED rtmidi)
-    link_directories(${SDL3_LIBRARY_DIRS} ${RTMIDI_LIBRARY_DIRS})
-    add_compile_definitions(USE_RTMIDI)
-endif (USE_RTMIDI)
-
-
 file(GLOB m8c_SRC "src/*.h" "src/*.c" "src/backends/*.h" "src/backends/*.c" "src/fonts/*.h")
 
 set(MACOS_CONTENTS "${CMAKE_CURRENT_SOURCE_DIR}/package/macos/m8c.app/Contents")
+set(MACOS_ENTITLEMENTS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/package/macos/Entitlements.plist")
 
 set(APP_ICON ${MACOS_CONTENTS}/Resources/m8c.icns)
 set_source_files_properties(${APP_ICON} PROPERTIES
         MACOSX_PACKAGE_LOCATION "Resources")
 
-add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE ${APP_ICON} ${m8c_SRC})
+if (APPLE)
+    add_executable(${APP_NAME} MACOSX_BUNDLE ${APP_ICON} ${m8c_SRC})
+elseif (WIN32)
+    add_executable(${APP_NAME} WIN32 ${m8c_SRC})
+else ()
+    add_executable(${APP_NAME} ${m8c_SRC})
+endif ()
 
+find_package(PkgConfig REQUIRED pkgconfig)
+pkg_check_modules(SDL3 REQUIRED SDL3)
+target_link_options(${APP_NAME} PRIVATE ${SDL3_LDFLAGS})
+target_include_directories(${APP_NAME} PRIVATE ${SDL3_INCLUDE_DIRS})
+target_compile_options(${APP_NAME} PRIVATE ${SDL3_CFLAGS_OTHER})
+
 if (USE_LIBSERIALPORT)
-    target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBSERIALPORT_LIBRARIES})
-    target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${LIBSERIALPORT_INCLUDE_DIRS})
-    target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${LIBSERIALPORT_CFLAGS_OTHER})
+    pkg_check_modules(LIBSERIALPORT REQUIRED libserialport)
+    target_link_options(${APP_NAME} PRIVATE ${LIBSERIALPORT_LDFLAGS})
+    target_include_directories(${APP_NAME} PRIVATE ${LIBSERIALPORT_INCLUDE_DIRS})
+    target_compile_options(${APP_NAME} PRIVATE ${LIBSERIALPORT_CFLAGS_OTHER})
+    target_compile_definitions(${APP_NAME} PRIVATE USE_LIBSERIALPORT)
 endif ()
 
 if (USE_LIBUSB)
-    target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBUSB_LIBRARIES})
-    target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${LIBUSB_INCLUDE_DIRS})
-    target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${LIBUSB_CFLAGS_OTHER})
+    pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
+    target_link_options(${APP_NAME} PRIVATE ${LIBUSB_LDFLAGS})
+    target_include_directories(${APP_NAME} PRIVATE ${LIBUSB_INCLUDE_DIRS})
+    target_compile_options(${APP_NAME} PRIVATE ${LIBUSB_CFLAGS_OTHER})
+    target_compile_definitions(${APP_NAME} PRIVATE USE_LIBUSB)
 endif ()
 
 if (USE_RTMIDI)
-    target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${RTMIDI_LIBRARIES})
-    target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${RTMIDI_INCLUDE_DIRS})
-    target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${RTMIDI_CFLAGS_OTHER})
+    pkg_check_modules(RTMIDI REQUIRED rtmidi)
+    target_link_options(${APP_NAME} PRIVATE ${RTMIDI_LDFLAGS})
+    target_include_directories(${APP_NAME} PRIVATE ${RTMIDI_INCLUDE_DIRS})
+    target_compile_options(${APP_NAME} PRIVATE ${RTMIDI_CFLAGS_OTHER})
+    target_compile_definitions(${APP_NAME} PRIVATE USE_RTMIDI)
 endif ()
 
+if (WIN32)
+target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBSERIALPORT_LIBRARIES})
+endif ()
+
 if (APPLE)
     # Destination paths below are relative to ${CMAKE_INSTALL_PREFIX}
     install(TARGETS ${APP_NAME}
@@ -64,21 +66,28 @@
             RUNTIME DESTINATION bin COMPONENT Runtime
     )
 
+    set(CODESIGN_CERT_NAME "" CACHE STRING "The developer ID cert name for codesign")
+
     set_target_properties(${APP_NAME} PROPERTIES
             MACOSX_BUNDLE TRUE
             MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/package/macos/m8c.app/Contents/Info.plist"
             MACOSX_BUNDLE_BUNDLE_NAME "m8c"
-            MACOSX_BUNDLE_BUNDLE_VERSION "1"
             MACOSX_BUNDLE_COPYRIGHT "Copyright © 2021 laamaa. All rights reserved."
             MACOSX_BUNDLE_GUI_IDENTIFIER "fi.laamaa.m8c"
-            MACOSX_BUNDLE_SHORT_VERSION_STRING "2.0.0"
-            MACOSX_BUNDLE_ICON_FILE "m8c.icns")
+            MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}"
+            MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION}"
+            MACOSX_BUNDLE_ICON_FILE "m8c.icns"
+    )
 
     set(APPS "\${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app")
 
     install(CODE "include(BundleUtilities)
     fixup_bundle(\"${APPS}\" \"\" \"\")
-    execute_process(COMMAND codesign --force --deep --sign - \${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app)")
+    execute_process(COMMAND codesign --force --options runtime --deep --entitlements ../package/macos/Entitlements.plist --sign \"${CODESIGN_CERT_NAME}\" --timestamp  \${CMAKE_INSTALL_PREFIX}/${APP_NAME}.app)")
+
+    set(CPACK_PACKAGE_NAME "m8c")
+    set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
+    set(CPACK_PACKAGE_DIRECTORY "package-output")
     set(CPACK_GENERATOR "DragNDrop")
     include(CPack)
 endif ()
--- /dev/null
+++ b/package/macos/Entitlements.plist
@@ -1,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+   <key>com.apple.security.device.audio-input</key>
+   <true/>
+</dict>
+</plist>
\ No newline at end of file
--- a/package/macos/m8c.app/Contents/Info.plist
+++ b/package/macos/m8c.app/Contents/Info.plist
@@ -23,7 +23,7 @@
 	<key>CFBundleShortVersionString</key>
 	<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
 	<key>CFBundleSignature</key>
-	<string>????</string>
+	<string>APPL</string>
 	<key>CFBundleVersion</key>
 	<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
 	<key>CSResourcesFileMapped</key>
--- a/src/backends/audio_sdl.c
+++ b/src/backends/audio_sdl.c
@@ -3,7 +3,6 @@
 #ifndef USE_LIBUSB
 #include "audio.h"
 #include <SDL3/SDL.h>
-#include <stdint.h>
 
 SDL_AudioStream *audio_stream_in, *audio_stream_out;
 
--- a/src/backends/m8.h
+++ b/src/backends/m8.h
@@ -1,7 +1,7 @@
 // Copyright 2021 Jonne Kokkonen
 // Released under the MIT licence, https://opensource.org/licenses/MIT
-#ifndef _M8_H_
-#define _M8_H_
+#ifndef M8_H_
+#define M8_H_
 
 #include "../config.h"
 
--- a/src/backends/queue.c
+++ b/src/backends/queue.c
@@ -1,6 +1,5 @@
 #include "queue.h"
 #include <SDL3/SDL.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
--- a/src/gamepads.c
+++ b/src/gamepads.c
@@ -3,10 +3,6 @@
 //
 
 #include "gamepads.h"
-#include "backends/m8.h"
-#include "config.h"
-#include "events.h"
-#include "render.h"
 
 #include <SDL3/SDL.h>
 #include <stdio.h>
--- a/src/main.c
+++ b/src/main.c
@@ -16,7 +16,6 @@
 #include "backends/m8.h"
 #include "common.h"
 #include "config.h"
-#include "events.h"
 #include "gamepads.h"
 #include "render.h"
 
--