Skip to content

Commit e346f84

Browse files
[One .NET] dotnet new project and item templates (#5348)
Context: https://docs.microsoft.com/dotnet/core/tutorials/cli-templates-create-template-pack Context: https://github.com/dotnet/templating/wiki Context: dotnet/designs#120 This implements basic Android templates that are contained in a `Microsoft.Android.Templates.nupkg` file. We can define a template pack in `WorkloadManifest.json`: "Microsoft.Android.Templates": { "kind": "template", "version": "@TEMPLATE_PACK_VERSION@" } This allows the workload to locate the `*.nupkg` file in: C:\Program Files\dotnet\template-packs /usr/local/share/dotnet/template-packs Our .NET 6 preview installers simply have to place the `*.nupkg` files in the right place for them to be picked up by `dotnet new`. Some example project templates: dotnet new android --output MyAndroidApp --packageName com.mycompany.myandroidapp dotnet new androidlib --output MyAndroidLibrary dotnet new android-bindinglib --output MyJavaBinding And item templates: dotnet new android-activity --name LoginActivity --namespace MyAndroidApp dotnet new android-layout --name MyLayout --output Resources/layout Note that the `android-bindinglib` template is not a special project type. It has additional help files for writing bindings as we have in the current Xamarin.Android templates. I also updated the `XASdkTests` to `dotnet new` each template and `dotnet build` the resulting output. Finally, the `<GenerateWixFile/>` task (68be8d8) will now add `<Directory/>` entries such as: <Directory Id="packs" Name="packs" FileSource="C:\Users\myuser\android-toolchain\dotnet\packs"> and: <Directory Id="templatepacks" Name="template-packs" FileSource="C:\Users\myuser\android-toolchain\dotnet\template-packs"> <Component Id="SC983E605827BDDA589CA4DFF082E29CDFEC2CD059B4AF3C01421CC95568A8D74"> <File Id="SC983E605827BDDA589CA4DFF082E29CDFEC2CD059B4AF3C01421CC95568A8D74" Name="Microsoft.Android.Templates.11.0.100-ci.dotnet-new.259.nupkg" KeyPath="yes" /> </Component> </Directory> In the latter case, MSI has weird rules around the `Id` value. Consequently, file hashes were used.
1 parent a74fe4a commit e346f84

File tree

48 files changed

+512
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+512
-20
lines changed

Documentation/guides/OneDotNet.md

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,47 @@ It is recommended to migrate to the new linker settings, as
195195
There are currently a few "verbs" we are aiming to get working in
196196
Xamarin.Android:
197197

198+
dotnet new
198199
dotnet build
199200
dotnet publish
200201
dotnet run
201202

202-
Currently in .NET 5 console apps, `dotnet publish` is where all the
203-
work to produce a self-contained "app" happens:
203+
### dotnet new
204+
205+
To support `dotnet new`, we created a few basic project and item
206+
templates for Android that are named following the patterns and naming
207+
of existing .NET templates:
208+
209+
Templates Short Name Language Tags
210+
-------------------------------------------- ------------------- ---------- ----------------------
211+
Android Activity template android-activity [C#] Android
212+
Android Java Library Binding android-bindinglib [C#] Android
213+
Android Layout template android-layout [C#] Android
214+
Android Class library androidlib [C#] Android
215+
Android Application android [C#] Android
216+
Console Application console [C#],F#,VB Common/Console
217+
Class library classlib [C#],F#,VB Common/Library
218+
WPF Application wpf [C#],VB Common/WPF
219+
WPF Class library wpflib [C#],VB Common/WPF
220+
NUnit 3 Test Project nunit [C#],F#,VB Test/NUnit
221+
NUnit 3 Test Item nunit-test [C#],F#,VB Test/NUnit
222+
223+
To create different types of Android projects:
224+
225+
dotnet new android --output MyAndroidApp --packageName com.mycompany.myandroidapp
226+
dotnet new androidlib --output MyAndroidLibrary
227+
dotnet new android-bindinglib --output MyJavaBinding
228+
229+
Once the projects are created, some basic item templates can also be
230+
used such as:
231+
232+
dotnet new android-activity --name LoginActivity --namespace MyAndroidApp
233+
dotnet new android-layout --name MyLayout --output Resources/layout
234+
235+
### dotnet build & publish
236+
237+
Currently in .NET console apps, `dotnet publish` is where all the work
238+
to produce a self-contained "app" happens:
204239

205240
* The linker via the `<IlLink/>` MSBuild task
206241
* .NET Core's version of AOT, named "ReadyToRun"
@@ -229,12 +264,18 @@ Play, ad-hoc distribution, etc. It could be able to sign the `.apk` or
229264
`.aab` with different keys. As a starting point, this will currently
230265
copy the output to a `publish` directory on disk.
231266

267+
[illink]: https://github.com/mono/linker/blob/master/src/linker/README.md
268+
269+
### dotnet run
270+
232271
`dotnet run` can be used to launch applications on a
233272
device or emulator via the `--project` switch:
234273

235274
dotnet run --project HelloAndroid.csproj
236275

237-
[illink]: https://github.com/mono/linker/blob/master/src/linker/README.md
276+
Alternatively, you could use the `Run` MSBuild target such as:
277+
278+
dotnet build HelloAndroid.csproj -t:Run
238279

239280
### Preview testing
240281

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/GenerateWixFile.cs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,22 @@ public override bool Execute ()
108108
packWriter.WriteStartElement ("Directory");
109109
packWriter.WriteAttributeString ("Id", "packs");
110110
packWriter.WriteAttributeString ("Name", "packs");
111+
packWriter.WriteAttributeString ("FileSource", packs_dir);
111112
foreach (var directory in Directory.EnumerateDirectories (packs_dir, "Microsoft.Android.*")) {
112113
RecurseDirectory (packs_dir, packWriter, componentWriter, directory);
113114
}
115+
packWriter.WriteEndElement (); // </Directory> packs
116+
117+
// template-packs
118+
var templates_dir = Path.Combine (DotNetPath, "template-packs");
119+
packWriter.WriteStartElement ("Directory");
120+
packWriter.WriteAttributeString ("Id", "templatepacks");
121+
packWriter.WriteAttributeString ("Name", "template-packs");
122+
packWriter.WriteAttributeString ("FileSource", templates_dir);
123+
foreach (var file in Directory.EnumerateFiles (templates_dir, "Microsoft.Android.Templates.*.nupkg")) {
124+
AddFile (templates_dir, packWriter, componentWriter, file);
125+
}
126+
packWriter.WriteEndElement (); // </Directory> template-packs
114127

115128
packWriter.WriteEndDocument (); // </Directory>
116129
componentWriter.WriteEndDocument (); // </ComponentGroup>
@@ -145,22 +158,27 @@ static void RecurseDirectory (string top_dir, XmlWriter packWriter, XmlWriter co
145158
var fileName = Path.GetFileName (file);
146159
if (fileName.StartsWith (".") || fileName.StartsWith ("_"))
147160
continue;
148-
var componentId = GetId (top_dir, file);
149-
packWriter.WriteStartElement ("Component");
150-
packWriter.WriteAttributeString ("Id", componentId);
151-
packWriter.WriteStartElement ("File");
152-
packWriter.WriteAttributeString ("Id", componentId);
153-
packWriter.WriteAttributeString ("Name", Path.GetFileName (file));
154-
packWriter.WriteAttributeString ("KeyPath", "yes");
155-
packWriter.WriteEndElement (); // </File>
156-
packWriter.WriteEndElement (); // </Component>
157-
componentWriter.WriteStartElement ("ComponentRef");
158-
componentWriter.WriteAttributeString ("Id", componentId);
159-
componentWriter.WriteEndElement (); // </ComponentRef>
161+
AddFile (top_dir, packWriter, componentWriter, file);
160162
}
161163
packWriter.WriteEndElement (); // </Directory>
162164
}
163165

166+
static void AddFile (string top_dir, XmlWriter packWriter, XmlWriter componentWriter, string file)
167+
{
168+
string componentId = GetId (top_dir, file);
169+
packWriter.WriteStartElement ("Component");
170+
packWriter.WriteAttributeString ("Id", componentId);
171+
packWriter.WriteStartElement ("File");
172+
packWriter.WriteAttributeString ("Id", componentId);
173+
packWriter.WriteAttributeString ("Name", Path.GetFileName (file));
174+
packWriter.WriteAttributeString ("KeyPath", "yes");
175+
packWriter.WriteEndElement (); // </File>
176+
packWriter.WriteEndElement (); // </Component>
177+
componentWriter.WriteStartElement ("ComponentRef");
178+
componentWriter.WriteAttributeString ("Id", componentId);
179+
componentWriter.WriteEndElement (); // </ComponentRef>
180+
}
181+
164182
static string GetId (string top_dir, string path)
165183
{
166184
if (string.IsNullOrEmpty (path))

build-tools/create-dotnet-pkg/create-dotnet-pkg.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
<_FilesToCopy Include="$(DotNetPreviewPath)\sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**\*" />
3636
<_FilesToCopy Include="$(DotNetPreviewPath)\packs\Microsoft.Android.Ref\**\*" />
3737
<_FilesToCopy Include="$(DotNetPreviewPath)\packs\Microsoft.Android.Sdk.osx-x64\**\*" />
38+
<_FilesToCopy Include="$(DotNetPreviewPath)\template-packs\Microsoft.Android.Templates.*.nupkg" />
3839
</ItemGroup>
3940
<MakeDir Directories="$(PkgOutputPath);$(PayloadDir);$(PkgResourcesPath);$(LicenseDestination)"/>
4041
<ReplaceFileContents

build-tools/create-packs/Directory.Build.targets

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@
8282
<Exec Command="$(DotNetPreviewTool) pack @(_GlobalProperties, ' ') -p:AndroidHostRID=osx-x64 &quot;$(MSBuildThisFileDirectory)Microsoft.Android.Sdk.proj&quot;" Condition=" '$(HostOS)' == 'Darwin' " />
8383
<Exec Command="$(DotNetPreviewTool) pack @(_GlobalProperties, ' ') -p:AndroidHostRID=win-x64 &quot;$(MSBuildThisFileDirectory)Microsoft.Android.Sdk.proj&quot;" Condition=" '$(HostOS)' != 'Linux' " /> <!-- Windows pack should be built both Windows and macOS -->
8484
<Exec Command="$(DotNetPreviewTool) pack @(_GlobalProperties, ' ') &quot;$(MSBuildThisFileDirectory)Microsoft.NET.Workload.Android.proj&quot;" />
85+
<Exec Command="$(DotNetPreviewTool) pack @(_GlobalProperties, ' ') &quot;$(XamarinAndroidSourcePath)src\Microsoft.Android.Templates\Microsoft.Android.Templates.csproj&quot;" />
8586
</Target>
8687

8788
<Target Name="ExtractWorkloadPacks"
@@ -92,6 +93,7 @@
9293
<_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Sdk.osx-x64.*.nupkg" Condition=" '$(HostOS)' == 'Darwin' " />
9394
<_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Sdk.win-x64.*.nupkg" Condition=" '$(HostOS)' == 'Windows' " />
9495
<_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Ref.*.nupkg" />
96+
<_WLTemplates Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Templates.*.nupkg" />
9597
<!-- Runtime packs are not yet supported by workloads -->
9698
<!-- <_WLPacks Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\nupkgs\Microsoft.Android.Runtime.*.nupkg" /> -->
9799
</ItemGroup>
@@ -106,6 +108,8 @@
106108
SourceFiles="@(_WLPacks)"
107109
DestinationFolder="$(DotNetPreviewPath)packs\$([System.String]::Copy('%(_WLPacks.Filename)').Replace('.$(_WLPackVersion)', ''))\$(_WLPackVersion)"
108110
/>
111+
<MakeDir Directories="$(DotNetPreviewPath)template-packs" />
112+
<Copy SourceFiles="@(_WLTemplates)" DestinationFolder="$(DotNetPreviewPath)template-packs" />
109113
<ItemGroup>
110114
<_UnixExecutables Include="$(DotNetPreviewPath)packs\Microsoft.Android.Sdk.*\*\tools\$(HostOS)\**\*.*" />
111115
<_FilesToTouch Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**" />
@@ -129,6 +133,7 @@
129133
<_PackFilesToDelete Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.Android.Workload\**\*.*" />
130134
<_PackFilesToDelete Include="$(DotNetPreviewPath)sdk-manifests\$(DotNetPreviewVersionBand)\Microsoft.NET.Workload.Android\**\*.*" />
131135
<_PackFilesToDelete Include="$(DotNetPreviewPath)packs\Microsoft.Android*\**\*.*" />
136+
<_PackFilesToDelete Include="$(DotNetPreviewPath)template-packs\Microsoft.Android.Templates.*.nupkg" />
132137
</ItemGroup>
133138
<RemoveDir Directories="%(_PackFilesToDelete.RootDir)%(_PackFilesToDelete.Directory)" />
134139
<Delete Files="$(_WorkloadResolverFlagFile)" />

build-tools/create-packs/Microsoft.NET.Workload.Android.proj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ workload manifest pack containing information about the various Microsoft.Androi
3636
<ReplaceFileContents
3737
SourceFile="$(XamarinAndroidSourcePath)src\Xamarin.Android.Build.Tasks\Microsoft.NET.Workload.Android\WorkloadManifest.in.json"
3838
DestinationFile="$(WorkloadManifestJsonPath)"
39-
Replacements="@SDK_PACK_VERSION@=$(AndroidPackVersionLong);@REF_PACK_VERSION@=$(AndroidPackVersionLong)">
39+
Replacements="@SDK_PACK_VERSION@=$(AndroidPackVersionLong);@REF_PACK_VERSION@=$(AndroidPackVersionLong);@TEMPLATE_PACK_VERSION@=$(AndroidPackVersionLong);">
4040
</ReplaceFileContents>
4141

4242
<ItemGroup>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<Project>
2+
<Import Project="..\..\build-tools\scripts\XAVersionInfo.targets" />
3+
<PropertyGroup>
4+
<BeforePack>
5+
_GetDefaultPackageVersion;
6+
$(BeforePack);
7+
</BeforePack>
8+
</PropertyGroup>
9+
<Target Name="_GetDefaultPackageVersion"
10+
DependsOnTargets="GetXAVersionInfo" >
11+
<PropertyGroup>
12+
<PackageVersion>$(AndroidPackVersionLong)+sha.$(XAVersionHash)</PackageVersion>
13+
</PropertyGroup>
14+
</Target>
15+
</Project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<PackageType>Template</PackageType>
6+
<PackageId>Microsoft.Android.Templates</PackageId>
7+
<Title>.NET Android Templates</Title>
8+
<Authors>Microsoft</Authors>
9+
<Description>Templates for Android platforms.</Description>
10+
<IncludeContentInPack>true</IncludeContentInPack>
11+
<IncludeBuildOutput>false</IncludeBuildOutput>
12+
<ContentTargetFolders>content</ContentTargetFolders>
13+
<OutputPath>..\..\bin\Build$(Configuration)\nupkgs\</OutputPath>
14+
</PropertyGroup>
15+
16+
<Import Project="..\..\Configuration.props" />
17+
18+
<ItemGroup>
19+
<Content Include="**\*" Exclude="**\bin\**;**\obj\**" />
20+
<Compile Remove="**\*" />
21+
</ItemGroup>
22+
23+
</Project>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"$schema": "http://json.schemastore.org/template",
3+
"author": "Microsoft",
4+
"classifications": [ "Android" ],
5+
"name": "Android Activity template",
6+
"description": "An Android Activity class",
7+
"tags": {
8+
"language": "C#",
9+
"type": "item"
10+
},
11+
"identity": "Microsoft.Android.AndroidActivity",
12+
"shortName": "android-activity",
13+
"sourceName": "Activity1",
14+
"primaryOutputs": [
15+
{ "path": "Activity1.cs" }
16+
],
17+
"defaultName": "Activity1",
18+
"symbols": {
19+
"namespace": {
20+
"description": "namespace for the generated code",
21+
"replaces": "AndroidApp1",
22+
"type": "parameter"
23+
}
24+
}
25+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Android.App;
2+
using Android.OS;
3+
using Android.Runtime;
4+
using Android.Widget;
5+
6+
namespace AndroidApp1
7+
{
8+
[Activity(Label = "@string/app_name", MainLauncher = true)]
9+
public class Activity1 : Activity
10+
{
11+
protected override void OnCreate(Bundle savedInstanceState)
12+
{
13+
base.OnCreate(savedInstanceState);
14+
15+
// Create your application here
16+
}
17+
}
18+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"$schema": "http://json.schemastore.org/template",
3+
"author": "Microsoft",
4+
"classifications": [ "Android" ],
5+
"identity": "Microsoft.Android.AndroidBinding",
6+
"name": "Android Java Library Binding",
7+
"description": "A project for creating an Android class library that binds to a native Java library",
8+
"shortName": "android-bindinglib",
9+
"tags": {
10+
"language": "C#",
11+
"type": "project"
12+
},
13+
"sourceName": "AndroidBinding1",
14+
"preferNameDirectory": true,
15+
"primaryOutputs": [
16+
{ "path": "AndroidBinding1.csproj" }
17+
],
18+
"defaultName": "AndroidBinding1"
19+
}

0 commit comments

Comments
 (0)