diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index af67c76c..5a49ed43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,6 +46,41 @@ jobs: - uses: actions/checkout@v4 - run: sh scripts/clone_dependencies.sh - run: cd ./Dev/Cpp/macosx/ && sh ./build_cmake.sh + - name: Validate notarization secrets on push + if: ${{ github.event_name == 'push' }} + env: + APPLE_CERT_P12_BASE64: ${{ secrets.APPLE_CERT_P12_BASE64 }} + APPLE_CERT_P12_PASSWORD: ${{ secrets.APPLE_CERT_P12_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_NOTARY_APPLE_ID: ${{ secrets.APPLE_NOTARY_APPLE_ID }} + APPLE_NOTARY_TEAM_ID: ${{ secrets.APPLE_NOTARY_TEAM_ID }} + APPLE_NOTARY_APP_PASSWORD: ${{ secrets.APPLE_NOTARY_APP_PASSWORD }} + run: | + set -eu + required=( + APPLE_CERT_P12_BASE64 + APPLE_CERT_P12_PASSWORD + APPLE_SIGNING_IDENTITY + APPLE_NOTARY_APPLE_ID + APPLE_NOTARY_TEAM_ID + APPLE_NOTARY_APP_PASSWORD + ) + for name in "${required[@]}"; do + if [ -z "${!name}" ]; then + echo "::error::Missing required notarization secret: ${name}" + exit 1 + fi + done + - name: Sign and notarize macOS dylib + if: ${{ github.event_name == 'push' || (secrets.APPLE_CERT_P12_BASE64 != '' && secrets.APPLE_CERT_P12_PASSWORD != '' && secrets.APPLE_SIGNING_IDENTITY != '' && secrets.APPLE_NOTARY_APPLE_ID != '' && secrets.APPLE_NOTARY_TEAM_ID != '' && secrets.APPLE_NOTARY_APP_PASSWORD != '') }} + env: + APPLE_CERT_P12_BASE64: ${{ secrets.APPLE_CERT_P12_BASE64 }} + APPLE_CERT_P12_PASSWORD: ${{ secrets.APPLE_CERT_P12_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_NOTARY_APPLE_ID: ${{ secrets.APPLE_NOTARY_APPLE_ID }} + APPLE_NOTARY_TEAM_ID: ${{ secrets.APPLE_NOTARY_TEAM_ID }} + APPLE_NOTARY_APP_PASSWORD: ${{ secrets.APPLE_NOTARY_APP_PASSWORD }} + run: bash ci/notarize_macos_dylib.sh Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib - name: Upload ios uses: actions/upload-artifact@v4 with: @@ -246,7 +281,7 @@ jobs: mv Android/Android/libs/x86/libEffekseerUnity.so Dev/Plugin/Assets/Effekseer/Plugins/Android/libs/x86/ mv mac_iOS/iOS/libEffekseerUnity.a Dev/Plugin/Assets/Effekseer/Plugins/iOS/libEffekseerUnity.a rm -rf Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle - cp -f -r mac_iOS/EffekseerUnity.bundle Dev/Plugin/Assets/Effekseer/Plugins/ + mv mac_iOS/macOS/EffekseerUnity.dylib Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib mv WebGL_2-0-19/WebGL/2.0.19-64bit/libEffekseerUnity.bc Dev/Plugin/Assets/Effekseer/Plugins/WebGL/2.0.19-64bit/ mv WebGL_3-1-8/WebGL/3.1.8-64bit/libEffekseerUnity.bc Dev/Plugin/Assets/Effekseer/Plugins/WebGL/3.1.8-64bit/ mv WebGL_3-1-38/WebGL/3.1.38-64bit/libEffekseerUnity.bc Dev/Plugin/Assets/Effekseer/Plugins/WebGL/3.1.38-64bit/ diff --git a/Dev/Cpp/CMakeLists.txt b/Dev/Cpp/CMakeLists.txt index 1d300966..7c46140a 100644 --- a/Dev/Cpp/CMakeLists.txt +++ b/Dev/Cpp/CMakeLists.txt @@ -77,10 +77,11 @@ if(APPLE) else() list(APPEND srcs ${effekseer_gl_src}) - add_library(EffekseerUnity MODULE + add_library(EffekseerUnity SHARED ${srcs} ) - set_target_properties(EffekseerUnity PROPERTIES BUNDLE TRUE) + # Keep the binary name as EffekseerUnity.dylib for Unity DllImport("EffekseerUnity"). + set_target_properties(EffekseerUnity PROPERTIES PREFIX "") endif() target_link_libraries(EffekseerUnity PRIVATE diff --git a/Dev/Cpp/macosx/build_cmake.sh b/Dev/Cpp/macosx/build_cmake.sh index c1e08070..465a04ae 100644 --- a/Dev/Cpp/macosx/build_cmake.sh +++ b/Dev/Cpp/macosx/build_cmake.sh @@ -30,5 +30,7 @@ libtool -static -o libEffekseerUnity_ios_sim.a ../../build_ios_sim/Install/lib/l lipo -create libEffekseerUnity_ios.a libEffekseerUnity_ios_sim.a -output libEffekseerUnity.a # Copy to PluginProject -cp -rf ../../build_macosx/Install/lib/EffekseerUnity.bundle ../../Plugin/Assets/Effekseer/Plugins/ +rm -rf ../../Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle +mkdir -p ../../Plugin/Assets/Effekseer/Plugins/macOS +cp -f ../../build_macosx/Install/lib/EffekseerUnity.dylib ../../Plugin/Assets/Effekseer/Plugins/macOS/ cp libEffekseerUnity.a ../../Plugin/Assets/Effekseer/Plugins/iOS/ diff --git a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS.meta b/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS.meta deleted file mode 100644 index be609fac..00000000 --- a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS.meta +++ /dev/null @@ -1,9 +0,0 @@ -fileFormatVersion: 2 -guid: 21b03b442a6b2a74eb0276bd719cc288 -folderAsset: yes -timeCreated: 1425480812 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS/EffekseerUnity.meta b/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS/EffekseerUnity.meta deleted file mode 100644 index 50e20bdc..00000000 --- a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents/MacOS/EffekseerUnity.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 04fbbd6af322a1b4b89bc7223933a60d -timeCreated: 1457532355 -licenseType: Free -DefaultImporter: - userData: - assetBundleName: - assetBundleVariant: diff --git a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents.meta b/Dev/Plugin/Assets/Effekseer/Plugins/macOS.meta similarity index 67% rename from Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents.meta rename to Dev/Plugin/Assets/Effekseer/Plugins/macOS.meta index 311c611d..d8fdb70b 100644 --- a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle/Contents.meta +++ b/Dev/Plugin/Assets/Effekseer/Plugins/macOS.meta @@ -1,7 +1,7 @@ fileFormatVersion: 2 -guid: 8b62a854166eec649b458d0d99404a74 +guid: 4c5c6391f8f84fc4b1a9f317ea13c46c folderAsset: yes -timeCreated: 1425480812 +timeCreated: 1457372930 licenseType: Free DefaultImporter: userData: diff --git a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle.meta b/Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib.meta similarity index 76% rename from Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle.meta rename to Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib.meta index 1c4989b6..79e58410 100644 --- a/Dev/Plugin/Assets/Effekseer/Plugins/EffekseerUnity.bundle.meta +++ b/Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib.meta @@ -1,8 +1,5 @@ fileFormatVersion: 2 guid: 3e51f2c8c991d5d44b5633911fdc0b07 -folderAsset: yes -timeCreated: 1425480812 -licenseType: Free PluginImporter: serializedVersion: 1 iconMap: {} @@ -23,17 +20,17 @@ PluginImporter: DefaultValueInitialized: true OS: OSX Linux: - enabled: 1 + enabled: 0 settings: - CPU: x86 + CPU: None Linux64: - enabled: 1 + enabled: 0 settings: - CPU: x86_64 + CPU: None LinuxUniversal: - enabled: 1 + enabled: 0 settings: - CPU: AnyCPU + CPU: None OSXIntel: enabled: 1 settings: @@ -47,13 +44,13 @@ PluginImporter: settings: CPU: AnyCPU Win: - enabled: 1 + enabled: 0 settings: - CPU: AnyCPU + CPU: None Win64: - enabled: 1 + enabled: 0 settings: - CPU: AnyCPU + CPU: None userData: assetBundleName: assetBundleVariant: diff --git a/ci/notarize_macos_dylib.sh b/ci/notarize_macos_dylib.sh new file mode 100755 index 00000000..08341336 --- /dev/null +++ b/ci/notarize_macos_dylib.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + exit 1 +fi + +PLUGIN_PATH="$1" +if [ ! -f "$PLUGIN_PATH" ]; then + echo "Dylib not found: $PLUGIN_PATH" + exit 1 +fi + +required_envs=( + APPLE_CERT_P12_BASE64 + APPLE_CERT_P12_PASSWORD + APPLE_SIGNING_IDENTITY + APPLE_NOTARY_APPLE_ID + APPLE_NOTARY_TEAM_ID + APPLE_NOTARY_APP_PASSWORD +) + +for name in "${required_envs[@]}"; do + if [ -z "${!name:-}" ]; then + echo "Required environment variable is missing: $name" + exit 1 + fi +done + +TMP_DIR="${RUNNER_TEMP:-/tmp}" +CERTIFICATE_PATH="$TMP_DIR/effekseer_apple_certificate.p12" +KEYCHAIN_PATH="$TMP_DIR/effekseer-signing.keychain-db" +NOTARY_ARCHIVE_PATH="$TMP_DIR/effekseer_unity_macos_notary.zip" +KEYCHAIN_PASSWORD="$(uuidgen)" + +cleanup() { + security delete-keychain "$KEYCHAIN_PATH" >/dev/null 2>&1 || true + rm -f "$CERTIFICATE_PATH" "$NOTARY_ARCHIVE_PATH" +} +trap cleanup EXIT + +decode_base64_to_file() { + local output="$1" + if printf '%s' "$APPLE_CERT_P12_BASE64" | base64 --decode >"$output" 2>/dev/null; then + return 0 + fi + + printf '%s' "$APPLE_CERT_P12_BASE64" | base64 -D >"$output" +} + +decode_base64_to_file "$CERTIFICATE_PATH" + +security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" +security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" +security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" +security import "$CERTIFICATE_PATH" -k "$KEYCHAIN_PATH" -P "$APPLE_CERT_P12_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" + +echo "Signing $PLUGIN_PATH" +codesign --force --keychain "$KEYCHAIN_PATH" --sign "$APPLE_SIGNING_IDENTITY" --options runtime --timestamp "$PLUGIN_PATH" +codesign --verify --verbose=2 "$PLUGIN_PATH" + +ditto -c -k --keepParent "$PLUGIN_PATH" "$NOTARY_ARCHIVE_PATH" + +echo "Submitting for notarization..." +xcrun notarytool submit "$NOTARY_ARCHIVE_PATH" \ + --apple-id "$APPLE_NOTARY_APPLE_ID" \ + --team-id "$APPLE_NOTARY_TEAM_ID" \ + --password "$APPLE_NOTARY_APP_PASSWORD" \ + --wait + +echo "Notarization completed: $PLUGIN_PATH" diff --git a/docs/Development/MacOSNotarizationCI.md b/docs/Development/MacOSNotarizationCI.md new file mode 100644 index 00000000..09be3736 --- /dev/null +++ b/docs/Development/MacOSNotarizationCI.md @@ -0,0 +1,50 @@ +# macOS dylib Notarization in CI + +This repository notarizes the macOS native plugin (`EffekseerUnity.dylib`) in GitHub Actions. + +- Workflow: `.github/workflows/build.yml` +- Script: `ci/notarize_macos_dylib.sh` + +The `mac_ios` job does the following: + +1. Build `EffekseerUnity.dylib` +2. Sign the dylib with `Developer ID Application` +3. Submit the signed dylib to Apple Notary Service (`xcrun notarytool submit --wait`) +4. Upload the notarized dylib as part of the `mac_iOS` artifact + +## Required GitHub Secrets + +Set these repository secrets before running `push` workflows: + +1. `APPLE_CERT_P12_BASE64`: Base64-encoded `.p12` file of your `Developer ID Application` certificate (including private key) +2. `APPLE_CERT_P12_PASSWORD`: Password used when exporting the `.p12` +3. `APPLE_SIGNING_IDENTITY`: Full signing identity, for example `Developer ID Application: Example Corp (TEAMID1234)` +4. `APPLE_NOTARY_APPLE_ID`: Apple ID used for notarization +5. `APPLE_NOTARY_TEAM_ID`: Apple Developer Team ID +6. `APPLE_NOTARY_APP_PASSWORD`: App-specific password for the Apple ID above + +## How to prepare the `.p12` secret value + +Example (macOS): + +```bash +base64 -i developer_id_application.p12 | pbcopy +``` + +Example (Linux): + +```bash +base64 -w 0 developer_id_application.p12 +``` + +Paste the Base64 result into `APPLE_CERT_P12_BASE64`. + +## Workflow behavior + +- On `push`, notarization secrets are mandatory. If any required secret is missing, the `mac_ios` job fails. +- On `pull_request`, notarization runs only when all notarization secrets are available. Otherwise it is skipped. + +## Notes + +- `xcrun stapler` is not used in this flow because the target artifact is a standalone `.dylib`. +- The merged package job consumes the notarized file at `Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib`. diff --git a/docs/Development/MacOSNotarizationCI_ja.md b/docs/Development/MacOSNotarizationCI_ja.md new file mode 100644 index 00000000..0b6387d8 --- /dev/null +++ b/docs/Development/MacOSNotarizationCI_ja.md @@ -0,0 +1,52 @@ +# CIでのmacOS dylib公証 + +このリポジトリでは、GitHub Actions上で macOS ネイティブプラグイン(`EffekseerUnity.dylib`)を公証します。 +通常はこの公証済み成果物を配布するため、ユーザー側での公証は不要です。 +ただし、ユーザー自身でネイティブプラグインをビルドする場合は、公証が必要です。 + +- ワークフロー: `.github/workflows/build.yml` +- 実行スクリプト: `ci/notarize_macos_dylib.sh` + +`mac_ios` ジョブでは次を実行します。 + +1. `EffekseerUnity.dylib` をビルド +2. `Developer ID Application` 証明書で署名 +3. Apple Notary Service に提出(`xcrun notarytool submit --wait`) +4. 公証済み dylib を `mac_iOS` アーティファクトとしてアップロード + +## 必須の GitHub Secrets + +`push` ワークフロー実行前に、以下のリポジトリシークレットを設定してください。 + +1. `APPLE_CERT_P12_BASE64`: `Developer ID Application` 証明書(秘密鍵を含む)を `.p12` で書き出し、Base64化した値 +2. `APPLE_CERT_P12_PASSWORD`: `.p12` エクスポート時のパスワード +3. `APPLE_SIGNING_IDENTITY`: 署名ID(例: `Developer ID Application: Example Corp (TEAMID1234)`) +4. `APPLE_NOTARY_APPLE_ID`: 公証に使用する Apple ID +5. `APPLE_NOTARY_TEAM_ID`: Apple Developer Team ID +6. `APPLE_NOTARY_APP_PASSWORD`: 上記 Apple ID の app-specific password + +## `.p12` の Base64 値を作る方法 + +macOS の例: + +```bash +base64 -i developer_id_application.p12 | pbcopy +``` + +Linux の例: + +```bash +base64 -w 0 developer_id_application.p12 +``` + +出力された文字列を `APPLE_CERT_P12_BASE64` に設定してください。 + +## ワークフローの挙動 + +- `push` では公証用シークレットが必須です。1つでも不足していると `mac_ios` ジョブは失敗します。 +- `pull_request` では、必要シークレットがすべて利用可能な場合のみ公証を実行し、足りない場合は公証ステップをスキップします。 + +## 補足 + +- 対象が単体 `.dylib` のため、このフローでは `xcrun stapler` は使用しません。 +- マージジョブは `Dev/Plugin/Assets/Effekseer/Plugins/macOS/EffekseerUnity.dylib` の公証済みファイルを使用します。 diff --git a/docs/MacOS_En.md b/docs/MacOS_En.md index 5f367e4e..eb0513a9 100644 --- a/docs/MacOS_En.md +++ b/docs/MacOS_En.md @@ -1,26 +1,12 @@ -# Regarding the warning on MacOS +# Regarding macOS warnings -Currently, native notarization is not available when using Unity on MacOS. -Therefore, if you want to use EffekseerForUnity, you need to install or handle it in the following way. +The macOS native plugin (`EffekseerUnity.dylib`) is basically notarized by maintainers. +In normal usage, users do not need to notarize it. +If you build the native plugin by yourself, notarization is required. -# Use the Unity PackageManager +## CI notarization settings (for maintainers) -Install Effekseer with PackageManager. This is the easiest way. +See: -https://docs.unity3d.com/2019.4/Documentation/Manual/upm-ui-giturl.html - -``` -https://github.com/effekseer/EffekseerForUnity_Release.git?path=Assets/Effekseer -``` - -# Share data with your team using git. - -Even if you don't use Unity PackageManager, as long as you synchronize your data with other PCs via git, you won't have any problems. - -# Use xattr -rc. - -If you want to share data with multiple PCs by compressing them into a zip or other format without using PackageManager or git, you need to enter the following command before starting Unity. - -``` -xattr -rc UnityProject -``` +- `docs/Development/MacOSNotarizationCI.md` +- `docs/Development/MacOSNotarizationCI_ja.md` diff --git a/docs/MacOS_Ja.md b/docs/MacOS_Ja.md index cb988737..692cffb4 100644 --- a/docs/MacOS_Ja.md +++ b/docs/MacOS_Ja.md @@ -1,26 +1,12 @@ -# MacOSにおける警告について +# macOSにおける警告について -現在、MacOSでUnityを使用する場合、ネイティブの公証ができません。 -そのため、EffekseerForUnityを使用する場合は下記の方法で導入、もしくは取り扱う必要があります。 +macOS向けネイティブプラグイン(`EffekseerUnity.dylib`)の公証は、基本的に開発側で実施します。 +そのため、通常の利用ではユーザー側で公証は不要です。 +ただし、ユーザー自身でネイティブプラグインをビルドする場合は、公証が必要です。 -# Unity PackageManagerを使用する +## CI公証設定(メンテナ向け) -EffekseerをPackageManagerでインストールします。最も簡単な方法です。 +以下を参照してください。 -https://docs.unity3d.com/ja/2019.4/Manual/upm-ui-giturl.html - -``` -https://github.com/effekseer/EffekseerForUnity_Release.git?path=Assets/Effekseer -``` - -# チーム内でgitを用いてデータを共有する。 - -Unity PackageManagerを使用しなくとも、gitで他のPCとデータを同期している限り、問題は発生しません。 - -# xattr -rcを使用する。 - -PackageManagerやgitを使用せずに、zip等に圧縮して複数PCでデータを共有する場合、Unityを起動する前に下記のコマンドを入力する必要があります。 - -``` -xattr -rc Unityのプロジェクト -``` +- `docs/Development/MacOSNotarizationCI.md` +- `docs/Development/MacOSNotarizationCI_ja.md` diff --git a/readme_macOS.txt b/readme_macOS.txt index 38265870..30a75f7c 100644 --- a/readme_macOS.txt +++ b/readme_macOS.txt @@ -1,11 +1,15 @@ -Currently, UnityPlugin for macOS cannot be notarized due to the circumstances of Unity. +The macOS Unity plugin (`EffekseerUnity.dylib`) can be notarized in CI. +In normal usage, users do not need to notarize because maintainers distribute notarized binaries. +If you build the native plugin by yourself, notarization is required. -現在、macOS向けのUnityPluginはUnityの都合により公証できない状態です。 +macOS向けUnityPlugin(`EffekseerUnity.dylib`)はCIで公証可能です。 +通常は開発側が公証済みバイナリを配布するため、ユーザー側で公証は不要です。 +ただし、ユーザー自身でネイティブプラグインをビルドする場合は、公証が必要です。 -Be sure to read this document before using EffekseerForUnity. +If you need to notarize, please read the documents below. -必ずこのドキュメントを読んだ後に、EffekseerForUnityを使用してください。 +公証をする場合は、下記のドキュメントを読んでください。 - [English](https://github.com/effekseer/EffekseerForUnity/blob/master/docs/MacOS_En.md)