prebuild.sh raw
1 #!/bin/bash
2 #
3 # Fennec build scripts
4 # Copyright (C) 2020-2024 Matías Zúñiga, Andrew Nayenko, Tavi
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as
8 # published by the Free Software Foundation, either version 3 of the
9 # License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
15 #
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <https://www.gnu.org/licenses/>.
18 #
19
20 set -e
21
22 if [ -z "$1" ] || [ -z "$2" ]; then
23 echo "Usage: $0 versionName versionCode" >&1
24 exit 1
25 fi
26
27 # shellcheck source=paths.sh
28 source "$(dirname "$0")/paths.sh"
29
30 function localize_maven {
31 # Replace custom Maven repositories with mavenLocal()
32 find ./* -name '*.gradle' -type f -print0 | xargs -0 \
33 sed -n -i \
34 -e '/maven {/{:loop;N;/}$/!b loop;/plugins.gradle.org/!s/maven .*/mavenLocal()/};p'
35 # Make gradlew scripts call our Gradle wrapper
36 find ./* -name gradlew -type f | while read -r gradlew; do
37 echo -e '#!/bin/sh\ngradle "$@"' > "$gradlew"
38 chmod 755 "$gradlew"
39 done
40 }
41
42 function apply_patch {
43 echo "Apply $1"
44 patch -p1 --no-backup-if-mismatch --quiet < "$1"
45 }
46
47 # Set up Rust
48 rustup default 1.93.0
49
50 #
51 # Fenix
52 #
53
54 pushd "$fenix"
55
56 # Set up the app ID, version name and version code
57 sed -i \
58 -e 's|org\.mozilla\.firefox|lol.smesh.felice|' \
59 -e "s/Config.releaseVersionName(project)/'$1'/" \
60 -e "s/Config.generateFennecVersionCode(abi)/$2/" \
61 app/build.gradle
62 sed -i \
63 -e '/android:targetPackage/s/org\.mozilla\.firefox/lol.smesh.felice/' \
64 app/src/release/res/xml/shortcuts.xml
65
66 # Disable crash reporting
67 sed -i -e '/CRASH_REPORTING/s/true/false/' app/build.gradle
68
69 # Disable MetricController
70 sed -i -e '/TELEMETRY/s/true/false/' app/build.gradle
71
72 # Let it be Felice
73 sed -i -e 's/Firefox Daylight/Felice/; s/Firefox/Felice/g' \
74 app/src/*/res/values*/*strings.xml
75
76 # Fenix uses reflection to create a instance of profile based on the text of
77 # the label, see
78 # app/src/main/java/org/mozilla/fenix/perf/ProfilerStartDialogFragment.kt#185
79 sed -i \
80 -e 's/ProfilerSettings.Firefox/ProfilerSettings.Felice/' \
81 app/src/main/java/org/mozilla/fenix/perf/ProfilerStartDialogFragment.kt
82 sed -i \
83 -e '/Firefox(.*, .*)/s/Firefox/Felice/' \
84 -e 's/firefox_threads/felice_threads/' \
85 -e 's/firefox_features/felice_features/' \
86 app/src/main/java/org/mozilla/fenix/perf/ProfilerUtils.kt
87
88 # Replace proprietary artwork
89 sed -i -e 's|@drawable/animated_splash_screen<|@drawable/splash_screen<|' \
90 app/src/main/res/values-v*/styles.xml
91 find "$patches/fenix-overlay" -type f | while read -r src; do
92 dst=app/src/release/${src#"$patches/fenix-overlay/"}
93 mkdir -p "$(dirname "$dst")"
94 cp "$src" "$dst"
95 done
96 # Drop the Fennec fox vector; the release overlay provides Felice webps at every density
97 rm -f app/src/main/res/drawable/ic_firefox.xml
98
99 # Route completed .xpi downloads into AddonManager instead of the download-complete snackbar
100 sed -i \
101 -e '/^import org\.mozilla\.fenix\.components\.AppStore$/a\
102 import org.mozilla.fenix.ext.components' \
103 -e '/\/\/ If the download is just paused/i\
104 if (downloadJobStatus == Status.COMPLETED \&\&\
105 (downloadState.contentType == "application\/x-xpinstall" ||\
106 downloadState.fileName?.endsWith(".xpi") == true)) {\
107 val safeContext = context ?: return\
108 val fileUri = "file:\/\/" + downloadState.filePath\
109 safeContext.components.addonManager.installAddon(\
110 fileUri,\
111 mozilla.components.concept.engine.webextension.InstallationMethod.FROM_FILE,\
112 onSuccess = { },\
113 onError = { _ -> },\
114 )\
115 return\
116 }\
117 ' app/src/main/java/org/mozilla/fenix/browser/DownloadUtils.kt
118
119 # Register as handler for .xpi extension files
120 sed -i '/<action android:name="android.intent.action.SEND" \/>/i\
121 <intent-filter>\
122 <action android:name="android.intent.action.VIEW" \/>\
123 <category android:name="android.intent.category.BROWSABLE" \/>\
124 <category android:name="android.intent.category.DEFAULT" \/>\
125 <data android:scheme="http" \/>\
126 <data android:scheme="https" \/>\
127 <data android:mimeType="application\/x-xpinstall" \/>\
128 <\/intent-filter>\
129 \
130 <intent-filter>\
131 <action android:name="android.intent.action.VIEW" \/>\
132 <category android:name="android.intent.category.BROWSABLE" \/>\
133 <category android:name="android.intent.category.DEFAULT" \/>\
134 <data android:scheme="content" \/>\
135 <data android:scheme="file" \/>\
136 <data android:mimeType="application\/x-xpinstall" \/>\
137 <\/intent-filter>\
138 \
139 <intent-filter>\
140 <action android:name="android.intent.action.VIEW" \/>\
141 <category android:name="android.intent.category.BROWSABLE" \/>\
142 <category android:name="android.intent.category.DEFAULT" \/>\
143 <data android:scheme="content" \/>\
144 <data android:scheme="file" \/>\
145 <data android:host="*" \/>\
146 <data android:pathPattern=".*\\\\.xpi" \/>\
147 <\/intent-filter>\
148 ' app/src/main/AndroidManifest.xml
149
150 # There are a lot of "No cast needed" warnings in the generated code
151 sed -i -e '/compilerOptions.allWarningsAsErrors/s/true/false/' build.gradle
152
153 # Enable about:config
154 sed -i \
155 -e 's/aboutConfigEnabled(.*)/aboutConfigEnabled(true)/' \
156 app/src/*/java/org/mozilla/fenix/*/GeckoProvider.kt
157
158 # Disable remote improvements by default
159 sed -i \
160 -e '/android:defaultValue=/s/"true"/"false"/' \
161 app/src/main/res/xml/remote_improvements_preferences.xml
162
163 # Add wallpaper URL
164 echo 'https://gitlab.com/relan/fennecmedia/-/raw/master/wallpapers/android' > .wallpaper_url
165
166 # Set up target parameters
167 case $(echo "$2" | cut -c 6) in
168 0)
169 abi=armeabi-v7a
170 target=arm-linux-androideabi
171 echo "ARM" > "$llvm/targets_to_build"
172 rusttarget=arm
173 rustup target add thumbv7neon-linux-androideabi
174 rustup target add armv7-linux-androideabi
175 ;;
176 1)
177 abi=x86_64
178 target=x86_64-linux-android
179 echo "X86" > "$llvm/targets_to_build"
180 rusttarget=x86_64
181 rustup target add x86_64-linux-android
182 ;;
183 2)
184 abi=arm64-v8a
185 target=aarch64-linux-android
186 echo "AArch64" > "$llvm/targets_to_build"
187 rusttarget=arm64
188 rustup target add aarch64-linux-android
189 ;;
190 *)
191 echo "Unknown target code in $2." >&2
192 exit 1
193 ;;
194 esac
195 sed -i -e "s/include \".*\"/include \"$abi\"/" app/build.gradle
196
197 # Disable FUS Service or we'll get errors like:
198 # Exception while loading configuration for :app: Could not load the value of field `__buildFusService__` of task `:app:compileFenixReleaseKotlin` of type `org.jetbrains.kotlin.gradle.tasks.KotlinCompile`.
199 echo "kotlin.internal.collectFUSMetrics=false" >> local.properties
200
201 popd
202
203 #
204 # Glean
205 #
206
207 pushd "$glean"
208 echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties
209 localize_maven
210 popd
211
212 #
213 # Glean for Application Services
214 #
215
216 pushd "$glean_as"
217 echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties
218 localize_maven
219 popd
220
221 #
222 # Android Components
223 #
224
225 pushd "$android_components"
226 find "$patches/a-c-overlay" -type f | while read -r src; do
227 cp "$src" "${src#"$patches/a-c-overlay/"}"
228 done
229 # Add the added search engines as `general` engines
230 sed -i \
231 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "brave",' \
232 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "ddghtml",' \
233 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "ddglite",' \
234 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "metager",' \
235 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "mojeek",' \
236 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "qwantlite",' \
237 -e '/GENERAL_SEARCH_ENGINE_IDS = setOf/a\ "startpage",' \
238 components/feature/search/src/main/java/mozilla/components/feature/search/storage/SearchEngineReader.kt
239 popd
240
241 #
242 # UnifiedPush Android Component
243 #
244
245 pushd "$unifiedpush_ac"
246 localize_maven
247 # Set A-C version
248 echo "mozilla.version=${1%.0}" >> local.properties
249 # Set A-S version
250 sed -i -e 's/0.0.1-SNAPSHOT-+/149.0/' gradle/libs.versions.toml
251 popd
252
253 #
254 # Application Services
255 #
256
257 pushd "$application_services"
258 rm -vrf components/remote_settings/dumps/*/attachments/search-config-icons/*
259 find "$patches/a-s-overlay" -type f | while read -r src; do
260 cp "$src" "${src#"$patches/a-s-overlay/"}"
261 done
262 # Remove Mozilla repositories substitution and explicitly add the required ones
263 apply_patch "$patches/a-s-localize_maven.patch"
264 # Configure default search engines
265 apply_patch "$patches/a-s-configure-default-search-engines.patch"
266 # Break the dependency on older A-C
267 sed -i -e '/android-components = /s/"146\.0\.1"/"149.0"/' gradle/libs.versions.toml
268 echo "rust.targets=linux-x86-64,$rusttarget" >> local.properties
269 sed -i -e '/NDK ez-install/,/^$/d' libs/verify-android-ci-environment.sh
270 popd
271
272 #
273 # WASI SDK
274 #
275
276 pushd "$wasi"
277 apply_patch "$mozilla_release/taskcluster/scripts/misc/wasi-sdk.patch"
278 popd
279
280 #
281 # GeckoView
282 #
283
284 pushd "$mozilla_release"
285
286 # Remove unneeded dependecies
287 apply_patch "$patches/gecko-dependencies.patch"
288
289 # Remove Mozilla repositories substitution and explicitly add the required ones
290 apply_patch "$patches/gecko-localize_maven.patch"
291
292 # Replace GMS with microG client library
293 apply_patch "$patches/gecko-liberate.patch"
294
295 # Work-around upstream bug to fix compilation with WASI SDK 20, see
296 # https://bugzilla.mozilla.org/show_bug.cgi?id=1994063
297 apply_patch "$patches/gecko-unbreak-wasi-sdk-20-clang.patch"
298
299 # Add UnifiedPush support
300 apply_patch "$unifiedpush_ac/patches/a-c-unifiedpush.patch"
301 apply_patch "$unifiedpush_ac/patches/fenix-unifiedpush.patch"
302
303 # Patch the use of proprietary and tracking libraries
304 apply_patch "$patches/fenix-liberate.patch"
305
306 # Disable search engines configuration fetching from a Mozilla server
307 apply_patch "$patches/fenix-disable-remote-search-configuration.patch"
308 sed -i 's|https://firefox.settings.services.allizom.org/v1/buckets/main/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs
309 sed -i 's|https://firefox.settings.services.allizom.org/v1/buckets/main-preview/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs
310 sed -i 's|https://firefox.settings.services.mozilla.com/v1/buckets/main/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs
311 sed -i 's|https://firefox.settings.services.mozilla.com/v1/buckets/main-preview/collections/search-config/records||g' toolkit/components/search/SearchUtils.sys.mjs
312
313 # Remove the use of RemoteSettingsCrashPull, the part of the crash reporter
314 apply_patch "$patches/fenix-disable-crashpull.patch"
315
316 # Remove "Sent from Firefox" reference on sharing
317 apply_patch "$patches/fenix-disable-sent-from-fx.patch"
318
319 # Add "Enable UnifiedPush" and "Use UnifiedPush" settings
320 apply_patch "$patches/fenix-use-unifiedpush.patch"
321
322 # Fail on use of prebuilt binary
323 sed -i 's|https://|hxxps://|' mobile/android/gradle/plugins/nimbus-gradle-plugin/src/main/groovy/org/mozilla/appservices/tooling/nimbus/NimbusGradlePlugin.groovy
324
325 # Make Nimbus Gradle Plugin use obj/dist/host/bin/nimbus-fml which we copy
326 # there manually from A-S. Otherwise Nimbus Gradle Plugin tries to download
327 # nimbus-fml from Mozilla.
328 sed -i 's/project.gradle.ext.mozconfig.substs.MOZ_APPSERVICES_IN_TREE/true/' mobile/android/gradle/plugins/nimbus-gradle-plugin/src/main/groovy/org/mozilla/appservices/tooling/nimbus/NimbusGradlePlugin.groovy
329
330 # Fix v125 aar output not including native libraries
331 sed -i \
332 -e 's/singleVariant("debug")/singleVariant("release")/' \
333 mobile/android/exoplayer2/build.gradle
334 sed -i \
335 -e "s/singleVariant('debug')/singleVariant('release')/" \
336 mobile/android/geckoview/build.gradle
337
338 # Hack the timeout for
339 # geckoview:generateJNIWrappersForGeneratedWithGeckoBinariesDebug
340 sed -i \
341 -e 's/max_wait_seconds=600/max_wait_seconds=1800/' \
342 mobile/android/gradle.py
343
344 # Patch the LLVM source code
345 # Search clang- in https://android.googlesource.com/platform/ndk/+/refs/tags/ndk-r28b/ndk/toolchains.py
346 LLVM_SVN='530567'
347 python3 "$toolchain_utils/llvm_tools/patch_manager.py" \
348 --svn_version "$LLVM_SVN" \
349 --patch_metadata_file "$llvm_android/patches/PATCHES.json" \
350 --src_path "$llvm"
351
352 # Fail on use of prebuilt binary
353 sed -i 's|https://github.com|hxxps://github.com|' python/mozboot/mozboot/android.py
354
355 # Make the build system think we installed the emulator and an AVD
356 mkdir -p "$ANDROID_HOME/emulator"
357 touch "$ANDROID_HOME/emulator/emulator"
358 chmod +x "$ANDROID_HOME/emulator/emulator"
359 mkdir -p "$HOME/.mozbuild/android-device/avd"
360
361 # Use terser from Debian
362 sed -i \
363 -e 's|terser_path = terser_dir / ".*"|terser_path = Path("/usr/bin/terser")|' \
364 python/mozbuild/mozpack/files.py
365
366 # Configure
367 cat << EOF > mozconfig
368 ac_add_options --disable-crashreporter
369 ac_add_options --disable-debug
370 ac_add_options --disable-tests
371 ac_add_options --disable-updater
372 ac_add_options --enable-application=mobile/android
373 ac_add_options --enable-release
374 ac_add_options --enable-update-channel=release
375 ac_add_options --target=$target
376 ac_add_options --with-android-ndk="$ANDROID_NDK"
377 ac_add_options --with-android-sdk="$ANDROID_SDK"
378 ac_add_options --with-libclang-path="$llvm/out/lib"
379 ac_add_options --with-java-bin-path="/usr/bin"
380 ac_add_options --with-gradle=$(command -v gradle)
381 ac_add_options --with-wasi-sysroot="$wasi/build/install/wasi/share/wasi-sysroot"
382 ac_add_options CC="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/clang"
383 ac_add_options CXX="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++"
384 ac_add_options STRIP="$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip"
385 ac_add_options WASM_CC="$wasi/build/install/wasi/bin/clang"
386 ac_add_options WASM_CXX="$wasi/build/install/wasi/bin/clang++"
387 mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj
388 mk_add_options MOZ_MAKE_FLAGS="-j1"
389 export MOZ_REQUIRE_SIGNING=
390 EOF
391
392 # Disable Gecko Media Plugins and casting
393 sed -i -e '/gmp-provider/d; /casting.enabled/d' mobile/android/app/geckoview-prefs.js
394 cat << EOF >> mobile/android/app/geckoview-prefs.js
395
396 // Disable Encrypted Media Extensions
397 pref("media.eme.enabled", false);
398
399 // Disable Gecko Media Plugins
400 pref("media.gmp-provider.enabled", false);
401
402 // Avoid openh264 being downloaded
403 pref("media.gmp-manager.url.override", "data:text/plain,");
404
405 // Disable openh264 if it is already downloaded
406 pref("media.gmp-gmpopenh264.enabled", false);
407
408 // Disable RemoteSettingsCrashPull
409 pref("browser.crashReports.crashPull", false, locked);
410 pref("browser.crashReports.requestedNeverShowAgain", true, locked);
411
412 // Disable mandatory extension signing
413 pref("xpinstall.signatures.required", false);
414
415 // Allow extension installs from any site
416 pref("xpinstall.whitelist.fileRequest", true);
417 pref("extensions.langpacks.signatures.required", false);
418 pref("extensions.experiments.enabled", true);
419 pref("extensions.install.requireBuiltInCerts", false);
420 pref("extensions.webextensions.restrictedDomains", "");
421 pref("xpinstall.whitelist.required", false);
422 pref("xpinstall.whitelist.directRequest", true);
423
424 pref("browser.startup.homepage_override.mstone", "ignore");
425 EOF
426
427 popd
428
429 # On cold start with no tabs to restore and no intent URL, open smesh.lol.
430 # Fenix ignores browser.startup.homepage on Android — this is the only way.
431 sed -i '/maybeShowSetAsDefaultBrowserPrompt()$/i\
432 if (!settings().shouldReturnToBrowser) {\
433 openToBrowserAndLoad(\
434 searchTermOrURL = "https:\/\/smesh.lol",\
435 newTab = true,\
436 from = BrowserDirection.FromGlobal,\
437 )\
438 }' "$fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt"
439