CARVIEW |
Select Language
HTTP/2 200
date: Sat, 26 Jul 2025 18:10:38 GMT
content-type: text/html; charset=utf-8
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
x-repository-download: git clone https://github.com/dotnet/android.git
etag: W/"08761288af2358454dd26d39c98d2a22"
cache-control: max-age=0, private, must-revalidate
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
content-encoding: gzip
accept-ranges: bytes
set-cookie: _gh_sess=4T7CKyBJBpmFGvy9lYFhZRgNmQwtnxI4OmMTlCmx%2BEWjiMpElZI%2B6b%2BII0KDRA6bsG5VPLChfb%2B9YPp%2BTH4Oi%2B1C57rL8izFmf5kA%2BTG%2FsmR6F3UteZmYBLrimjq7fV6RAdOcnQbtYc8sj1lP7T5rVtuk705Xt%2BPECrQt7PGSwEpnc88kvQ69dVkenj8PPNr4WL%2BJ%2FGd0vv6Riqx5Kv8pBf52xe6hIdB4j2EGUNpkEBaMUcPf89SEbilHOQukAsK%2FIm0ANJfWuFcppdRuM67ww%3D%3D--OjeevGKGl249cc1a--yc2mdpKyhGWzzboRT3p5Sg%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.808935469.1753553437; Path=/; Domain=github.com; Expires=Sun, 26 Jul 2026 18:10:37 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Sun, 26 Jul 2026 18:10:37 GMT; HttpOnly; Secure; SameSite=Lax
x-github-request-id: C7BE:29FD1F:7F7924:A46A18:68851A1D
[Xamarin.Android.Build.Tasks] generate R.java like Android Studio (#2… · dotnet/android@0355558 · GitHub
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
Copy file name to clipboard
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
Skip to content
Navigation Menu
{{ message }}
-
Notifications
You must be signed in to change notification settings - Fork 555
Commit 0355558
[Xamarin.Android.Build.Tasks] generate R.java like Android Studio (#2896)
Context: https://android.googlesource.com/platform/tools/base/+/refs/heads/master/build-system/builder/
Fixes: #2680
Fixes: #2836
The current behavior in the `_GenerateJavaDesignerForComponent`
MSBuild target does the following:
* For each library that has Android resources... (in parallel)
* Run an instance of `aapt`/`aapt2` to generate the `R.java` file
for each library.
* This actually creates an `R.java` file that contains *every*
resource id for *every* library. These libraries are not using
most of these ids.
This has a few problems:
* Issue #2680 notes a problem where a file is locked on Windows
during `_GenerateJavaDesignerForComponent`:
Xamarin.Android.Common.targets(1541,2): The process cannot access the file 'C:\repos\msalnet\tests\devapps\XForms\XForms.Android\obj\Debug\90\lp\26\jl\manifest\AndroidManifest.xml' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.StreamWriter.CreateFile(String path, Boolean append, Boolean checkHost)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding, Int32 bufferSize, Boolean checkHost)
at System.IO.StreamWriter..ctor(String path, Boolean append, Encoding encoding)
at Xamarin.Android.Tasks.ManifestDocument.Save(String filename)
at Xamarin.Android.Tasks.Aapt.GenerateCommandLineCommands(String ManifestFile, String currentAbi, String currentResourceOutputFile)
at Xamarin.Android.Tasks.Aapt.ProcessManifest(ITaskItem manifestFile)
at System.Threading.Tasks.Parallel.<>c__DisplayClass30_0`2.<ForEachWorker>b__0(Int32 i)
at System.Threading.Tasks.Parallel.<>c__DisplayClass17_0`1.<ForWorker>b__1()
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.InnerInvokeWithArg(Task childTask)
at System.Threading.Tasks.Task.<>c__DisplayClass176_0.<ExecuteSelfReplicating>b__0(Object ) [C:\repos\msalnet\tests\devapps\XForms\XForms.Android\XForms.Android.csproj]
* We are hugely contributing to the dex limit for fields. Apps
contain exponentially more fields for each library with resources.
An example from @PureWeen:
1> trouble writing output: Too many field references to fit in one dex file: 70468; max is 65536.
* Quite a few instances of `aapt`/`aapt2` startup on developer's
machines: this pegs the CPU. We have had a few general
complaints about it.
Reviewing the source code for the Android gradle plugin, here is what
they do:
1. Build the main app's "full" `R.txt` file.
2. For each library, load its `R.txt` file.
3. Map each resource in the library's `R.txt` back to the main app
4. Write a small `R.java` file for each library containing *only*
the lines from the `R.txt` and updated integer values from the
main app `R.txt` file.
Looking into this, can we do the exact same thing? We have the
`R.txt` file one directory above where we extract resources for each
library. We already had code parsing `R.txt` files we could
repurpose. The only thing *new* is a `R.java` writer: a pretty
simple port from java.
The results are great!
Before:
3173 ms _GenerateJavaDesignerForComponentAapt2 1 calls
After:
20 ms GenerateLibraryResources 1 calls
`_GenerateJavaDesignerForComponent` is now completely gone. This is
a total savings of ~3 seconds on first build and incremental builds
with library changes.
To compare APKs, I used:
$ ~/android-toolchain/sdk/tools/bin/apkanalyzer dex packages Xamarin.Forms_Performance_Integration-Before.apk | grep ^F
Which omits a line for each field such as:
F d 0 0 16 xamarin.forms_performance_integration.R$color int abc_background_cache_hint_selector_material_dark
So then, before these changes there were ~30000 fields:
$ ~/android-toolchain/sdk/tools/bin/apkanalyzer dex packages Xamarin.Forms_Performance_Integration-Before.apk | grep ^F | wc -l
29681
After, there are less than 18000 (58%!):
$ ~/android-toolchain/sdk/tools/bin/apkanalyzer dex packages Xamarin.Forms_Performance_Integration-After.apk | grep ^F | wc -l
17210
12K less fields in a "Hello World" Xamarin.Forms app!
Comparing file sizes seems good, too:
$ zipinfo Xamarin.Forms_Performance_Integration-Before.apk | grep classes.dex
-rw-rw-r-- 6.3 unx 3657872 b- defX 19-Mar-28 16:37 classes.dex
$ zipinfo Xamarin.Forms_Performance_Integration-After.apk | grep classes.dex
-rw-rw-r-- 6.3 unx 3533120 b- defX 19-Mar-28 16:20 classes.dex
The `.dex` file in the `.apk` is ~120KB smaller.
~~ What if R.txt is missing? ~~
I found this was the case when the
`<GetAdditionalResourcesFromAssemblies/>` MSBuild task runs. This is
an old codepath that allowed old support libraries to work.
In this case, a directory is created such as:
* `obj\Debug\resourcecache\CF390EBB0064FDA00BB090E733D37E89`
* `aidl`
* `AndroidManifest.xml`
* `assets`
* `classes.jar`
* `libs`
* `res`
No `R.txt` file?
Checking the zip files we download:
$ for z in ~/.local/share/Xamarin/zips/*.zip; do zipinfo $z; done | grep R.txt
# no results
This actually makes sense, since the zip file contains the
*actual resources*.
To make this case work properly, we should just process the main
app's `R.txt` file when no library `R.txt` file is found. This will
still be faster than invoking `aapt`, even though we have more
fields than needed.
~~ Tests ~~
I added a set of unit tests for the `<GenerateLibraryResources/>`
MSBuild task. I also had to remove a few assertions that looked for
the `_GenerateJavaDesignerForComponent` MSBuild target.
Lastly, I added some assertions to a test that uses an old support
library to verify it's main `R.java` reasonably matches the library
`R.java` we generate.1 parent 04f76f8 commit 0355558Copy full SHA for 0355558
File tree
Expand file treeCollapse file tree
8 files changed
+498
-111
lines changedFilter options
- src/Xamarin.Android.Build.Tasks
- MSBuild/Xamarin/Android
- Tasks
- Tests/Xamarin.Android.Build.Tests
- Tasks
Expand file treeCollapse file tree
8 files changed
+498
-111
lines changedsrc/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets-28Lines changed: 0 additions & 28 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
138 | 138 |
| |
139 | 139 |
| |
140 | 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 | 141 |
|
src/Xamarin.Android.Build.Tasks/Tasks/GenerateLibraryResources.cs
Copy file name to clipboard+234Lines changed: 234 additions & 0 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
| 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 | + |
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs+1-31Lines changed: 1 addition & 31 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
638 | 638 |
| |
639 | 639 |
| |
640 | 640 |
| |
641 |
| - | |
642 |
| - | |
643 |
| - | |
644 |
| - | |
645 |
| - | |
646 |
| - | |
647 |
| - | |
648 |
| - | |
649 |
| - | |
650 |
| - | |
651 |
| - | |
652 |
| - | |
653 |
| - | |
654 |
| - | |
655 |
| - | |
656 |
| - | |
657 |
| - | |
658 |
| - | |
659 |
| - | |
660 |
| - | |
661 |
| - | |
662 |
| - | |
663 |
| - | |
664 |
| - | |
665 |
| - | |
666 |
| - | |
667 |
| - | |
668 |
| - | |
669 |
| - | |
670 |
| - | |
671 | 641 |
| |
672 | 642 |
| |
673 | 643 |
| |
| |||
1421 | 1391 |
| |
1422 | 1392 |
| |
1423 | 1393 |
| |
1424 |
| - | |
| 1394 | + | |
1425 | 1395 |
| |
1426 | 1396 |
| |
1427 | 1397 |
| |
|
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
Copy file name to clipboardExpand all lines: src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs+31-2Lines changed: 31 additions & 2 deletions
Original file line number | Diff line number | Diff line change | |
---|---|---|---|
| |||
350 | 350 |
| |
351 | 351 |
| |
352 | 352 |
| |
353 |
| - | |
354 | 353 |
| |
355 | 354 |
| |
356 | 355 |
| |
| |||
455 | 454 |
| |
456 | 455 |
| |
457 | 456 |
| |
458 |
| - | |
459 | 457 |
| |
460 | 458 |
| |
461 | 459 |
| |
| |||
2443 | 2441 |
| |
2444 | 2442 |
| |
2445 | 2443 |
| |
| 2444 | + | |
| 2445 | + | |
| 2446 | + | |
| 2447 | + | |
| 2448 | + | |
| 2449 | + | |
| 2450 | + | |
| 2451 | + | |
| 2452 | + | |
| 2453 | + | |
| 2454 | + | |
| 2455 | + | |
| 2456 | + | |
| 2457 | + | |
| 2458 | + | |
| 2459 | + | |
| 2460 | + | |
| 2461 | + | |
| 2462 | + | |
| 2463 | + | |
| 2464 | + | |
| 2465 | + | |
| 2466 | + | |
| 2467 | + | |
| 2468 | + | |
| 2469 | + | |
| 2470 | + | |
| 2471 | + | |
| 2472 | + | |
| 2473 | + | |
| 2474 | + | |
2446 | 2475 |
| |
2447 | 2476 |
| |
2448 | 2477 |
| |
|
You can’t perform that action at this time.
0 commit comments