Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: build macOS SDK as a dylib from sentry-cocoa #710

Merged
merged 28 commits into from
May 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f232380
feat: build macOS SDK as a dylib from sentry-cocoa
vaind Apr 27, 2022
1bb39ca
refactor: reuse iOS native bridge for macOS
vaind Apr 27, 2022
0888057
feat: add MacosNativeSupportEnabled option
vaind Apr 27, 2022
25b0ea4
fix: SmokeTester.cs compilation for iOS
vaind Apr 25, 2022
7aac180
feat: extend SentryNativeBridge with macOS support
vaind Apr 27, 2022
347cf5d
feat: implement macOS cocoa SDK start with options
vaind Apr 27, 2022
b4fceb0
Format code
getsentry-bot Apr 27, 2022
0eaacee
feat: finish macOS native bridge & update iOS copy
vaind Apr 28, 2022
9f8b771
fix: cocoa unit tests
vaind Apr 28, 2022
c7891d3
chore: add macOS to DownloadNativeSDKs
vaind Apr 28, 2022
74b68b7
fix: macOS SentryNativeBridge.m for Unity 2019
vaind Apr 28, 2022
db92e04
fix: SentryNativeBridge.m iOS compilation
vaind Apr 28, 2022
fbc48df
ci: sdk cache key must include static files in package-dev/Plugins/Pl…
vaind Apr 28, 2022
733a82f
ci: sdk cache key must include static files
vaind Apr 29, 2022
b50ab18
chore: update package-release snapshot
vaind Apr 29, 2022
86afcf9
fix: macOS environment vs diagnosticLevel options init
vaind Apr 29, 2022
7fd94e9
feat: macOS debug symbol upload
vaind Apr 29, 2022
f7d1d49
ci: add macOS smoke test
vaind Apr 29, 2022
bd504df
chore: fix integration test scripts for macOS CI
vaind May 2, 2022
b92f1f4
chore: remove unused Unity symlink for Windows (reverts #423)
vaind May 2, 2022
c7b0a4e
chore: avoid full path for Unity logfile to support running in docker
vaind May 2, 2022
2f6b35d
chore: fix RunUnityCustom CI script
vaind May 3, 2022
9619a25
chore: update smoke-test script for macOS
vaind May 3, 2022
786b15d
Update scripts/unity.ps1
vaind May 4, 2022
9e68701
refactor: macOS native bridge - add SentryConfigureScope()
vaind May 4, 2022
e93e599
Update CHANGELOG.md
vaind May 5, 2022
feb0b9a
chore: fix CI
vaind May 5, 2022
3dd16f3
chore: review changes
vaind May 5, 2022
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
1 change: 0 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@ BasedOnStyle: WebKit
IndentWidth: 4
IndentPPDirectives: AfterHash
ColumnLimit: 100
AlwaysBreakAfterDefinitionReturnType: All
vaind marked this conversation as resolved.
Show resolved Hide resolved
PointerAlignment: Right
ForEachMacros: ['SENTRY_WITH_SCOPE', 'SENTRY_WITH_SCOPE_MUT']
48 changes: 26 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ jobs:
target: iOS
runsOn: macos-latest

macos-sdk:
uses: ./.github/workflows/sdk.yml
with:
target: macOS
runsOn: macos-latest

windows-sdk:
uses: ./.github/workflows/sdk.yml
with:
Expand Down Expand Up @@ -90,6 +96,12 @@ jobs:
path: package-dev/Plugins/iOS
wait-timeout: 3600

- uses: vaind/download-artifact@989a39a417730897d098ab11c34e49ac4e13ed70
with:
name: macOS-sdk
path: package-dev/Plugins/macOS
wait-timeout: 3600

- uses: vaind/download-artifact@989a39a417730897d098ab11c34e49ac4e13ed70
with:
name: Windows-sdk
Expand Down Expand Up @@ -260,16 +272,21 @@ jobs:
# pwsh ./test/Scripts.Tests/test-pack-contents.ps1 accept
run: ./test/Scripts.Tests/test-pack-contents.ps1

windows-smoke-test:
name: Run Windows Unity ${{ matrix.unity-version }} Smoke Test
runs-on: windows-latest
desktop-smoke-test:
name: Run ${{ matrix.os }} Smoke Test - ${{ matrix.unity-version }}
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
matrix:
unity-version: ['2019', '2020', '2021']
os: ['windows', 'macos']
include:
- os: windows-latest
- os: windows
unity-modules: windows-il2cpp
unity-config-path: C:/ProgramData/Unity/config/
- os: macos
unity-modules: mac-il2cpp
unity-config-path: /Library/Application Support/Unity/config/
defaults:
run:
shell: pwsh
Expand All @@ -281,20 +298,11 @@ jobs:
id: env
run: echo "::set-output name=unityVersion::$(./scripts/ci-env.ps1 "unity${{ matrix.unity-version }}")"

# Caching the whole Unity installation would overflow the 10 GiB limit repositories have but we can cache the Hub
# to achieve some speedup here at a low size cost.
# See https://github.com/kuler90/setup-unity/blob/797ebd0cc9d0e0ca5bcd6cc280ec1a6e685fbf83/src/setup.js#L36
- name: Cache Unity Hub
uses: actions/cache@v2
with:
path: 'C:/Program Files/Unity Hub'
key: unity-hub|windows

- name: Setup Unity
uses: getsentry/setup-unity@46c2e082d98cc3a825a5b59038cb31705fe9ff56
with:
unity-version: ${{ steps.env.outputs.unityVersion }}
unity-modules: windows-il2cpp
unity-modules: ${{ matrix.unity-modules }}

- run: echo "::add-mask::${{ secrets.LICENSE_SERVER_URL }}"

Expand All @@ -303,15 +311,11 @@ jobs:
New-Item -Path '${{ matrix.unity-config-path }}' -ItemType Directory
Set-Content -Path '${{ matrix.unity-config-path }}services-config.json' -Value '${{ secrets.UNITY_LICENSE_SERVER_CONFIG }}'

# Step used to reduce the Unity path to avoid long path errors on Windows.
- name: Make symbolic link for Unity (Windows)
run: New-Item -ItemType SymbolicLink -Path "C:\${{ steps.env.outputs.unityVersion }}" -Target "C:\Program Files\Unity\Hub\Editor\${{ steps.env.outputs.unityVersion }}"
vaind marked this conversation as resolved.
Show resolved Hide resolved

- name: Create new Project
run: ./test/Scripts.Integration.Test/integration-create-project.ps1 "${{ env.UNITY_PATH }}"
run: ./test/Scripts.Integration.Test/integration-create-project.ps1 -UnityPath "${{ env.UNITY_PATH }}"

- name: Build Standalone Player without Sentry SDK
run: ./test/Scripts.Integration.Test/integration-build-project.ps1 "${{ env.UNITY_PATH }}"
run: ./test/Scripts.Integration.Test/integration-build-project.ps1 -UnityPath "${{ env.UNITY_PATH }}"

- name: Download UPM package
uses: vaind/download-artifact@989a39a417730897d098ab11c34e49ac4e13ed70
Expand All @@ -324,10 +328,10 @@ jobs:
run: ./test/Scripts.Integration.Test/integration-extract-package.ps1

- name: Add Sentry to test project
run: ./test/Scripts.Integration.Test/integration-update-sentry.ps1 "${{ env.UNITY_PATH }}"
run: ./test/Scripts.Integration.Test/integration-update-sentry.ps1 -UnityPath "${{ env.UNITY_PATH }}"

- name: Build Standalone Player Sentry SDK
run: ./test/Scripts.Integration.Test/integration-build-project.ps1 "${{ env.UNITY_PATH }}"
run: ./test/Scripts.Integration.Test/integration-build-project.ps1 -UnityPath "${{ env.UNITY_PATH }}"

- name: Run Player - Smoke Test
run: ./test/Scripts.Integration.Test/integration-run-smoke-test.ps1 -Smoke
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
- name: Get submodules status
run: git submodule status | tee submodules-status

- run: cp -r package-dev/Plugins/${{ inputs.target }} sdk-static || echo "never mind, no files checked in..."
shell: bash

- name: Restore from cache
uses: actions/cache@v2
id: cache
Expand All @@ -32,15 +35,15 @@ jobs:
path: |
package-dev/Plugins
modules/sentry-java/sentry-android-ndk/build/intermediates/merged_native_libs/release/out/lib
key: sdk=${{ inputs.target }}-${{ hashFiles('submodules-status', 'package/package.json', 'Directory.Build.targets') }}
key: sdk=${{ inputs.target }}-${{ hashFiles('submodules-status', 'package/package.json', 'Directory.Build.targets', 'sdk-static/**') }}

- name: Checkout submodules
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
if [[ "${{ inputs.target }}" == "Android" ]]; then
submodules="modules/sentry-java"
elif [[ "${{ inputs.target }}" == "iOS" ]]; then
elif [[ "${{ inputs.target }}" == "iOS" || "${{ inputs.target }}" == "macOS" ]]; then
submodules="modules/sentry-cocoa"
else
submodules="modules/sentry-native"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ package-dev/**/*.meta
package-dev/**/*.framework
package-dev/**/*.pdb
package-dev/**/*.xml
package-dev/**/*.dylib
package-dev/**/*.dSYM
package-dev/**/TestSentryOptions.json
package-dev/Tests/Editor/TestFiles/
package-dev/Plugins/*/Sentry/crashpad_handler*
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- macOS native crash support ([#710](https://github.com/getsentry/sentry-unity/pull/710))
- The SentryUnityOptions now provide a method to disable the UnityLoggingIntegration ([#724](https://github.com/getsentry/sentry-unity/pull/724))

### Fixes
Expand Down
27 changes: 23 additions & 4 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<SentryCocoaRoot>$(RepoRoot)modules/sentry-cocoa/</SentryCocoaRoot>
<SentryiOSDeviceArtifactsDestination>$(SentryArtifactsDestination)/iOS/Device/Sentry.framework/</SentryiOSDeviceArtifactsDestination>
<SentryiOSSimulatorArtifactsDestination>$(SentryArtifactsDestination)/iOS/Simulator/Sentry.framework/</SentryiOSSimulatorArtifactsDestination>
<SentrymacOSArtifactsDestination>$(SentryArtifactsDestination)/macOS/Sentry/</SentrymacOSArtifactsDestination>
<!-- Android -->
<SentryAndroidRoot>$(RepoRoot)modules/sentry-java/</SentryAndroidRoot>
<SentryAndroidArtifactsDestination>$(SentryArtifactsDestination)/Android/Sentry/</SentryAndroidArtifactsDestination>
Expand All @@ -39,8 +40,6 @@
<UnityRoot Condition="Exists('C:\Program Files\Unity\Hub\Editor\$(UnityVersion)\Editor\Data\Managed\UnityEngine.dll')">C:\Program Files\Unity\Hub\Editor\$(UnityVersion)\Editor</UnityRoot>
<!--If not using Unity Hub, tries to pick whatever Unity version is installed on the machine-->
<UnityRoot Condition="$(UnityRoot) == '' AND Exists('C:\Program Files\Unity\Editor\Data\Managed\UnityEngine.dll')">C:\Program Files\Unity\Editor</UnityRoot>
<!--Short version for GitHub Actions to avoid long path names errors on Windows-->
<UnityRoot Condition="Exists('C:\$(UnityVersion)\Editor\Data\Managed\UnityEngine.dll')">C:\$(UnityVersion)\Editor</UnityRoot>
<UnityManagedPath>$(UnityRoot)\Data\Managed</UnityManagedPath>
<UnityExec>&quot;$(UnityRoot)\Unity.exe&quot;</UnityExec>
<StandaloneBuildMethod>Builder.BuildWindowsIl2CPPPlayer</StandaloneBuildMethod>
Expand Down Expand Up @@ -107,6 +106,7 @@ Expected to exist:
</Target>

<Target Name="CleaniOSSDK" AfterTargets="Clean" Condition="'$(MSBuildProjectName)' == 'Sentry.Unity'">
<RemoveDir Directories="$(SentryCocoaRoot)Carthage" ContinueOnError="true" />
<RemoveDir Directories="$(SentryiOSDeviceArtifactsDestination)" ContinueOnError="true" />
<RemoveDir Directories="$(SentryiOSSimulatorArtifactsDestination)" ContinueOnError="true" />
</Target>
Expand All @@ -117,6 +117,12 @@ Expected to exist:
<RemoveDir Directories="$(SentryAndroidArtifactsDestination)" ContinueOnError="true" />
</Target>

<Target Name="CleanmacOSSDK" AfterTargets="Clean" Condition="'$(MSBuildProjectName)' == 'Sentry.Unity'">
<RemoveDir Directories="$(SentryCocoaRoot)Carthage/Build/Mac" ContinueOnError="true" />
<Delete Files="$(SentrymacOSArtifactsDestination)/Sentry.dylib" ContinueOnError="true" />
<Delete Files="$(SentrymacOSArtifactsDestination)/Sentry.dylib.dSYM" ContinueOnError="true" />
</Target>

<Target Name="CleanWindowsSDK" AfterTargets="Clean" Condition="'$(MSBuildProjectName)' == 'Sentry.Unity'">
<RemoveDir Directories="$(SentryNativeRoot)build/" ContinueOnError="true" />
<RemoveDir Directories="$(SentryWindowsArtifactsDestination)" ContinueOnError="true" />
Expand All @@ -143,8 +149,20 @@ Expected to exist:
<Copy SourceFiles="@(iOSSimulatorBuildPath)" DestinationFiles="@(iOSSimulatorBuildPath->'$(SentryiOSSimulatorArtifactsDestination)%(RecursiveDir)%(Filename)%(Extension)')">
</Copy>

<Error Condition="(!Exists('$(SentryiOSDeviceArtifactsDestination)') OR !Exists('$(SentryiOSSimulatorArtifactsDestination)'))" Text="Failed to build the Cocoa SDK.">
</Error>
<Error Condition="(!Exists('$(SentryiOSDeviceArtifactsDestination)') OR !Exists('$(SentryiOSSimulatorArtifactsDestination)'))" Text="Failed to build the iOS SDK." />
</Target>

<!-- Build the macOS SDK: dotnet msbuild /t:BuildmacOSSDK src/Sentry.Unity -->
<Target Name="BuildmacOSSDK" BeforeTargets="BeforeBuild" Condition="$([MSBuild]::IsOSPlatform('OSX'))
And '$(MSBuildProjectName)' == 'Sentry.Unity'
And (!Exists('$(SentrymacOSArtifactsDestination)/Sentry.dylib') Or !Exists('$(SentrymacOSArtifactsDestination)/Sentry.dylib.dSYM'))">
<Error Condition="!Exists('$(SentryCocoaRoot)')" Text="Couldn't find the Cocoa root at $(SentryCocoaRoot)."></Error>
<Message Importance="High" Text="Building Sentry macOS SDK."></Message>

<Exec WorkingDirectory="$(SentryCocoaRoot)" Command="carthage build --no-skip-current --platform macOS"></Exec>

<Copy SourceFiles="$(SentryCocoaRoot)Carthage/Build/Mac/Sentry.framework/Sentry" DestinationFiles="$(SentrymacOSArtifactsDestination)/Sentry.dylib" />
<Copy SourceFiles="$(SentryCocoaRoot)Carthage/Build/Mac/Sentry.framework.dSYM/Contents/Resources/DWARF/Sentry" DestinationFiles="$(SentrymacOSArtifactsDestination)/Sentry.dylib.dSYM" />
</Target>

<!-- Build the Android SDK: dotnet msbuild /t:BuildAndroidSDK src/Sentry.Unity -->
Expand Down Expand Up @@ -501,6 +519,7 @@ void PrintFailedTests(XElement element)
<ItemGroup>
<SDK Include="Windows"/>
<SDK Include="iOS"/>
<SDK Include="macOS"/>
<SDK Include="Android"/>
</ItemGroup>
<Message Importance="High" Text="Replacing $(SentryArtifactsDestination)%(SDK.Identity)" />
Expand Down
83 changes: 45 additions & 38 deletions package-dev/Plugins/iOS/SentryNativeBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,116 +2,123 @@

NS_ASSUME_NONNULL_BEGIN

int CrashedLastRun() {
return [SentrySDK crashedLastRun] ? 1 : 0;
}
// macOS only
int SentryNativeBridgeLoadLibrary() { return 0; }
void *SentryNativeBridgeOptionsNew() { return nil; }
void SentryNativeBridgeOptionsSetString(void *options, const char *name, const char *value) { }
void SentryNativeBridgeOptionsSetInt(void *options, const char *name, int32_t value) { }
void SentryNativeBridgeStartWithOptions(void *options) { }

void Close() {
[SentrySDK close];
}
int SentryNativeBridgeCrashedLastRun() { return [SentrySDK crashedLastRun] ? 1 : 0; }

void SentryNativeBridgeAddBreadcrumb(const char* timestamp, const char* message, const char* type, const char* category, int level) {
void SentryNativeBridgeClose() { [SentrySDK close]; }

void SentryNativeBridgeAddBreadcrumb(
const char *timestamp, const char *message, const char *type, const char *category, int level)
{
if (timestamp == NULL && message == NULL && type == NULL && category == NULL) {
return;
}

[SentrySDK configureScope:^(SentryScope * scope) {
SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc] init];
[SentrySDK configureScope:^(SentryScope *scope) {
SentryBreadcrumb *breadcrumb = [[SentryBreadcrumb alloc]
initWithLevel:level
category:(category ? [NSString stringWithUTF8String:category] : nil)];

if (timestamp != NULL) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:NSCalendarIdentifierISO8601];
breadcrumb.timestamp = [dateFormatter dateFromString:[NSString stringWithCString:timestamp encoding:NSUTF8StringEncoding]];
breadcrumb.timestamp =
[dateFormatter dateFromString:[NSString stringWithUTF8String:timestamp]];
}

if (message != NULL) {
breadcrumb.message = [NSString stringWithCString:message encoding:NSUTF8StringEncoding];
breadcrumb.message = [NSString stringWithUTF8String:message];
}

if (type != NULL) {
breadcrumb.type = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
}

if (category != NULL) {
breadcrumb.category = [NSString stringWithCString:category encoding:NSUTF8StringEncoding];
breadcrumb.type = [NSString stringWithUTF8String:type];
}

breadcrumb.level = level;

[scope addBreadcrumb:breadcrumb];
}];
}

void SentryNativeBridgeSetExtra(const char* key, const char* value) {
void SentryNativeBridgeSetExtra(const char *key, const char *value)
{
if (key == NULL) {
return;
}

[SentrySDK configureScope:^(SentryScope * scope) {
[SentrySDK configureScope:^(SentryScope *scope) {
if (value != NULL) {
[scope setExtraValue:[NSString stringWithUTF8String:value] forKey:[NSString stringWithUTF8String:key]];
[scope setExtraValue:[NSString stringWithUTF8String:value]
forKey:[NSString stringWithUTF8String:key]];
} else {
[scope removeExtraForKey:[NSString stringWithUTF8String:key]];
}
}];
}

void SentryNativeBridgeSetTag(const char* key, const char* value) {
void SentryNativeBridgeSetTag(const char *key, const char *value)
{
if (key == NULL) {
return;
}

[SentrySDK configureScope:^(SentryScope * scope) {
[SentrySDK configureScope:^(SentryScope *scope) {
if (value != NULL) {
[scope setTagValue:[NSString stringWithUTF8String:value] forKey:[NSString stringWithUTF8String:key]];
[scope setTagValue:[NSString stringWithUTF8String:value]
forKey:[NSString stringWithUTF8String:key]];
} else {
[scope removeTagForKey:[NSString stringWithUTF8String:key]];
}
}];
}

void SentryNativeBridgeUnsetTag(const char* key) {
void SentryNativeBridgeUnsetTag(const char *key)
{
if (key == NULL) {
return;
}

[SentrySDK configureScope:^(SentryScope * scope) {
[scope removeTagForKey:[NSString stringWithUTF8String:key]];
}];
[SentrySDK configureScope:^(
SentryScope *scope) { [scope removeTagForKey:[NSString stringWithUTF8String:key]]; }];
}

void SentryNativeBridgeSetUser(const char* email, const char* userId, const char* ipAddress, const char* username) {
void SentryNativeBridgeSetUser(
const char *email, const char *userId, const char *ipAddress, const char *username)
{
if (email == NULL && userId == NULL && ipAddress == NULL && username == NULL) {
return;
}

[SentrySDK configureScope:^(SentryScope * scope) {
[SentrySDK configureScope:^(SentryScope *scope) {
SentryUser *user = [[SentryUser alloc] init];

if (email != NULL) {
user.email = [NSString stringWithCString:email encoding:NSUTF8StringEncoding];
user.email = [NSString stringWithUTF8String:email];
}

if (userId != NULL) {
user.userId = [NSString stringWithCString:userId encoding:NSUTF8StringEncoding];
user.userId = [NSString stringWithUTF8String:userId];
}

if (ipAddress != NULL) {
user.ipAddress = [NSString stringWithCString:ipAddress encoding:NSUTF8StringEncoding];
user.ipAddress = [NSString stringWithUTF8String:ipAddress];
}

if (username != NULL) {
user.username = [NSString stringWithCString:username encoding:NSUTF8StringEncoding];
user.username = [NSString stringWithUTF8String:username];
vaind marked this conversation as resolved.
Show resolved Hide resolved
}

[scope setUser:user];
}];
}

void SentryNativeBridgeUnsetUser() {
[SentrySDK configureScope:^(SentryScope * scope) {
[scope setUser:nil];
}];
void SentryNativeBridgeUnsetUser()
{
[SentrySDK configureScope:^(SentryScope *scope) { [scope setUser:nil]; }];
}

NS_ASSUME_NONNULL_END
Loading