From 7e27544f3860098acc9c5615754c5063ecec3a00 Mon Sep 17 00:00:00 2001 From: "CSIGS@microsoft.com" Date: Wed, 20 Mar 2024 03:47:48 -0700 Subject: [PATCH 01/17] LEGO: Merge pull request 8820 LEGO: Merge pull request 8820 --- .../localize/templatestrings.json.lcl | 7 +++-- .../localize/templatestrings.json.lcl | 7 +++-- .../Properties/Resources.resx.lcl | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/Localize/loc/de/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.json.lcl b/Localize/loc/de/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.json.lcl index b37273d5fd6..fc936621b19 100644 --- a/Localize/loc/de/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.json.lcl +++ b/Localize/loc/de/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.json.lcl @@ -29,10 +29,13 @@ - + - + + + + diff --git a/Localize/loc/de/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.json.lcl b/Localize/loc/de/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.json.lcl index 81656e3e69f..99fc8394055 100644 --- a/Localize/loc/de/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.json.lcl +++ b/Localize/loc/de/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.json.lcl @@ -29,10 +29,13 @@ - + - + + + + diff --git a/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 3177ea9dd5a..0b6be50bb81 100644 --- a/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -417,6 +417,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + From ed2739b346a7314ba9d68845f1f08090c8d47148 Mon Sep 17 00:00:00 2001 From: VS MobileTools Engineering Service 2 Date: Wed, 20 Mar 2024 07:35:11 -0700 Subject: [PATCH 02/17] Localized file check-in by OneLocBuild Task (#8819) Context: https://aka.ms/onelocbuild Context: https://aka.ms/AllAboutLoc Build definition ID 17928: Build ID 9273182 --- .../.template.config/localize/templatestrings.cs.json | 2 +- .../.template.config/localize/templatestrings.es.json | 2 +- .../.template.config/localize/templatestrings.fr.json | 2 +- .../.template.config/localize/templatestrings.it.json | 2 +- .../.template.config/localize/templatestrings.ja.json | 2 +- .../.template.config/localize/templatestrings.ko.json | 2 +- .../.template.config/localize/templatestrings.pl.json | 2 +- .../.template.config/localize/templatestrings.pt-BR.json | 2 +- .../.template.config/localize/templatestrings.ru.json | 2 +- .../.template.config/localize/templatestrings.tr.json | 2 +- .../.template.config/localize/templatestrings.zh-Hans.json | 2 +- .../.template.config/localize/templatestrings.zh-Hant.json | 2 +- .../.template.config/localize/templatestrings.cs.json | 2 +- .../.template.config/localize/templatestrings.es.json | 2 +- .../.template.config/localize/templatestrings.fr.json | 2 +- .../.template.config/localize/templatestrings.it.json | 2 +- .../.template.config/localize/templatestrings.ja.json | 2 +- .../.template.config/localize/templatestrings.ko.json | 2 +- .../.template.config/localize/templatestrings.pl.json | 2 +- .../.template.config/localize/templatestrings.pt-BR.json | 2 +- .../.template.config/localize/templatestrings.ru.json | 2 +- .../.template.config/localize/templatestrings.tr.json | 2 +- .../.template.config/localize/templatestrings.zh-Hans.json | 2 +- .../.template.config/localize/templatestrings.zh-Hant.json | 2 +- .../Properties/Resources.cs.resx | 6 +++--- .../Properties/Resources.es.resx | 6 +++--- .../Properties/Resources.fr.resx | 6 +++--- .../Properties/Resources.it.resx | 6 +++--- .../Properties/Resources.ja.resx | 6 +++--- .../Properties/Resources.ko.resx | 6 +++--- .../Properties/Resources.pl.resx | 6 +++--- .../Properties/Resources.pt-BR.resx | 6 +++--- .../Properties/Resources.ru.resx | 6 +++--- .../Properties/Resources.tr.resx | 6 +++--- .../Properties/Resources.zh-Hans.resx | 6 +++--- .../Properties/Resources.zh-Hant.resx | 6 +++--- 36 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.cs.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.cs.json index 2c7a5fb488e..9aca093e47a 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.cs.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.cs.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Aktivita na Androidu", "description": "Třída aktivity Androidu", "symbols/namespace/description": "obor názvů pro vygenerovaný kód", "postActions/openInEditor/description": "Otevře soubor Activity1.cs v editoru" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.es.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.es.json index 0b5889febf4..a54693781fa 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.es.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.es.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Actividad de Android", "description": "Una clase de actividad de Android", "symbols/namespace/description": "espacio de nombres para el código generado", "postActions/openInEditor/description": "Abre Activity1.cs en el editor" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.fr.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.fr.json index 9ef7a13d917..01669851d48 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.fr.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.fr.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Activité Android", "description": "Une classe d’activité Android", "symbols/namespace/description": "espace de noms pour le code généré", "postActions/openInEditor/description": "Ouvre Activity1.cs dans l’éditeur" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.it.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.it.json index 7c156f6c459..1e243d91ed2 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.it.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.it.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Attività di Android", "description": "Classe di attività Android", "symbols/namespace/description": "spazio dei nomi per il codice generato", "postActions/openInEditor/description": "Apre Activity1.cs nell'editor" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ja.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ja.json index d25bf9506c0..f4a4aa3f6f3 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ja.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ja.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Android アクティビティ", "description": "Android アクティビティ クラス", "symbols/namespace/description": "生成されたコードの名前空間", "postActions/openInEditor/description": "エディターで Activity1.cs を開きます" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ko.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ko.json index 23314be7f1c..30e13980a91 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ko.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ko.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Android 활동", "description": "Android 활동 클래스", "symbols/namespace/description": "생성된 코드의 네임스페이스", "postActions/openInEditor/description": "편집기에서 Activity1.cs를 엽니다." diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pl.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pl.json index c08d08cd96f..4cff6911e44 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pl.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pl.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Działanie systemu Android", "description": "Klasa Aktywność systemu Android", "symbols/namespace/description": "przestrzeń nazw wygenerowanego kodu.", "postActions/openInEditor/description": "Otwiera plik Activity1.cs w edytorze" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pt-BR.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pt-BR.json index 661ea64b3fc..e7af7028ace 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pt-BR.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.pt-BR.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Atividade do Android", "description": "Uma classe de Atividade do Android", "symbols/namespace/description": "namespace do código gerado", "postActions/openInEditor/description": "Abre Activity1.cs no editor" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ru.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ru.json index b14a5c3819f..b8daaa654d7 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ru.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.ru.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Действие Android", "description": "Класс активности Android", "symbols/namespace/description": "пространство имен для созданного кода", "postActions/openInEditor/description": "Открывает Activity1.cs в редакторе" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.tr.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.tr.json index 11e6fca1286..ba40b023e83 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.tr.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.tr.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Android Etkinliği", "description": "Android Etkinlik sınıfı", "symbols/namespace/description": "oluşturulan kod için ad alanı", "postActions/openInEditor/description": "Activity1.cs dosyasını düzenleyicide açar" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hans.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hans.json index aae1495fad4..fb37b2363c2 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hans.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hans.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Android 活动", "description": "Android 活动类", "symbols/namespace/description": "生成的代码的命名空间", "postActions/openInEditor/description": "在编辑器中打开 Activity1.cs" diff --git a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hant.json b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hant.json index 93e88a5b136..1729b644f7e 100644 --- a/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hant.json +++ b/src/Microsoft.Android.Templates/android-activity/.template.config/localize/templatestrings.zh-Hant.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Activity", + "name": "Android 活動", "description": "Android 活動類別", "symbols/namespace/description": "適用於產生之程式碼的命名空間", "postActions/openInEditor/description": "在編輯器中開啟 Activity1.cs" diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.cs.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.cs.json index a7d8196424b..83e9616b84c 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.cs.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.cs.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Rozložení Androidu", "description": "Soubor rozložení Androidu (XML)", "postActions/openInEditor/description": "Otevře soubor Layout1.xml v editoru" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.es.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.es.json index 12eaf398ce4..5c531350db7 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.es.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.es.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Diseño de Android", "description": "Un archivo de diseño de Android (XML)", "postActions/openInEditor/description": "Abre Layout1.xml en el editor" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.fr.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.fr.json index febaf069f42..e0ee3fdde59 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.fr.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.fr.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Navigation Android", "description": "Fichier de disposition Android (XML)", "postActions/openInEditor/description": "Ouvre Layout1.xml dans l’éditeur" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.it.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.it.json index 509976aca0d..2d047e7c052 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.it.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.it.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Layout Android", "description": "File di layout Android (XML)", "postActions/openInEditor/description": "Apre Layout1.xml nell'editor" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ja.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ja.json index 2271bc56c75..5cbce40d892 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ja.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ja.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Android レイアウト", "description": "Android レイアウト (XML) ファイル", "postActions/openInEditor/description": "エディターで Layout1.xml を開きます" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ko.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ko.json index 32164416b0f..e48c806e419 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ko.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ko.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Android 레이아웃", "description": "Android 레이아웃(XML) 파일", "postActions/openInEditor/description": "편집기에서 Layout1.xml 엽니다." } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pl.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pl.json index 1d07b020667..504c3e59ab5 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pl.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pl.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Układ systemu Android", "description": "Plik układu systemu Android (XML)", "postActions/openInEditor/description": "Otwiera plik Layout1.xml w edytorze" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pt-BR.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pt-BR.json index b0b529cfe55..f69325989ed 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pt-BR.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.pt-BR.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Layout do Android", "description": "Um arquivo de layout do Android (XML)", "postActions/openInEditor/description": "Abre Layout1.xml no editor" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ru.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ru.json index 9ef322a8c76..e4765a0198f 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ru.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.ru.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Макет Android", "description": "Файл макета Android (XML)", "postActions/openInEditor/description": "Открывает Layout1.xml в редакторе" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.tr.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.tr.json index 05823701f09..50e9231a49e 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.tr.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.tr.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Android Düzeni", "description": "Android düzeni (XML) dosyası", "postActions/openInEditor/description": "Layout1.xml dosyasını düzenleyicide açar" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hans.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hans.json index 93b7e549967..3aaae6f5cdf 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hans.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hans.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Android 布局", "description": "Android 布局 (XML) 文件", "postActions/openInEditor/description": "在编辑器中打开 Layout1.xml" } \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hant.json b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hant.json index 0adcbc216da..baa1b6fe942 100644 --- a/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hant.json +++ b/src/Microsoft.Android.Templates/android-layout/.template.config/localize/templatestrings.zh-Hant.json @@ -1,6 +1,6 @@ { "author": "Microsoft", - "name": "Android Layout", + "name": "Android 配置", "description": "Android 配置 (XML) 檔案", "postActions/openInEditor/description": "在編輯器中開啟 Layout1.xml" } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx index 7b3a141387c..23f9179bd4d 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Metadata položek %(AndroidAsset.AssetPack) a %(AndroidAsset.AssetPack) se podporují jenom v případě, že $(AndroidApplication) je true. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + @(AndroidAsset) {0} má neplatná metadata DeliveryType pro {1}. Podporované hodnoty jsou installtime, ondemand nebo fastfollow. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + Hodnota AssetPack definovaná pro {0} obsahuje neplatné znaky. Hodnota {1} by měla obsahovat pouze znaky A–Z, a–z, 0–9 nebo podtržítko. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx index 5468dc4a071..79780efc298 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Los metadatos de elemento de "AndroidAsset.AssetPack") y "AndroidAsset.AssetPack" solo se admiten cuando "$(AndroidApplication)" es "true". - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + '@(AndroidAsset)' '{0}' tiene metadatos 'DeliveryType' no válidos de '{1}'. Los valores admitidos son "installtime", "ondemand" o "fastfollow". {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + El valor AssetPack definido para '{0}' tiene caracteres no válidos. '{1}' solo debe contener A-z, a-z, 0-9 o un carácter de subrayado. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx index 5887bd7c892..7d5d33c0b48 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Les métadonnées des éléments %(AndroidAsset.AssetPack) et %(AndroidAsset.AssetPack) sont uniquement prises en charge lorsque `$(AndroidApplication)` est `true`. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + `@(AndroidAsset)`{0}` a une métadonnée `DeliveryType` invalide de `{1}`. Les valeurs prises en charge sont `installtime`, `ondemand` ou `fastfollow`. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + La valeur AssetPack définie pour `{0}` contient des caractères non valides. `{1}` doit contenir uniquement A-z, a-z, 0-9 ou un trait de soulignement. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx index 626403495a0..b325500c2f8 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + I metadati degli elementi %(AndroidAsset.AssetPack) e %(AndroidAsset.AssetPack) sono supportati solo quando '$(AndroidApplication)' è 'true'. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + '@(AndroidAsset)' '{0}' contiene metadati 'DeliveryType' non validi di '{1}'. I valori supportati sono 'installtime', 'ondemand' o 'fastfollow'. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + Il valore AssetPack definito per '{0}' contiene caratteri non validi. '{1}' deve contenere solo A-z, a-z, 0-9 o un carattere di sottolineatura. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx index d739e788d1a..fe841ef5138 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + %(AndroidAsset.AssetPack) および %(AndroidAsset.AssetPack) 項目メタデータは、'$(AndroidApplication)' が 'true' の場合にのみサポートされます。 - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + '@(AndroidAsset)' '{0}' に、'{1}' の無効な 'DeliveryType' メタデータがあります。サポートされている値は、'installtime'、'ondemand'、または 'fastfollow' です。 {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + '{0}' に定義された AssetPack 値に無効な文字が含まれています。'{1}' には、A-z、a-z、0-9、またはアンダースコアのみを含める必要があります。 {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx index e9ff8e5cb5a..8141f11381e 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + %(AndroidAsset.AssetPack) 및 %(AndroidAsset.AssetPack) 항목 메타데이터는 '$(AndroidApplication)'이 'true'인 경우에만 지원됩니다. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + '@(AndroidAsset)' '{0}'에 '{1}'의 잘못된 'DeliveryType' 메타데이터가 있습니다. 지원되는 값은 'installtime', 'ondemand' 또는 'fastfollow'입니다. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + '{0}'에 대해 정의된 AssetPack 값에 잘못된 문자가 있습니다. '{1}'은(는) A-z, a-z, 0-9 또는 밑줄만 포함해야 합니다. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx index 95e41b7f1b3..6e51cc77b1a 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Metadane elementów %(AndroidAsset.AssetPack) i %(AndroidAsset.AssetPack) są obsługiwane tylko wtedy, gdy parametr „$(AndroidApplication)” ma wartość „true”. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + Plik „@(AndroidAsset)” „{0}” ma nieprawidłowe metadane „DeliveryType” atrybutu „{1}”. Obsługiwane wartości to „installtime”, „ondemand” lub „fastfollow”. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + Wartość AssetPack zdefiniowana dla pliku „{0}” zawiera nieprawidłowe znaki. Wartość atrybutu „{1}” powinna zawierać tylko znaki A-z, a-z, 0-9 lub podkreślenie. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx index 5cf638fb51c..bbc7f72f033 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Os metadados do item %(AndroidAsset.AssetPack) e %(AndroidAsset.AssetPack) só têm suporte quando “$(AndroidApplication)” é “true”. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + “{0}” do “@(AndroidAsset)” tem um metadado “DeliveryType” inválido de “{1}”. Os valores com suporte são “installtime”, “ondemand” ou “fastfollow”. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + O valor do AssetPack definido para “{0}” tem caracteres inválidos. “{1}” deve conter apenas A-z, a-z, 0-9 ou um sublinhado. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx index 1dcfa59c35b..f9155c1a0be 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + Метаданные элементов %(AndroidAsset.AssetPack) и %(AndroidAsset.AssetPack) поддерживаются, только если "$(AndroidApplication)" имеет значение "true". - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + "@(AndroidAsset)" "{0}" содержит недопустимые метаданные DeliveryType "{1}". Поддерживаемые значения: "installtime", "ondemand" или "fastfollow". {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + Значение AssetPack, определенное для "{0}", содержит недопустимые символы. "{1}" должен содержать только A-z, a-z, 0-9 или символ подчеркивания. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx index 5a937c38be2..4dcfe4ba2d6 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + %(AndroidAsset.AssetPack) ve %(AndroidAsset.AssetPack) öğe meta verileri yalnızca `$(AndroidApplication)` değeri `true` olduğunda desteklenir. - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + `@(AndroidAsset)` `{0}` geçersiz `DeliveryType` `{1}` meta verisini içeriyor. Desteklenen değerler şunlardır: `installtime`, `ondemand` veya `fastfollow`. {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + `{0}` için tanımlanan AssetPack geçersiz karakterler içeriyor. `{1}` yalnızca A-z, a-z, 0-9 veya alt çizgi içermelidir. {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx index c65728ddaea..80702147f25 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + 仅当 `$(AndroidApplication)` 为 `true` 时,才支持 %(AndroidAsset.AssetPack)和 %(AndroidAsset.AssetPack)项元数据。 - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + `@(AndroidAsset)` `{0}` 的 `DeliveryType` 元数据 `{1}` 无效。支持的值为 `installtime`、`ondemand` 或 `fastfollow`。 {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + 为 `{0}` 定义的 AssetPack 值包含无效字符。`{1}` 应仅包含 A-z、a-z、0-9 或下划线。 {0} - The file name {1} - The value of the attribute in the metadata. diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx index 43503b28e39..941b9f87b3b 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx @@ -330,16 +330,16 @@ The capitalized word "Portable" that appears earlier in the message is plain tex {0} - The file name of a deprecated symbol file - %(AndroidAsset.AssetPack) and %(AndroidAsset.AssetPack) item metadata are only supported when `$(AndroidApplication)` is `true`. + 只有在 '$(AndroidApplication)' 為 'true' 時,才支援 %(AndroidAsset.AssetPack) 與 %(AndroidAsset.AssetPack) 項目中繼資料。 - `@(AndroidAsset)` `{0}` has an invalid `DeliveryType` metadata of `{1}`. Supported values are `installtime`, `ondemand` or `fastfollow`. + '@(AndroidAsset)' '{0}' 的 'DeliveryType' 中繼資料 '{1}' 無效。支援的值為 'installtime'、'ondemand' 或 'fastfollow'。 {0} - The file name {1} - The value of the attribute in the project file. - The AssetPack value defined for `{0}` has invalid characters. `{1}` should only contain A-z, a-z, 0-9 or an underscore. + 為 `{0}` 定義的 AssetPack 值包含無效字元。`{1}` 只能包含 A-z、a-z、0-9 或底線。 {0} - The file name {1} - The value of the attribute in the metadata. From 9a782d7f404d83240fb7dce9548fccbb0d679e17 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 20 Mar 2024 12:57:20 -0500 Subject: [PATCH 03/17] [One .NET] new "greenfield" projects are trimmed by default (#8805) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: 5205a5f0f0d6f85a765038138a4713c1c2e0a783 Context: 8a5b2a0b2c3a5998c6225492bb68863828aedad7 Context: https://github.com/xamarin/xamarin-android/issues/8724 Context: https://github.com/xamarin/xamarin-android/issues/8797 As we have solved all trimming warnings (5205a5f0. 8a5b2a0b) in the Android workload, we can now go "all in" on trimming. Early in .NET 6 (maybe even 5?) we "hid" many trimming warnings as we did not yet plan to solve them: true These warnings were not *actionable* at the time for customers, as many warnings were in `Mono.Android.dll`, `Java.Interop.dll`, etc. Going forward, let's stop suppressing these warnings for `$(TrimMode)`=full. We can also enable trimming for new projects: * `dotnet new android` * `dotnet new android-wear` New projects will have the [`$(TrimMode)`][0] property set to `Full` by default: full We wouldn't want to do this for existing projects *yet*, as they might have existing code, NuGet packages, etc. where trimming warnings might be present. We can also improve the templates for Android class libraries: * `dotnet new androidlib` * `dotnet new android-bindinglib` New class library projects will have the [`$(IsTrimmable)`][1] property set to `true` by default: true This way, new class libraries will be "trimmable" by default and be able to react to trimming warnings. We can also use `$(TrimMode)=full` in many of our existing tests: * MSBuild tests that assert 0 warnings can use `$(TrimMode)=full`. * On-device tests can use `$(TrimMode)=full`. ~~ General trimming warnings ~~ This was discovered through `Mono.Android-NET-Tests.csproj`, but there were a few trimmer warnings in the "layout bindings" feature: …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(79,56): warning IL2091: Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0.b__0(Activity): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.FragmentManager.FindFragmentById(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.<>c__DisplayClass8_0' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(35,5): warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView(Int32, T&): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.App.Activity.FindViewById(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView(Int32, T&)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. …\dotnet\packs\Microsoft.Android.Sdk.Windows\…\tools\LayoutBinding.cs(37,5): warning IL2091: Xamarin.Android.Design.LayoutBinding.FindView(Int32, T&): 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Android.Views.View.FindViewById(Int32)'. The generic parameter 'T' of 'Xamarin.Android.Design.LayoutBinding.FindView(Int32, T&)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to. We can `[DynamicallyAccessedMembers(Constructors)]` to fix these. ~~ Trimming warnings in tests ~~ Several tests that verify "trimming unsafe features" just specify: [RequiresUnreferencedCode ("Tests trimming unsafe features")] If the test might have an issue under NativeAOT, I used: // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 #pragma warning disable IL3050 Places that use `Assembly.GetType()` can use `Type.GetType()` instead: -var JavaProxyThrowable_type = typeof (Java.Lang.Object) - .Assembly - .GetType ("Android.Runtime.JavaProxyThrowable"); +var JavaProxyThrowable_type = Type.GetType ("Android.Runtime.JavaProxyThrowable, Mono.Android"); `SystemTests.AppDomainTest` was just ignored (and had warnings). Update to just verify `PlatformNotSupportedException` is thrown. ~~ Test failures ~~ `JsonSerializerTest` requires setting [`$(JsonSerializerIsReflectionEnabledByDefault)`][2]=true: true Otherwise, an exception is thrown: System.InvalidOperationException : JsonSerializerIsReflectionDisabled `Java.Interop-Tests` were initially not loaded at all, with the log message: W NUnit : Failed to load tests from assembly 'Java.Interop-Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065 If we make `Java.Interop-Tests.dll` a `@(TrimmerRootAssembly)`: Then all the tests cases are preserved and can be run, in the same way the "main app assembly" is preserved. `Android.GraphicsTests.NinePatchTests` failed with: The drawable created from resource tile should be a NinePatchDrawable. Expected: not null But was: null The only usage of `NinePatchDrawable` was: Assert.IsNotNull (d as NinePatchDrawable); `NinePatchDrawable` likely needs its interfaces and constructors preserved for this test to pass. I added an attribute for just `All` members for the test to pass: [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (NinePatchDrawable))] `Xamarin.Android.RuntimeTests.CustomWidgetTests` failed with: (Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView) at Java.Interop.JniEnvironment.InstanceMethods.CallObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* ) at Java.Interop.JniPeerMembers.JniInstanceMethods.InvokeVirtualObjectMethod(String , IJavaPeerable , JniArgumentValue* ) at Android.Views.LayoutInflater.Inflate(Int32 , ViewGroup ) at Xamarin.Android.RuntimeTests.CustomWidgetTests.<>c.b__0_0() at NUnit.Framework.Constraints.VoidInvocationDescriptor.Invoke() at NUnit.Framework.Constraints.ExceptionInterceptor.Intercept(Object ) --- End of managed Java.Lang.RuntimeException stack trace --- android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView Caused by: android.view.InflateException: Binary XML file line #1 in Mono.Android.NET_Tests:layout/uppercase_custom: Error inflating class Mono.Android_Test.Library.CustomTextView Caused by: java.lang.ClassNotFoundException: Mono.Android_Test.Library.CustomTextView at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:454) at android.view.LayoutInflater.createView(LayoutInflater.java:815) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1006) at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:961) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1123) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.inflate(LayoutInflater.java:682) at android.view.LayoutInflater.inflate(LayoutInflater.java:534) at android.view.LayoutInflater.inflate(LayoutInflater.java:481) at crc643df67da7b13bb6b1.TestInstrumentation_1.n_onStart(Native Method) at crc643df67da7b13bb6b1.TestInstrumentation_1.onStart(TestInstrumentation_1.java:32) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) Caused by: java.lang.ClassNotFoundException: Didn't find class "Mono.Android_Test.Library.CustomTextView" on path In this case, `Mono.Android_Test.Library.CustomTextView` was used from an Android layout, but not used anywhere in managed code. To fix, I added: [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (Mono.Android_Test.Library.CustomTextView))] I could have also made `Mono.Android_Test.Library` a `@(TrimmerRootAssembly)`. TODO: `View` subclasses used within Android Layout `.axml` files should be automatically preserved; see xamarin/xamarin-android#8797. [0]: https://learn.microsoft.com/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-8-0#trimming-granularity [1]: https://learn.microsoft.com/dotnet/core/deploying/trimming/prepare-libraries-for-trimming?pivots=dotnet-8-0#enable-project-specific-trimming [2]: https://learn.microsoft.com/dotnet/core/compatibility/serialization/8.0/publishtrimmed --- .../android-bindinglib/AndroidBinding1.csproj | 5 +++ .../android-wear/AndroidApp1.csproj | 7 ++++ .../android/AndroidApp1.csproj | 7 ++++ .../androidlib/AndroidLib1.csproj | 5 +++ ...soft.Android.Sdk.DefaultProperties.targets | 3 +- .../Resources/LayoutBinding.cs | 31 ++++++++++++++--- .../Xamarin.Android.Build.Tests/BuildTest2.cs | 4 +++ .../Android/AndroidLinkMode.cs | 6 ++++ .../Android/KnownProperties.cs | 3 +- .../XamarinAndroidApplicationProject.cs | 5 +++ .../BindingTests.cs | 4 ++- .../Xamarin.Android.JcwGen-Tests.csproj | 4 +++ .../Android.Graphics/NinePatchTests.cs | 4 ++- .../Android.Widget/CustomWidgetTests.cs | 7 +++- .../Java.Lang/ObjectTest.cs | 12 +++++-- .../Mono.Android.NET-Tests.csproj | 4 +++ .../System/AppContextTests.cs | 7 +++- .../System.Drawing/TypeConverterTest.cs | 6 ++++ .../System.Text.Json/JsonSerializerTest.cs | 9 +++++ .../System/AppDomainTest.cs | 34 ++----------------- .../System/ExceptionTest.cs | 7 ++-- .../AndroidClientHandlerTests.cs | 2 ++ 22 files changed, 129 insertions(+), 47 deletions(-) diff --git a/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj b/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj index 5f78e42ab48..56c74d9fc01 100644 --- a/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj +++ b/src/Microsoft.Android.Templates/android-bindinglib/AndroidBinding1.csproj @@ -5,6 +5,11 @@ AndroidBinding1 enable enable + + true + + full + diff --git a/src/Microsoft.Android.Templates/android/AndroidApp1.csproj b/src/Microsoft.Android.Templates/android/AndroidApp1.csproj index 5a71d2ab599..c539a1f4c45 100644 --- a/src/Microsoft.Android.Templates/android/AndroidApp1.csproj +++ b/src/Microsoft.Android.Templates/android/AndroidApp1.csproj @@ -10,4 +10,11 @@ 1 1.0 + + + full + \ No newline at end of file diff --git a/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj b/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj index 3c076d5fd9d..d50d9b99196 100644 --- a/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj +++ b/src/Microsoft.Android.Templates/androidlib/AndroidLib1.csproj @@ -5,5 +5,10 @@ AndroidLib1 enable enable + + true \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets index 8504ad98ec8..5d4506284cd 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets @@ -74,8 +74,9 @@ SdkOnly None - link + full partial + false true android-arm;android-arm64;android-x86;android-x64 diff --git a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs index 86a260258f2..457c91add45 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs +++ b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs @@ -1,5 +1,5 @@ using System; - +using System.Diagnostics.CodeAnalysis; using Android.App; using Android.Views; @@ -9,6 +9,8 @@ namespace Xamarin.Android.Design abstract class LayoutBinding { + const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; + Activity boundActivity; View boundView; OnLayoutItemNotFoundHandler onLayoutItemNotFound; @@ -25,7 +27,13 @@ protected LayoutBinding (View view, OnLayoutItemNotFoundHandler onLayoutItemNotF this.onLayoutItemNotFound = onLayoutItemNotFound; } - protected T FindView (int resourceId, ref T cachedField) where T: View + protected T FindView < + [DynamicallyAccessedMembers (Constructors)] + T + > ( + int resourceId, + ref T cachedField) + where T: View { if (cachedField != null) return cachedField; @@ -58,7 +66,14 @@ Activity EnsureActivity () throw new InvalidOperationException ("Finding fragments is supported only for Activity instances"); } - T __FindFragment (int resourceId, Func finder, ref T cachedField) where T: Java.Lang.Object + T __FindFragment< + [DynamicallyAccessedMembers (Constructors)] + T + > ( + int resourceId, + Func finder, + ref T cachedField) + where T: Java.Lang.Object { if (cachedField != null) return cachedField; @@ -74,7 +89,15 @@ T __FindFragment (int resourceId, Func finder, ref T cachedField return ret; } #if __ANDROID_11__ - protected T FindFragment (int resourceId, global::Android.App.Fragment __ignoreMe, ref T cachedField) where T: global::Android.App.Fragment + protected T FindFragment< + [DynamicallyAccessedMembers (Constructors)] + T + > ( + int resourceId, + global::Android.App.Fragment __ignoreMe, + ref T cachedField + ) + where T: global::Android.App.Fragment { return __FindFragment (resourceId, (activity) => activity.FragmentManager.FindFragmentById (resourceId), ref cachedField); } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 507fb5c8aef..8e625dc3ab7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -240,6 +240,10 @@ public void BuildHasNoWarnings (bool isRelease, bool xamarinForms, bool multidex new XamarinFormsAndroidApplicationProject () : new XamarinAndroidApplicationProject (); proj.IsRelease = isRelease; + // Enable full trimming + if (!xamarinForms && isRelease) { + proj.TrimModeRelease = TrimMode.Full; + } if (multidex) { proj.SetProperty ("AndroidEnableMultiDex", "True"); } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidLinkMode.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidLinkMode.cs index eb3204389df..40dcd0946da 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidLinkMode.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidLinkMode.cs @@ -9,4 +9,10 @@ public enum AndroidLinkMode SdkOnly, Full, } + + public enum TrimMode + { + Partial, + Full, + } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs index 9473811e49e..fa20a560acd 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Xamarin.ProjectTools { @@ -18,6 +18,7 @@ public static class KnownProperties public const string RuntimeIdentifiers = "RuntimeIdentifiers"; public const string RunAOTCompilation = "RunAOTCompilation"; public const string PublishTrimmed = "PublishTrimmed"; + public const string TrimMode = "TrimMode"; public const string SupportedOSPlatformVersion = "SupportedOSPlatformVersion"; public const string Deterministic = "Deterministic"; diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index 67b77daceee..5b54d4b2201 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -155,6 +155,11 @@ public AndroidLinkMode AndroidLinkModeRelease { set { SetProperty (ReleaseProperties, KnownProperties.AndroidLinkMode, value.ToString ()); } } + public TrimMode TrimModeRelease { + get => Enum.TryParse (GetProperty (ReleaseProperties, KnownProperties.TrimMode), out TrimMode trimMode) ? trimMode : TrimMode.Partial; + set => SetProperty (ReleaseProperties, KnownProperties.TrimMode, value.ToString ().ToLowerInvariant ()); + } + public bool EnableMarshalMethods { get { return string.Equals (GetProperty (KnownProperties.AndroidEnableMarshalMethods), "True", StringComparison.OrdinalIgnoreCase); } set { SetProperty (KnownProperties.AndroidEnableMarshalMethods, value.ToString ()); } diff --git a/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/BindingTests.cs b/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/BindingTests.cs index 76ff290748d..33132c9479e 100644 --- a/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/BindingTests.cs +++ b/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/BindingTests.cs @@ -1,6 +1,7 @@ using System; using System.Reflection; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using NUnit.Framework; @@ -180,6 +181,7 @@ public void VirtualMethodBinding () } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void JavaAbstractMethodTest () { // Library is referencing APIv1, ICursor is from APIv2 @@ -198,7 +200,7 @@ public void JavaAbstractMethodTest () throw e; } - var mi = ic.GetType ().GetMethod ("global::Test.Bindings.ICursor.MethodWithCursor", BindingFlags.Instance | BindingFlags.NonPublic); + var mi = typeof (Library.MyClrCursor).GetMethod ("global::Test.Bindings.ICursor.MethodWithCursor", BindingFlags.Instance | BindingFlags.NonPublic); Assert.IsNotNull (mi, "ICursor.MethodWithCursor not found"); if (mi.GetMethodBody ()?.LocalVariables?.Count is not int x || x == 0) throw new Exception ("FixAbstractMethodStep broken, MethodWithRT added, while it should not be"); diff --git a/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj b/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj index da9c1c1f6e1..9b78edfbbbe 100644 --- a/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj +++ b/tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj @@ -18,6 +18,10 @@ ..\..\..\bin\Test$(Configuration) + + full + + diff --git a/tests/Mono.Android-Tests/Android.Graphics/NinePatchTests.cs b/tests/Mono.Android-Tests/Android.Graphics/NinePatchTests.cs index ecaf082aaca..5b342c2108c 100644 --- a/tests/Mono.Android-Tests/Android.Graphics/NinePatchTests.cs +++ b/tests/Mono.Android-Tests/Android.Graphics/NinePatchTests.cs @@ -1,5 +1,5 @@ using System; - +using System.Diagnostics.CodeAnalysis; using Android.App; using Android.Content.Res; using Android.Graphics; @@ -25,6 +25,7 @@ public class NinePatchTests }; [Test, TestCaseSource (nameof (NinePatchDrawables))] + [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (NinePatchDrawable))] public void DrawableFromRes_ShouldBeTypeNinePatchDrawable (int resId, string name) { var d = Application.Context.Resources.GetDrawable (resId); @@ -33,6 +34,7 @@ public void DrawableFromRes_ShouldBeTypeNinePatchDrawable (int resId, string nam } [Test, TestCaseSource (nameof (NinePatchDrawables))] + [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (NinePatchDrawable))] public void DrawableFromResStream_ShouldBeTypeNinePatchDrawable (int resId, string name) { var value = new Android.Util.TypedValue (); diff --git a/tests/Mono.Android-Tests/Android.Widget/CustomWidgetTests.cs b/tests/Mono.Android-Tests/Android.Widget/CustomWidgetTests.cs index 9ffd36a7328..ec2ab5bdc1d 100644 --- a/tests/Mono.Android-Tests/Android.Widget/CustomWidgetTests.cs +++ b/tests/Mono.Android-Tests/Android.Widget/CustomWidgetTests.cs @@ -1,9 +1,11 @@ -using Android.App; +using System.Diagnostics.CodeAnalysis; +using Android.App; using Android.Content; using Android.Util; using Android.Views; using Android.Widget; using NUnit.Framework; +using Mono.Android_Test.Library; namespace Xamarin.Android.RuntimeTests { @@ -12,6 +14,7 @@ public class CustomWidgetTests { // https://bugzilla.xamarin.com/show_bug.cgi?id=23880 [Test] + [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (CustomTextView))] public void UpperCaseCustomWidget_ShouldNotThrowInflateException () { Assert.DoesNotThrow (() => { @@ -21,6 +24,7 @@ public void UpperCaseCustomWidget_ShouldNotThrowInflateException () } [Test] + [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (CustomTextView))] public void LowerCaseCustomWidget_ShouldNotThrowInflateException () { Assert.DoesNotThrow (() => { @@ -30,6 +34,7 @@ public void LowerCaseCustomWidget_ShouldNotThrowInflateException () } [Test] + [DynamicDependency (DynamicallyAccessedMemberTypes.All, typeof (CustomTextView))] public void UpperAndLowerCaseCustomWidget_FromLibrary_ShouldNotThrowInflateException () { Assert.DoesNotThrow (() => { diff --git a/tests/Mono.Android-Tests/Java.Lang/ObjectTest.cs b/tests/Mono.Android-Tests/Java.Lang/ObjectTest.cs index 302ef9b2ac5..629f4dfdce3 100644 --- a/tests/Mono.Android-Tests/Java.Lang/ObjectTest.cs +++ b/tests/Mono.Android-Tests/Java.Lang/ObjectTest.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.IO.Compression; using System.Linq; @@ -47,12 +48,19 @@ public void JavaConvert_FromJavaObject_ShouldNotBreakExistingReferences () static Func GetIJavaObjectToInt32 () { - var JavaConvert = typeof (Java.Lang.Object).Assembly.GetType ("Java.Interop.JavaConvert"); + [UnconditionalSuppressMessage ("Trimming", "IL2060", Justification = "")] + static MethodInfo MakeGenericMethod (MethodInfo method, Type type) => + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + #pragma warning disable IL3050 + method.MakeGenericMethod (type); + #pragma warning restore IL3050 + + var JavaConvert = Type.GetType ("Java.Interop.JavaConvert, Mono.Android"); var FromJavaObject_T = JavaConvert.GetMethods (BindingFlags.Public | BindingFlags.Static) .First (m => m.Name == "FromJavaObject" && m.IsGenericMethod); return (Func) Delegate.CreateDelegate ( typeof(Func), - FromJavaObject_T.MakeGenericMethod (typeof (int))); + MakeGenericMethod (FromJavaObject_T, typeof (int))); } [Test] diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj index f21c94de80f..604d33d234a 100644 --- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj +++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj @@ -36,9 +36,13 @@ r8 + full + + true + <_AndroidRemapMembers Include="Remaps.xml" /> diff --git a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/System/AppContextTests.cs b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/System/AppContextTests.cs index da3228cffe5..9ac37a97742 100644 --- a/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/System/AppContextTests.cs +++ b/tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/System/AppContextTests.cs @@ -1,5 +1,6 @@ using NUnit.Framework; using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; namespace SystemTests @@ -44,7 +45,11 @@ public void GetData (string name, string expected) [Test] [TestCaseSource (nameof (TestPrivateSwitchesSource))] - public void TestPrivateSwitches (string className, string propertyName, object expected) + public void TestPrivateSwitches ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] + string className, + string propertyName, + object expected) { var type = Type.GetType (className, throwOnError: true); var members = type.GetMember (propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); diff --git a/tests/Mono.Android-Tests/System.Drawing/TypeConverterTest.cs b/tests/Mono.Android-Tests/System.Drawing/TypeConverterTest.cs index 18c164a3d6d..dbfb5d4ab65 100644 --- a/tests/Mono.Android-Tests/System.Drawing/TypeConverterTest.cs +++ b/tests/Mono.Android-Tests/System.Drawing/TypeConverterTest.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.Drawing; using NUnit.Framework; @@ -10,6 +11,7 @@ namespace System.Drawing { public class TypeConverterTest { [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void ColorConverter () { var typeConverter = TypeDescriptor.GetConverter (typeof (Color)); @@ -22,6 +24,7 @@ public void ColorConverter () } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void RectangleConverter () { var typeConverter = TypeDescriptor.GetConverter (typeof (Rectangle)); @@ -34,6 +37,7 @@ public void RectangleConverter () } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void PointConverter () { var typeConverter = TypeDescriptor.GetConverter (typeof (Point)); @@ -44,6 +48,7 @@ public void PointConverter () } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void SizeConverter () { var typeConverter = TypeDescriptor.GetConverter (typeof (Size)); @@ -54,6 +59,7 @@ public void SizeConverter () } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void SizeFConverter () { var typeConverter = TypeDescriptor.GetConverter (typeof (SizeF)); diff --git a/tests/Mono.Android-Tests/System.Text.Json/JsonSerializerTest.cs b/tests/Mono.Android-Tests/System.Text.Json/JsonSerializerTest.cs index 18714d9c99c..ce179773315 100644 --- a/tests/Mono.Android-Tests/System.Text.Json/JsonSerializerTest.cs +++ b/tests/Mono.Android-Tests/System.Text.Json/JsonSerializerTest.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using System.Text.Json; using NUnit.Framework; @@ -9,16 +10,24 @@ namespace System.Text.JsonTests { public class JsonSerializerTest { [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void Serialize () { + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + #pragma warning disable IL3050 string text = JsonSerializer.Serialize(42); + #pragma warning restore IL3050 Assert.AreEqual("42", text); } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void Deserialize () { + // FIXME: https://github.com/xamarin/xamarin-android/issues/8724 + #pragma warning disable IL3050 object value = JsonSerializer.Deserialize("42", typeof(int)); + #pragma warning restore IL3050 Assert.AreEqual(42, value); } } diff --git a/tests/Mono.Android-Tests/System/AppDomainTest.cs b/tests/Mono.Android-Tests/System/AppDomainTest.cs index 362804634d1..f2fd832dadf 100644 --- a/tests/Mono.Android-Tests/System/AppDomainTest.cs +++ b/tests/Mono.Android-Tests/System/AppDomainTest.cs @@ -1,10 +1,5 @@ using System; using System.Globalization; - -using Android.App; -using Android.Content; -using Android.Runtime; - using NUnit.Framework; namespace SystemTests { @@ -13,34 +8,9 @@ namespace SystemTests { public class AppDomainTest { [Test] - [Category ("HybridAotNotWorking")] // See https://github.com/xamarin/xamarin-android/issues/1536 - [Category ("DotNetIgnore")] // System.PlatformNotSupportedException : Secondary AppDomains are not supported on this platform. - public void DateTime_Now_Works () - { - new Boom().Bang(); - - - var otherDomain = AppDomain.CreateDomain ("other domain"); - - var otherType = typeof (Boom); - var obj = (Boom) otherDomain.CreateInstanceAndUnwrap ( - otherType.Assembly.FullName, - otherType.FullName); - obj.Bang (); - } - } - - class Boom : MarshalByRefObject - { - public void Bang() - { - var x = DateTime.Now; - Console.WriteLine ("Within AppDomain {0}, DateTime.Now={1}.", AppDomain.CurrentDomain.FriendlyName, x); - } - - public override object InitializeLifetimeService () + public void AppDomain_CreateDomain_Throws () { - return null; + Assert.Throws (() => AppDomain.CreateDomain ("other domain")); } } } diff --git a/tests/Mono.Android-Tests/System/ExceptionTest.cs b/tests/Mono.Android-Tests/System/ExceptionTest.cs index 19b1098d89c..a1511e393d2 100644 --- a/tests/Mono.Android-Tests/System/ExceptionTest.cs +++ b/tests/Mono.Android-Tests/System/ExceptionTest.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; @@ -16,9 +17,7 @@ public class ExceptionTest { static Java.Lang.Throwable CreateJavaProxyThrowable (Exception e) { - var JavaProxyThrowable_type = typeof (Java.Lang.Object) - .Assembly - .GetType ("Android.Runtime.JavaProxyThrowable"); + var JavaProxyThrowable_type = Type.GetType ("Android.Runtime.JavaProxyThrowable, Mono.Android"); MethodInfo? create = JavaProxyThrowable_type.GetMethod ( "Create", BindingFlags.Static | BindingFlags.Public, @@ -30,6 +29,7 @@ static Java.Lang.Throwable CreateJavaProxyThrowable (Exception e) } [Test] + [RequiresUnreferencedCode ("Tests trimming unsafe features")] public void InnerExceptionIsSet () { Exception ex; @@ -48,6 +48,7 @@ public void InnerExceptionIsSet () Assert.AreSame (ex, alias.InnerException); } + [RequiresUnreferencedCode ("Tests trimming unsafe features")] void CompareStackTraces (Exception ex, Java.Lang.Throwable throwable) { var managedTrace = new StackTrace (ex); diff --git a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs index 9046c528909..061319d86d4 100644 --- a/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs +++ b/tests/Mono.Android-Tests/Xamarin.Android.Net/AndroidClientHandlerTests.cs @@ -30,6 +30,7 @@ using System.Reflection; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Net.Http; @@ -160,6 +161,7 @@ static bool IsSecureChannelFailure (Exception e) return Exceptions (e).Any (v => (v as WebException)?.Status == WebExceptionStatus.SecureChannelFailure); } + [UnconditionalSuppressMessage ("Trimming", "IL2075", Justification = "Tests private fields are preserved by other means")] static Type GetInnerHandlerType (HttpClient httpClient) { BindingFlags bflasgs = BindingFlags.Instance | BindingFlags.NonPublic; From 385091a98dfb911ae22e24dcbddf1ce41dc41c31 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 22 Mar 2024 18:47:29 +0000 Subject: [PATCH 04/17] Fix assembly count when satellite assemblies are present (#8790) Fixes: https://github.com/xamarin/xamarin-android/issues/8789 The old method of satellite assembly counting relied on the `RelativePath` MSBuild item metadata, which appears to have gone missing somewhere in .NET8+. Update the code to check for presence of the following metadata, in order given, to determine assembly's culture, if any: * `Culture` * `RelativePath` * `DestinationSubDirectory` Failure to count satellite assemblies can, and sometimes will, result in a segfault since we generate a number of native code arrays based on the assembly count and the runtime assumes that what the build told it is true. --- .../Tasks/GeneratePackageManagerJava.cs | 2 +- .../Utilities/MonoAndroidHelper.cs | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs index 2f3e7bed8ef..cecfd42ada2 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs @@ -236,7 +236,7 @@ void AddEnvironment () HashSet archAssemblyNames = null; HashSet uniqueAssemblyNames = new HashSet (StringComparer.OrdinalIgnoreCase); Action updateAssemblyCount = (ITaskItem assembly) => { - string? culture = assembly.GetMetadata ("Culture"); + string? culture = MonoAndroidHelper.GetAssemblyCulture (assembly); string fileName = Path.GetFileName (assembly.ItemSpec); string assemblyName; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index fb598eadf2a..8fb845dd9df 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -585,6 +585,38 @@ public static string GetNativeLibsRootDirectoryPath (string androidBinUtilsDirec return Path.GetFullPath (Path.Combine (androidBinUtilsDirectory, relPath, "lib")); } + public static string? GetAssemblyCulture (ITaskItem assembly) + { + // The best option + string? culture = assembly.GetMetadata ("Culture"); + if (!String.IsNullOrEmpty (culture)) { + return TrimSlashes (culture); + } + + // ...slightly worse + culture = assembly.GetMetadata ("RelativePath"); + if (!String.IsNullOrEmpty (culture)) { + return TrimSlashes (Path.GetDirectoryName (culture)); + } + + // ...not ideal + culture = assembly.GetMetadata ("DestinationSubDirectory"); + if (!String.IsNullOrEmpty (culture)) { + return TrimSlashes (culture); + } + + return null; + + string? TrimSlashes (string? s) + { + if (String.IsNullOrEmpty (s)) { + return null; + } + + return s.TrimEnd ('/').TrimEnd ('\\'); + } + } + /// /// Process a collection of assembly `ITaskItem` objects, splitting it on the assembly architecture () while, at the same time, ignoring /// all assemblies which are **not** in the collection. If necessary, the selection can be further controlled by passing a qualifier From e206c52aee9afecfe63c1b4c0ad48bc90ed54ac1 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 22 Mar 2024 18:50:53 +0000 Subject: [PATCH 05/17] [runtime] Optionally disable inlining (#8798) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The native runtime by default builds with function inlining enabled, making heavy use of the feature in order to generate faster code. However, when debugging a native crash inlining causes stack traces to point to unlikely locations, reporting the outer function as the crash location instead of the inlined function where crash actually happened. In order to make such debugging easier, do one of the following: * Export the `XA_NO_INLINE` environment variable to "true-ish" export XA_NO_INLINE=1 * Set the `$(DoNotInlineMonodroid)` MSBuild property to true, either by adding to `Configuration.Override.props`: true> or by specifying on the command-line: ./dotnet-local.sh build Xamarin.Android.sln -p:DoNotInlineMonodroid=true … This will force all normally inlined functions to be strictly preserved and kept separate. The generated code will be slower, but crash stack traces should be much more precise. Additionally, `strip`ing of the native shared runtime can be disabled, making it easier to get full debug symbols. This can similarly be enabled by doing one of the following: * Export the `XA_NO_STRIP` environment variable to "true-ish" export XA_NO_STRIP=1 * Set the `$(DoNotStripMonodroid)` MSBuild property to true, either by adding to `Configuration.Override.props`: true> or by specifying on the command-line: ./dotnet-local.sh build Xamarin.Android.sln -p:DoNotStripMonodroid=true … In a Debug configuration build of xamarin-android, `libmono-android*.so` will *not* be `strip`d by `src/monodroid`. --- Documentation/building/configuration.md | 52 +++++++++++++++++++++++- build-tools/cmake/xa_macros.cmake | 1 - src/monodroid/CMakeLists.txt | 41 ++++++++++++++++--- src/monodroid/jni/cpp-util.hh | 5 +++ src/monodroid/jni/embedded-assemblies.hh | 2 +- src/monodroid/jni/helpers.hh | 4 +- src/monodroid/jni/platform-compat.hh | 9 +++- src/monodroid/monodroid.targets | 4 +- 8 files changed, 103 insertions(+), 15 deletions(-) diff --git a/Documentation/building/configuration.md b/Documentation/building/configuration.md index 5a7fe77425e..8114776ba72 100644 --- a/Documentation/building/configuration.md +++ b/Documentation/building/configuration.md @@ -1,3 +1,12 @@ + +- [Build Configuration](#build-configuration) + - [Options suitable to use in builds for public use](#options-suitable-to-use-in-builds-for-public-use) + - [Options suitable for local development](#options-suitable-for-local-development) + - [Native runtime (`src/monodroid`)](#native-runtime-srcmonodroid) + - [Disable function inlining](#disable-function-inlining) + - [Don't strip the runtime shared libraries](#dont-strip-the-runtime-shared-libraries) + + # Build Configuration The Xamarin.Android build is heavily dependent on MSBuild, with the *intention* @@ -10,6 +19,8 @@ However, some properties may need to be altered in order to suit your requirements, such as the location of a cache directory to store the Android SDK and NDK. +## Options suitable to use in builds for public use + To modify the build process, copy [`Configuration.Override.props.in`](../../Configuration.Override.props.in) to `Configuration.Override.props`, and edit the file as appropriate. @@ -93,7 +104,7 @@ Overridable MSBuild properties include: * `$(IgnoreMaxMonoVersion)`: Skip the enforcement of the `$(MonoRequiredMaximumVersion)` property. This is so that developers can run against the latest - and greatest. But the build system can enforce the min and max + and greatest. But the build system can enforce the min and max versions. The default is `true`, however on CI we use: /p:IgnoreMaxMonoVersion=False @@ -129,6 +140,43 @@ Overridable MSBuild properties include: * `4`: Mono 4.6 support. * `5`: Mono 4.8 and above support. This is the default. - * `$(AndroidEnableAssemblyCompression)`: Defaults to `True`. When enabled, all the + * `$(AndroidEnableAssemblyCompression)`: Defaults to `True`. When enabled, all the assemblies placed in the APK will be compressed in `Release` builds. `Debug` builds are not affected. + +## Options suitable for local development + +### Native runtime (`src/monodroid`) + +Note that in order for the native build settings to have full effect, one needs to make sure that +the entire native runtime is rebuilt **and** that all `cmake` files are regenerated. This is true +on the very first build, but rebuilds may require forcing the entire runtime to be rebuilt. + +The simplest way to do it is to remove `src/monodroid/obj` and run the usual build from the +repository's root directory. + +#### Disable function inlining + +The native runtime by default builds with function inlining enabled, making heavy use of +the feature in order to generate faster code. However, when debugging a native crash inlining +causes stack traces to point to unlikely locations, reporting the outer function as the crash +location instead of the inlined function where crash actually happened. There are two ways to +enable this mode of operation: + + 1. Export the `XA_NO_INLINE` environment variable before building either the entire repository + or just `src/monodroid/` + 2. Set the MSBuild property `DoNotInlineMonodroid` to `true`, when building `src/monodroid/monodroid.csproj` + +Doing either will force all normally inlined functions to be strictly preserved and kept +separate. The generated code will be slower, but crash stack traces should be much more precise. + +#### Don't strip the runtime shared libraries + +Similar to the previous section, this option makes crash stack traces more informative. In normal +builds, all the debugging information is stripped from the runtime shared libraries, thus making +stack traces rarely point to anything more than the surrounding function name (which may sometimes +be misleading, too). Just as for inlining, the no-strip mode can be enabled with one of two ways: + + 1. Export the `XA_NO_STRIP` environment variable before building either the entire repository + or just `src/monodroid/` + 2. Set the MSBuild property `DoNotStripMonodroid` to `true`, when building `src/monodroid/monodroid.csproj` diff --git a/build-tools/cmake/xa_macros.cmake b/build-tools/cmake/xa_macros.cmake index 58e75192bfd..df23bdedcd0 100644 --- a/build-tools/cmake/xa_macros.cmake +++ b/build-tools/cmake/xa_macros.cmake @@ -202,7 +202,6 @@ function(xa_common_prepare) -fno-strict-aliasing -ffunction-sections -funswitch-loops - -finline-limit=300 -Wa,-noexecstack -fPIC -g diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt index 7994193121a..e63f38aeb2b 100644 --- a/src/monodroid/CMakeLists.txt +++ b/src/monodroid/CMakeLists.txt @@ -29,14 +29,35 @@ set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_C_EXTENSIONS OFF) +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set(DEBUG_BUILD True) +else() + set(DEBUG_BUILD False) +endif() + +set(XA_NO_INLINE "$ENV{XA_NO_INLINE}") +if(XA_NO_INLINE) + set(DONT_INLINE_DEFAULT ON) +else() + set(DONT_INLINE_DEFAULT OFF) +endif() + +set(XA_NO_STRIP "$ENV{XA_NO_STRIP}") +if(XA_NO_STRIP OR DEBUG_BUILD) + set(STRIP_DEBUG_DEFAULT OFF) +endif() + option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF) option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF) if(ENABLE_CLANG_ASAN OR ENABLE_CLANG_UBSAN) + # ASAN and UBSAN always require the debug symbols to be left in the binary set(STRIP_DEBUG_DEFAULT OFF) set(ANALYZERS_ENABLED ON) else() - set(STRIP_DEBUG_DEFAULT ON) + if(NOT XA_NO_STRIP) + set(STRIP_DEBUG_DEFAULT ON) + endif() set(ANALYZERS_ENABLED OFF) endif() @@ -44,6 +65,7 @@ option(ENABLE_TIMING "Build with timing support" OFF) option(STRIP_DEBUG "Strip debugging information when linking" ${STRIP_DEBUG_DEFAULT}) option(DISABLE_DEBUG "Disable the built-in debugging code" OFF) option(USE_CCACHE "Use ccache, if found, to speed up recompilation" ON) +option(DONT_INLINE "Do not inline any functions which are usually inlined, to get better stack traces" ${DONT_INLINE_DEFAULT}) if(USE_CCACHE) if(CMAKE_CXX_COMPILER MATCHES "/ccache/") @@ -58,11 +80,7 @@ if(USE_CCACHE) endif() endif() -if(CMAKE_BUILD_TYPE STREQUAL Debug) - set(DEBUG_BUILD True) -else() - set(DEBUG_BUILD False) -endif() + if(ANDROID_STL STREQUAL none) set(USES_LIBSTDCPP False) @@ -179,6 +197,10 @@ add_compile_definitions(MONO_DLL_EXPORT) add_compile_definitions(NET) add_compile_definitions(JI_NO_VISIBILITY) +if(DONT_INLINE) + add_compile_definitions(NO_INLINE) +endif() + if(DEBUG_BUILD AND NOT DISABLE_DEBUG) add_compile_definitions(DEBUG) endif() @@ -293,6 +315,13 @@ endif() if(STRIP_DEBUG) list(APPEND LOCAL_COMMON_LINKER_ARGS LINKER:-S) +else() + # When not stripping symbols, we likely want to have precise stack traces, so + # we won't omit frame pointers + list(APPEND LOCAL_COMMON_COMPILER_ARGS + -fno-omit-frame-pointer + -fno-limit-debug-info + ) endif() # Parameters to both functions are (all required): diff --git a/src/monodroid/jni/cpp-util.hh b/src/monodroid/jni/cpp-util.hh index 4e698660b68..8f50149eb33 100644 --- a/src/monodroid/jni/cpp-util.hh +++ b/src/monodroid/jni/cpp-util.hh @@ -33,6 +33,11 @@ do_abort_unless (const char* fmt, ...) #define abort_if_invalid_pointer_argument(_ptr_) abort_unless ((_ptr_) != nullptr, "Parameter '%s' must be a valid pointer", #_ptr_) #define abort_if_negative_integer_argument(_arg_) abort_unless ((_arg_) > 0, "Parameter '%s' must be larger than 0", #_arg_) +// Helpers to use in "printf debugging". Normally not used in code anywhere. No code should be shipped with any +// of the macros present. +#define PD_LOG_LOCATION() log_info_nocheck (LOG_DEFAULT, "loc: %s:%d (%s)", __FILE__, __LINE__, __FUNCTION__) +#define PD_LOG_FUNCTION() log_info_nocheck (LOG_DEFAULT, "%s [%s:%d]", __PRETTY_FUNCTION__, __FILE__, __LINE__) + namespace xamarin::android { template diff --git a/src/monodroid/jni/embedded-assemblies.hh b/src/monodroid/jni/embedded-assemblies.hh index 72682132caf..be31ae1046c 100644 --- a/src/monodroid/jni/embedded-assemblies.hh +++ b/src/monodroid/jni/embedded-assemblies.hh @@ -282,7 +282,7 @@ namespace xamarin::android::internal { && ((application_config.have_runtime_config_blob && runtime_config_blob_found) || !application_config.have_runtime_config_blob); } - static force_inline c_unique_ptr to_utf8 (const MonoString *s) noexcept + force_inline static c_unique_ptr to_utf8 (const MonoString *s) noexcept { return c_unique_ptr (mono_string_to_utf8 (const_cast(s))); } diff --git a/src/monodroid/jni/helpers.hh b/src/monodroid/jni/helpers.hh index fa89be2f66c..88d4904e92d 100644 --- a/src/monodroid/jni/helpers.hh +++ b/src/monodroid/jni/helpers.hh @@ -16,7 +16,7 @@ namespace xamarin::android { public: template - static force_inline Ret add_with_overflow_check (const char *file, uint32_t line, P1 a, P2 b) noexcept + force_inline static Ret add_with_overflow_check (const char *file, uint32_t line, P1 a, P2 b) noexcept { Ret ret; @@ -40,7 +40,7 @@ namespace xamarin::android // fail // template - static force_inline Ret multiply_with_overflow_check (const char *file, uint32_t line, size_t a, size_t b) noexcept + force_inline static Ret multiply_with_overflow_check (const char *file, uint32_t line, size_t a, size_t b) noexcept { Ret ret; diff --git a/src/monodroid/jni/platform-compat.hh b/src/monodroid/jni/platform-compat.hh index 89992af8e0b..c632b32480f 100644 --- a/src/monodroid/jni/platform-compat.hh +++ b/src/monodroid/jni/platform-compat.hh @@ -5,7 +5,12 @@ static inline constexpr int DEFAULT_DIRECTORY_MODE = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; -#define force_inline inline __attribute__((always_inline)) -#define never_inline __attribute__((noinline)) +#if defined(NO_INLINE) +#define force_inline [[gnu::noinline]] +#define inline_calls [[gnu::flatten]] +#else +#define force_inline [[gnu::always_inline]] +#define inline_calls +#endif #endif // __PLATFORM_COMPAT_HH diff --git a/src/monodroid/monodroid.targets b/src/monodroid/monodroid.targets index 4578d663952..ed667e7fc44 100644 --- a/src/monodroid/monodroid.targets +++ b/src/monodroid/monodroid.targets @@ -75,7 +75,9 @@ Inputs="@(_ConfigureRuntimesInputs)" Outputs="@(_ConfigureRuntimesOutputs)"> - <_CmakeAndroidFlags>--debug-output -GNinja -DCMAKE_MAKE_PROGRAM="$(NinjaPath)" -DXA_BUILD_CONFIGURATION=$(Configuration) -DXA_LIB_TOP_DIR=$(MicrosoftAndroidSdkOutDir) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DMONO_PATH="$(MonoSourceFullPath)" -DANDROID_STL="none" -DANDROID_CPP_FEATURES="no-rtti no-exceptions" -DANDROID_TOOLCHAIN=clang -DCMAKE_TOOLCHAIN_FILE="$(AndroidNdkDirectory)/build/cmake/android.toolchain.cmake" -DANDROID_NDK=$(AndroidNdkDirectory) + <_NoInline Condition=" '$(DoNotInlineMonodroid)' == 'true' ">-DDONT_INLINE=ON + <_NoStrip Condition=" '$(DoNotStripMonodroid)' == 'true' ">-DSTRIP_DEBUG=OFF + <_CmakeAndroidFlags>$(_NoInline) $(_NoStrip) --debug-output -GNinja -DCMAKE_MAKE_PROGRAM="$(NinjaPath)" -DXA_BUILD_CONFIGURATION=$(Configuration) -DXA_LIB_TOP_DIR=$(MicrosoftAndroidSdkOutDir) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DMONO_PATH="$(MonoSourceFullPath)" -DANDROID_STL="none" -DANDROID_CPP_FEATURES="no-rtti no-exceptions" -DANDROID_TOOLCHAIN=clang -DCMAKE_TOOLCHAIN_FILE="$(AndroidNdkDirectory)/build/cmake/android.toolchain.cmake" -DANDROID_NDK=$(AndroidNdkDirectory) From 4696bf3ebb84df075731e54b44832929e36453d4 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Fri, 22 Mar 2024 09:09:50 -1000 Subject: [PATCH 06/17] [Xamarin.Android.Build.Tasks] Enable POM verification features. (#8649) Fixes: https://github.com/xamarin/xamarin-android/issues/4528 Context: 36597667f0ac70c8c3b7b204dd6883fb6ff0539d Context: https://github.com/xamarin/java.interop/commit/1c9c8c9c981647d27ff41e205754105bc88d890a Commit 36597667 mentioned: > There are 2 parts to xamarin/xamarin-android#4528: > > 1. Downloading artifacts from Maven > 2. Ensuring all dependencies specified in the POM file are met > > Only (1) is currently addressed. (2) will be addressed in the future. Implement support for (2): use `Java.Interop.Tools.Maven.dll` from xamarin/java.interop@1c9c8c9c to download and parse [Maven POM files][0] and ensure that all required Java dependencies are fulfilled. POM files are downloaded into `$(MavenCacheDirectory)` (36597667). Java dependency verification is a critical step that users often miss or make mistakes, resulting in non-functional bindings. Consider a classlib project with the following snippet: With the new POM verification features, the above snippet will produce the following errors: error XA4242: Java dependency 'com.squareup.okio:okio:2.8.0' is not satisfied. Microsoft maintains the NuGet package 'Square.OkIO' that could fulfill this dependency. error XA4242: Java dependency 'org.jetbrains.kotlin:kotlin-stdlib:1.4.10' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Kotlin.StdLib' that could fulfill this dependency. This is accomplished by automatically downloading the POM file (and any needed parent/imported POM files) for the specified artifact and using them to determine all required dependencies. There are many documented ways of fixing these errors, the best way is using the latest versions of the suggested NuGet packages: Note this commit replaces our previous usage of `MavenNet` with `Java.Interop.Tools.Maven`. Thus it removes the `MavenNet` TPN. Some future concerns: - Can we automatically determine which dependencies are met by a `@(ProjectReference)`? Today, the user must manually add the metadata `%(ProjectReference.JavaArtifact)` and `%(ProjectReference.JavaVersion)` to specify this. - We use the link https://aka.ms/ms-nuget-packages to download [`microsoft-packages.json`][1], which is used to provide NuGet suggestions. We need to figure out a permanent home for this file and a process for generating it. Luckily we can ship a preview for now and change the `aka.ms` link to point to the permanent home later. [0]: https://maven.apache.org/pom.html [1]: https://raw.githubusercontent.com/jpobst/Prototype.Android.MavenBindings/main/microsoft-packages.json --- Documentation/guides/AndroidMavenLibrary.md | 3 +- .../guides/JavaDependencyVerification.md | 115 ++++ .../guides/ResolvingJavaDependencies.md | 101 ++++ .../guides/building-apps/build-items.md | 59 +++ Documentation/guides/messages/README.md | 13 + Documentation/guides/messages/xa4234.md | 34 ++ Documentation/guides/messages/xa4235.md | 34 ++ Documentation/guides/messages/xa4236.md | 37 ++ Documentation/guides/messages/xa4237.md | 24 + Documentation/guides/messages/xa4239.md | 34 ++ Documentation/guides/messages/xa4241.md | 22 + Documentation/guides/messages/xa4242.md | 27 + Documentation/guides/messages/xa4243.md | 36 ++ Documentation/guides/messages/xa4244.md | 36 ++ Documentation/guides/messages/xa4245.md | 32 ++ Documentation/guides/messages/xa4246.md | 21 + Documentation/guides/messages/xa4247.md | 22 + Documentation/guides/messages/xa4248.md | 21 + .../installers/create-installers.targets | 5 +- .../xaprepare/ThirdPartyNotices/MavenNet.cs | 40 -- ...indings.JavaDependencyVerification.targets | 39 ++ .../Xamarin.Android.Bindings.Maven.targets | 4 +- .../Microsoft.Android.Sdk.After.targets | 1 + .../Properties/Resources.Designer.cs | 73 +++ .../Properties/Resources.resx | 67 ++- .../Tasks/GetMicrosoftNuGetPackagesMap.cs | 112 ++++ .../Tasks/JavaDependencyVerification.cs | 428 +++++++++++++++ .../Tasks/MavenDownload.cs | 144 +++-- .../BindingBuildTest.cs | 98 ++++ .../GetMicrosoftNuGetPackagesMapTests.cs | 158 ++++++ .../Tasks/JavaDependencyVerificationTests.cs | 497 ++++++++++++++++++ .../Tasks/MavenDownloadTests.cs | 42 +- .../Utilities/MavenExtensions.cs | 227 +++----- .../Xamarin.Android.Build.Tasks.csproj | 10 +- .../Xamarin.Android.Build.Tasks.targets | 7 +- 35 files changed, 2333 insertions(+), 290 deletions(-) create mode 100644 Documentation/guides/JavaDependencyVerification.md create mode 100644 Documentation/guides/ResolvingJavaDependencies.md create mode 100644 Documentation/guides/messages/xa4234.md create mode 100644 Documentation/guides/messages/xa4235.md create mode 100644 Documentation/guides/messages/xa4236.md create mode 100644 Documentation/guides/messages/xa4237.md create mode 100644 Documentation/guides/messages/xa4239.md create mode 100644 Documentation/guides/messages/xa4241.md create mode 100644 Documentation/guides/messages/xa4242.md create mode 100644 Documentation/guides/messages/xa4243.md create mode 100644 Documentation/guides/messages/xa4244.md create mode 100644 Documentation/guides/messages/xa4245.md create mode 100644 Documentation/guides/messages/xa4246.md create mode 100644 Documentation/guides/messages/xa4247.md create mode 100644 Documentation/guides/messages/xa4248.md delete mode 100644 build-tools/xaprepare/xaprepare/ThirdPartyNotices/MavenNet.cs create mode 100644 src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.JavaDependencyVerification.targets create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/GetMicrosoftNuGetPackagesMap.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetMicrosoftNuGetPackagesMapTests.cs create mode 100644 src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs diff --git a/Documentation/guides/AndroidMavenLibrary.md b/Documentation/guides/AndroidMavenLibrary.md index e1e22bc5659..df3e09d6707 100644 --- a/Documentation/guides/AndroidMavenLibrary.md +++ b/Documentation/guides/AndroidMavenLibrary.md @@ -17,9 +17,10 @@ Note: This feature is only available in .NET 9+. ``` -This will do two things at build time: +This will do several things at build time: - Download the Java [artifact](https://central.sonatype.com/artifact/com.squareup.okhttp3/okhttp/4.9.3) with group id `com.squareup.okhttp3`, artifact id `okhttp`, and version `4.9.3` from [Maven Central](https://central.sonatype.com/) to a local cache (if not already cached). - Add the cached package to the .NET Android bindings build as an [``](https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/building-apps/build-items.md#androidlibrary). +- Download the Java artifact's POM file (and any needed parent/imported POM files) to enable [Java Dependency Verification](JavaDependencyVerification.md). To opt out of this feature, add `VerifyDependencies="false"` to the `` item. Note that only the requested Java artifact is added to the .NET Android bindings build. Any artifact dependencies are not added. If the requested artifact has dependencies, they must be fulfilled individually. diff --git a/Documentation/guides/JavaDependencyVerification.md b/Documentation/guides/JavaDependencyVerification.md new file mode 100644 index 00000000000..8972ae4117e --- /dev/null +++ b/Documentation/guides/JavaDependencyVerification.md @@ -0,0 +1,115 @@ +# Java Dependency Verification + +Note: This feature is only available in .NET 9+. + +## Description + +A common problem when creating Java binding libraries for .NET Android is not providing the required Java dependencies. The binding process ignores API that requires missing dependencies, so this can result in large portions of desired API not being bound. + +Unlike .NET assemblies, a Java library does not specify its dependencies in the package. The dependency information is stored in external files called POM files. In order to consume this information to ensure correct dependencies an additional layer of files must be added to a binding project. + +Note: the preferred way of interacting with this system is to use [``](AndroidMavenLibrary.md) which will automatically download any needed POM files. + +For example: + +```xml + +``` + +automatically gets expanded to: + +```xml + + + + +etc. +``` + +However it is also possible to manually opt in to Java dependency verification using the build items documented here. + +## Specification + +To manually opt in to Java dependency verification, add the `Manifest`, `JavaArtifact`, and `JavaVersion` attributes to an `` item: + +```xml + + + + +``` + +Building the binding project now should result in verification errors if `my_binding_library.pom` specifies dependencies that are not met. + +For example: + +``` +error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. +``` + +Seeing these error(s) or no errors should indicate that the Java dependency verification is working. Follow the [Resolving Java Dependencies](ResolvingJavaDependencies.md) guide to fix any missing dependency errors. + +## Additional POM Files + +POM files can sometimes have some optional features in use that make them more complicated than the above example. + +That is, a POM file can depend on a "parent" POM file: + +```xml + + com.squareup.okio + okio-parent + 1.17.4 + +``` + +Additionally, a POM file can "import" dependency information from another POM file: + +```xml + + + + com.squareup.okio + okio-bom + 3.0.0 + pom + import + + + +``` + +Dependency information cannot be accurately determined without also having access to these additional POM files, and will results in an error like: + +``` +error : Unable to resolve POM for artifact 'com.squareup.okio:okio-parent:1.17.4'. +``` + +In this case, we need to provide the POM file for `com.squareup.okio:okio-parent:1.17.4`: + +```xml + + + + +``` + +Note that as "Parent" and "Import" POMs can themselves have parent and imported POMs, this step may need to be repeated until all POM files can be resolved. + +Note also that if using `` this should all be handled automatically. + +At this point, if there are dependency errors, follow the [Resolving Java Dependencies](ResolvingJavaDependencies.md) guide to fix any missing dependency errors. \ No newline at end of file diff --git a/Documentation/guides/ResolvingJavaDependencies.md b/Documentation/guides/ResolvingJavaDependencies.md new file mode 100644 index 00000000000..3bc48d0aa02 --- /dev/null +++ b/Documentation/guides/ResolvingJavaDependencies.md @@ -0,0 +1,101 @@ +# Resolving Java Dependencies + +Note: This feature is only available in .NET 9+. + +## Description + +Once Java dependency verification has been enabled for a bindings project, either automatically via `` or manually via ``, there may be errors to resolve, such as: + +``` +error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. +``` + +These dependencies can be fulfilled in many different ways. + +## `` + +In the best case scenario, there is already an existing binding of the Java dependency available on NuGet.org. This package may be provided by Microsoft or the .NET community. Packages maintained by Microsoft may be surfaced in the error message like this: + +``` +error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Collection' that could fulfill this dependency. +``` + +Adding the `Xamarin.AndroidX.Collection` package to the project should automatically resolve this error, as the package provides metadata to advertise that it provides the `androidx.collection:collection` dependency. This is done by looking for a specially crafted NuGet tag. For example, for the AndroidX Collection library, the tag looks like this: + +```xml + +artifact=androidx.collection:collection:1.0.0 +``` + +However there may be NuGet packages which fulfill a dependency but have not had this metadata added to it. In this case, you will need to explicitly specify which dependency the package contains with `JavaArtifact` and `JavaVersion`: + +```xml + +``` + +With this, the binding process knows the Java dependency is satisfied by the NuGet package. + +> Note: NuGet packages specify their own dependencies, so you will not need to worry about transitive dependencies. + +## `` + +If the needed Java dependency is provided by another project in your solution, you can annotate the `` to specify the dependency it fulfills: + +```xml + +``` + +With this, the binding process knows the Java dependency is satisfied by the referenced project. + +> Note: Each project specifies their own dependencies, so you will not need to worry about transitive dependencies. + +## `` + +If you are creating a public NuGet package, you will want to follow NuGet's "one library per package" policy so that the NuGet dependency graph works. However, if creating a binding for private use, you may want to include your Java dependencies directly inside the parent binding. + +This can be done by adding additional `` items to the project: + +```xml + + + +``` + +To include the Java library but not produce C# bindings for it, mark it with `Bind="false"`: + +```xml + + + +``` + +Alternatively, `` can be used to retrieve a Java library from a Maven repository: + +```xml + + + + + +``` + +> Note: If the dependency library has its own dependencies, you will be required to ensure they are fulfilled. + +## `` + +As a last resort, a needed Java dependency can be ignored. An example of when this is useful is if the dependency library is a collection of Java annotations that are only used at compile type and not runtime. + +Note that while the error message will go away, it does not mean the package will magically work. If the dependency is actually needed at runtime and not provided the Android application will crash with a `Java.Lang.NoClassDefFoundError` error. + +```xml + + + +``` diff --git a/Documentation/guides/building-apps/build-items.md b/Documentation/guides/building-apps/build-items.md index 176e875aa3a..e6d6d954d75 100644 --- a/Documentation/guides/building-apps/build-items.md +++ b/Documentation/guides/building-apps/build-items.md @@ -14,6 +14,30 @@ ms.date: 07/26/2022 Build items control how a Xamarin.Android application or library project is built. +## AndroidAdditionalJavaManifest + +`` is used in conjunction with [Java Dependency Resolution](../JavaDependencyVerification.md). + +It is used to specify additional POM files that will be needed to verify dependencies. +These are often parent or imported POM files referenced by a Java library's POM file. + +```xml + + + +``` + +The following MSBuild metadata are required: + +- `%(JavaArtifact)`: The group and artifact id of the Java library matching the specifed POM + file in the form `{GroupId}:{ArtifactId}`. +- `%(JavaVersion)`: The version of the Java library matching the specified POM file. + +See the [Java Dependency Resolution documentation](../JavaDependencyVerification.md) +for more details. + +This build action was introduced in .NET 9. + ## AndroidAsset Supports [Android Assets](https://developer.android.com/guide/topics/resources/providing-resources#OriginalFiles), @@ -115,6 +139,30 @@ Files with a Build action of `AndroidJavaLibrary` are Java Archives ( `.jar` files) that will be included in the final Android package. +## AndroidIgnoredJavaDependency + +`` is used in conjunction with [Java Dependency Resolution](../JavaDependencyVerification.md). + +It is used to specify a Java dependency that should be ignored. This can be +used if a dependency will be fulfilled in a way that Java dependency resolution +cannot detect. + +```xml + + + + +``` + +The following MSBuild metadata are required: + +- `%(Version)`: The version of the Java library matching the specified `%(Include)`. + +See the [Java Dependency Resolution documentation](../JavaDependencyVerification.md) +for more details. + +This build action was introduced in .NET 9. + ## AndroidJavaSource Files with a Build action of `AndroidJavaSource` are Java source code that @@ -218,6 +266,17 @@ hosted in Maven. ``` + +The following MSBuild metadata are supported: + +- `%(Version)`: Required version of the Java library referenced by `%(Include)`. +- `%(Repository)`: Optional Maven repository to use. Supported values are `Central` (default), + `Google`, or an `https` URL to a Maven repository. + +The `` item is translated to an +[``](https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/building-apps/build-items.md#androidlibrary) +item, so any metadata supported by `` like `Bind` or `Pack` are also supported. + See the [AndroidMavenLibrary documentation](../AndroidMavenLibrary.md) for more details. diff --git a/Documentation/guides/messages/README.md b/Documentation/guides/messages/README.md index df2c6915f35..e44f87d9b9b 100644 --- a/Documentation/guides/messages/README.md +++ b/Documentation/guides/messages/README.md @@ -186,6 +186,19 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla + XA4230: Error parsing XML: {exception} + [XA4231](xa4231.md): The Android class parser value 'jar2xml' is deprecated and will be removed in a future version of Xamarin.Android. Update the project properties to use 'class-parse'. + [XA4232](xa4232.md): The Android code generation target 'XamarinAndroid' is deprecated and will be removed in a future version of Xamarin.Android. Update the project properties to use 'XAJavaInterop1'. ++ [XA4234](xa4234.md): '<{item}>' item '{itemspec}' is missing required attribute '{name}'. ++ [XA4235](xa4235.md): Maven artifact specification '{artifact}' is invalid. The correct format is 'group_id:artifact_id'. ++ [XA4236](xa4236.md): Cannot download Maven artifact '{group}:{artifact}'. - {jar}: {exception} - {aar}: {exception} ++ [XA4237](xa4237.md): Cannot download POM file for Maven artifact '{artifact}'. - {exception} ++ [XA4239](xa4239.md): Unknown Maven repository: '{repository}'. ++ [XA4241](xa4241.md): Java dependency '{artifact}' is not satisfied. ++ [XA4242](xa4242.md): Java dependency '{artifact}' is not satisfied. Microsoft maintains the NuGet package '{nugetId}' that could fulfill this dependency. ++ [XA4243](xa4243.md): Attribute '{name}' is required when using '{name}' for '{element}' item '{itemspec}'. ++ [XA4244](xa4244.md): Attribute '{name}' cannot be empty for '{element}' item '{itemspec}'. ++ [XA4245](xa4245.md): Specified POM file '{file}' does not exist. ++ [XA4246](xa4246.md): Could not parse POM file '{file}'. - {exception} ++ [XA4247](xa4247.md): Could not resolve POM file for artifact '{artifact}'. ++ [XA4248](xa4248.md): Could not find NuGet package '{nugetId}' version '{version}' in lock file. Ensure NuGet Restore has run since this was added. + XA4300: Native library '{library}' will not be bundled because it has an unsupported ABI. + [XA4301](xa4301.md): Apk already contains the item `xxx`. + [XA4302](xa4302.md): Unhandled exception merging \`AndroidManifest.xml\`: {ex} diff --git a/Documentation/guides/messages/xa4234.md b/Documentation/guides/messages/xa4234.md new file mode 100644 index 00000000000..acb67c440fa --- /dev/null +++ b/Documentation/guides/messages/xa4234.md @@ -0,0 +1,34 @@ +--- +title: .NET Android error XA4234 +description: XA4234 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4234 + +## Example message + +``` +error XA4234: '' item 'com.example:mylib' is missing required attribute 'Version'. +``` + +## Issue + +The specified MSBuild XML item requires the specified XML attribute. + +For example the following item is missing the required 'Version' attribute: + +```xml + + + +``` + +## Solution + +To resolve this error, ensure that the specified XML contains the specified attribute: + +```xml + + + +``` diff --git a/Documentation/guides/messages/xa4235.md b/Documentation/guides/messages/xa4235.md new file mode 100644 index 00000000000..256115b42ce --- /dev/null +++ b/Documentation/guides/messages/xa4235.md @@ -0,0 +1,34 @@ +--- +title: .NET Android error XA4235 +description: XA4235 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4235 + +## Example message + +``` +error XA4235: Maven artifact specification 'com.example' is invalid. The correct format is 'group_id:artifact_id'. +``` + +## Issue + +The specified Maven artifact specification is invalid. + +For example the following item uses a comma separator instead of a colon: + +```xml + + + +``` + +## Solution + +To resolve this error, ensure that the artifact specification is of the form 'group_id:artifact_id': + +```xml + + + +``` diff --git a/Documentation/guides/messages/xa4236.md b/Documentation/guides/messages/xa4236.md new file mode 100644 index 00000000000..ba352dae46a --- /dev/null +++ b/Documentation/guides/messages/xa4236.md @@ -0,0 +1,37 @@ +--- +title: .NET Android error XA4236 +description: XA4236 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4236 + +## Example message + +``` +error XA4236: Cannot download Maven artifact 'com.example:mylib'. +error XA4236: - mylib-1.0.0.jar: Response status code does not indicate success: 404 (Not Found). +error XA4236: - mylib-1.0.0.aar: Response status code does not indicate success: 404 (Not Found). +``` + +## Issue + +Errors were encountered while trying to download the requested Java library from Maven. + +For example the following item doesn't actually exist on Maven Central, resulting in "Not Found": + +```xml + + + +``` + +## Solution + +Resolving this error depends on the error message specified. + +It could be things like: +- Check your internet connection. +- Ensure you have specified the correct group id and artifact id. +- Ensure you have specified the correct Maven repository. + +Additional documentation about configuring `` is available [here](../AndroidMavenLibrary.md). diff --git a/Documentation/guides/messages/xa4237.md b/Documentation/guides/messages/xa4237.md new file mode 100644 index 00000000000..d02c16d8481 --- /dev/null +++ b/Documentation/guides/messages/xa4237.md @@ -0,0 +1,24 @@ +--- +title: .NET Android error XA4237 +description: XA4237 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4237 + +## Example message + +``` +error XA4237: Cannot download POM file for Maven artifact 'com.example:mylib':1.0.0. +error XA4237: - mylib-1.0.0.pom: Response status code does not indicate success: 404 (Not Found). +``` + +## Issue + +An error was encountered while trying to download the requested POM file from Maven. + +## Solution + +Resolving this error depends on the error message specified. + +It could be things like: +- Check your internet connection. diff --git a/Documentation/guides/messages/xa4239.md b/Documentation/guides/messages/xa4239.md new file mode 100644 index 00000000000..dfc49124f7e --- /dev/null +++ b/Documentation/guides/messages/xa4239.md @@ -0,0 +1,34 @@ +--- +title: .NET Android error XA4239 +description: XA4239 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4239 + +## Example message + +``` +error XA4239: Unknown Maven repository: 'example.com'. +``` + +## Issue + +The specified Maven repository is invalid. + +For example the following Maven repository must be specified with `https://`: + +```xml + + + +``` + +## Solution + +To resolve this error, ensure that the Maven repository follows the [documented values](../AndroidMavenLibrary.md): + +```xml + + + +``` diff --git a/Documentation/guides/messages/xa4241.md b/Documentation/guides/messages/xa4241.md new file mode 100644 index 00000000000..8b2efb91dfb --- /dev/null +++ b/Documentation/guides/messages/xa4241.md @@ -0,0 +1,22 @@ +--- +title: .NET Android error XA4241 +description: XA4241 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4241 + +## Example message + +``` +error XA4241: Java dependency 'org.jetbrains.kotlin:kotlin-stdlib:1.9.0' is not satisfied. +``` + +## Issue + +The specified Java dependency could not be verified using the [Java Dependency Verification](../JavaDependencyVerification.md) +feature. + +## Solution + +To resolve this error, follow the available options in the [Resolving Java Dependencies](../ResolvingJavaDependencies.md) +documentation. diff --git a/Documentation/guides/messages/xa4242.md b/Documentation/guides/messages/xa4242.md new file mode 100644 index 00000000000..f3c6b0a2e7e --- /dev/null +++ b/Documentation/guides/messages/xa4242.md @@ -0,0 +1,27 @@ +--- +title: .NET Android error XA4242 +description: XA4242 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4242 + +## Example message + +Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + +``` +error XA4242: Java dependency 'org.jetbrains.kotlin:kotlin-stdlib:1.9.0' is not satisfied. +Microsoft maintains the NuGet package 'Xamarin.Kotlin.StdLib' that could fulfill this dependency. +``` + +## Issue + +The specified Java dependency could not be verified using the [Java Dependency Verification](../JavaDependencyVerification.md) +feature. + +## Solution + +Add a reference to the specified NuGet package to the project. + +Alternatively, choose one of the other available options in the [Resolving Java Dependencies](../ResolvingJavaDependencies.md) +documentation. diff --git a/Documentation/guides/messages/xa4243.md b/Documentation/guides/messages/xa4243.md new file mode 100644 index 00000000000..02e26b882a5 --- /dev/null +++ b/Documentation/guides/messages/xa4243.md @@ -0,0 +1,36 @@ +--- +title: .NET Android error XA4243 +description: XA4243 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4243 + +## Example message + +``` +error XA4243: Attribute 'JavaVersion' is required when using 'JavaArtifact' for 'ProjectReference' item '../ReferenceProject.csproj'. +``` + +## Issue + +The referenced MSBuild item XML specifies an attribute that makes an additional attribute required. + +For example, using the `JavaArtifact` attribute on a `` requires `JavaVersion` to also be specified. + +Invalid: + +```xml + + + +``` + +## Solution + +To resolve this error, specify the required XML attribute: + +```xml + + + +``` diff --git a/Documentation/guides/messages/xa4244.md b/Documentation/guides/messages/xa4244.md new file mode 100644 index 00000000000..016a1d72d80 --- /dev/null +++ b/Documentation/guides/messages/xa4244.md @@ -0,0 +1,36 @@ +--- +title: .NET Android error XA4244 +description: XA4244 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4244 + +## Example message + +``` +error XA4244: Attribute 'JavaVersion' cannot be empty for 'ProjectReference' item '../ReferenceProject.csproj'. +``` + +## Issue + +The referenced MSBuild item XML specifies a required attribute but omits a required value. + +For example, the `JavaArtifact` attribute on a `` cannot have an empty value. + +Invalid: + +```xml + + + +``` + +## Solution + +To resolve this error, specify a value for the required XML attribute: + +```xml + + + +``` diff --git a/Documentation/guides/messages/xa4245.md b/Documentation/guides/messages/xa4245.md new file mode 100644 index 00000000000..7d72a3c6017 --- /dev/null +++ b/Documentation/guides/messages/xa4245.md @@ -0,0 +1,32 @@ +--- +title: .NET Android error XA4245 +description: XA4245 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4245 + +## Example message + +``` +error XA4245: Specified POM file 'mylib.pom' does not exist. +``` + +## Issue + +The referenced MSBuild item XML specifies a POM file that cannot be found. + +```xml + + + +``` + +```xml + + + +``` + +## Solution + +To resolve this error, ensure the requested POM file exists in the specified location. diff --git a/Documentation/guides/messages/xa4246.md b/Documentation/guides/messages/xa4246.md new file mode 100644 index 00000000000..ce118c42ea5 --- /dev/null +++ b/Documentation/guides/messages/xa4246.md @@ -0,0 +1,21 @@ +--- +title: .NET Android error XA4246 +description: XA4246 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4246 + +## Example message + +``` +error XA4246: Could not parse POM file 'mylib.pom'. +error XA4246: - There is an error in XML document (1, 1). +``` + +## Issue + +The referenced POM file cannot be parsed. + +## Solution + +To resolve this error, ensure the requested POM file is valid XML. diff --git a/Documentation/guides/messages/xa4247.md b/Documentation/guides/messages/xa4247.md new file mode 100644 index 00000000000..0e86ad7326c --- /dev/null +++ b/Documentation/guides/messages/xa4247.md @@ -0,0 +1,22 @@ +--- +title: .NET Android error XA4247 +description: XA4247 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4247 + +## Example message + +``` +error XA4247: Could not resolve POM file for artifact 'com.example:mylib-parent:1.0.0'. +``` + +## Issue + +The specified POM file is needed to complete Java dependency verification, but it could +not be found. This may be due to a missing parent or imported POM file. + +## Solution + +For solutions for fixing this error, refer to the "Additional POM Files" section of the +[Java Dependency Verification](../JavaDependencyVerification.md) documentation. diff --git a/Documentation/guides/messages/xa4248.md b/Documentation/guides/messages/xa4248.md new file mode 100644 index 00000000000..a6508b777cf --- /dev/null +++ b/Documentation/guides/messages/xa4248.md @@ -0,0 +1,21 @@ +--- +title: .NET Android error XA4248 +description: XA4248 error code +ms.date: 02/26/2024 +--- +# .NET Android error XA4248 + +## Example message + +``` +error XA4248: Could not find NuGet package 'Xamarin.Kotlin.StdLib' version '1.9.0' in lock file. Ensure NuGet Restore has run since this was added. +``` + +## Issue + +The NuGet lock file has not been generated and thus Java dependencies from NuGet packages +cannot be resolved. + +## Solution + +Run NuGet Restore for the project to ensure the lock file has been generated. diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index 85c8b990475..daa577014a5 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -104,14 +104,14 @@ <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)HtmlAgilityPack.dll" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)HtmlAgilityPack.pdb" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Irony.dll" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Java.Interop.Tools.Maven.dll" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Java.Interop.Tools.Maven.pdb" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java-interop.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java-source-utils.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)LayoutBinding.cs" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libZipSharp.dll" /> <_MSBuildFiles Include="@(_LocalizationLanguages->'$(MicrosoftAndroidSdkOutDir)%(Identity)\libZipSharp.resources.dll')" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)libZipSharp.pdb" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)MavenNet.dll" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)MavenNet.pdb" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Mono.Unix.dll" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Mono.Unix.pdb" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Microsoft.Android.Build.BaseTasks.dll" /> @@ -139,6 +139,7 @@ <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Assets.targets" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Bindings.ClassParse.targets" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Bindings.Core.targets" /> + <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Bindings.JavaDependencyVerification.targets" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Bindings.Maven.targets" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Tasks.dll" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)Xamarin.Android.Build.Tasks.pdb" /> diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/MavenNet.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/MavenNet.cs deleted file mode 100644 index a09a63de12f..00000000000 --- a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/MavenNet.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Xamarin.Android.Prepare -{ - [TPN] - class MavenNet_TPN : ThirdPartyNotice - { - static readonly Uri url = new Uri ("https://github.com/Redth/MavenNet/"); - - public override string LicenseFile => string.Empty; - public override string Name => "Redth/MavenNet"; - public override Uri SourceUrl => url; - public override string LicenseText => @" -MIT License - -Copyright (c) 2017 Jonathan Dick - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the ""Software""), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE."; - - public override bool Include (bool includeExternalDeps, bool includeBuildDeps) => includeExternalDeps; - } -} diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.JavaDependencyVerification.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.JavaDependencyVerification.targets new file mode 100644 index 00000000000..7fa94d517d1 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.JavaDependencyVerification.targets @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets index e47e4b6bd93..07e287a991a 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets @@ -19,7 +19,7 @@ This file contains MSBuild targets used to enable @(AndroidMavenLibrary) support $([MSBuild]::EnsureTrailingSlash('$(MavenCacheDirectory)')) - @@ -27,11 +27,13 @@ This file contains MSBuild targets used to enable @(AndroidMavenLibrary) support + + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets index 95063269a7b..53614fc28f1 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.After.targets @@ -18,6 +18,7 @@ This file is imported *after* the Microsoft.NET.Sdk/Sdk.targets. + diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs index c5df25bdcc2..0c326142438 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs @@ -1191,6 +1191,79 @@ public static string XA4239 { } } + /// + /// Looks up a localized string similar to Java dependency '{0}' is not satisfied.. + /// + public static string XA4241 { + get { + return ResourceManager.GetString("XA4241", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency.. + /// + public static string XA4242 { + get { + return ResourceManager.GetString("XA4242", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'.. + /// + public static string XA4243 { + get { + return ResourceManager.GetString("XA4243", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attribute '{0}' cannot be empty for '{1}' item '{2}'.. + /// + public static string XA4244 { + get { + return ResourceManager.GetString("XA4244", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified POM file '{0}' does not exist.. + /// + public static string XA4245 { + get { + return ResourceManager.GetString("XA4245", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not parse POM file '{0}'. + ///- {1}. + /// + public static string XA4246 { + get { + return ResourceManager.GetString("XA4246", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not resolve POM file for artifact '{0}'.. + /// + public static string XA4247 { + get { + return ResourceManager.GetString("XA4247", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added.. + /// + public static string XA4248 { + get { + return ResourceManager.GetString("XA4248", resourceCulture); + } + } + /// /// Looks up a localized string similar to Native library '{0}' will not be bundled because it has an unsupported ABI. Move this file to a directory with a valid Android ABI name such as 'libs/armeabi-v7a/'.. /// diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx index f473cd0f265..390cd9272da 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx @@ -968,7 +968,7 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS - '<{0}>' item '{1}' is missing required metadata '{2}' + '<{0}>' item '{1}' is missing required attribute '{2}'. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,23 +991,12 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}:{1}'. -- {2}: {3} + Cannot download POM file for Maven artifact '{0}'. +- {1} The following are literal names and should not be translated: POM, Maven -{0} - Maven artifact group id -{1} - Maven artifact id -{2} - The .pom filename we tried to download -{3} - The HttpClient reported download exception message +{0} - Maven artifact id +{1} - The HttpClient reported download exception message - - - Cannot download parent POM file for Maven artifact '{0}:{1}'. -- {2}: {3} - The following are literal names and should not be translated: POM, Maven -{0} - Maven artifact group id -{1} - Maven artifact id -{2} - The .pom filename we tried to download -{3} - The HttpClient reported download exception message Unknown Maven repository: '{0}'. @@ -1024,4 +1013,50 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS The Android Support libraries are not supported in .NET 9 and later, please migrate to AndroidX. See https://aka.ms/xamarin/androidx for more details. The following are literal names and should not be translated: Android Support, AndroidX, .NET. + + Java dependency '{0}' is not satisfied. + The following are literal names and should not be translated: Java. +{0} - Maven dependency id + + + Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + The following are literal names and should not be translated: Java, Microsoft, NuGet. +{0} - Maven dependency id +{1} - NuGet package id + + + Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + {0}, {1} - MSBuild XML attribute +{2} - MSBuild XML element name +{3} - MSBuild ItemSpec value + + + Attribute '{0}' cannot be empty for '{1}' item '{2}'. + {0} - MSBuild XML attribute +{1} - MSBuild XML element name +{2} - MSBuild ItemSpec value + + + Specified POM file '{0}' does not exist. + The following are literal names and should not be translated: POM. +{0} - File path to POM file + + + Could not parse POM file '{0}'. +- {1} + The following are literal names and should not be translated: POM. +{0} - File path to POM file +{1} - Exception message + + + Could not resolve POM file for artifact '{0}'. + The following are literal names and should not be translated: POM. +{0} - Java artifact id + + + Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + The following are literal names and should not be translated: NuGet, PackageReference. +{0} - NuGet package id +{1} - NuGet package version + \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetMicrosoftNuGetPackagesMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetMicrosoftNuGetPackagesMap.cs new file mode 100644 index 00000000000..d6a1557944d --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetMicrosoftNuGetPackagesMap.cs @@ -0,0 +1,112 @@ +#nullable enable + +using System; +using System.IO; +using Microsoft.Build.Framework; +using Microsoft.Android.Build.Tasks; +using System.Net.Http; +using System.Diagnostics.CodeAnalysis; +using System.Collections.Generic; +using System.Linq; + +namespace Xamarin.Android.Tasks; + +public class GetMicrosoftNuGetPackagesMap : AndroidAsyncTask +{ + static readonly HttpClient http_client = new HttpClient (); + + public override string TaskPrefix => "GNP"; + + /// + /// The cache directory to use for Maven artifacts. + /// + [Required] + public string MavenCacheDirectory { get; set; } = null!; // NRT enforced by [Required] + + [Output] + public string? ResolvedPackageMap { get; set; } + + public override async System.Threading.Tasks.Task RunTaskAsync () + { + Directory.CreateDirectory (MavenCacheDirectory); + + // We're going to store the resolved package map in the cache directory as + // "microsoft-packages-{YYYYMMDD}.json". If the file is older than today, + // we'll try to download a new one. + var all_files = PackagesFile.FindAll (MavenCacheDirectory); + + if (!all_files.Any (x => x.IsToday)) { + // No file for today, download a new one + try { + var json = await http_client.GetStringAsync ("https://aka.ms/ms-nuget-packages"); + var outfile = Path.Combine (MavenCacheDirectory, $"microsoft-packages-{DateTime.Today:yyyyMMdd}.json"); + + File.WriteAllText (outfile, json); + + if (PackagesFile.TryParse (outfile, out var packagesFile)) + all_files.Insert (0, packagesFile); // Sorted so this one is first + + } catch (Exception ex) { + Log.LogMessage ("Could not download microsoft-packages.json: {0}", ex.Message); + } + } + + // Delete all files but the latest + foreach (var file in all_files.Skip (1)) { + try { + File.Delete (Path.Combine (MavenCacheDirectory, file.FileName)); + } catch { + // Ignore exceptions + } + } + + ResolvedPackageMap = all_files.FirstOrDefault ()?.FileName; + } +} + +class PackagesFile +{ + public string FileName { get; } + public DateTime DownloadDate { get; } + public bool IsToday => DownloadDate == DateTime.Today; + + PackagesFile (string filename, DateTime downloadDate) + { + FileName = filename; + DownloadDate = downloadDate; + } + + public static List FindAll (string directory) + { + var files = new List (); + + foreach (var file in Directory.GetFiles (directory, "microsoft-packages-*.json")) { + if (TryParse (file, out var packagesFile)) + files.Add (packagesFile); + } + + files.OrderByDescending (x => x.DownloadDate); + + return files; + } + + public static bool TryParse (string filepath, [NotNullWhen (true)]out PackagesFile? file) + { + file = default; + + var filename = Path.GetFileNameWithoutExtension (filepath); + + if (!filename.StartsWith ("microsoft-packages-", StringComparison.OrdinalIgnoreCase)) + return false; + + var date = filename.Substring ("microsoft-packages-".Length); + + if (!DateTime.TryParseExact (date, "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out var downloadDate)) + return false; + + file = new PackagesFile (filepath, downloadDate); + + return true; + } +} + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs new file mode 100644 index 00000000000..441e1b3ccd5 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs @@ -0,0 +1,428 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Java.Interop.Tools.Maven; +using Java.Interop.Tools.Maven.Models; +using Microsoft.Android.Build.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Newtonsoft.Json; +using NuGet.ProjectModel; + +namespace Xamarin.Android.Tasks; + +public class JavaDependencyVerification : AndroidTask +{ + public override string TaskPrefix => "JDV"; + + /// + /// Java libraries whose dependencies we are being asked to verify. + /// + public ITaskItem []? AndroidLibraries { get; set; } + + /// + /// Additional POM files (like parent POMs) that we should use to resolve dependencies. + /// + public ITaskItem []? AdditionalManifests { get; set; } + + /// + /// NuGet packages this project consumes, which may fulfill Java dependencies. + /// + public ITaskItem []? PackageReferences { get; set; } + + /// + /// Projects this project references, which may fulfill Java dependencies. + /// + public ITaskItem []? ProjectReferences { get; set; } + + /// + /// Dependencies that we should ignore if they are missing. + /// + public ITaskItem []? IgnoredDependencies { get; set; } + + /// + /// The file location of 'microsoft-packages.json'. + /// + public string? MicrosoftPackagesFile { get; set; } + + public string? ProjectAssetsLockFile { get; set; } + + public override bool RunTask () + { + // Bail if no specifies a "Manifest" we need to verify + if (!(AndroidLibraries?.Select (al => al.GetMetadata ("Manifest")).Any (al => al.HasValue ()) ?? false)) + return true; + + // Populate the POM resolver with the POMs we know about + var pom_resolver = new MSBuildLoggingPomResolver (Log); + var poms_to_verify = new List (); + + foreach (var pom in AndroidLibraries ?? []) + if (pom_resolver.RegisterFromAndroidLibrary (pom) is Artifact art) + poms_to_verify.Add (art); + + foreach (var pom in AdditionalManifests ?? []) + pom_resolver.RegisterFromAndroidAdditionalJavaManifest (pom); + + // If there were errors loading the requested POMs, bail + if (Log.HasLoggedErrors) + return false; + + // Populate the dependency resolver with every dependency we know about + var resolver = new DependencyResolver (ProjectAssetsLockFile, Log); + + resolver.AddAndroidLibraries (AndroidLibraries); + resolver.AddPackageReferences (PackageReferences); + resolver.AddProjectReferences (ProjectReferences); + resolver.AddIgnoredDependencies (IgnoredDependencies); + + // Parse microsoft-packages.json so we can provide package recommendations + var ms_packages = new MicrosoftNuGetPackageFinder (MicrosoftPackagesFile, Log); + + // Verify dependencies + foreach (var pom in poms_to_verify) { + if (TryResolveProject (pom, pom_resolver, out var resolved_pom)) { + foreach (var dependency in resolved_pom.Dependencies.Where (d => (d.IsRuntimeDependency () || d.IsCompileDependency ()) && !d.IsOptional ())) + resolver.EnsureDependencySatisfied (dependency, ms_packages); + } + } + + return !Log.HasLoggedErrors; + } + + static bool TryResolveProject (Artifact artifact, IProjectResolver resolver, [NotNullWhen (true)]out ResolvedProject? project) + { + // ResolvedProject.FromArtifact will throw if a POM cannot be resolved, but our MSBuildLoggingPomResolver + // has already logged the failure as an MSBuild error. We don't want to log it again as an unhandled exception. + try { + project = ResolvedProject.FromArtifact (artifact, resolver); + return true; + } catch { + project = null; + return false; + } + } +} + +class DependencyResolver +{ + readonly Dictionary artifacts = new (); + + readonly NuGetPackageVersionFinder? finder; + readonly TaskLoggingHelper log; + + public DependencyResolver (string? lockFile, TaskLoggingHelper log) + { + this.log = log; + + if (File.Exists (lockFile)) + finder = NuGetPackageVersionFinder.Create (lockFile!, log); + } + + public bool EnsureDependencySatisfied (ResolvedDependency dependency, MicrosoftNuGetPackageFinder packages) + { + if (!dependency.Version.HasValue ()) + log.LogMessage ("Could not determine required version of Java dependency '{0}:{1}'. Validation of this dependency will not take version into account.", dependency.GroupId, dependency.ArtifactId); + + var satisfied = TrySatisfyDependency (dependency); + + if (satisfied) + return true; + + var suggestion = packages.GetNuGetPackage ($"{dependency.GroupId}:{dependency.ArtifactId}"); + var artifact_spec = dependency.Version.HasValue () ? dependency.VersionedArtifactString : dependency.ArtifactString; + + if (suggestion is string nuget) + log.LogCodedError ("XA4242", Properties.Resources.XA4242, artifact_spec, nuget); + else + log.LogCodedError ("XA4241", Properties.Resources.XA4241, artifact_spec); + + return false; + } + + public void AddAndroidLibraries (ITaskItem []? tasks) + { + foreach (var task in tasks.OrEmpty ()) { + var id = task.GetMetadataOrDefault ("JavaArtifact", string.Empty); + var version = task.GetMetadataOrDefault ("JavaVersion", string.Empty); + + // TODO: Should raise an error if JavaArtifact is specified but JavaVersion is not + if (!id.HasValue () || !version.HasValue ()) + continue; + + if (version != null && MavenExtensions.TryParseArtifactWithVersion (id, version, log, out var art)) { + log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from AndroidLibrary '{3}'", art.GroupId, art.Id, art.Version, task.ItemSpec); + artifacts.Add (art.ArtifactString, art); + } + } + } + + public void AddPackageReferences (ITaskItem []? tasks) + { + foreach (var task in tasks.OrEmpty ()) { + + // See if JavaArtifact/JavaVersion overrides were used + if (task.TryParseJavaArtifactAndJavaVersion ("PackageReference", log, out var explicit_artifact, out var attributes_specified)) { + artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact); + continue; + } + + // If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback + if (attributes_specified) + continue; + + // Try parsing the NuGet metadata for Java version information instead + var artifact = finder?.GetJavaInformation (task.ItemSpec, task.GetMetadataOrDefault ("Version", string.Empty), log); + + if (artifact != null) { + log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from PackageReference '{3}'", artifact.GroupId, artifact.Id, artifact.Version, task.ItemSpec); + artifacts.Add (artifact.ArtifactString, artifact); + + continue; + } + + log.LogMessage ("No Java artifact information found for PackageReference '{0}'", task.ItemSpec); + } + } + + public void AddProjectReferences (ITaskItem []? tasks) + { + foreach (var task in tasks.OrEmpty ()) { + // See if JavaArtifact/JavaVersion overrides were used + if (task.TryParseJavaArtifactAndJavaVersion ("ProjectReference", log, out var explicit_artifact, out var attributes_specified)) { + artifacts.Add (explicit_artifact.ArtifactString, explicit_artifact); + continue; + } + + // If user tried to specify JavaArtifact or JavaVersion, but did it incorrectly, we do not perform any fallback + if (attributes_specified) + continue; + + // There currently is no alternate way to figure this out. Perhaps in + // the future we could somehow parse the project to find it automatically? + } + } + + public void AddIgnoredDependencies (ITaskItem []? tasks) + { + foreach (var task in tasks.OrEmpty ()) { + var id = task.ItemSpec; + var version = task.GetRequiredMetadata ("AndroidIgnoredJavaDependency", "Version", log); + + if (version is null) + continue; + + if (version != null && MavenExtensions.TryParseArtifactWithVersion (id, version, log, out var art)) { + log.LogMessage ("Ignoring Java dependency '{0}:{1}' version '{2}'", art.GroupId, art.Id, art.Version); + artifacts.Add (art.ArtifactString, art); + } + } + } + + bool TrySatisfyDependency (ResolvedDependency dependency) + { + if (!dependency.Version.HasValue ()) + return artifacts.ContainsKey (dependency.ArtifactString); + + var dep_versions = MavenVersionRange.Parse (dependency.Version); + + if (artifacts.TryGetValue (dependency.ArtifactString, out var artifact)) + return dep_versions.Any (r => r.ContainsVersion (MavenVersion.Parse (artifact.Version))); + + return false; + } +} + +class MSBuildLoggingPomResolver : IProjectResolver +{ + readonly TaskLoggingHelper logger; + readonly Dictionary poms = new (); + + public MSBuildLoggingPomResolver (TaskLoggingHelper logger) + { + this.logger = logger; + } + + public Artifact? RegisterFromAndroidLibrary (ITaskItem item) + { + var pom_file = item.GetMetadata ("Manifest"); + + if (!pom_file.HasValue ()) + return null; + + return RegisterFromTaskItem (item, "AndroidLibrary", pom_file); + } + + public Artifact? RegisterFromAndroidAdditionalJavaManifest (ITaskItem item) + => RegisterFromTaskItem (item, "AndroidAdditionalJavaManifest", item.ItemSpec); + + Artifact? RegisterFromTaskItem (ITaskItem item, string itemName, string filename) + { + item.TryParseJavaArtifactAndJavaVersion (itemName, logger, out var artifact, out var _); + + if (!File.Exists (filename)) { + logger.LogCodedError ("XA4245", Properties.Resources.XA4245, filename); + return null; + } + + try { + using (var file = File.OpenRead (filename)) { + var project = Project.Load (file); + var registered_artifact = Artifact.Parse (project.VersionedArtifactString); + + // Return the registered artifact, preferring any overrides specified in the task item + var final_artifact = new Artifact ( + artifact?.GroupId ?? registered_artifact.GroupId, + artifact?.Id ?? registered_artifact.Id, + artifact?.Version ?? registered_artifact.Version + ); + + // Use index instead of Add to handle duplicates + poms [final_artifact.VersionedArtifactString] = project; + + logger.LogDebugMessage ("Registered POM for artifact '{0}' from '{1}'", final_artifact, filename); + + return final_artifact; + } + } catch (Exception ex) { + logger.LogCodedError ("XA4246", Properties.Resources.XA4246, filename, ex.Message); + return null; + } + } + + public Project Resolve (Artifact artifact) + { + if (poms.TryGetValue (artifact.VersionedArtifactString, out var project)) + return project; + + logger.LogCodedError ("XA4247", Properties.Resources.XA4247, artifact); + + throw new InvalidOperationException ($"No POM registered for {artifact}"); + } +} + +class MicrosoftNuGetPackageFinder +{ + readonly PackageListFile? package_list; + + public MicrosoftNuGetPackageFinder (string? file, TaskLoggingHelper log) + { + if (file is null || !File.Exists (file)) { + log.LogMessage ("'microsoft-packages.json' file not found, Android NuGet suggestions will not be provided"); + return; + } + + try { + var json = File.ReadAllText (file); + package_list = JsonConvert.DeserializeObject (json); + } catch (Exception ex) { + log.LogMessage ("There was an error reading 'microsoft-packages.json', Android NuGet suggestions will not be provided: {0}", ex); + } + } + + public string? GetNuGetPackage (string javaId) + { + return package_list?.Packages?.FirstOrDefault (p => p.JavaId?.Equals (javaId, StringComparison.OrdinalIgnoreCase) == true)?.NuGetId; + } + + public class PackageListFile + { + [JsonProperty ("packages")] + public List? Packages { get; set; } + } + + public class Package + { + [JsonProperty ("javaId")] + public string? JavaId { get; set; } + + [JsonProperty ("nugetId")] + public string? NuGetId { get; set; } + } +} + +public class NuGetPackageVersionFinder +{ + readonly LockFile lock_file; + readonly Dictionary cache = new Dictionary (); + readonly Regex tag = new Regex ("artifact_versioned=(?.+)?:(?.+?):(?.+)\\s?", RegexOptions.Compiled); + readonly Regex tag2 = new Regex ("artifact=(?.+)?:(?.+?):(?.+)\\s?", RegexOptions.Compiled); + + NuGetPackageVersionFinder (LockFile lockFile) + { + lock_file = lockFile; + } + + public static NuGetPackageVersionFinder? Create (string filename, TaskLoggingHelper log) + { + try { + var lock_file_format = new LockFileFormat (); + var lock_file = lock_file_format.Read (filename); + return new NuGetPackageVersionFinder (lock_file); + } catch (Exception e) { + log.LogMessage ("Could not parse NuGet lock file. Java dependencies fulfilled by NuGet packages may not be available: '{0}'.", e.Message); + return null; + } + } + + public Artifact? GetJavaInformation (string library, string version, TaskLoggingHelper log) + { + // Check if we already have this one in the cache + var dictionary_key = $"{library.ToLowerInvariant ()}:{version}"; + + if (cache.TryGetValue (dictionary_key, out var artifact)) + return artifact; + + // Find the LockFileLibrary + var nuget = lock_file.GetLibrary (library, new NuGet.Versioning.NuGetVersion (version)); + + if (nuget is null) { + log.LogCodedError ("XA4248", Properties.Resources.XA4248, library, version); + return null; + } + + foreach (var path in lock_file.PackageFolders) + if (CheckFilePath (path.Path, nuget) is Artifact art) { + cache.Add (dictionary_key, art); + return art; + } + + return null; + } + + Artifact? CheckFilePath (string nugetPackagePath, LockFileLibrary package) + { + // Check NuGet tags + var nuspec = package.Files.FirstOrDefault (f => f.EndsWith (".nuspec", StringComparison.OrdinalIgnoreCase)); + + if (nuspec is null) + return null; + + nuspec = Path.Combine (nugetPackagePath, package.Path, nuspec); + + if (!File.Exists (nuspec)) + return null; + + var reader = new NuGet.Packaging.NuspecReader (nuspec); + var tags = reader.GetTags (); + + // Try the first tag format + var match = tag.Match (tags); + + // Try the second tag format + if (!match.Success) + match = tag2.Match (tags); + + if (!match.Success) + return null; + + // TODO: Define a well-known file that can be included in the package like "java-package.txt" + + return new Artifact (match.Groups ["GroupId"].Value, match.Groups ["ArtifactId"].Value, match.Groups ["Version"].Value); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs b/src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs index 1a0928d1552..383cc1a2d2f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs @@ -1,8 +1,14 @@ +#nullable enable + using System; using System.Collections.Generic; +using System.IO; using System.Linq; -using MavenNet; -using MavenNet.Models; +using System.Security.Cryptography; +using System.Text; +using Java.Interop.Tools.Maven; +using Java.Interop.Tools.Maven.Models; +using Java.Interop.Tools.Maven.Repositories; using Microsoft.Android.Build.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -30,11 +36,18 @@ public class MavenDownload : AndroidAsyncTask [Output] public ITaskItem []? ResolvedAndroidMavenLibraries { get; set; } + /// + /// The set of additional parent and imported POM files needed to verify these Maven libraries. + /// + [Output] + public ITaskItem []? AndroidAdditionalJavaManifest { get; set; } + public async override System.Threading.Tasks.Task RunTaskAsync () { var resolved = new List (); + var additional_poms = new List (); - // Note each called function is responsible for raising any errors it encounters to the user + // Note each called function is responsible for reporting any errors it encounters to the user foreach (var library in AndroidMavenLibraries.OrEmpty ()) { // Validate artifact @@ -43,14 +56,12 @@ public async override System.Threading.Tasks.Task RunTaskAsync () if (version is null) continue; - - var artifact = MavenExtensions.ParseArtifact (id, version, Log); - - if (artifact is null) + + if (!MavenExtensions.TryParseArtifactWithVersion (id, version, Log, out var artifact)) continue; // Check for repository files - if (await GetRepositoryArtifactOrDefault (artifact, library, Log) is TaskItem result) { + if (await GetRepositoryArtifactOrDefault (artifact, library, additional_poms) is TaskItem result) { library.CopyMetadataTo (result); resolved.Add (result); continue; @@ -58,9 +69,10 @@ public async override System.Threading.Tasks.Task RunTaskAsync () } ResolvedAndroidMavenLibraries = resolved.ToArray (); + AndroidAdditionalJavaManifest = additional_poms.ToArray (); } - async System.Threading.Tasks.Task GetRepositoryArtifactOrDefault (Artifact artifact, ITaskItem item, TaskLoggingHelper log) + async System.Threading.Tasks.Task GetRepositoryArtifactOrDefault (Artifact artifact, ITaskItem item, List additionalPoms) { // Handles a Repository="Central|Google|" entry, like: // TryGetParentPom (ITaskItem item, TaskLoggingHelper log) - { - var child_pom_file = item.GetRequiredMetadata ("AndroidMavenLibrary", "ArtifactPom", Log); + // Resolve and download POM, and any parent or imported POMs + try { + var resolver = new LoggingPomResolver (repository); + var project = ResolvedProject.FromArtifact (artifact, resolver); - // Shouldn't be possible because we just created this items - if (child_pom_file is null) - return null; + // Set the POM file path for _this_ artifact + var primary_pom = resolver.ResolvedPoms [artifact.VersionedArtifactString]; + result.SetMetadata ("Manifest", primary_pom); - // No parent POM needed - if (!(MavenExtensions.CheckForNeededParentPom (child_pom_file) is Artifact artifact)) - return null; + Log.LogMessage ("Found POM file '{0}' for Java artifact '{1}'.", primary_pom, artifact); - // Initialize repo (parent will be in same repository as child) - var repository = GetRepository (item); + // Create TaskItems for any other POMs we resolved + foreach (var kv in resolver.ResolvedPoms.Where (k => k.Key != artifact.VersionedArtifactString)) { - if (repository is null) - return null; + var pom_item = new TaskItem (kv.Value); + var pom_artifact = Artifact.Parse (kv.Key); - artifact.Repository = repository; + pom_item.SetMetadata ("JavaArtifact", $"{pom_artifact.GroupId}:{pom_artifact.Id}"); + pom_item.SetMetadata ("JavaVersion", pom_artifact.Version); - // Download POM - var pom_file = await MavenExtensions.DownloadPom (artifact, MavenCacheDirectory, Log, CancellationToken); + additionalPoms.Add (pom_item); - if (pom_file is null) + Log.LogMessage ("Found POM file '{0}' for Java artifact '{1}'.", kv.Value, pom_artifact); + } + } catch (Exception ex) { + Log.LogCodedError ("XA4237", Properties.Resources.XA4237, artifact, ex.Unwrap ().Message); return null; - - var result = new TaskItem ($"{artifact.GroupId}:{artifact.Id}"); - - result.SetMetadata ("Version", artifact.Versions.FirstOrDefault ()); - result.SetMetadata ("ArtifactPom", pom_file); - - // Copy repository data - item.CopyMetadataTo (result); + } return result; } - MavenRepository? GetRepository (ITaskItem item) + CachedMavenRepository? GetRepository (ITaskItem item) { var type = item.GetMetadataOrDefault ("Repository", "Central"); var repo = type.ToLowerInvariant () switch { - "central" => MavenRepository.FromMavenCentral (), - "google" => MavenRepository.FromGoogle (), - _ => (MavenRepository?) null + "central" => MavenRepository.Central, + "google" => MavenRepository.Google, + _ => null }; - if (repo is null && type.StartsWith ("http", StringComparison.OrdinalIgnoreCase)) - repo = MavenRepository.FromUrl (type); + if (repo is null && type.StartsWith ("http", StringComparison.OrdinalIgnoreCase)) { + using var hasher = SHA256.Create (); + var hash = hasher.ComputeHash (Encoding.UTF8.GetBytes (type)); + var cache_name = Convert.ToBase64String (hash); + + repo = new MavenRepository (type, cache_name); + } if (repo is null) Log.LogCodedError ("XA4239", Properties.Resources.XA4239, type); - return repo; + return repo is not null ? new CachedMavenRepository (MavenCacheDirectory, repo) : null; + } +} + +// This wrapper around CachedMavenRepository is used to log the POMs that are resolved. +// We need these on-disk file locations so we can pass them as items. +class LoggingPomResolver : IProjectResolver +{ + readonly CachedMavenRepository repository; + + public Dictionary ResolvedPoms { get; } = new Dictionary (); + + public LoggingPomResolver (CachedMavenRepository repository) + { + this.repository = repository; + } + + public Project Resolve (Artifact artifact) + { + if (repository.TryGetFilePath (artifact, $"{artifact.Id}-{artifact.Version}.pom", out var path)) { + using (var stream = File.OpenRead (path)) { + var pom = Project.Load (stream) ?? throw new InvalidOperationException ($"Could not deserialize POM for {artifact}"); + + // Use index instead of Add to handle duplicates + ResolvedPoms [artifact.VersionedArtifactString] = path; + + return pom; + } + } + + throw new InvalidOperationException ($"No POM found for {artifact}"); } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index d4e24312561..58d8012352a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -791,5 +791,103 @@ public void AndroidMavenLibrary () FileAssert.Exists (cs_file); } } + + [Test] + public void AndroidMavenLibrary_FailsDueToUnverifiedDependency () + { + // Test that triggers Java dependency verification + // + var item = new BuildItem ("AndroidMavenLibrary", "androidx.core:core"); + item.Metadata.Add ("Version", "1.9.0"); + item.Metadata.Add ("Repository", "Google"); + + var proj = new XamarinAndroidBindingProject { + Jars = { item } + }; + + using (var b = CreateDllBuilder ()) { + b.ThrowOnBuildFailure = false; + Assert.IsFalse (b.Build (proj), "Build should have failed."); + + // Ensure an error was raised + StringAssertEx.Contains ("error XA4242: Java dependency 'androidx.annotation:annotation:1.2.0' is not satisfied.", b.LastBuildOutput); + } + } + + [Test] + public void AndroidMavenLibrary_IgnoreDependencyVerification () + { + // Test that ignores Java dependency verification + // + var item = new BuildItem ("AndroidMavenLibrary", "androidx.core:core"); + item.Metadata.Add ("Version", "1.9.0"); + item.Metadata.Add ("Repository", "Google"); + item.Metadata.Add ("VerifyDependencies", "false"); + item.Metadata.Add ("Bind", "false"); + + var proj = new XamarinAndroidBindingProject { + Jars = { item } + }; + + using (var b = CreateDllBuilder ()) { + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + } + } + + [Test] + public void AndroidMavenLibrary_AllDependenciesAreVerified () + { + // Test that triggers Java dependency verification and that + // all dependencies are verified via various supported mechanisms + + // + var item = new BuildItem ("AndroidMavenLibrary", "androidx.core:core"); + item.Metadata.Add ("Version", "1.9.0"); + item.Metadata.Add ("Repository", "Google"); + item.Metadata.Add ("Bind", "false"); + + // Dependency fulfilled by + var annotations_nuget = new Package { + Id = "Xamarin.AndroidX.Annotation", + Version = "1.7.0.3" + }; + + // Dependency fulfilled by + var annotations_experimental_androidlib = new BuildItem ("AndroidMavenLibrary", "androidx.annotation:annotation-experimental"); + annotations_experimental_androidlib.Metadata.Add ("Version", "1.3.0"); + annotations_experimental_androidlib.Metadata.Add ("Repository", "Google"); + annotations_experimental_androidlib.Metadata.Add ("Bind", "false"); + annotations_experimental_androidlib.Metadata.Add ("VerifyDependencies", "false"); + + // Dependency fulfilled by + var collection = new XamarinAndroidBindingProject (); + + // Dependencies ignored by + var concurrent = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.concurrent:concurrent-futures"); + concurrent.Metadata.Add ("Version", "1.1.0"); + + var lifecycle = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.lifecycle:lifecycle-runtime"); + lifecycle.Metadata.Add ("Version", "2.6.2"); + + var parcelable = new BuildItem ("AndroidIgnoredJavaDependency", "androidx.versionedparcelable:versionedparcelable"); + parcelable.Metadata.Add ("Version", "1.2.0"); + + var proj = new XamarinAndroidBindingProject { + Jars = { item, annotations_experimental_androidlib }, + PackageReferences = { annotations_nuget }, + OtherBuildItems = { concurrent, lifecycle, parcelable }, + }; + + proj.AddReference (collection); + var collection_proj = proj.References.First (); + collection_proj.Metadata.Add ("JavaArtifact", "androidx.collection:collection"); + collection_proj.Metadata.Add ("JavaVersion", "1.3.0"); + + using var a = CreateDllBuilder (); + using var b = CreateDllBuilder (); + + Assert.IsTrue (a.Build (proj), "ProjectReference build should have succeeded."); + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetMicrosoftNuGetPackagesMapTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetMicrosoftNuGetPackagesMapTests.cs new file mode 100644 index 00000000000..c07a33bdc1c --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetMicrosoftNuGetPackagesMapTests.cs @@ -0,0 +1,158 @@ +#nullable enable + +using System; +using System.IO; +using System.Threading.Tasks; +using NUnit.Framework; +using Xamarin.Android.Tasks; + +namespace Xamarin.Android.Build.Tests +{ + public class GetMicrosoftNuGetPackagesMapTests + { + [Test] + public async Task NoCachedFile () + { + var engine = new MockBuildEngine (TestContext.Out, []); + var temp_cache_dir = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ()); + var today_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today:yyyyMMdd}.json"); + + try { + var task = new GetMicrosoftNuGetPackagesMap { + BuildEngine = engine, + MavenCacheDirectory = temp_cache_dir, + }; + + await task.RunTaskAsync (); + + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (today_file, task.ResolvedPackageMap); + Assert.IsTrue (File.Exists (today_file)); + + } finally { + MavenDownloadTests.DeleteTempDirectory (temp_cache_dir); + } + } + + [Test] + public async Task CachedTodayFile () + { + // If a file already exists for today, it should be used and nothing new should be downloaded + var engine = new MockBuildEngine (TestContext.Out, []); + var temp_cache_dir = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ()); + var today_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today:yyyyMMdd}.json"); + + try { + Directory.CreateDirectory (temp_cache_dir); + File.WriteAllText (today_file, "dummy file"); + + var task = new GetMicrosoftNuGetPackagesMap { + BuildEngine = engine, + MavenCacheDirectory = temp_cache_dir, + }; + + await task.RunTaskAsync (); + + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (today_file, task.ResolvedPackageMap); + Assert.IsTrue (File.Exists (today_file)); + + // Ensure file didn't change + var text = File.ReadAllText (today_file); + Assert.AreEqual ("dummy file", text); + + } finally { + MavenDownloadTests.DeleteTempDirectory (temp_cache_dir); + } + } + + [Test] + public async Task CachedYesterdayFile () + { + // If a file only exists for yesterday, a new one should be downloaded and the old one should be deleted + var engine = new MockBuildEngine (TestContext.Out, []); + var temp_cache_dir = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ()); + var yesterday_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today.AddDays (-1):yyyyMMdd}.json"); + var today_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today:yyyyMMdd}.json"); + + try { + Directory.CreateDirectory (temp_cache_dir); + File.WriteAllText (yesterday_file, "dummy file"); + + var task = new GetMicrosoftNuGetPackagesMap { + BuildEngine = engine, + MavenCacheDirectory = temp_cache_dir, + }; + + await task.RunTaskAsync (); + + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (today_file, task.ResolvedPackageMap); + Assert.IsFalse (File.Exists (yesterday_file)); + + } finally { + MavenDownloadTests.DeleteTempDirectory (temp_cache_dir); + } + } + + [Test] + public async Task MalformedFileName () + { + // Make sure a malformed file name doesn't cause an exception, a new file should be downloaded and returned + var engine = new MockBuildEngine (TestContext.Out, []); + var temp_cache_dir = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ()); + var malformed_file = Path.Combine (temp_cache_dir, $"microsoft-packages-dummy.json"); + var today_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today:yyyyMMdd}.json"); + + try { + Directory.CreateDirectory (temp_cache_dir); + File.WriteAllText (malformed_file, "dummy file"); + + var task = new GetMicrosoftNuGetPackagesMap { + BuildEngine = engine, + MavenCacheDirectory = temp_cache_dir, + }; + + await task.RunTaskAsync (); + + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (today_file, task.ResolvedPackageMap); + Assert.IsTrue (File.Exists (today_file)); + + } finally { + MavenDownloadTests.DeleteTempDirectory (temp_cache_dir); + } + } + + // This test can only be run manually, since it requires changing the URL to a non-existent one. + // But I wanted to ensure I had tested this scenario. + //[Test] + public async Task CachedYesterdayFile_NewFileFails () + { + // If a file only exists for yesterday, but we fail to download a new file today, return + // the old file and don't delete it + var engine = new MockBuildEngine (TestContext.Out, []); + var temp_cache_dir = Path.Combine (Path.GetTempPath (), Guid.NewGuid ().ToString ()); + var yesterday_file = Path.Combine (temp_cache_dir, $"microsoft-packages-{DateTime.Today.AddDays (-1):yyyyMMdd}.json"); + + try { + Directory.CreateDirectory (temp_cache_dir); + File.WriteAllText (yesterday_file, "dummy file"); + + var task = new GetMicrosoftNuGetPackagesMap { + BuildEngine = engine, + MavenCacheDirectory = temp_cache_dir, + }; + + await task.RunTaskAsync (); + + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (yesterday_file, task.ResolvedPackageMap); + Assert.IsTrue (File.Exists (yesterday_file)); + + } finally { + MavenDownloadTests.DeleteTempDirectory (temp_cache_dir); + } + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs new file mode 100644 index 00000000000..f854c422b7e --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs @@ -0,0 +1,497 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Xml; +using Java.Interop.Tools.Maven.Models; +using Microsoft.Build.Utilities; +using NUnit.Framework; +using Xamarin.Android.Tasks; + +namespace Xamarin.Android.Build.Tests; + +public class JavaDependencyVerificationTests +{ + [Test] + public void NoManifestsSpecified () + { + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + }; + + Assert.True (task.RunTask ()); + } + + [Test] + public void MissingPom () + { + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", "missing.pom")], + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.AreEqual ("Specified POM file 'missing.pom' does not exist.", engine.Errors [0].Message); + } + + [Test] + public void MalformedPom () + { + using var pom = new TemporaryFile ("this is not valid XML"); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath)], + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.True (engine.Errors [0].Message?.StartsWith ("Could not parse POM file")); + } + + [Test] + public void NoSpecifiedDependencies () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0").BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath)], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void MissingSpecifiedDependency () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "missing", "1.0") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath)], + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.AreEqual ("Java dependency 'com.google.android:missing:1.0' is not satisfied.", engine.Errors [0].Message); + } + + [Test] + public void MissingParentSpecifiedDependency () + { + using var parent_pom = new PomBuilder ("com.google.android", "material-parent", "1.0") + .WithDependencyManagement ("com.google.android", "missing", "2.0") + .BuildTemporary (); + + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithParent ("com.google.android", "material-parent", "1.0") + .WithDependency ("com.google.android", "missing", "") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath)], + AdditionalManifests = [CreateAndroidAdditionManifestTaskItem (parent_pom.FilePath)], + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.AreEqual ("Java dependency 'com.google.android:missing:2.0' is not satisfied.", engine.Errors [0].Message); + } + + [Test] + public void MissingSpecifiedDependencyWithNugetSuggestion () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + using var package_finder = CreateMicrosoftNuGetPackageFinder ("com.google.android:material-core", "Xamarin.Google.Material.Core"); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath)], + MicrosoftPackagesFile = package_finder.FilePath, + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.AreEqual ("Java dependency 'com.google.android:material-core:1.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Google.Material.Core' that could fulfill this dependency.", engine.Errors [0].Message); + } + + [Test] + public void MalformedMicrosoftPackagesJson () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + using var package_finder = new TemporaryFile ("This is not valid json!", "microsoft-packages.json"); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"), + ], + MicrosoftPackagesFile = package_finder.FilePath, + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void DependencyFulfilledByAndroidLibrary () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"), + ], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void DependencyFulfilledByProjectReferenceExplicitMetadata () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + ], + ProjectReferences = [ + CreateAndroidLibraryTaskItem ("Google.Material.Core.csproj", null, "com.google.android:material-core", "1.0"), + ], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void DependencyFulfilledByPackageReferenceExplicitMetadata () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + ], + PackageReferences = [ + CreateAndroidLibraryTaskItem ("Xamarin.Google.Material.Core", null, "com.google.android:material-core", "1.0"), + ], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void DependencyIgnored () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", "1.0") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + ], + IgnoredDependencies = [ + CreateAndroidLibraryTaskItem ("com.google.android:material-core", rawVersion: "1.0"), + ], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + + [Test] + public void DependencyWithoutVersionFulfilled () + { + // The dependency is fulfilled but the version isn't checked + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", null) + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, [], []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + CreateAndroidLibraryTaskItem ("com.google.android.material-core.jar", null, "com.google.android:material-core", "1.0"), + ], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + Assert.AreEqual (0, engine.Warnings.Count); + } + + [Test] + public void DependencyWithoutVersionNotFulfilled () + { + using var pom = new PomBuilder ("com.google.android", "material", "1.0") + .WithDependency ("com.google.android", "material-core", null) + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, [], []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [ + CreateAndroidLibraryTaskItem ("com.google.android.material.jar", pom.FilePath), + ], + }; + + var result = task.RunTask (); + + Assert.False (result); + Assert.AreEqual (1, engine.Errors.Count); + Assert.AreEqual ("Java dependency 'com.google.android:material-core' is not satisfied.", engine.Errors [0].Message); + } + + TaskItem CreateAndroidLibraryTaskItem (string name, string? manifest = null, string? javaArtifact = null, string? javaVersion = null, string? rawVersion = null) + { + var item = new TaskItem (name); + + if (manifest is not null) + item.SetMetadata ("Manifest", manifest); + if (javaArtifact is not null) + item.SetMetadata ("JavaArtifact", javaArtifact); + if (javaVersion is not null) + item.SetMetadata ("JavaVersion", javaVersion); + if (rawVersion is not null) + item.SetMetadata ("Version", rawVersion); + + return item; + } + + TaskItem CreateAndroidAdditionManifestTaskItem (string name) + { + var item = new TaskItem (name); + + return item; + } + + TemporaryFile CreateMicrosoftNuGetPackageFinder (string javaId, string nugetId) + { + var package = new MicrosoftNuGetPackageFinder.PackageListFile { + Packages = [new MicrosoftNuGetPackageFinder.Package { JavaId = javaId, NuGetId = nugetId }] + }; + + return new TemporaryFile (JsonSerializer.Serialize (package), "microsoft-packages.json"); + } +} + +class TemporaryFile : IDisposable +{ + public string Content { get; } + public string FilePath { get; } + + public TemporaryFile (string content, string? filename = null) + { + Content = content; + FilePath = Path.Combine (Path.GetTempPath (), filename ?? Path.GetTempFileName ()); + + File.WriteAllText (FilePath, content); + } + + public void Dispose () + { + try { + File.Delete (FilePath); + } catch { + } + } +} + +class PomBuilder +{ + public string GroupId { get; } + public string ArtifactId { get; } + public string? Version { get; } + public List Dependencies { get; } = new (); + public List DependencyManagement { get; } = new (); + public string? ParentGroupId { get; set; } + public string? ParentArtifactId { get; set; } + public string? ParentVersion { get; set; } + + public PomBuilder (string groupId, string artifactId, string? version) + { + GroupId = groupId; + ArtifactId = artifactId; + Version = version; + } + + public string Build () + { + using var sw = new Utf8StringWriter (); + using var xw = XmlWriter.Create (sw); + + xw.WriteStartDocument (); + xw.WriteStartElement ("project", "http://maven.apache.org/POM/4.0.0"); + + xw.WriteElementString ("modelVersion", "4.0.0"); + xw.WriteElementString ("groupId", GroupId); + xw.WriteElementString ("artifactId", ArtifactId); + + if (Version.HasValue ()) + xw.WriteElementString ("version", Version); + + if (ParentGroupId.HasValue () && ParentArtifactId.HasValue ()) { + xw.WriteStartElement ("parent"); + + xw.WriteElementString ("groupId", ParentGroupId); + xw.WriteElementString ("artifactId", ParentArtifactId); + + if (ParentVersion.HasValue ()) + xw.WriteElementString ("version", ParentVersion); + + xw.WriteEndElement (); // parent + } + + if (DependencyManagement.Any ()) { + xw.WriteStartElement ("dependencyManagement"); + xw.WriteStartElement ("dependencies"); + + foreach (var dependency in DependencyManagement) { + xw.WriteStartElement ("dependency"); + + xw.WriteElementString ("groupId", dependency.GroupId); + xw.WriteElementString ("artifactId", dependency.ArtifactId); + + if (dependency.Version.HasValue ()) + xw.WriteElementString ("version", dependency.Version); + + xw.WriteEndElement (); // dependency + } + + xw.WriteEndElement (); // dependencies + xw.WriteEndElement (); // dependencyManagement + } + + + if (Dependencies.Any ()) { + xw.WriteStartElement ("dependencies"); + + foreach (var dependency in Dependencies) { + xw.WriteStartElement ("dependency"); + + xw.WriteElementString ("groupId", dependency.GroupId); + xw.WriteElementString ("artifactId", dependency.ArtifactId); + + if (dependency.Version.HasValue ()) + xw.WriteElementString ("version", dependency.Version); + + xw.WriteEndElement (); // dependency + } + + xw.WriteEndElement (); // dependencies + } + xw.WriteEndElement (); // project + xw.Close (); + + return sw.ToString (); + } + + public PomBuilder WithDependency (string groupId, string artifactId, string? version) + { + Dependencies.Add (new Dependency { + GroupId = groupId, + ArtifactId = artifactId, + Version = version, + }); + + return this; + } + + public PomBuilder WithDependencyManagement (string groupId, string artifactId, string? version) + { + DependencyManagement.Add (new Dependency { + GroupId = groupId, + ArtifactId = artifactId, + Version = version, + }); + + return this; + } + + public PomBuilder WithParent (string groupId, string artifactId, string? version) + { + ParentGroupId = groupId; + ParentArtifactId = artifactId; + ParentVersion = version; + + return this; + } + + public TemporaryFile BuildTemporary () => new TemporaryFile (Build ()); + + // Trying to write XML to a StringWriter defaults to UTF-16, but we want UTF-8 + class Utf8StringWriter : StringWriter + { + public override Encoding Encoding => Encoding.UTF8; + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs index 5d9c6bda151..c2ad0117fe4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Collections.Generic; using System.IO; @@ -22,7 +24,7 @@ public async Task MissingVersionMetadata () await task.RunTaskAsync (); Assert.AreEqual (1, engine.Errors.Count); - Assert.AreEqual ("'' item 'com.google.android.material:material' is missing required metadata 'Version'", engine.Errors [0].Message); + Assert.AreEqual ("'' item 'com.google.android.material:material' is missing required attribute 'Version'.", engine.Errors [0].Message); } [Test] @@ -83,7 +85,7 @@ public async Task UnknownArtifact () await task.RunTaskAsync (); Assert.AreEqual (1, engine.Errors.Count); - Assert.AreEqual ($"Cannot download Maven artifact 'com.example:dummy'.{Environment.NewLine}- com.example_dummy.jar: Response status code does not indicate success: 404 (Not Found).{Environment.NewLine}- com.example_dummy.aar: Response status code does not indicate success: 404 (Not Found).", engine.Errors [0].Message.ReplaceLineEndings ()); + Assert.AreEqual ($"Cannot download Maven artifact 'com.example:dummy'.{Environment.NewLine}- dummy-1.0.0.jar: Response status code does not indicate success: 404 (Not Found).{Environment.NewLine}- dummy-1.0.0.aar: Response status code does not indicate success: 404 (Not Found).", engine.Errors [0].Message?.ReplaceLineEndings ()); } [Test] @@ -100,15 +102,15 @@ public async Task UnknownPom () }; // Create the dummy jar so we bypass that step and try to download the dummy pom - var dummy_jar = Path.Combine (temp_cache_dir, "central", "com.example", "dummy", "1.0.0", "com.example_dummy.jar"); - Directory.CreateDirectory (Path.GetDirectoryName (dummy_jar)); + var dummy_jar = Path.Combine (temp_cache_dir, "central", "com.example", "dummy", "1.0.0", "dummy-1.0.0.jar"); + Directory.CreateDirectory (Path.GetDirectoryName (dummy_jar)!); using (File.Create (dummy_jar)) { } await task.RunTaskAsync (); Assert.AreEqual (1, engine.Errors.Count); - Assert.AreEqual ($"Cannot download POM file for Maven artifact 'com.example:dummy'.{Environment.NewLine}- com.example_dummy.pom: Response status code does not indicate success: 404 (Not Found).", engine.Errors [0].Message.ReplaceLineEndings ()); + Assert.AreEqual ($"Cannot download POM file for Maven artifact 'com.example:dummy:1.0.0'.{Environment.NewLine}- Response status code does not indicate success: 404 (Not Found).", engine.Errors [0].Message?.ReplaceLineEndings ()); } finally { DeleteTempDirectory (temp_cache_dir); } @@ -130,16 +132,13 @@ public async Task MavenCentralSuccess () await task.RunTaskAsync (); Assert.AreEqual (0, engine.Errors.Count); - Assert.AreEqual (1, task.ResolvedAndroidMavenLibraries.Length); - - var output_item = task.ResolvedAndroidMavenLibraries [0]; + Assert.AreEqual (1, task.ResolvedAndroidMavenLibraries?.Length); - Assert.AreEqual ("com.google.auto.value:auto-value-annotations", output_item.GetMetadata ("ArtifactSpec")); - Assert.AreEqual (Path.Combine (temp_cache_dir, "central", "com.google.auto.value", "auto-value-annotations", "1.10.4", "com.google.auto.value_auto-value-annotations.jar"), output_item.GetMetadata ("ArtifactFile")); - Assert.AreEqual (Path.Combine (temp_cache_dir, "central", "com.google.auto.value", "auto-value-annotations", "1.10.4", "com.google.auto.value_auto-value-annotations.pom"), output_item.GetMetadata ("ArtifactPom")); + var output_item = task.ResolvedAndroidMavenLibraries! [0]; - Assert.True (File.Exists (output_item.GetMetadata ("ArtifactFile"))); - Assert.True (File.Exists (output_item.GetMetadata ("ArtifactPom"))); + Assert.AreEqual ("com.google.auto.value:auto-value-annotations", output_item.GetMetadata ("JavaArtifact")); + Assert.AreEqual ("1.10.4", output_item.GetMetadata ("JavaVersion")); + Assert.AreEqual (Path.Combine (temp_cache_dir, "central", "com.google.auto.value", "auto-value-annotations", "1.10.4", "auto-value-annotations-1.10.4.pom"), output_item.GetMetadata ("Manifest")); } finally { DeleteTempDirectory (temp_cache_dir); } @@ -161,22 +160,19 @@ public async Task MavenGoogleSuccess () await task.RunTaskAsync (); Assert.AreEqual (0, engine.Errors.Count); - Assert.AreEqual (1, task.ResolvedAndroidMavenLibraries.Length); - - var output_item = task.ResolvedAndroidMavenLibraries [0]; + Assert.AreEqual (1, task.ResolvedAndroidMavenLibraries?.Length); - Assert.AreEqual ("androidx.core:core", output_item.GetMetadata ("ArtifactSpec")); - Assert.AreEqual (Path.Combine (temp_cache_dir, "google", "androidx.core", "core", "1.12.0", "androidx.core_core.aar"), output_item.GetMetadata ("ArtifactFile")); - Assert.AreEqual (Path.Combine (temp_cache_dir, "google", "androidx.core", "core", "1.12.0", "androidx.core_core.pom"), output_item.GetMetadata ("ArtifactPom")); + var output_item = task.ResolvedAndroidMavenLibraries! [0]; - Assert.True (File.Exists (output_item.GetMetadata ("ArtifactFile"))); - Assert.True (File.Exists (output_item.GetMetadata ("ArtifactPom"))); + Assert.AreEqual ("androidx.core:core", output_item.GetMetadata ("JavaArtifact")); + Assert.AreEqual ("1.12.0", output_item.GetMetadata ("JavaVersion")); + Assert.AreEqual (Path.Combine (temp_cache_dir, "google", "androidx.core", "core", "1.12.0", "core-1.12.0.pom"), output_item.GetMetadata ("Manifest")); } finally { DeleteTempDirectory (temp_cache_dir); } } - ITaskItem CreateMavenTaskItem (string name, string version, string repository = null) + ITaskItem CreateMavenTaskItem (string name, string? version, string? repository = null) { var item = new TaskItem (name); @@ -188,7 +184,7 @@ ITaskItem CreateMavenTaskItem (string name, string version, string repository = return item; } - void DeleteTempDirectory (string dir) + public static void DeleteTempDirectory (string dir) { try { Directory.Delete (dir, true); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MavenExtensions.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MavenExtensions.cs index 4fc7f031833..a9b881adec6 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MavenExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MavenExtensions.cs @@ -1,16 +1,15 @@ +#nullable enable + using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml; -using System.Xml.Serialization; -using MavenNet; -using MavenNet.Models; +using Java.Interop.Tools.Maven.Models; +using Java.Interop.Tools.Maven.Repositories; using Microsoft.Android.Build.Tasks; +using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Xamarin.Android.Tasks; @@ -18,7 +17,6 @@ namespace Xamarin.Android.Tasks; static class MavenExtensions { static readonly char [] separator = [':']; - static XmlSerializer pom_serializer = new XmlSerializer (typeof (Project)); /// /// Shortcut for !string.IsNullOrWhiteSpace (s) @@ -31,53 +29,87 @@ public static T [] OrEmpty (this T []? value) return value ?? Array.Empty (); } - public static Artifact? ParseArtifact (string id, string version, TaskLoggingHelper log) + // Removes AggregateException wrapping around an exception + public static Exception Unwrap (this Exception ex) { + while (ex is AggregateException && ex.InnerException is not null) + ex = ex.InnerException; + + return ex; + } + + public static bool TryParseArtifactWithVersion (string id, string version, TaskLoggingHelper log, [NotNullWhen (true)] out Artifact? artifact) + { + artifact = null; + var parts = id.Split (separator, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 2 || parts.Any (string.IsNullOrWhiteSpace)) { log.LogCodedError ("XA4235", Properties.Resources.XA4235, id); - return null; + return false; } - var artifact = new Artifact (parts [1], parts [0], version); + artifact = new Artifact (parts [0], parts [1], version); - return artifact; + return true; } - public static Project ParsePom (string pomFile) + public static bool TryParseJavaArtifactAndJavaVersion (this ITaskItem task, string type, TaskLoggingHelper log, [NotNullWhen (true)] out Artifact? artifact, out bool attributesSpecified) { - Project result = null; + artifact = null; + var item_name = task.ItemSpec; - using (var sr = File.OpenRead (pomFile)) - result = (Project) pom_serializer.Deserialize (new XmlTextReader (sr) { - Namespaces = false, - }); + // Convert "../../src/blah/Blah.csproj" to "Blah.csproj" + if (type == "ProjectReference") + item_name = Path.GetFileName (item_name); - return result; - } + var has_artifact = task.HasMetadata ("JavaArtifact"); + var has_version = task.HasMetadata ("JavaVersion"); - public static Artifact? CheckForNeededParentPom (string pomFile) - => ParsePom (pomFile).GetParentPom (); + // Lets callers know if user attempted to specify JavaArtifact or JavaVersion, even if they did it incorrectly + attributesSpecified = has_artifact || has_version; - public static Artifact? GetParentPom (this Project? pom) - { - if (pom?.Parent != null) - return new Artifact (pom.Parent.ArtifactId, pom.Parent.GroupId, pom.Parent.Version); + if (has_artifact && !has_version) { + log.LogCodedError ("XA4243", Properties.Resources.XA4243, "JavaVersion", "JavaArtifact", type, item_name); + return false; + } - return null; + if (!has_artifact && has_version) { + log.LogCodedError ("XA4243", Properties.Resources.XA4243, "JavaArtifact", "JavaVersion", type, item_name); + return false; + } + + if (has_artifact && has_version) { + var id = task.GetMetadata ("JavaArtifact"); + var version = task.GetMetadata ("JavaVersion"); + + if (string.IsNullOrWhiteSpace (id)) { + log.LogCodedError ("XA4244", Properties.Resources.XA4244, "JavaArtifact", type, item_name); + return false; + } + + if (string.IsNullOrWhiteSpace (version)) { + log.LogCodedError ("XA4244", Properties.Resources.XA4244, "JavaVersion", type, item_name); + return false; + } + + if (TryParseArtifactWithVersion (id, version, log, out artifact)) { + log.LogMessage ("Found Java dependency '{0}:{1}' version '{2}' from {3} '{4}' (JavaArtifact)", artifact.GroupId, artifact.Id, artifact.Version, type, item_name); + return true; + } + } + + return false; } // Returns artifact output path - public static async Task DownloadPayload (Artifact artifact, string cacheDir, TaskLoggingHelper log, CancellationToken cancellationToken) + public static async Task DownloadPayload (CachedMavenRepository repository, Artifact artifact, string cacheDir, TaskLoggingHelper log, CancellationToken cancellationToken) { - var version = artifact.Versions.First (); - - var output_directory = Path.Combine (cacheDir, artifact.GetRepositoryCacheName (), artifact.GroupId, artifact.Id, version); + var output_directory = Path.Combine (cacheDir, repository.Name, artifact.GroupId, artifact.Id, artifact.Version); Directory.CreateDirectory (output_directory); - var filename = $"{artifact.GroupId}_{artifact.Id}"; + var filename = $"{artifact.Id}-{artifact.Version}"; var jar_filename = Path.Combine (output_directory, Path.Combine ($"{filename}.jar")); var aar_filename = Path.Combine (output_directory, Path.Combine ($"{filename}.aar")); @@ -88,10 +120,10 @@ public static Project ParsePom (string pomFile) if (File.Exists (aar_filename)) return aar_filename; - if (await TryDownloadPayload (artifact, jar_filename, cancellationToken) is not string jar_error) + if (await TryDownloadPayload (repository, artifact, jar_filename, cancellationToken) is not string jar_error) return jar_filename; - if (await TryDownloadPayload (artifact, aar_filename, cancellationToken) is not string aar_error) + if (await TryDownloadPayload (repository, artifact, aar_filename, cancellationToken) is not string aar_error) return aar_filename; log.LogCodedError ("XA4236", Properties.Resources.XA4236, artifact.GroupId, artifact.Id, Path.GetFileName (jar_filename), jar_error, Path.GetFileName (aar_filename), aar_error); @@ -99,130 +131,27 @@ public static Project ParsePom (string pomFile) return null; } - // Returns artifact output path - public static async Task DownloadPom (Artifact artifact, string cacheDir, TaskLoggingHelper log, CancellationToken cancellationToken, bool isParent = false) + // Return value is download error message, null represents success (async methods cannot have out parameters) + static async Task TryDownloadPayload (CachedMavenRepository repository, Artifact artifact, string filename, CancellationToken cancellationToken) { - var version = artifact.Versions.First (); - var output_directory = Path.Combine (cacheDir, artifact.GetRepositoryCacheName (), artifact.GroupId, artifact.Id, version); - - Directory.CreateDirectory (output_directory); - - var filename = $"{artifact.GroupId}_{artifact.Id}"; - var pom_filename = Path.Combine (output_directory, Path.Combine ($"{filename}.pom")); - - // We don't need to redownload if we already have a cached copy - if (File.Exists (pom_filename)) - return pom_filename; - - if (await TryDownloadPayload (artifact, pom_filename, cancellationToken) is not string pom_error) - return pom_filename; - - if (!isParent) - log.LogCodedError ("XA4237", Properties.Resources.XA4237, artifact.GroupId, artifact.Id, Path.GetFileName (pom_filename), pom_error); - else - log.LogCodedError ("XA4238", Properties.Resources.XA4238, artifact.GroupId, artifact.Id, Path.GetFileName (pom_filename), pom_error); - - return null; - } + var maven_filename = $"{artifact.Id}-{artifact.Version}{Path.GetExtension (filename)}"; - // Return value indicates download success - static async Task TryDownloadPayload (Artifact artifact, string filename, CancellationToken cancellationToken) - { try { - using var src = await artifact.OpenLibraryFile (artifact.Versions.First (), Path.GetExtension (filename)); - using var sw = File.Create (filename); + if ((await repository.GetFilePathAsync (artifact, maven_filename, cancellationToken)) is string path) { + return null; + } else { + // This probably(?) cannot be hit, everything should come back as an exception + return $"Could not download {maven_filename}"; + } - await src.CopyToAsync (sw, 81920, cancellationToken); - - return null; } catch (Exception ex) { - return ex.Message; - } - } - - public static string GetRepositoryCacheName (this Artifact artifact) - { - var type = artifact.Repository; - - if (type is MavenCentralRepository) - return "central"; - - if (type is GoogleMavenRepository) - return "google"; - - if (type is UrlMavenRepository url) { - using var hasher = SHA256.Create (); - var hash = hasher.ComputeHash (Encoding.UTF8.GetBytes (url.BaseUri.ToString ())); - return Convert.ToBase64String (hash); - } - - // Should never be hit - throw new ArgumentException ($"Unexpected repository type: {type.GetType ()}"); - } - - public static void FixDependency (Project project, Project? parent, Dependency dependency) - { - // Handle Parent POM - if ((string.IsNullOrEmpty (dependency.Version) || string.IsNullOrEmpty (dependency.Scope)) && parent != null) { - var parent_dependency = parent.FindParentDependency (dependency); - - // Try to fish a version out of the parent POM - if (string.IsNullOrEmpty (dependency.Version)) - dependency.Version = ReplaceVersionProperties (parent, parent_dependency?.Version); - - // Try to fish a scope out of the parent POM - if (string.IsNullOrEmpty (dependency.Scope)) - dependency.Scope = parent_dependency?.Scope; + return ex.Unwrap ().Message; } - - var version = dependency.Version; - - if (string.IsNullOrWhiteSpace (version)) - return; - - version = ReplaceVersionProperties (project, version); - - // VersionRange.Parse cannot handle single number versions that we sometimes see in Maven, like "1". - // Fix them to be "1.0". - // https://github.com/NuGet/Home/issues/10342 - if (version != null && !version.Contains (".")) - version += ".0"; - - dependency.Version = version; - } - - static string? ReplaceVersionProperties (Project project, string? version) - { - // Handle versions with Properties, like: - // - // 1.8 - // 2.8.6 - // - // - // - // com.google.code.gson - // gson - // ${gson.version} - // - // - if (string.IsNullOrWhiteSpace (version) || project?.Properties == null) - return version; - - foreach (var prop in project.Properties.Any) - version = version?.Replace ($"${{{prop.Name.LocalName}}}", prop.Value); - - return version; } - public static bool IsCompileDependency (this Dependency dependency) => string.IsNullOrWhiteSpace (dependency.Scope) || dependency.Scope.IndexOf ("compile", StringComparison.OrdinalIgnoreCase) != -1; + public static bool IsCompileDependency (this ResolvedDependency dependency) => string.IsNullOrWhiteSpace (dependency.Scope) || dependency.Scope.IndexOf ("compile", StringComparison.OrdinalIgnoreCase) != -1; - public static bool IsRuntimeDependency (this Dependency dependency) => dependency?.Scope != null && dependency.Scope.IndexOf ("runtime", StringComparison.OrdinalIgnoreCase) != -1; - - public static Dependency? FindParentDependency (this Project project, Dependency dependency) - { - return project.DependencyManagement?.Dependencies?.FirstOrDefault ( - d => d.GroupAndArtifactId () == dependency.GroupAndArtifactId () && d.Classifier != "sources"); - } + public static bool IsRuntimeDependency (this ResolvedDependency dependency) => dependency?.Scope != null && dependency.Scope.IndexOf ("runtime", StringComparison.OrdinalIgnoreCase) != -1; - public static string GroupAndArtifactId (this Dependency dependency) => $"{dependency.GroupId}.{dependency.ArtifactId}"; + public static bool IsOptional (this ResolvedDependency dependency) => dependency?.Optional != null && dependency.Optional.IndexOf ("true", StringComparison.OrdinalIgnoreCase) != -1; } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 3bef384882d..2588f29e729 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -14,7 +14,7 @@ true $(MicrosoftAndroidSdkOutDir) false - $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;ANDROID_24;ANDROID_26;ANDROID_31 + $(DefineConstants);TRACE;HAVE_CECIL;MSBUILD;ANDROID_24;ANDROID_26;ANDROID_31;INTERNAL_NULLABLE_ATTRIBUTES ..\..\src\Mono.Android\obj\$(Configuration)\$(DotNetTargetFramework)\android-$(AndroidLatestStablePlatformId)\mcw 8632 false @@ -28,7 +28,9 @@ - + + + @@ -98,6 +100,9 @@ Utilities\StringRocks.cs + + Utilities\NullableAttributes.cs + Mono.Android\UsesLibraryAttribute.cs @@ -225,6 +230,7 @@ + 34.99.0 - preview.3 + preview.4 From bea92a58e0e8ef64d2c4775d18a0744c21386461 Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Mon, 25 Mar 2024 14:51:46 -0700 Subject: [PATCH 09/17] [Xamarin.Android.Build.Tasks] Bump to NuGet 6.7.1 (#8833) Context: https://github.com/xamarin/xamarin-android/security/dependabot/1 Bumps NuGet.Packaging and related packages from version 6.7.0 to 6.7.1 to address a security issue. --- .../Xamarin.Android.Build.Tasks.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 2588f29e729..05a4fa33ba6 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -28,9 +28,9 @@ - - - + + + From d798cc9ffb8c46b3bfc30f435048132528485460 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 26 Mar 2024 16:54:41 +0000 Subject: [PATCH 10/17] [Xamarin.Android.Build.Tasks] DTBs should not rm generator output (#8706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/xamarin/xamarin-android/issues/8658 Fixes: https://github.com/xamarin/xamarin-android/issues/8698 Design-time builds don't play nicely with binding project builds: % dotnet new androidlib % cat > Example.java < + + + <_LibrariesToBind Include="@(EmbeddedJar)" /> + <_LibrariesToBind Include="@(InputJar)" /> + <_LibrariesToBind Include="@(LibraryProjectZip)" /> + <_LibrariesToBind Include="@(_JavaBindingSource)" Condition=" '%(_JavaBindingSource.Bind)' == 'true' "/> + + + + Condition=" '@(_LibrariesToBind->Count())' != '0' "> <_AndroidGenerateManagedBindings>true - + <_GeneratedManagedBindingFiles Include="$(GeneratedOutputPath)**\*.cs" /> @@ -75,7 +83,6 @@ It is shared between "legacy" binding projects and .NET 5 projects. @@ -135,14 +142,17 @@ It is shared between "legacy" binding projects and .NET 5 projects. + + + + > true diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets index b932c578336..4c2a8ed5173 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets @@ -21,7 +21,9 @@ It is shared between "legacy" binding projects and .NET 7+ projects. <_AndroidIntermediateBindingClassesZip>$(IntermediateOutputPath)binding\bin\$(MSBuildProjectName).jar <_AndroidIntermediateBindingClassesDocs>$(IntermediateOutputPath)binding\bin\$(MSBuildProjectName)-docs.xml <_AndroidCompileJavaStampFile>$(_AndroidStampDirectory)_CompileJava.stamp + <_AndroidCompileJavaFileList>$(IntermediateOutputPath)_CompileJava.FileList.txt <_AndroidCompileBindingJavaStampFile>$(_AndroidStampDirectory)_CompileBindingJava.stamp + <_AndroidCompileBindingJavaFileList>$(IntermediateOutputPath)_CompileBindingJava.FileList.txt @@ -74,18 +76,36 @@ It is shared between "legacy" binding projects and .NET 7+ projects. <_JavaBindingSource Include="@(AndroidJavaSource)" Condition=" '%(AndroidJavaSource.Bind)' == 'True' " /> + + + + <_JavaSource Include="@(AndroidJavaSource)" Condition=" '%(AndroidJavaSource.Bind)' != 'True' " /> + + + + @@ -132,7 +152,7 @@ It is shared between "legacy" binding projects and .NET 7+ projects. diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index 31c9442e8e9..df4dab646d8 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -120,9 +120,6 @@ properties that determine build ordering. UpdateAndroidResources; _BuildResourceDesigner; UpdateAndroidInterfaceProxies; - _SetAndroidGenerateManagedBindings; - _ClearGeneratedManagedBindings; - AddBindingsToCompile; _CheckForInvalidDesignerConfig; @@ -144,6 +141,13 @@ properties that determine build ordering. _AddAndroidDefines; _IncludeLayoutBindingSources; AddLibraryJarsToBind; + _CollectLibrariesToBind; + _SetAndroidGenerateManagedBindings; + ExportJarToXml; + GenerateBindings; + _CollectGeneratedManagedBindingFiles; + _ClearGeneratedManagedBindings; + AddBindingsToCompile; _BuildResourceDesigner; _AddResourceDesignerFiles; $(CompileDependsOn); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs index bb76b585a1d..15f04ccf5e6 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs @@ -6,7 +6,9 @@ using System.Linq; using System.Xml; using System.Xml.Linq; +using System.Xml.XPath; using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; using Microsoft.Android.Build.Tasks; namespace Xamarin.Android.Tasks diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index 58d8012352a..81acffd0fb1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -39,7 +39,7 @@ public void DotNetBuildBinding () proj.OtherBuildItems.Add (new BuildItem ("JavaSourceJar", "javaclasses-sources.jar") { BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar, }); - proj.OtherBuildItems.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") { + proj.AndroidJavaSources.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") { Encoding = Encoding.ASCII, TextContent = () => ResourceData.JavaSourceTestExtension, Metadata = { { "Bind", "True"} }, @@ -75,6 +75,7 @@ public void BindingLibraryIncremental (string classParser) "_ResolveLibraryProjectImports", "CoreCompile", "_CreateAar", + "_ClearGeneratedManagedBindings", }; var proj = new XamarinAndroidBindingProject () { @@ -112,6 +113,23 @@ public void BindingLibraryIncremental (string classParser) foreach (var target in targets) { Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!"); } + + Assert.IsTrue (b.DesignTimeBuild (proj, target: "UpdateGeneratedFiles"), "DTB should have succeeded."); + var cs_file = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "generated", "src", "Com.Larvalabs.Svgandroid.SVGParser.cs"); + FileAssert.Exists (cs_file); + Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "third build should succeed"); + foreach (var target in targets) { + Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!"); + } + // Fast Update Check Build + Assert.IsTrue (b.DesignTimeBuild (proj, target: "PrepareResources;_GenerateCompileInputs"), "DTB should have succeeded."); + cs_file = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "generated", "src", "Com.Larvalabs.Svgandroid.SVGParser.cs"); + FileAssert.Exists (cs_file); + Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "forth build should succeed"); + foreach (var target in targets) { + Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!"); + } + } } @@ -671,6 +689,10 @@ public void BindingWithAndroidJavaSource () StringAssertEx.ContainsText (File.ReadAllLines (generatedIface), "string GreetWithQuestion (string name, global::Java.Util.Date date, string question);"); Assert.IsTrue (libBuilder.Build (lib), "Library build should have succeeded."); Assert.IsTrue (libBuilder.Output.IsTargetSkipped ("_CompileBindingJava"), $"`_CompileBindingJava` should be skipped on second build!"); + Assert.IsTrue (libBuilder.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings"), $"`_ClearGeneratedManagedBindings` should be skipped on second build!"); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on second build."); + Assert.IsTrue (libBuilder.DesignTimeBuild (lib, target: "UpdateGeneratedFiles"), "DTB should have succeeded."); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on DTB build."); Assert.IsTrue (appBuilder.Build (app), "App build should have succeeded."); appBuilder.Target = "SignAndroidPackage"; Assert.IsTrue (appBuilder.Build (app), "App SignAndroidPackage should have succeeded."); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index b0b69ff759b..fce460a2c6d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -70,7 +70,7 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo proj.OtherBuildItems.Add (new BuildItem ("JavaSourceJar", "javaclasses-sources.jar") { BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar, }); - proj.OtherBuildItems.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") { + proj.AndroidJavaSources.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") { Encoding = Encoding.ASCII, TextContent = () => ResourceData.JavaSourceTestExtension, Metadata = { { "Bind", "True"} }, @@ -1511,7 +1511,7 @@ public void BuildApplicationWithJavaSourceUsingAndroidX ([Values(true, false)] b { var proj = new XamarinAndroidApplicationProject () { IsRelease = isRelease, - OtherBuildItems = { + AndroidJavaSources = { new BuildItem (AndroidBuildActions.AndroidJavaSource, "ToolbarEx.java") { TextContent = () => @"package com.unnamedproject.unnamedproject; import android.content.Context; @@ -1556,11 +1556,11 @@ public void BuildApplicationCheckThatAddStaticResourcesTargetDoesNotRerun () public void CheckJavaError () { var proj = new XamarinAndroidApplicationProject (); - proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe.java") { + proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe.java") { TextContent = () => "public classo TestMe { }", Encoding = Encoding.ASCII }); - proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe2.java") { + proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe2.java") { TextContent = () => "public class TestMe2 {" + "public vod Test ()" + "}", diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 8e625dc3ab7..83d47a85bdc 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -1000,14 +1000,14 @@ public void BuildProguardEnabledProject (string rid) XamarinAndroidApplicationProject CreateMultiDexRequiredApplication (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release") { var proj = new XamarinAndroidApplicationProject (debugConfigurationName, releaseConfigurationName); - proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") { + proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") { TextContent = () => "public class ManyMethods { \n" + string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}")) + "}", Encoding = Encoding.ASCII, Metadata = { { "Bind", "False "}}, }); - proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") { + proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") { TextContent = () => "public class ManyMethods2 { \n" + string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}")) + "}", @@ -1064,8 +1064,8 @@ public void BuildAfterMultiDexIsNotRequired () } //Now build project again after it no longer requires multidex, remove the *HUGE* AndroidJavaSource build items - while (proj.OtherBuildItems.Count > 1) - proj.OtherBuildItems.RemoveAt (proj.OtherBuildItems.Count - 1); + while (proj.AndroidJavaSources.Count > 1) + proj.AndroidJavaSources.RemoveAt (proj.AndroidJavaSources.Count - 1); proj.SetProperty ("AndroidEnableMultiDex", "False"); Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "Build should have succeeded."); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs index 853003056f7..a5692e315ba 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs @@ -52,9 +52,9 @@ public List GetAssemblyMapCache () return File.ReadLines (path).ToList (); } - public bool IsTargetSkipped (string target) => IsTargetSkipped (Builder.LastBuildOutput, target); + public bool IsTargetSkipped (string target, bool defaultIfNotUsed = false) => IsTargetSkipped (Builder.LastBuildOutput, target, defaultIfNotUsed); - public static bool IsTargetSkipped (IEnumerable output, string target) + public static bool IsTargetSkipped (IEnumerable output, string target, bool defaultIfNotUsed = false) { bool found = false; foreach (var line in output) { @@ -69,7 +69,7 @@ public static bool IsTargetSkipped (IEnumerable output, string target) if (found) return true; } - return false; + return defaultIfNotUsed; } /// diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs index 32425e363c0..30ae44a3628 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs @@ -17,10 +17,12 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string Sources = new List (); OtherBuildItems = new List (); + AndroidJavaSources = new List (); ItemGroupList.Add (References); ItemGroupList.Add (OtherBuildItems); ItemGroupList.Add (Sources); + ItemGroupList.Add (AndroidJavaSources); SetProperty ("RootNamespace", () => RootNamespace ?? ProjectName); SetProperty ("AssemblyName", () => AssemblyName ?? ProjectName); @@ -40,6 +42,7 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string public IList OtherBuildItems { get; private set; } public IList Sources { get; private set; } + public IList AndroidJavaSources { get; private set; } public IList ActiveConfigurationProperties { get { return IsRelease ? ReleaseProperties : DebugProperties; } diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs index 20f9de4f0e6..c7e625c0707 100644 --- a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs +++ b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs @@ -611,5 +611,73 @@ public void AdbTargetChangesAppBundle () var after = File.GetLastWriteTimeUtc (apkset); Assert.AreNotEqual (before, after, $"{apkset} should change!"); } + + [Test] + public void AppWithAndroidJavaSource () + { + var path = Path.Combine ("temp", TestName); + var itemToDelete = new AndroidItem.AndroidJavaSource ("TestJavaClass2.java") { + Encoding = Encoding.ASCII, + TextContent = () => @"package com.test.java; + +public class TestJavaClass2 { + + public String test(){ + + return ""Java is called""; + } +}", + Metadata = { + { "Bind", "True" }, + }, + }; + var proj = new XamarinAndroidApplicationProject { + EnableDefaultItems = true, + AndroidJavaSources = { + new AndroidItem.AndroidJavaSource ("TestJavaClass.java") { + Encoding = Encoding.ASCII, + TextContent = () => @"package com.test.java; + +public class TestJavaClass { + + public String test(){ + + return ""Java is called""; + } +}", + Metadata = { + { "Bind", "True" }, + }, + }, + itemToDelete, + }, + }; + using (var b = CreateApkBuilder ()) { + b.ThrowOnBuildFailure = false; + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + b.AssertHasNoWarnings (); + var generatedCode = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, + "generated", "src", "Com.Test.Java.TestJavaClass.cs"); + var generatedCode2 = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, + "generated", "src", "Com.Test.Java.TestJavaClass2.cs"); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have been generated."); + FileAssert.Exists (generatedCode2, $"'{generatedCode2}' should have been generated."); + Assert.IsTrue (b.DesignTimeBuild (proj, target: "UpdateGeneratedFiles"), "DTB should have succeeded."); + Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings", defaultIfNotUsed: true), $"`_ClearGeneratedManagedBindings` should be skipped on DTB build!"); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on DTB build."); + FileAssert.Exists (generatedCode2, $"'{generatedCode2}' should have not be deleted on DTB build."); + proj.AndroidJavaSources.Remove (itemToDelete); + File.Delete (Path.Combine (Root, b.ProjectDirectory, itemToDelete.Include ())); + Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "Second build should have succeeded."); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on second build."); + FileAssert.DoesNotExist (generatedCode2, $"'{generatedCode2}' should have be deleted on second build."); + Assert.IsFalse (b.Output.IsTargetSkipped ("_CompileBindingJava"), $"`_CompileBindingJava` should run on second build!"); + Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings"), $"`_ClearGeneratedManagedBindings` should be skipped on second build!"); + // Call Install directly so Build does not get called automatically + Assert.IsTrue (b.RunTarget (proj, "Install", doNotCleanupOnUpdate: true, saveProject: false), "Install build should have succeeded."); + FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on Install build."); + Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings", defaultIfNotUsed: true), $"`_ClearGeneratedManagedBindings` should be skipped on Install build!"); + } + } } } From 9884bd0bc63fc25cc4a5c9719a6ff00cf32b08ab Mon Sep 17 00:00:00 2001 From: Peter Collins Date: Tue, 26 Mar 2024 11:00:58 -0700 Subject: [PATCH 11/17] [ci] Use managed identity for ApiScan (#8823) I've configured a new [managed identity][0] (MSI) for API Scan, which allows us to enable a more modern authentication approach when running API Scan on the `MAUI-1ESPT` agent pool. A new `$(ApiScanMAUI1ESPTManagedId)` variable has been configured in the pipeline settings to pass the app ID for this MSI to the API Scan task. [0]: https://ms.portal.azure.com/#@microsoft.onmicrosoft.com/resource/subscriptions/cd4829e2-e38b-43d2-8316-2f2009f36f97/resourcegroups/1esobjects/providers/microsoft.managedidentity/userassignedidentities/maui1esptapiscanidentity/overview --- build-tools/automation/azure-pipelines-nightly.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-tools/automation/azure-pipelines-nightly.yaml b/build-tools/automation/azure-pipelines-nightly.yaml index a71b2ac0872..49a37060c02 100644 --- a/build-tools/automation/azure-pipelines-nightly.yaml +++ b/build-tools/automation/azure-pipelines-nightly.yaml @@ -289,8 +289,8 @@ stages: - job: api_scan displayName: API Scan pool: - name: Azure Pipelines - vmImage: windows-2022 + name: MAUI-1ESPT + demands: ImageOverride -equals $(WindowsPoolImage1ESPT) timeoutInMinutes: 480 workspace: clean: all @@ -335,7 +335,7 @@ stages: isLargeApp: true toolVersion: Latest env: - AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId);TenantId=$(ApiScanTenant);AppKey=$(ApiScanSecret) + AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanMAUI1ESPTManagedId) - task: SdtReport@2 displayName: Guardian Export - Security Report From 150e1d99ec6d4deb600a185bd759ab4cbc9050ed Mon Sep 17 00:00:00 2001 From: "CSIGS@microsoft.com" Date: Wed, 27 Mar 2024 03:36:30 -0700 Subject: [PATCH 12/17] LEGO: Merge pull request 8837 LEGO: Merge pull request 8837 --- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- .../Properties/Resources.resx.lcl | 89 ++++++++++++++++--- 13 files changed, 1027 insertions(+), 130 deletions(-) diff --git a/Localize/loc/cs/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/cs/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 43d40aa37eb..07183fea021 100644 --- a/Localize/loc/cs/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/cs/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - {1} chybí požadovaná metadata {2}]]> + {1} chybí požadovaný atribut {2}.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + spustilo obnovení NuGet.]]> diff --git a/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 0b6be50bb81..092a4d3f9c6 100644 --- a/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/de/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - "-Element "{1}" fehlen die erforderlichen Metadaten "{2}"]]> + “-Element „{1}“ fehlt das erforderliche Attribut „{2}“.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + ausgeführt wurde.]]> diff --git a/Localize/loc/es/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/es/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 53997d48643..e6a045c4278 100644 --- a/Localize/loc/es/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/es/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - " el elemento "{1}" en los metadatos necesarios "{2}"]]> + + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + .]]> diff --git a/Localize/loc/fr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/fr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index d47387f7731..cc742b166a4 100644 --- a/Localize/loc/fr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/fr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' '{1}' ne contient pas les métadonnées requises '{2}']]> +  » l’élément « {1} » n’a pas l’attribut requis « {2} ».]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + .]]> diff --git a/Localize/loc/it/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/it/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 5f304f66a4b..0e02820190e 100644 --- a/Localize/loc/it/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/it/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' '{1}' mancano i metadati obbligatori '{2}']]> + ' L’elemento '{1}' non dispone dell'attributo '{2}' richiesto.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + .]]> diff --git a/Localize/loc/ja/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/ja/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 58ca38745bf..f677e676b17 100644 --- a/Localize/loc/ja/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/ja/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' 項目 '{1}' に必要なメタデータ '{2}' がありません]]> + ' アイテム '{1}' には、必要な属性 '{2}' がありません。]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + が追加されてから NuGet の復元が実行されていることを確認します。]]> diff --git a/Localize/loc/ko/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/ko/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 980a46dc037..0bc7e43e6c8 100644 --- a/Localize/loc/ko/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/ko/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' 항목 '{1}'에 필수 메타데이터 '{2}'이(가) 없습니다.]]> + ' 항목 '{1}'에 필수 특성 '{2}'이(가) 없습니다.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + 이 추가된 이후 NuGet 복원이 실행되었는지 확인합니다.]]> diff --git a/Localize/loc/pl/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/pl/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 0e30a224437..48edd4152aa 100644 --- a/Localize/loc/pl/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/pl/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ” „{1}” brakuje wymaganych metadanych „{2}”]]> + ” „{1}” brakuje wymaganego atrybutu „{2}”.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + .]]> diff --git a/Localize/loc/pt-BR/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/pt-BR/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index e824d4bb83a..bf30bb31f1b 100644 --- a/Localize/loc/pt-BR/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/pt-BR/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - '' item ''{1}'' não tem os metadados necessários ''{2}'']]> + " "{1}" não tem o atributo necessário "{2}".]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + foi adicionado.]]> diff --git a/Localize/loc/ru/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/ru/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 2be4b4745cf..d8e84148f3c 100644 --- a/Localize/loc/ru/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/ru/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - " "{1}" отсутствуют обязательные метаданные "{2}"]]> + " "{1}" не содержит необходимого атрибута "{2}".]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + .]]> diff --git a/Localize/loc/tr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/tr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 5d3f24be10b..3b58969d7e7 100644 --- a/Localize/loc/tr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/tr/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' '{1}' öğesinde gerekli '{2}' meta verileri eksik]]> + ', '{1} öğesinde gereken '{2}' özniteliği eksik.]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + eklendikten sonra NuGet Geri Yükleme'nin çalıştırıldığından emin olun.]]> diff --git a/Localize/loc/zh-Hans/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/zh-Hans/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index 530821af33c..d645ffe27b8 100644 --- a/Localize/loc/zh-Hans/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/zh-Hans/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ”项“{1}”缺少所需的元数据“{2}”]]> + ”项“{1}”缺少必需的特性“{2}”。]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + 后 NuGet 还原已运行。]]> diff --git a/Localize/loc/zh-Hant/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl b/Localize/loc/zh-Hant/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl index c1b10dc9ade..aa1adac5008 100644 --- a/Localize/loc/zh-Hant/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl +++ b/Localize/loc/zh-Hant/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx.lcl @@ -1190,10 +1190,13 @@ - ' item '{1}' is missing required metadata '{2}']]> + ' item '{1}' is missing required attribute '{2}'.]]> - ' 項目 '{1}' 遺漏必要中繼資料 '{2}']]> + ' 項目 '{1}' 缺少必要屬性 '{2}'。]]> + + ' item '{1}' is missing required metadata '{2}']]> + @@ -1217,27 +1220,93 @@ - + - + + + + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + was added.]]> + + 後,已執行 NuGet 還原。]]> From 751eb965f3a28d9b8efb07438231fad236ab601b Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Wed, 27 Mar 2024 18:23:06 +0000 Subject: [PATCH 13/17] [LayoutBindings] Fix '[Preserve]' is obsolete warnings (#8529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/xamarin/xamarin-android/issues/7480 Context: e60483341c2243a4f07a5b1c919a14f0655b7575 When [Layout Bindings][0] are enabled, a set of `partial` classes will be generated which "mirrors" the `.axml` structure in C#. Consider: dotnet new android -n com.example.codebehind You enable Code-Behind by: 1. Setting the `$(AndroidGenerateLayoutBindings)` MSBuild property to `true`. 2. Using `android:id` on elements within `.axml` files. Consider this patch to the above `dotnet new`: diff --git a/Resources/layout/activity_main.xml b/Resources/layout/activity_main.xml index f949852..c74521c 100644 --- a/Resources/layout/activity_main.xml +++ b/Resources/layout/activity_main.xml @@ -8,6 +8,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" + android:id="@+id/text" android:text="@string/app_text" /> diff --git a/com.example.codebehind.csproj b/com.example.codebehind.csproj index 3fdbcb5..8190f84 100644 --- a/com.example.codebehind.csproj +++ b/com.example.codebehind.csproj @@ -8,5 +8,6 @@ com.companyname.com.example.codebehind 1 1.0 + true The resulting output contains `$(IntermediateOutputPath)codebehind\Binding.activity_main.g.cs`, which declares a type based on the `.axml` file name, and a mirror of the structure: namespace Binding { // typename based on `activity_main.xml` filename sealed partial class activity_main : global::Xamarin.Android.Design.LayoutBinding { [global::Android.Runtime.PreserveAttribute (Conditional=true)] public activity_main (Activity client, …); // … // `text` is via `android:id="@+id/text"` public TextView text => …; } } The problem is the use of `PreserveAttribute` in the generated code; it's been `[Obsolete]` since e6048334 (over two years ago), which means all projects using Layout Bindings and Layout Code-Behind always have [CS0618][1] warnings. Remove the emission of `PreserveAttribute`, so that CS0618 is no longer generated. Additionally, within the generated files disable the [CS1591][2] and [CS8981][3] warnings: * CS1591 is around missing XML documentation comments. These code behind files do not have XML documentation comments, so if/when `$(DocumentationFile)` is set, these will be emitted for the generated code. We do not currently plan on emitting XML documentation comments, so disable this warning. * CS8981 is emitted when a type name consists solely of lowercase characters. As the generated Binding types are based on the filename -- which is frequently all lowercase -- this warning may be emitted. Finally, add `#nullable enable` to `LayoutBinding.cs` and fix the nullable reference type warnings. [0]: https://github.com/xamarin/xamarin-android/blob/2f4e01ec15102dd9cd922cbd833f6482d69512b5/Documentation/guides/LayoutCodeBehind.md [1]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/cs0618 [2]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/cs1591 [3]: https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-messages/warning-waves#cs8981---the-type-name-only-contains-lower-cased-ascii-characters --- .../Resources/LayoutBinding.cs | 46 +++++++++---------- ...GenerateLayoutBindings.BindingGenerator.cs | 17 +++---- ...teLayoutBindings.CSharpBindingGenerator.cs | 44 ++++++++++++------ ...nerateResourceDesignerIntermediateClass.cs | 4 ++ .../CodeBehindTests.cs | 4 +- .../CodeBehindBuildTests.NET.csproj | 2 +- .../BuildTests/MainMergeActivity.cs | 2 + .../BuildTests/Properties/AndroidManifest.xml | 1 - .../CommonSampleLibrary.NET.csproj | 6 +++ .../CommonSampleLibrary/Logger/LogFragment.cs | 12 ++++- 10 files changed, 86 insertions(+), 52 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs index 457c91add45..3f18da73069 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs +++ b/src/Xamarin.Android.Build.Tasks/Resources/LayoutBinding.cs @@ -1,27 +1,29 @@ -using System; +#nullable enable + +using System; using System.Diagnostics.CodeAnalysis; using Android.App; using Android.Views; namespace Xamarin.Android.Design { - public delegate Java.Lang.Object OnLayoutItemNotFoundHandler (int resourceId, Type expectedViewType); + public delegate Java.Lang.Object? OnLayoutItemNotFoundHandler (int resourceId, Type expectedViewType); abstract class LayoutBinding { const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors; - Activity boundActivity; - View boundView; - OnLayoutItemNotFoundHandler onLayoutItemNotFound; + Activity? boundActivity; + View? boundView; + OnLayoutItemNotFoundHandler? onLayoutItemNotFound; - protected LayoutBinding (Activity activity, OnLayoutItemNotFoundHandler onLayoutItemNotFound = null) + protected LayoutBinding (Activity activity, OnLayoutItemNotFoundHandler? onLayoutItemNotFound = null) { boundActivity = activity ?? throw new ArgumentNullException (nameof (activity)); this.onLayoutItemNotFound = onLayoutItemNotFound; } - protected LayoutBinding (View view, OnLayoutItemNotFoundHandler onLayoutItemNotFound = null) + protected LayoutBinding (View view, OnLayoutItemNotFoundHandler? onLayoutItemNotFound = null) { boundView = view ?? throw new ArgumentNullException (nameof (view)); this.onLayoutItemNotFound = onLayoutItemNotFound; @@ -38,14 +40,14 @@ protected T FindView < if (cachedField != null) return cachedField; - T ret; + T? ret = null; if (boundActivity != null) ret = boundActivity.FindViewById (resourceId); - else + else if (boundView != null) ret = boundView.FindViewById (resourceId); if (ret == null && onLayoutItemNotFound != null) - ret = (T)onLayoutItemNotFound (resourceId, typeof (T)); + ret = (T?)onLayoutItemNotFound (resourceId, typeof (T)); if (ret == null) throw new global::System.InvalidOperationException ($"View not found (Resource ID: {resourceId})"); @@ -71,8 +73,8 @@ T __FindFragment< T > ( int resourceId, - Func finder, - ref T cachedField) + Func finder, + ref T? cachedField) where T: Java.Lang.Object { if (cachedField != null) @@ -80,7 +82,7 @@ T __FindFragment< var ret = finder (EnsureActivity ()); if (ret == null && onLayoutItemNotFound != null) - ret = (T)onLayoutItemNotFound (resourceId, typeof (T)); + ret = (T?)onLayoutItemNotFound (resourceId, typeof (T)); if (ret == null) throw new InvalidOperationException ($"Fragment not found (ID: {resourceId}; Type: {typeof (T)})"); @@ -89,29 +91,25 @@ T __FindFragment< return ret; } #if __ANDROID_11__ +#pragma warning disable CA1422 protected T FindFragment< [DynamicallyAccessedMembers (Constructors)] T > ( int resourceId, - global::Android.App.Fragment __ignoreMe, - ref T cachedField + global::Android.App.Fragment? __ignoreMe, + ref T? cachedField ) where T: global::Android.App.Fragment { - return __FindFragment (resourceId, (activity) => activity.FragmentManager.FindFragmentById (resourceId), ref cachedField); + return __FindFragment (resourceId, (activity) => activity.FragmentManager?.FindFragmentById (resourceId), ref cachedField); } +#pragma warning restore CA1422 #endif // __ANDROID_11__ -#if __HAVE_SUPPORT__ - protected T FindFragment (int resourceId, global::Android.Support.V4.App.Fragment __ignoreMe, ref T cachedField) where T: global::Android.Support.V4.App.Fragment - { - return __FindFragment (resourceId, (activity) => activity.FragmentManager.FindFragmentById (resourceId), ref cachedField); - } -#endif // __HAVE_SUPPORT__ - #if __HAVE_ANDROIDX__ - protected T FindFragment (int resourceId, global::AndroidX.Fragment.App.Fragment __ignoreMe, ref T cachedField) where T: global::AndroidX.Fragment.App.Fragment + protected T FindFragment (int resourceId, global::AndroidX.Fragment.App.Fragment? __ignoreMe, ref T? cachedField) + where T : global::AndroidX.Fragment.App.Fragment { return __FindFragment(resourceId, (activity) => { if (activity is AndroidX.Fragment.App.FragmentActivity activity_) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs index b404d91156e..a31cecb1c08 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.BindingGenerator.cs @@ -30,8 +30,6 @@ public sealed class State // generating code for the partial Activity class public string BindingClassName { get; } - public bool LinkerPreserveConstructors { get; set; } - public List ExtraImportNamespaces { get; } = new List (); public string AndroidFragmentType { get; } @@ -155,20 +153,18 @@ protected virtual void WriteOnSetContentViewPartials (State state) WritePartialClassOnSetContentViewPartial_Int (state); } - public State BeginBindingFile (StreamWriter writer, string layoutResourceId, string classNamespace, string className, string androidFragmentType, bool linkerPreserveConstructors = true) + public State BeginBindingFile (StreamWriter writer, string layoutResourceId, string classNamespace, string className, string androidFragmentType) { - var state = new State (writer, className, !String.IsNullOrWhiteSpace (classNamespace), androidFragmentType) { - LinkerPreserveConstructors = linkerPreserveConstructors - }; + var state = new State (writer, className, !String.IsNullOrWhiteSpace (classNamespace), androidFragmentType); BeginBindingFile (state, layoutResourceId, classNamespace, className); - WriteBindingConstructors (state, className, state.LinkerPreserveConstructors); + WriteBindingConstructors (state, className); return state; } protected abstract void BeginBindingFile (State state, string layoutResourceId, string classNamespace, string className); public abstract void EndBindingFile (State state); - protected abstract void WriteBindingConstructors (State state, string className, bool linkerPreserve); + protected abstract void WriteBindingConstructors (State state, string className); protected abstract void WriteBindingViewProperty (State state, LayoutWidget widget, string resourceNamespace); protected abstract void WriteBindingFragmentProperty (State state, LayoutWidget widget, string resourceNamespace); protected abstract void WriteBindingMixedProperty (State state, LayoutWidget widget, string resourceNamespace); @@ -287,10 +283,11 @@ protected void WriteBindingPropertyBackingField (State state, LayoutWidget widge WriteResetLocation (state); } - public void WriteComment (State state, string text) + public void WriteComment (State state, params string [] text) { EnsureArgument (state, nameof (state)); - WriteLineIndent (state, $"{LineCommentString}{text}"); + foreach (string line in text) + WriteLineIndent (state, $"{LineCommentString}{line}"); } public void WriteComment (State state, ICollection lines) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs index bc2b9ff6db4..92372d223e7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateLayoutBindings.CSharpBindingGenerator.cs @@ -157,8 +157,33 @@ void WriteClassClose (State state) WriteLineIndent (state, "}"); } + void WriteDisableWarnings (State state) + { + state.WriteLine ("#pragma warning disable CS8981"); + state.WriteLine ("#pragma warning disable CS1591"); + } + + void WriteEnableWarnings (State state) + { + state.WriteLine ("#pragma warning restore CS1591"); + state.WriteLine ("#pragma warning restore CS8981"); + } + + void WriteAutoGeneratedComment (State state) + { + state.WriteLine (@"//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------"); + } + void WriteFilePreamble (State state, string classNamespace) { + WriteAutoGeneratedComment (state); WriteUsings (state); state.WriteLine (); WriteNamespaceOpen (state, classNamespace); @@ -172,6 +197,7 @@ void WriteNamespaceOpen (State state, string classNamespace) state.WriteLine ($"namespace {classNamespace}"); state.WriteLine ("{"); state.IncreaseIndent (); + WriteDisableWarnings (state); } void WriteNamespaceClose (State state) @@ -179,6 +205,7 @@ void WriteNamespaceClose (State state) if (!state.IsInNamespace) return; + WriteEnableWarnings (state); state.DecreaseIndent (); state.WriteLine ("}"); } @@ -200,15 +227,14 @@ void WriteUsing (State state, string ns) state.WriteLine ($"using global::{ns};"); } - protected override void WriteBindingConstructors (State state, string className, bool linkerPreserve) + protected override void WriteBindingConstructors (State state, string className) { - WriteConstructor (state, className, "Android.App.Activity", linkerPreserve); - WriteConstructor (state, className, "Android.Views.View", linkerPreserve); + WriteConstructor (state, className, "Android.App.Activity"); + WriteConstructor (state, className, "Android.Views.View"); } - void WriteConstructor (State state, string className, string clientType, bool linkerPreserve) + void WriteConstructor (State state, string className, string clientType) { - WritePreserveAtribute (state, linkerPreserve); WriteLineIndent (state, $"public {className} ("); state.IncreaseIndent (); WriteLineIndent (state, $"global::{clientType} client,"); @@ -221,14 +247,6 @@ void WriteConstructor (State state, string className, string clientType, bool li state.WriteLine (); } - void WritePreserveAtribute (State state, bool linkerPreserve) - { - if (!linkerPreserve) - return; - - WriteLineIndent (state, $"[global::Android.Runtime.PreserveAttribute (Conditional=true)]"); - } - public override void EndBindingFile (State state) { EnsureArgument (state, nameof (state)); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs index b6d89a6aaf6..22f9d4cf338 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesignerIntermediateClass.cs @@ -24,6 +24,10 @@ public class GenerateResourceDesignerIntermediateClass : AndroidTask namespace %NAMESPACE% { #pragma warning disable IDE0002 + /// + /// Android Resource Designer class. + /// Exposes the Android Resource designer assembly into the project Namespace. + /// public partial class Resource : %BASECLASS% { } #pragma warning restore IDE0002 diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs index b79a61409d8..59a6d1742ed 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/CodeBehindTests.cs @@ -339,6 +339,7 @@ void SuccessfulBuild_AndroidX (TestProjectInfo testInfo, bool many, bool dtb, Lo CopyLogs (testInfo, true); Assert.That (success, Is.True, "Build should have succeeded"); + Assert.IsTrue (StringAssertEx.ContainsText (builder.LastBuildOutput, " 0 Warning(s)"), $"{builder.BuildLogFile} should have no MSBuild warnings."); CopyGeneratedFiles (testInfo); @@ -508,7 +509,8 @@ string GetBuildTarget (bool isDTB) string[] GetBuildProperties (LocalBuilder builder, bool manyBuild, bool dtbBuild, bool referenceAndroidX, params string[] extraConstants) { var ret = new List { - "AndroidGenerateLayoutBindings=true" + "AndroidGenerateLayoutBindings=true", + "\"NoWarn=CS0414;CA1416;CS1591;XA1005;XA4225\"" }; if (manyBuild) ret.Add ("ForceParallelBuild=true"); diff --git a/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj b/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj index 841b92a40eb..2175ae82a5d 100644 --- a/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj +++ b/tests/CodeBehind/BuildTests/CodeBehindBuildTests.NET.csproj @@ -64,6 +64,6 @@ - + diff --git a/tests/CodeBehind/BuildTests/MainMergeActivity.cs b/tests/CodeBehind/BuildTests/MainMergeActivity.cs index ec57f9540c8..d5b8600ed75 100644 --- a/tests/CodeBehind/BuildTests/MainMergeActivity.cs +++ b/tests/CodeBehind/BuildTests/MainMergeActivity.cs @@ -24,6 +24,8 @@ protected override void OnCreate (Bundle savedInstanceState) #if NOT_CONFLICTING_FRAGMENT CommonSampleLibrary.LogFragment log2 = secondary_log_fragment; +#elif __HAVE_ANDROIDX__ + global::AndroidX.Fragment.App.Fragment log2 = secondary_log_fragment; #else global::Android.App.Fragment log2 = secondary_log_fragment; #endif diff --git a/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml b/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml index a0230c27bfe..72a51695329 100644 --- a/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml +++ b/tests/CodeBehind/BuildTests/Properties/AndroidManifest.xml @@ -1,6 +1,5 @@  - diff --git a/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj b/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj index 6b1daa622d0..3765f0d1a57 100644 --- a/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj +++ b/tests/CodeBehind/CommonSampleLibrary/CommonSampleLibrary.NET.csproj @@ -5,4 +5,10 @@ CommonSampleLibrary false + + $(DefineConstants);$(ExtraConstants) + + + + diff --git a/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs b/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs index eec0fe59ae9..b6b29ff06fb 100644 --- a/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs +++ b/tests/CodeBehind/CommonSampleLibrary/Logger/LogFragment.cs @@ -19,14 +19,21 @@ using Android.Views; using Android.Widget; using Android.Graphics; +using Android.Util; namespace CommonSampleLibrary { + #pragma warning disable CA1422 /** * Simple fraggment which contains a LogView and uses is to output log data it receives * through the LogNode interface. */ - public class LogFragment : Fragment + public class LogFragment : +#if __HAVE_ANDROIDX__ + AndroidX.Fragment.App.Fragment +#else + Fragment +#endif { LogView mLogView; ScrollView mScrollView; @@ -60,7 +67,7 @@ public View InflateViews () mLogView.Gravity = GravityFlags.Bottom; mLogView.SetTextAppearance (Activity, Android.Resource.Style.TextAppearanceMedium); - + mScrollView.AddView (mLogView); return mScrollView; } @@ -77,5 +84,6 @@ public LogView LogView { get { return mLogView; } } } + #pragma warning restore CA1422 } From 32e1ad2ba50184abd3265661d9c1e5fd687d9417 Mon Sep 17 00:00:00 2001 From: VS MobileTools Engineering Service 2 Date: Thu, 28 Mar 2024 08:51:37 -0700 Subject: [PATCH 14/17] Localized file check-in by OneLocBuild Task (#8844) Context: https://aka.ms/onelocbuild Context: https://aka.ms/AllAboutLoc Build definition ID 17928: Build ID 9323313 --- .../Properties/Resources.cs.resx | 20 ++++++++-------- .../Properties/Resources.de.resx | 24 +++++++++---------- .../Properties/Resources.es.resx | 20 ++++++++-------- .../Properties/Resources.fr.resx | 20 ++++++++-------- .../Properties/Resources.it.resx | 20 ++++++++-------- .../Properties/Resources.ja.resx | 20 ++++++++-------- .../Properties/Resources.ko.resx | 20 ++++++++-------- .../Properties/Resources.pl.resx | 24 +++++++++---------- .../Properties/Resources.pt-BR.resx | 20 ++++++++-------- .../Properties/Resources.ru.resx | 24 +++++++++---------- .../Properties/Resources.tr.resx | 20 ++++++++-------- .../Properties/Resources.zh-Hans.resx | 20 ++++++++-------- .../Properties/Resources.zh-Hant.resx | 20 ++++++++-------- 13 files changed, 136 insertions(+), 136 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx index f3791c24b23..376e51eaa50 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.cs.resx @@ -968,7 +968,7 @@ Pokud chcete pro sestavení z příkazového řádku použít vlastní cestu JDK - '<{0}>' item '{1}' is missing required attribute '{2}'. + V položce <{0}> {1} chybí požadovaný atribut {2}. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Pokud chcete pro sestavení z příkazového řádku použít vlastní cestu JDK {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Nelze stáhnout soubor POM pro artefakt Maven {0}. - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Pokud chcete pro sestavení z příkazového řádku použít vlastní cestu JDK The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Závislosti Java {0} není vyhověno. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Závislosti Java {0} není vyhověno. Microsoft spravuje balíček NuGet {1}, který by mohl této závislosti vyhovět. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + Atribut {0} je vyžadován při použití {1} pro položku {2} {3}. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + Atribut {0} nemůže být pro položku {1} {2} prázdný. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Zadaný soubor POM {0} neexistuje. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + Nepovedlo se parsovat soubor POM {0}. - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Nepovedlo se přeložit soubor POM pro artefakt {0}. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + V souboru zámku se nepovedlo najít balíček NuGet {0} verze {1}. Ujistěte se, že se od přidání tohoto <PackageReference> spustilo obnovení NuGet. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.de.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.de.resx index 317d16757fa..925a2c51a38 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.de.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.de.resx @@ -968,7 +968,7 @@ Um einen benutzerdefinierten JDK-Pfad für einen Befehlszeilenbuild zu verwenden - '<{0}>' item '{1}' is missing required attribute '{2}'. + Für das „<{0}>“-Element „{1}“ fehlt das erforderliche Attribut „{2}“. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,8 +991,8 @@ Um einen benutzerdefinierten JDK-Pfad für einen Befehlszeilenbuild zu verwenden {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. -- {1} + Die POM-Datei für das Maven-Artefakt „{0}“ kann nicht heruntergeladen werden. +– {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id {1} - The HttpClient reported download exception message @@ -1014,47 +1014,47 @@ Um einen benutzerdefinierten JDK-Pfad für einen Befehlszeilenbuild zu verwenden The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Java-Abhängigkeit „{0}“ wurde nicht erfüllt. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Java-Abhängigkeit „{0}“ wurde nicht erfüllt. Microsoft verwaltet das NuGet-Paket „{1}“, das diese Abhängigkeit erfüllen könnte. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + Das Attribut „{0}“ ist erforderlich, wenn „{1}“ für das „{2}“-Element „{3}“ verwendet wird. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + Das Attribut „{0}“ darf für das „{1}“-Element „{2}“ nicht leer sein. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Die angegebene POM-Datei „{0}“ ist nicht vorhanden. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. -- {1} + Die POM-Datei „{0}“ konnte nicht analysiert werden. +– {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Die POM-Datei für das Artefakt „{0}“ konnte nicht aufgelöst werden. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Das NuGet-Paket „{0}“ der Version „{1}“ wurde in der Sperrdatei nicht gefunden. Stellen Sie sicher, dass die NuGet-Wiederherstellung seit dem Hinzufügen dieser <PackageReference> ausgeführt wurde. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx index bd609097665..2911162d5e3 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.es.resx @@ -968,7 +968,7 @@ Para usar una ruta de acceso de JDK personalizada para una compilación de líne - '<{0}>' item '{1}' is missing required attribute '{2}'. + El elemento "{0}" "{1}" no tiene el atributo "{2}" requerido {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Para usar una ruta de acceso de JDK personalizada para una compilación de líne {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + No se puede descargar el archivo POM para el artefacto de Maven "{0}". - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Para usar una ruta de acceso de JDK personalizada para una compilación de líne The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + No se cumple la dependencia de Java "{0}". The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + No se cumple la dependencia de Java "{0}". Microsoft mantiene el paquete NuGet "{1}" que podría satisfacer esta dependencia. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + Se requiere el atributo "{0}" cuando se usa "{1}" para el elemento "{2}" "{3}". {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + El atributo "{0}" no puede estar vacío para el elemento "{1}" "{2}". {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + El archivo POM especificado "{0}" no existe. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + No se pudo analizar el archivo POM "{0}". - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + No se pudo resolver el archivo POM para el artefacto "{0}". The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + No se encontró el paquete NuGet "{0}" versión "{1}" en el archivo de bloqueo. Asegúrese de que la restauración de NuGet se ha ejecutado desde que se agregó esta <PackageReference>. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx index 5a84540c68e..20a65b7c017 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.fr.resx @@ -968,7 +968,7 @@ Pour utiliser un chemin JDK personnalisé pour une build de ligne de commande, d - '<{0}>' item '{1}' is missing required attribute '{2}'. + « <{0}> » l’élément « {1} » n’a pas l’attribut requis « {2} ». {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Pour utiliser un chemin JDK personnalisé pour une build de ligne de commande, d {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Impossible de télécharger le fichier POM pour l’artefact Maven « {0} ». - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Pour utiliser un chemin JDK personnalisé pour une build de ligne de commande, d The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + La dépendance Java « {0} » n’est pas satisfaite. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + La dépendance Java « {0} » n’est pas satisfaite. Microsoft gère le package NuGet « {1} » qui pourrait satisfaire cette dépendance. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + Un attribut « {0} » est requis lors de l’utilisation de « {1} » pour l’élément « {2} » « {3} ». {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + L’attribut « {0} » ne peut pas être vide pour « {1} », élément « {2} ». {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Le fichier POM « {0} » spécifié n’existe pas. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + Impossible d’analyser le fichier POM « {0} ». - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Impossible de résoudre le fichier POM pour l'artefact « {0} ». The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Package NuGet « {0} » version « {1} » introuvable dans le fichier de verrouillage. Vérifiez que la restauration NuGet s’est exécutée depuis l’ajout de ce <PackageReference>. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx index 74834fccfaf..c99f5421d1b 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.it.resx @@ -968,7 +968,7 @@ Per usare un percorso JDK personalizzato per una compilazione della riga di coma - '<{0}>' item '{1}' is missing required attribute '{2}'. + '<{0}>' L’elemento '{1}' non dispone dell'attributo '{2}' richiesto. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Per usare un percorso JDK personalizzato per una compilazione della riga di coma {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Non è possibile scaricare il file POM per l'artefatto Maven '{0}'. - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Per usare un percorso JDK personalizzato per una compilazione della riga di coma The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + La dipendenza Java '{0}' non è soddisfatta. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + La dipendenza Java '{0}' non è soddisfatta. Microsoft gestisce il pacchetto NuGet '{1}' che può soddisfare questa dipendenza. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + L'attributo '{0}' è obbligatorio quando si usa '{1}' per '{2}' l’elemento '{3}'. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + L'attributo '{0}' non può essere vuoto per '{1}' l’elemento '{2}'. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Il file POM '{0}' specificato non esiste. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + Non è stato possibile analizzare file POM '{0}'. - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Non è stato possibile risolvere il file POM per l'artefatto '{0}'. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Non è stato possibile trovare il pacchetto NuGet '{0}' versione '{1}' nel file di blocco. Verificare che il ripristino NuGet sia stato eseguito dopo l'aggiunta di questo <PackageReference>. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx index 59feff70257..957c132ec53 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ja.resx @@ -969,7 +969,7 @@ In this message, the term "handheld app" means "app for handheld devices." - '<{0}>' item '{1}' is missing required attribute '{2}'. + '<{0}>' アイテム '{1}' には、必要な属性 '{2}' がありません。 {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -992,7 +992,7 @@ In this message, the term "handheld app" means "app for handheld devices." {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Maven 成果物 '{0}' の POM ファイルをダウンロードできません。 - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1015,47 +1015,47 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Java 依存関係 '{0}' が満たされていません。 The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Java 依存関係 '{0}' が満たされていません。Microsoft は、この依存関係を満たす可能性のある NuGet パッケージ '{1}' を保持しています。 The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + '{2}' 項目 '{3}' に '{1}' を使用する場合は、属性 '{0}' が必要です。 {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + '{1}' アイテム '{2}' の属性 '{0}' を空にすることはできません。 {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + 指定された POM ファイル '{0}' は存在しません。 The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + POM ファイル '{0}' を解析できませんでした。 - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + 成果物 '{0}' の POM ファイルを解決できませんでした。 The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + NuGet パッケージ '{0}' バージョン '{1}' がロック ファイルに見つかりませんでした。この <PackageReference> が追加されてから NuGet の復元が実行されていることを確認します。 The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx index 507b88baae1..fee33d6527e 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ko.resx @@ -968,7 +968,7 @@ In this message, the term "handheld app" means "app for handheld devices." - '<{0}>' item '{1}' is missing required attribute '{2}'. + '<{0}>' 항목 '{1}'에 필수 특성 '{2}'이(가) 없습니다. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ In this message, the term "handheld app" means "app for handheld devices." {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Maven 아티팩트 '{0}'에 대한 POM 파일 다운로드할 수 없습니다. - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Java 종속성 '{0}'이(가) 충족되지 않습니다. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Java 종속성 '{0}'이(가) 충족되지 않습니다. Microsoft는 이 종속성을 충족할 수 있는 NuGet 패키지 '{1}'을(를) 유지 관리합니다. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + '{2}' item '{3}'에 대해 '{1}'을(를) 사용하는 경우 '{0}' 특성이 필요합니다. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + '{1}' 항목 '{2}'에 대해 특성 '{0}'을(를) 비워 둘 수 없습니다. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + 지정한 POM 파일 '{0}'이(가) 없습니다. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + POM 파일 '{0}'을(를) 구문 분석할 수 없습니다. - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + 아티팩트 '{0}'에 대한 POM 파일 확인할 수 없습니다. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + 잠금 파일에서 NuGet 패키지 '{0}' 버전 '{1}'을(를) 찾을 수 없습니다. 이 <PackageReference>이 추가된 이후 NuGet 복원이 실행되었는지 확인합니다. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx index 172fbcecb81..5fb67462611 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pl.resx @@ -968,7 +968,7 @@ Aby użyć niestandardowej ścieżki zestawu JDK dla kompilacji wiersza poleceni - '<{0}>' item '{1}' is missing required attribute '{2}'. + W elemencie „<{0}>” „{1}” brakuje wymaganego atrybutu „{2}”. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,8 +991,8 @@ Aby użyć niestandardowej ścieżki zestawu JDK dla kompilacji wiersza poleceni {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. -- {1} + Nie można pobrać pliku POM dla artefaktu Maven „{0}”. +— {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id {1} - The HttpClient reported download exception message @@ -1014,47 +1014,47 @@ Aby użyć niestandardowej ścieżki zestawu JDK dla kompilacji wiersza poleceni The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Zależność Java „{0}” nie jest spełniona. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Zależność Java „{0}” nie jest spełniona. Firma Microsoft utrzymuje pakiet NuGet „{1}”, który może spełnić tę zależność. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + Atrybut „{0}” jest wymagany w przypadku używania elementu „{1}” dla elementu „{2}” „{3}”. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + Atrybut „{0}” nie może być pusty dla elementu „{1}” „{2}”. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Określony plik POM „{0}” nie istnieje. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. -- {1} + Nie można przeanalizować pliku POM „{0}”. +— {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Nie można rozpoznać pliku POM dla artefaktu „{0}”. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Nie można odnaleźć wersji „{1}” pakietu NuGet „{0}” w pliku blokady. Upewnij się, że narzędzie NuGet Restore zostało uruchomione od czasu dodania tego pakietu <PackageReference>. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx index ba3736e8cc7..3b7d5a7a3a0 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.pt-BR.resx @@ -968,7 +968,7 @@ Para usar um caminho JDK personalizado para um build de linha de comando, defina - '<{0}>' item '{1}' is missing required attribute '{2}'. + O item "<{0}>" "{1}" não tem o atributo necessário "{2}". {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Para usar um caminho JDK personalizado para um build de linha de comando, defina {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + Não é possível baixar o arquivo POM para o artefato Maven "{0}". - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Para usar um caminho JDK personalizado para um build de linha de comando, defina The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + A dependência de Java "{0}" não foi atendida. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + A dependência de Java "{0}" não foi atendida. A Microsoft mantém o pacote NuGet "{1}" que pode atender a essa dependência. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + O atributo "{0}" é necessário ao usar "{1}" para o item "{2}" "{3}". {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + O atributo "{0}" não pode estar vazio para o item "{1}" "{2}". {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + O arquivo POM especificado "{0}" não existe. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + Não foi possível analisar o arquivo POM "{0}". - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Não foi possível resolver o arquivo POM para o artefato "{0}". The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Não foi possível localizar o pacote NuGet "{0}" versão "{1}" no arquivo de bloqueio. Certifique-se de que a restauração do NuGet tenha sido executada desde que <PackageReference> foi adicionado. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx index 92ec45f2360..bf7d7705c6c 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.ru.resx @@ -968,7 +968,7 @@ In this message, the term "handheld app" means "app for handheld devices." - '<{0}>' item '{1}' is missing required attribute '{2}'. + Элемент "<{0}>" "{1}" не содержит необходимого атрибута "{2}". {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,8 +991,8 @@ In this message, the term "handheld app" means "app for handheld devices." {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. -- {1} + Не удается скачать файл POM для артефакта Maven "{0}". +— {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id {1} - The HttpClient reported download exception message @@ -1014,47 +1014,47 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + Зависимость Java "{0}" не удовлетворена. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + Зависимость Java "{0}" не удовлетворена. Корпорация Майкрософт поддерживает пакет NuGet "{1}", который может выполнить эту зависимость. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + При использовании "{1}" для элемента "{2}" "{3}" требуется атрибут "{0}". {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + Атрибут "{0}" не может быть пустым для элемента "{1}" "{2}". {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Указанный файл POM "{0}" не существует. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. -- {1} + Не удалось проанализировать файл POM "{0}". +— {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + Не удалось разрешить файл POM для артефакта "{0}". The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + Не удалось найти пакет NuGet "{0}" версии "{1}" в файле блокировки. Убедитесь, что восстановление NuGet запущено с момента добавления <PackageReference>. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx index 7351d045590..6b1ad7b8383 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.tr.resx @@ -968,7 +968,7 @@ Bir komut satırı derlemesi için özel bir SDK yolu kullanmak için 'JavaSdkDi - '<{0}>' item '{1}' is missing required attribute '{2}'. + '<{0}>', '{1} öğesinde gereken '{2}' özniteliği eksik. {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ Bir komut satırı derlemesi için özel bir SDK yolu kullanmak için 'JavaSdkDi {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + '{0}' Maven yapıtı için POM dosyası indirilemiyor. - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ Bir komut satırı derlemesi için özel bir SDK yolu kullanmak için 'JavaSdkDi The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + '{0}' Java bağımlılığı karşılanmadı. The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + '{0}' Java bağımlılığı karşılanmadı. Microsoft, bu bağımlılığı karşılayan '{1}' NuGet paketini korur. The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + '{0}' özniteliği '{2}', '{3}' öğesi için '{1}' kullanılırken gereklidir. {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + '{0}' özniteliği '{1}', '{2}' öğesi için boş olamaz. {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + Belirtilen '{0}' POM dosyası yok. The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + '{0}' POM dosyası ayrıştırılamadı. - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + '{0}' yapıt kimliği için POM dosyası çözümlenemedi. The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + '{0}' NuGet paketi '{1}' sürümü kilit dosyasında bulunamadı. Bu <PackageReference> eklendikten sonra NuGet Geri Yükleme'nin çalıştırıldığından emin olun. The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx index 3cb9de7df87..10dffd219c4 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hans.resx @@ -968,7 +968,7 @@ In this message, the term "handheld app" means "app for handheld devices." - '<{0}>' item '{1}' is missing required attribute '{2}'. + “<{0}>”项“{1}”缺少必需的特性“{2}”。 {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ In this message, the term "handheld app" means "app for handheld devices." {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + 无法下载 Maven 项目“{0}”的 POM 文件。 - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + 不满足 Java 依赖项“{0}”。 The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + 不满足 Java 依赖项“{0}”。Microsoft 将维护可以满足此依赖项的 NuGet 包“{1}”。 The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + 对“{2}”项“{3}”使用“{1}”时,需要属性“{0}”。 {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + “{1}”项“{2}”的属性“{0}”不能为空。 {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + 指定的POM 文件“{0}”不存在。 The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + 无法分析 POM 文件“{0}”。 - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + 无法解析项目“{0}”的POM 文件。 The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + 在锁定文件中找不到 NuGet 包“{0}”版本“{1}”。确保自添加此 <PackageReference> 后 NuGet 还原已运行。 The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx index e1874db294f..e84a1211910 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.zh-Hant.resx @@ -968,7 +968,7 @@ In this message, the term "handheld app" means "app for handheld devices." - '<{0}>' item '{1}' is missing required attribute '{2}'. + '<{0}>' 項目 '{1}' 缺少必要屬性 '{2}'。 {0} - The MSBuild ItemGroup Item name {1} - The MSBuild Item ItemSpec {2} - The omitted MSBuild Item metadata attribute @@ -991,7 +991,7 @@ In this message, the term "handheld app" means "app for handheld devices." {5} - The HttpClient provided download exception message - Cannot download POM file for Maven artifact '{0}'. + 無法下載 Maven 成品 '{0}' 的 POM 檔案。 - {1} The following are literal names and should not be translated: POM, Maven {0} - Maven artifact id @@ -1014,47 +1014,47 @@ In this message, the term "handheld app" means "app for handheld devices." The following are literal names and should not be translated: Android Support, AndroidX, .NET. - Java dependency '{0}' is not satisfied. + 無法滿足 JAVA 相依性 '{0}'。 The following are literal names and should not be translated: Java. {0} - Maven dependency id - Java dependency '{0}' is not satisfied. Microsoft maintains the NuGet package '{1}' that could fulfill this dependency. + 無法滿足 JAVA 相依性 '{0}'。Microsoft 會維護可以滿足此相依性的 NuGet 套件 '{1}'。 The following are literal names and should not be translated: Java, Microsoft, NuGet. {0} - Maven dependency id {1} - NuGet package id - Attribute '{0}' is required when using '{1}' for '{2}' item '{3}'. + 為 '{2}' 項目 '{3}' 使用 '{1}' 時,需要屬性 '{0}'。 {0}, {1} - MSBuild XML attribute {2} - MSBuild XML element name {3} - MSBuild ItemSpec value - Attribute '{0}' cannot be empty for '{1}' item '{2}'. + '{1}' 項目 '{2}' 的屬性 '{0}' 不能空白。 {0} - MSBuild XML attribute {1} - MSBuild XML element name {2} - MSBuild ItemSpec value - Specified POM file '{0}' does not exist. + 指定的 POM 檔案 '{0}' 不存在。 The following are literal names and should not be translated: POM. {0} - File path to POM file - Could not parse POM file '{0}'. + 無法剖析 POM 檔案 '{0}'。 - {1} The following are literal names and should not be translated: POM. {0} - File path to POM file {1} - Exception message - Could not resolve POM file for artifact '{0}'. + 無法解析成品 '{0}' 的 POM 檔案。 The following are literal names and should not be translated: POM. {0} - Java artifact id - Could not find NuGet package '{0}' version '{1}' in lock file. Ensure NuGet Restore has run since this <PackageReference> was added. + 在鎖定檔案中找不到 NuGet 套件 '{0}' 版本 '{1}'。請確認自新增此 <PackageReference> 後,已執行 NuGet 還原。 The following are literal names and should not be translated: NuGet, PackageReference. {0} - NuGet package id {1} - NuGet package version From 183e1ecbce942ffddab4ab2fcceb6d0c6a9f16af Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 28 Mar 2024 07:50:32 -1000 Subject: [PATCH 15/17] Bump 'NuGet.*' and 'Newtonsoft.Json' NuGet versions. (#8825) Update `NuGet.ProjectModel` to the latest version. This new version requires a newer version of `Newtonsoft.Json`, so update to the latest of it as well. Remove unneeded NuGet PackageReferences. --- Directory.Build.props | 2 +- .../Xamarin.Android.Build.Tasks.csproj | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 85c24b55c85..a2dd1312cb9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -44,7 +44,7 @@ 3.1.1 1.0.0 0.11.4 - 13.0.1 + 13.0.3 5.4.0 1.1.11 6.12.0.148 diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 05a4fa33ba6..06ad020c984 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -28,9 +28,7 @@ - - - + From 164a9b90986b1c7eb06cc807551bd1777fbeec79 Mon Sep 17 00:00:00 2001 From: Jonathan Pobst Date: Thu, 28 Mar 2024 07:51:11 -1000 Subject: [PATCH 16/17] [Xamarin.Android.Build.Tasks] Update to newer ILRepack which supports debug files. (#8839) `ILRepack` has a new (Microsoft) maintainer who is working on modernizing it. This includes updating to a newer version of `Mono.Cecil` which supports `portable` and `embedded` debug symbols: https://github.com/gluck/il-repack/pull/333 Updating to the latest version should fix our issue about being unable to debug `Xamarin.Android.Build.Tasks` or get full stack traces. --- .../Xamarin.Android.Build.Tasks.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 06ad020c984..58e0c21192b 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -26,7 +26,7 @@ - + From 378b4929ca69bc41a7c532ae4c77de0a0b74bddd Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:10:26 -0500 Subject: [PATCH 17/17] Bump to dotnet/installer/main@dc43d363d2 9.0.100-preview.4.24175.5 (#8828) Changes: https://github.com/dotnet/installer/compare/b40c44502d...dc43d363d2 Changes: https://github.com/dotnet/runtime/compare/596a1f7b64...17f8138a72 Changes: https://github.com/dotnet/emsdk/compare/a5f4de78fc...5dd0620274 Changes: https://github.com/dotnet/cecil/compare/ba53c75483...9c8ea966df Updates: * Microsoft.Dotnet.Sdk.Internal: from 9.0.100-preview.3.24165.20 to 9.0.100-preview.4.24175.5 * Microsoft.NETCore.App.Ref: from 9.0.0-preview.3.24162.31 to 9.0.0-preview.4.24173.6 * Microsoft.NET.Workload.Emscripten.Current.Manifest-9.0.100.Transport: from 9.0.0-preview.3.24156.3 to 9.0.0-preview.3.24160.1 * Microsoft.NET.ILLink.Tasks: from 9.0.0-preview.3.24162.31 to 9.0.0-preview.4.24173.6 * Microsoft.DotNet.Cecil: from 0.11.4-alpha.24158.1 to 0.11.4-alpha.24168.1 Other changes: * [tests] set `$(TrimmerSingleWarn)` to false This allows us to get more information, in the case of new trimmer warnings. * Default `$(_AndroidIncludeSystemGlobalizationNative)` to true Prevents runtime crash: 03-25 19:42:25.386 8502 8502 W Mono : DllImport unable to load library 'libSystem.Globalization.Native'. 03-25 19:42:25.409 8502 8502 W : Process terminated. * Update `.apkdesc` files for `libSystem.Globalization.Native.so` * FIXME: https://github.com/dotnet/runtime/issues/100256 Various tests have the trimmer warning: dotnet\packs\Microsoft.NETCore.App.Runtime.Mono.android-x86\9.0.0-preview.4.24173.6\runtimes\android-x86\native\System.Private.CoreLib.dll : warning IL2104: Assembly 'System.Private.CoreLib' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries ILLink warning IL2045: System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeCompiled: Attribute 'System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute' is being referenced in code but the trimmer was instructed to remove all instances of this attribute. If the attribute instances are necessary make sure to either remove the trimmer attribute XML portion which removes the attribute instances, or override the removal by using the trimmer XML descriptor to keep the attribute type (which in turn keeps all of its instances). For now, we can assert there are 4 warnings (one per RID). When this is fixed in the future, we can go back to asserting 0 warnings. Co-authored-by: Jonathan Peppers --- eng/Version.Details.xml | 20 ++-- eng/Versions.props | 10 +- ...oft.Android.Sdk.AssemblyResolution.targets | 3 + .../Xamarin.Android.Build.Tests/BuildTest2.cs | 8 +- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 11 +- .../BuildReleaseArm64SimpleDotNet.apkdesc | 41 +++---- .../BuildReleaseArm64XFormsDotNet.apkdesc | 105 +++++++++--------- 7 files changed, 109 insertions(+), 89 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 2945aa2ef96..72b69e51698 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,24 +1,24 @@ - + https://github.com/dotnet/installer - b40c44502deca1e7f51674b97b2d6ca2d5e0abac + dc43d363d284c26cb1b463683d6ebb2c88ab0b58 - + https://github.com/dotnet/runtime - 596a1f7b6429fc06cf71465238cb349cab4edc35 + 17f8138a726b8af269bffc59e9baa12dcb7abca5 - + https://github.com/dotnet/runtime - 596a1f7b6429fc06cf71465238cb349cab4edc35 + 17f8138a726b8af269bffc59e9baa12dcb7abca5 - + https://github.com/dotnet/emsdk - a5f4de78fca42544771977f8e8e04c4aa83e1d02 + 5dd0620274178dd73cac5049e5187c00e07ecf0c - + https://github.com/dotnet/cecil - ba53c75483aa4980a332fa48e61076f80adfec40 + 9c8ea966df62f764523b51772763e74e71040a92 diff --git a/eng/Versions.props b/eng/Versions.props index 7c14218b5df..7fc8a8bc1e4 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,15 +1,15 @@ - 9.0.100-preview.3.24165.20 - 9.0.0-preview.3.24162.31 - 9.0.0-preview.3.24162.31 + 9.0.100-preview.4.24175.5 + 9.0.0-preview.4.24173.6 + 9.0.0-preview.4.24173.6 7.0.0-beta.22103.1 7.0.0-beta.22103.1 - 9.0.0-preview.3.24156.3 + 9.0.0-preview.3.24160.1 $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) 7.0.100-rc.1.22410.7 - 0.11.4-alpha.24158.1 + 0.11.4-alpha.24168.1 $(MicrosoftNETCoreAppRefPackageVersion) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index d4aae16f7ee..05c6c56639f 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -212,6 +212,9 @@ _ResolveAssemblies MSBuild target. + + <_AndroidIncludeSystemGlobalizationNative Condition=" '$(_AndroidIncludeSystemGlobalizationNative)' == '' ">true + <_ResolvedNativeLibraries Include="@(ResolvedFileToPublish)" Condition=" '%(ResolvedFileToPublish.Extension)' == '.so' " /> diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index 83d47a85bdc..1f5cff5a437 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -257,9 +257,15 @@ public void BuildHasNoWarnings (bool isRelease, bool xamarinForms, bool multidex proj.PackageReferences.Add (new Package { Id = "BenchmarkDotNet", Version = "0.13.1" }); proj.SetProperty ("XamarinAndroidSupportSkipVerifyVersions", "True"); // Disables API 29 warning in Xamarin.Build.Download proj.SetProperty ("AndroidPackageFormat", packageFormat); + proj.SetProperty ("TrimmerSingleWarn", "false"); using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) { Assert.IsTrue (b.Build (proj), "Build should have succeeded."); - b.AssertHasNoWarnings (); + // FIXME: https://github.com/dotnet/runtime/issues/100256 + if (!xamarinForms && isRelease) { + Assert.IsTrue (StringAssertEx.ContainsText (b.LastBuildOutput, " 4 Warning(s)"), $"{b.BuildLogFile} should have 4 MSBuild warnings."); + } else { + b.AssertHasNoWarnings (); + } Assert.IsFalse (StringAssertEx.ContainsText (b.LastBuildOutput, "Warning: end of file not at end of a line"), "Should not get a warning from the task."); var lockFile = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, ".__lock"); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index 8864d67f6a3..54fb5b35130 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -37,12 +37,17 @@ public void DotNetNew ([Values ("android", "androidlib", "android-bindinglib", " Assert.IsTrue (dotnet.New ("android-layout", Path.Combine (dotnet.ProjectDirectory, "Resources", "layout")), "`dotnet new android-layout` should succeed"); // Debug build - Assert.IsTrue (dotnet.Build (parameters: new [] { "Configuration=Debug" }), "`dotnet build` should succeed"); + Assert.IsTrue (dotnet.Build (parameters: new [] { "Configuration=Debug", "TrimmerSingleWarn=false" }), "`dotnet build` should succeed"); dotnet.AssertHasNoWarnings (); // Release build - Assert.IsTrue (dotnet.Build (parameters: new [] { "Configuration=Release" }), "`dotnet build` should succeed"); - dotnet.AssertHasNoWarnings (); + Assert.IsTrue (dotnet.Build (parameters: new [] { "Configuration=Release", "TrimmerSingleWarn=false" }), "`dotnet build` should succeed"); + // FIXME: https://github.com/dotnet/runtime/issues/100256 + if (template.Contains ("lib")) { + dotnet.AssertHasNoWarnings (); + } else { + Assert.IsTrue (StringAssertEx.ContainsText (dotnet.LastBuildOutput, " 4 Warning(s)"), $"{dotnet.BuildLogFile} should have 4 MSBuild warnings."); + } } static readonly object[] DotNetPackTargetFrameworks = new object[] { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc index 5886262970d..f72d4cc5633 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc @@ -5,70 +5,73 @@ "Size": 3036 }, "classes.dex": { - "Size": 377684 + "Size": 377764 }, "lib/arm64-v8a/lib__Microsoft.Android.Resource.Designer.dll.so": { "Size": 1027 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 63889 + "Size": 64234 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 90449 + "Size": 91668 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 5145 + "Size": 5222 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 6541 + "Size": 6548 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { - "Size": 8647 + "Size": 8483 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 553289 + "Size": 566421 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 2545 + "Size": 2552 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 4022 + "Size": 4025 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { - "Size": 2932 + "Size": 2934 }, "lib/arm64-v8a/libarc.bin.so": { "Size": 1512 }, "lib/arm64-v8a/libmono-component-marshal-ilgen.so": { - "Size": 87080 + "Size": 87352 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 355872 + "Size": 354064 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3185656 + "Size": 3132992 + }, + "lib/arm64-v8a/libSystem.Globalization.Native.so": { + "Size": 67248 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 723560 }, "lib/arm64-v8a/libSystem.Native.so": { - "Size": 94504 + "Size": 94720 }, "lib/arm64-v8a/libSystem.Security.Cryptography.Native.Android.so": { - "Size": 155560 + "Size": 155568 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 12336 + "Size": 12656 }, "META-INF/BNDLTOOL.RSA": { "Size": 1221 }, "META-INF/BNDLTOOL.SF": { - "Size": 3147 + "Size": 3266 }, "META-INF/MANIFEST.MF": { - "Size": 3020 + "Size": 3139 }, "res/drawable-hdpi-v4/icon.png": { "Size": 2178 @@ -95,5 +98,5 @@ "Size": 1904 } }, - "PackageSize": 2668984 + "PackageSize": 2689557 } \ No newline at end of file diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc index 015199489b9..2d232c645fb 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc @@ -5,10 +5,10 @@ "Size": 6652 }, "classes.dex": { - "Size": 9418292 + "Size": 9440180 }, "classes2.dex": { - "Size": 150904 + "Size": 150920 }, "kotlin/annotation/annotation.kotlin_builtins": { "Size": 928 @@ -38,127 +38,127 @@ "Size": 8090 }, "lib/arm64-v8a/lib_Java.Interop.dll.so": { - "Size": 72360 + "Size": 72397 }, "lib/arm64-v8a/lib_Mono.Android.dll.so": { - "Size": 456663 + "Size": 458327 }, "lib/arm64-v8a/lib_Mono.Android.Runtime.dll.so": { - "Size": 5145 + "Size": 5222 }, "lib/arm64-v8a/lib_mscorlib.dll.so": { - "Size": 3992 + "Size": 3998 }, "lib/arm64-v8a/lib_netstandard.dll.so": { - "Size": 5625 + "Size": 5631 }, "lib/arm64-v8a/lib_System.Collections.Concurrent.dll.so": { "Size": 11520 }, "lib/arm64-v8a/lib_System.Collections.dll.so": { - "Size": 15411 + "Size": 15413 }, "lib/arm64-v8a/lib_System.Collections.NonGeneric.dll.so": { - "Size": 7442 + "Size": 7441 }, "lib/arm64-v8a/lib_System.ComponentModel.dll.so": { - "Size": 1935 + "Size": 1941 }, "lib/arm64-v8a/lib_System.ComponentModel.Primitives.dll.so": { - "Size": 2549 + "Size": 2555 }, "lib/arm64-v8a/lib_System.ComponentModel.TypeConverter.dll.so": { - "Size": 6084 + "Size": 6089 }, "lib/arm64-v8a/lib_System.Console.dll.so": { - "Size": 6576 + "Size": 6580 }, "lib/arm64-v8a/lib_System.Core.dll.so": { - "Size": 1969 + "Size": 1976 }, "lib/arm64-v8a/lib_System.Diagnostics.DiagnosticSource.dll.so": { - "Size": 9060 + "Size": 9065 }, "lib/arm64-v8a/lib_System.Diagnostics.TraceSource.dll.so": { - "Size": 6543 + "Size": 6552 }, "lib/arm64-v8a/lib_System.dll.so": { - "Size": 2326 + "Size": 2331 }, "lib/arm64-v8a/lib_System.Drawing.dll.so": { - "Size": 1932 + "Size": 1937 }, "lib/arm64-v8a/lib_System.Drawing.Primitives.dll.so": { - "Size": 11965 + "Size": 11968 }, "lib/arm64-v8a/lib_System.IO.Compression.Brotli.dll.so": { - "Size": 11187 + "Size": 11190 }, "lib/arm64-v8a/lib_System.IO.Compression.dll.so": { "Size": 15864 }, "lib/arm64-v8a/lib_System.IO.IsolatedStorage.dll.so": { - "Size": 9895 + "Size": 9897 }, "lib/arm64-v8a/lib_System.Linq.dll.so": { - "Size": 20514 + "Size": 20166 }, "lib/arm64-v8a/lib_System.Linq.Expressions.dll.so": { - "Size": 164629 + "Size": 164751 }, "lib/arm64-v8a/lib_System.Net.Http.dll.so": { - "Size": 67561 + "Size": 67559 }, "lib/arm64-v8a/lib_System.Net.Primitives.dll.so": { - "Size": 22354 + "Size": 22242 }, "lib/arm64-v8a/lib_System.Net.Requests.dll.so": { - "Size": 3588 + "Size": 3594 }, "lib/arm64-v8a/lib_System.ObjectModel.dll.so": { - "Size": 8565 + "Size": 8566 }, "lib/arm64-v8a/lib_System.Private.CoreLib.dll.so": { - "Size": 870644 + "Size": 872867 }, "lib/arm64-v8a/lib_System.Private.DataContractSerialization.dll.so": { - "Size": 193443 + "Size": 193446 }, "lib/arm64-v8a/lib_System.Private.Uri.dll.so": { - "Size": 42904 + "Size": 42910 }, "lib/arm64-v8a/lib_System.Private.Xml.dll.so": { - "Size": 216020 + "Size": 216089 }, "lib/arm64-v8a/lib_System.Private.Xml.Linq.dll.so": { - "Size": 16622 + "Size": 16631 }, "lib/arm64-v8a/lib_System.Runtime.dll.so": { - "Size": 2703 + "Size": 2709 }, "lib/arm64-v8a/lib_System.Runtime.InteropServices.dll.so": { - "Size": 4022 + "Size": 4025 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.dll.so": { - "Size": 1859 + "Size": 1865 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Formatters.dll.so": { - "Size": 2479 + "Size": 2484 }, "lib/arm64-v8a/lib_System.Runtime.Serialization.Primitives.dll.so": { - "Size": 3751 + "Size": 3758 }, "lib/arm64-v8a/lib_System.Security.Cryptography.dll.so": { - "Size": 8099 + "Size": 8102 }, "lib/arm64-v8a/lib_System.Text.RegularExpressions.dll.so": { - "Size": 161328 + "Size": 161398 }, "lib/arm64-v8a/lib_System.Xml.dll.so": { - "Size": 1754 + "Size": 1760 }, "lib/arm64-v8a/lib_System.Xml.Linq.dll.so": { - "Size": 1768 + "Size": 1776 }, "lib/arm64-v8a/lib_UnnamedProject.dll.so": { "Size": 5007 @@ -170,7 +170,7 @@ "Size": 6216 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.AppCompat.dll.so": { - "Size": 138025 + "Size": 138048 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CardView.dll.so": { "Size": 6959 @@ -179,7 +179,7 @@ "Size": 17921 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Core.dll.so": { - "Size": 126882 + "Size": 126998 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.CursorAdapter.dll.so": { "Size": 8978 @@ -188,7 +188,7 @@ "Size": 15286 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Fragment.dll.so": { - "Size": 51498 + "Size": 51531 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.Legacy.Support.Core.UI.dll.so": { "Size": 6233 @@ -206,7 +206,7 @@ "Size": 13063 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.RecyclerView.dll.so": { - "Size": 93516 + "Size": 93541 }, "lib/arm64-v8a/lib_Xamarin.AndroidX.SavedState.dll.so": { "Size": 5107 @@ -242,7 +242,10 @@ "Size": 354064 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 3210968 + "Size": 3132992 + }, + "lib/arm64-v8a/libSystem.Globalization.Native.so": { + "Size": 67248 }, "lib/arm64-v8a/libSystem.IO.Compression.Native.so": { "Size": 723560 @@ -254,7 +257,7 @@ "Size": 155568 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 118456 + "Size": 118880 }, "META-INF/androidx.activity_activity.version": { "Size": 6 @@ -407,10 +410,10 @@ "Size": 6 }, "META-INF/BNDLTOOL.RSA": { - "Size": 1221 + "Size": 1223 }, "META-INF/BNDLTOOL.SF": { - "Size": 98179 + "Size": 98298 }, "META-INF/com.android.tools/proguard/coroutines.pro": { "Size": 1345 @@ -437,7 +440,7 @@ "Size": 5 }, "META-INF/MANIFEST.MF": { - "Size": 98052 + "Size": 98171 }, "META-INF/maven/com.google.guava/listenablefuture/pom.properties": { "Size": 96 @@ -2477,5 +2480,5 @@ "Size": 812848 } }, - "PackageSize": 10193867 + "PackageSize": 10218536 } \ No newline at end of file