Repository navigation
Expand file tree
/
Copy pathBuildMacOSPackages.sh
More file actions
executable file
·257 lines (235 loc) · 8.67 KB
/
Copy pathBuildMacOSPackages.sh
File metadata and controls
executable file
·257 lines (235 loc) · 8.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
#!/bin/bash
APP_NAME="ULogViewer"
FRAMEWORK="net11.0"
DEFAULT_RID_LIST=("osx-arm64" "osx-x64")
DEFAULT_PUB_PLATFORM_LIST=("osx-arm64" "osx-x64")
RID_LIST=()
PUB_PLATFORM_LIST=()
CONFIG="Release"
TRIM_ASSEMBLIES="true"
TESTING_MODE_BUILD="false"
MACOS_SDK_VERSION="26.0" # Linked SDK version to write into the application binary, opts-in to the window design of macOS 26+
CERT_NAME="" # Name of certification to sign the application
SIGN_PACKAGE="true"
RUN_TESTS="true"
TESTS_ONLY="false"
# Print usage of this script.
print_usage() {
echo "Usage: BuildMacOSPackages.sh [options]"
echo " "
echo "Options:"
echo " -h, --help Print this help message and exit."
echo " --config <name> Build configuration to use. (Default: $CONFIG)"
echo " --rid <rid> Runtime identifier to build package for, can be specified multiple times."
echo " Supported: ${DEFAULT_RID_LIST[*]}. (Default: all of them)"
echo " --no-sign Do not sign the built application."
echo " --no-trim Do not trim assemblies while publishing the application."
echo " --testing-mode Build the application in testing mode."
echo " --no-tests Do not run test cases before building packages."
echo " --tests-only Only run test cases without building packages."
}
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
print_usage
exit 0
;;
--config)
if [ -z "$2" ]; then
echo "Missing value of '--config'"
exit 1
fi
CONFIG="$2"
shift 2
;;
--rid)
if [ -z "$2" ]; then
echo "Missing value of '--rid'"
exit 1
fi
RID_INDEX=-1
for i in "${!DEFAULT_RID_LIST[@]}"; do
if [ "${DEFAULT_RID_LIST[$i]}" = "$2" ]; then
RID_INDEX=$i
break
fi
done
if [ "$RID_INDEX" = "-1" ]; then
echo "Unsupported runtime identifier: $2"
echo "Supported runtime identifiers: ${DEFAULT_RID_LIST[*]}"
exit 1
fi
IS_RID_SELECTED="false"
for SELECTED_RID in "${RID_LIST[@]}"; do
if [ "$SELECTED_RID" = "$2" ]; then
IS_RID_SELECTED="true"
break
fi
done
if [ "$IS_RID_SELECTED" = "false" ]; then
RID_LIST+=("${DEFAULT_RID_LIST[$RID_INDEX]}")
PUB_PLATFORM_LIST+=("${DEFAULT_PUB_PLATFORM_LIST[$RID_INDEX]}")
fi
shift 2
;;
--no-sign)
SIGN_PACKAGE="false"
shift
;;
--no-trim)
TRIM_ASSEMBLIES="false"
shift
;;
--testing-mode)
TESTING_MODE_BUILD="true"
shift
;;
--no-tests)
RUN_TESTS="false"
shift
;;
--tests-only)
TESTS_ONLY="true"
shift
;;
*)
echo "Unknown argument: $1"
echo " "
print_usage
exit 1
;;
esac
done
# Select all runtime identifiers if none of them was specified
if [ ${#RID_LIST[@]} -eq 0 ]; then
RID_LIST=("${DEFAULT_RID_LIST[@]}")
PUB_PLATFORM_LIST=("${DEFAULT_PUB_PLATFORM_LIST[@]}")
fi
# Check conflict between arguments
if [ "$TESTS_ONLY" = "true" ] && [ "$RUN_TESTS" = "false" ]; then
echo "Cannot specify both '--no-tests' and '--tests-only'"
exit 1
fi
echo "********** Start building $APP_NAME **********"
# Run test cases
if [ "$RUN_TESTS" = "true" ]; then
echo "Run test cases"
dotnet test $APP_NAME.Tests -c $CONFIG
if [ "$?" != "0" ]; then
echo "Test cases failed"
exit 1
fi
fi
# Stop if only test cases need to be run
if [ "$TESTS_ONLY" = "true" ]; then
exit 0
fi
# Get application version
VERSION=$(dotnet run PackagingTool.cs -- get-current-version $APP_NAME/$APP_NAME.csproj)
if [ "$?" != "0" ]; then
echo "Unable to get version of $APP_NAME"
exit 1
fi
INFORMATIONAL_VERSION=$(dotnet run PackagingTool.cs -- get-current-informational-version $APP_NAME/$APP_NAME.csproj)
PACKAGE_VERSION=$VERSION
if [ ! -z "$INFORMATIONAL_VERSION" ]; then
PACKAGE_VERSION=$INFORMATIONAL_VERSION
fi
echo "Version: $VERSION ($PACKAGE_VERSION)"
# Create output directory
if [[ ! -d "./Packages" ]]; then
echo "Create directory 'Packages'"
mkdir ./Packages
if [ "$?" != "0" ]; then
exit 1
fi
fi
if [[ ! -d "./Packages/$VERSION" ]]; then
echo "Create directory 'Packages/$VERSION'"
mkdir ./Packages/$VERSION
if [ "$?" != "0" ]; then
exit 1
fi
fi
# Build packages
for i in "${!RID_LIST[@]}"; do
RID=${RID_LIST[$i]}
PUB_PLATFORM=${PUB_PLATFORM_LIST[$i]}
echo " "
echo "[$PUB_PLATFORM ($RID)]"
echo " "
# clean
rm -r ./$APP_NAME/bin/$CONFIG/$FRAMEWORK/$RID
dotnet clean $APP_NAME
dotnet restore $APP_NAME
if [ "$?" != "0" ]; then
exit 1
fi
# build
dotnet publish $APP_NAME -c $CONFIG -p:SelfContained=true -p:PublishSingleFile=false -p:PublishTrimmed=$TRIM_ASSEMBLIES -p:RuntimeIdentifier=$RID -p:TestingModeBuild=$TESTING_MODE_BUILD
dotnet msbuild $APP_NAME -t:BundleApp -property:Configuration=$CONFIG -p:SelfContained=true -p:PublishSingleFile=false -p:PublishTrimmed=$TRIM_ASSEMBLIES -p:RuntimeIdentifier=$RID -p:TestingModeBuild=$TESTING_MODE_BUILD
if [ "$?" != "0" ]; then
exit 1
fi
# create output directory
if [[ -d "./Packages/$VERSION/$PUB_PLATFORM" ]]; then
rm -r ./Packages/$VERSION/$PUB_PLATFORM
fi
echo "Create directory 'Packages/$VERSION/$PUB_PLATFORM'"
mkdir ./Packages/$VERSION/$PUB_PLATFORM
if [ "$?" != "0" ]; then
exit 1
fi
# copy .app directory to output directory
mv ./$APP_NAME/bin/$CONFIG/$FRAMEWORK/$RID/publish/$APP_NAME.app ./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app
if [ "$?" != "0" ]; then
exit 1
fi
# copy application icon and remove unnecessary files
cp ./$APP_NAME/$APP_NAME.icns ./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app/Contents/Resources/$APP_NAME.icns
if [ "$?" != "0" ]; then
exit 1
fi
rm -rf ./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app/Contents/MacOS/*.png
rm -rf ./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app/Contents/MacOS/*.pdb
rm -rf ./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app/Contents/MacOS/*.dSYM
# [Workaround] Rewrite the linked SDK version of the application binary to opt-in to the window design of macOS 26+.
# AppKit selects window chrome by the linked SDK version of the main executable, and the .NET apphost is still
# linked against an old SDK. Must be done before signing, otherwise the signature will be invalidated.
APP_BINARY="./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app/Contents/MacOS/$APP_NAME"
if [ -z "$(command -v vtool)" ]; then
echo "Unable to find 'vtool', please install Xcode"
exit 1
fi
MIN_OS_VERSION=$(vtool -show-build-version "$APP_BINARY" | awk '/minos/ { print $2; exit }')
if [ -z "$MIN_OS_VERSION" ]; then
echo "Unable to get minimum OS version from '$APP_BINARY'"
exit 1
fi
echo "Set linked SDK version of '$APP_BINARY' to $MACOS_SDK_VERSION"
vtool -set-build-version macos "$MIN_OS_VERSION" "$MACOS_SDK_VERSION" -replace -output "$APP_BINARY" "$APP_BINARY"
if [ "$?" != "0" ]; then
exit 1
fi
# sign application
if [ "$SIGN_PACKAGE" = "true" ]; then
echo "Sign package 'Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app'"
codesign --deep --force --options=runtime --timestamp --entitlements "./$APP_NAME/$APP_NAME.entitlements" -s "$CERT_NAME" "./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app"
if [ "$?" != "0" ]; then
echo "Failed to sign package 'Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app'"
rm -f "./Packages/$VERSION/$APP_NAME-$PACKAGE_VERSION-$PUB_PLATFORM.zip"
exit 1
fi
else
echo "Skip signing package 'Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app'"
codesign --deep --force -s - "./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app" # Restore ad-hoc signature invalidated by vtool
fi
# zip .app directory
ditto -c -k --sequesterRsrc --keepParent "./Packages/$VERSION/$PUB_PLATFORM/$APP_NAME.app" "./Packages/$VERSION/$APP_NAME-$PACKAGE_VERSION-$PUB_PLATFORM.zip"
if [ "$?" != "0" ]; then
exit 1
fi
done
# Generate package manifest
# dotnet run PackagingTool.cs -- create-package-manifest osx $APP_NAME $VERSION