Skip to content

Commit 6fd330d

Browse files
committed
[android-toolchain] Permit zero-configuration builds.
This might be a suspect idea, but lets see if we can make this work. [The Joel Test: 12 Steps to Better Code][0] outlines 12 steps to better code. The first two steps are: 1. Do you use source control? 2. Can you make a build in one step? github is being used for source control, so (1) is handled, but how simple can we make (2)? How easy can we make it to build Xamarin.Android upon a fresh checkout? The ideal to strive for is simple: Load Xamarin.Android.sln into your IDE and Build the project. I *know* we're not going to be able to do this, if only because we're going to be using git submodules, which will require a separate `git submodule init` invocation [1]. Knowing we can't reach that level of simplicitly doesn't mean we shouldn't *try* to reach it for all other parts of the build system. Which brings us to the Android NDK and SDK. The Android NDK will be required in order to build native code, such as libmonodroid.so, while the Android SDK will be required in order to compile Java Callable Wrappers (née Android Callable Wrappers [2]) and eventual samples and unit tests. There are three ways we can deal with the Android NDK and SDK: 1. Complicate the "build" process by requiring that developers go to the Android SDK Download Page [3], download and install "somewhere" the required bits, and then configure the Xamarin.Android build to use these bits. 2. Complicate the "build" process by requiring that developers run the Xamarin Unified Installer [4], let it install everything required, then configure the Xamarin.Android build to use those bits. 3. Painstakingly determine which files are actually required, then automatically download and extract those files into a "well-known" location known by the Xamarin.Android build process. (1) and (2) can be infuriating. Let's give (3) a try. :-) Add a Xamarin.Android.Tools.BootstrapTasks project which contains MSBuild tasks to facilitate downloading the Android SDK and NDK files. Add an android-toolchain project which uses Xamarin.Android.Tools.BootstrapTasks to download a painstakingly determined set of files and install them "somewhere". Unfortunately [5] the "somewhere" to download and install these files needs to be in a known absolute path, so I've arbitrary decided to download the files into $(HOME)\android-archives and install them into $(HOME)\android-toolchain. On windows, this is %HOMEDRIVE%%HOMEPATH%\android-archives and %HOMEDRIVE%%HOMEPATH%\android-toolchain. These locations may be modified by creating a Configuration.Override.props file; see README.md for details. TL;DR: This setup is able to magically download the Android NDK and SDK files and install them for later use in a reasonably overridable location, all within MSBuild. [0]: http://www.joelonsoftware.com/articles/fog0000000043.html [1]: Though maybe there's some MSBuild-fu we can use to address that. [2]: https://developer.xamarin.com/guides/android/advanced_topics/java_integration_overview/android_callable_wrappers/ [3]: http://developer.android.com/sdk/index.html [4]: https://www.xamarin.com/download [5]: Because I couldn't find a reliable way to use $(SolutionDir) when only building a project, and relative paths would require an in-tree installation location, which might not work.
1 parent 7ecbb12 commit 6fd330d

File tree

15 files changed

+501
-0
lines changed

15 files changed

+501
-0
lines changed

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.userprefs
2+
bin
3+
Configuration.Override.props
4+
obj
5+
packages

Configuration.Override.props.in

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<!-- These must be FULL PATHS -->
5+
<AndroidToolchainCacheDirectory>$(HOME)\android-archives</AndroidToolchainCacheDirectory>
6+
<AndroidToolchainDirectory>$(HOME)\android-toolchain</AndroidToolchainDirectory>
7+
</PropertyGroup>
8+
</Project>

Configuration.props

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="Configuration.Override.props" Condition="Exists('Configuration.Override.props')" />
4+
<PropertyGroup>
5+
<HostOS Condition=" '$(HostOS)' == '' And '$(OS)' == 'Windows_NT' ">Windows</HostOS>
6+
<HostOS Condition=" '$(HostOS)' == '' And '$(OS)' == 'Unix' And Exists ('/Applications') ">Darwin</HostOS>
7+
<HostOS Condition=" '$(HostOS)' == '' And '$(OS)' == 'Unix' ">Linux</HostOS>
8+
<HOME Condition=" '$(HOME)' == '' ">$(HOMEDRIVE)$(HOMEPATH)</HOME>
9+
<AndroidToolchainCacheDirectory Condition=" '$(AndroidToolchainCacheDirectory)' == '' ">$(HOME)\android-archives</AndroidToolchainCacheDirectory>
10+
<AndroidToolchainDirectory Condition=" '$(AndroidToolchainDirectory)' == '' ">$(HOME)\android-toolchain</AndroidToolchainDirectory>
11+
</PropertyGroup>
12+
</Project>

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CONFIGURATION = Debug
2+
MSBUILD = xbuild /p:Configuration=$(CONFIGURATION)
3+
4+
all:
5+
$(MSBUILD)
6+
7+
clean:
8+
$(MSBUILD) /t:Clean

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
Xamarin.Android
2+
===============
3+
4+
Xamarin.Android provides open-source bindings of the Android SDK for use with
5+
.NET managed languages such as C#.
6+
7+
# Build Configuration
8+
9+
Building Xamarin.Android requires the Java Development Kit (JDK), several
10+
pieces of the Android SDK, and the Android NDK.
11+
12+
The Java Development Kit may be downloaded from the
13+
[Oracle Java SE Downloads page][download-jdk].
14+
15+
[download-jdk]: http://www.oracle.com/technetwork/java/javase/downloads/
16+
17+
To simplify building Xamarin.Android, important pieces of the Android SDK
18+
and Android NDK will be automatically downloaded and installed from
19+
Google's website. Downloaded files are cached locally, by default into
20+
`$(HOME)\android-archives`. The Android NDK and SDK will be installed by
21+
default into `$(HOME)\android-toolchain`.
22+
23+
These directories may be changed by creating the file
24+
`Configuration.Override.props` in the toplevel directory and editing
25+
the MSBuild properties:
26+
27+
* `$(AndroidToolchainCacheDirectory)`: The directory to cache the downloaded
28+
Android NDK and SDK files.
29+
* `$(AndroidToolchainDirectory)`: The directory to install the downloaded
30+
Android NDK and SDK files.
31+
32+
The file [Configuration.Override.props.in][Configuration.Override.props.in]
33+
may be used as a template file for creating `Configuration.Override.props`.
34+
35+
The files that will be downloaded and installed are controlled by
36+
[build-tools/android-toolchain/android-toolchain.projitems][android-toolchain.projitems]
37+
via the `@(AndroidNdkItem)` and `@(AndroidSdkItem)` item groups, and the
38+
URL to download files from is controlled by the `$(AndroidUri)` property.
39+
40+
[android-toolchain.projitems]: build-tools/android-toolchain/android-toolchain.projitems
41+
42+
# Build
43+
44+
At this point in time, building Xamarin.Android is only supported on OS X.
45+
We will work to improve this.
46+
47+
To build Xamarin.Android, load `Xamarin.Android.sln` into Xamarin Studio 6
48+
and Build the project.

Xamarin.Android.sln

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
11

22
Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio 2012
4+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build-Tools", "Build-Tools", "{E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}"
5+
EndProject
6+
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "android-toolchain", "build-tools\android-toolchain\android-toolchain.mdproj", "{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}"
7+
EndProject
8+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.Tools.BootstrapTasks", "src\Xamarin.Android.Tools.BootstrapTasks\Xamarin.Android.Tools.BootstrapTasks.csproj", "{E8492EFB-D14A-4F32-AA28-88848322ECEA}"
9+
EndProject
410
Global
511
GlobalSection(SolutionConfigurationPlatforms) = preSolution
12+
Debug|AnyCPU = Debug|AnyCPU
13+
Release|AnyCPU = Release|AnyCPU
614
EndGlobalSection
715
GlobalSection(ProjectConfigurationPlatforms) = postSolution
16+
{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
17+
{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}.Release|AnyCPU.Build.0 = Release|AnyCPU
18+
{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
19+
{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}.Debug|AnyCPU.Build.0 = Debug|Any CPU
20+
{E8492EFB-D14A-4F32-AA28-88848322ECEA}.Release|AnyCPU.ActiveCfg = Release|AnyCPU
21+
{E8492EFB-D14A-4F32-AA28-88848322ECEA}.Release|AnyCPU.Build.0 = Release|AnyCPU
22+
{E8492EFB-D14A-4F32-AA28-88848322ECEA}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
23+
{E8492EFB-D14A-4F32-AA28-88848322ECEA}.Debug|AnyCPU.Build.0 = Debug|Any CPU
24+
EndGlobalSection
25+
GlobalSection(NestedProjects) = preSolution
26+
{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
27+
{E8492EFB-D14A-4F32-AA28-88848322ECEA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62}
28+
EndGlobalSection
29+
GlobalSection(MonoDevelopProperties) = preSolution
30+
Policies = $0
31+
$0.DotNetNamingPolicy = $1
32+
$1.DirectoryNamespaceAssociation = None
33+
$1.ResourceNamePolicy = FileFormatDefault
834
EndGlobalSection
935
EndGlobal
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5+
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6+
<ItemType>GenericProject</ItemType>
7+
<ProjectGuid>{8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA}</ProjectGuid>
8+
</PropertyGroup>
9+
<Import Project="..\..\Configuration.props" />
10+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
11+
<OutputPath>$(AndroidToolchainDirectory)</OutputPath>
12+
</PropertyGroup>
13+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
14+
<OutputPath>$(AndroidToolchainDirectory)</OutputPath>
15+
</PropertyGroup>
16+
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
17+
<PropertyGroup>
18+
<BuildDependsOn>
19+
ResolveReferences;
20+
_CopyBootstrapTasksAssembly;
21+
_DownloadItems;
22+
_UnzipFiles;
23+
_CreateNdkToolchains;
24+
</BuildDependsOn>
25+
</PropertyGroup>
26+
<Import Project="android-toolchain.targets" />
27+
<ItemGroup>
28+
<ProjectReference Include="..\..\src\Xamarin.Android.Tools.BootstrapTasks\Xamarin.Android.Tools.BootstrapTasks.csproj">
29+
<Project>{E8492EFB-D14A-4F32-AA28-88848322ECEA}</Project>
30+
<Name>Xamarin.Android.Tools.BootstrapTasks</Name>
31+
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
32+
<OutputItemType>Content</OutputItemType>
33+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
34+
</ProjectReference>
35+
</ItemGroup>
36+
<ItemGroup>
37+
<None Include="packages.config" />
38+
</ItemGroup>
39+
</Project>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<AndroidUri Condition=" '$(AndroidUri)' == '' ">https://dl-ssl.google.com/android/repository</AndroidUri>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<AndroidNdkItem Include="android-ndk-r11c-darwin-x86_64.zip">
8+
<HostOS>Darwin</HostOS>
9+
</AndroidNdkItem>
10+
<AndroidSdkItem Include="build-tools_r23-macosx.zip">
11+
<HostOS>Darwin</HostOS>
12+
<DestDir>build-tools\23.0.0</DestDir>
13+
</AndroidSdkItem>
14+
<AndroidSdkItem Include="platform-tools_r23-macosx.zip">
15+
<HostOS>Darwin</HostOS>
16+
<DestDir>platform-tools</DestDir>
17+
</AndroidSdkItem>
18+
<AndroidSdkItem Include="android-sdk_r24.4.1-macosx.zip">
19+
<HostOS>Darwin</HostOS>
20+
</AndroidSdkItem>
21+
<AndroidSdkItem Include="platform-N_r01.zip">
22+
<DestDir>platforms\android-N</DestDir>
23+
</AndroidSdkItem>
24+
<AndroidSdkItem Include="android-23_r01.zip">
25+
<DestDir>platforms\android-23</DestDir>
26+
</AndroidSdkItem>
27+
</ItemGroup>
28+
</Project>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<Import Project="android-toolchain.projitems" />
4+
<Target Name="_CopyBootstrapTasksAssembly"
5+
Outputs="$(OutputPath)\Xamarin.Android.Tools.BootstrapTasks.dll">
6+
<MSBuild
7+
Projects="..\..\src\Xamarin.Android.Tools.BootstrapTasks\Xamarin.Android.Tools.BootstrapTasks.csproj"
8+
Properties="OutputPath=$(AndroidToolchainDirectory)"
9+
/>
10+
</Target>
11+
<UsingTask AssemblyFile="$(OutputPath)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.CreateTemporaryDirectory" />
12+
<UsingTask AssemblyFile="$(OutputPath)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.DownloadUri" />
13+
<UsingTask AssemblyFile="$(OutputPath)\Xamarin.Android.Tools.BootstrapTasks.dll" TaskName="Xamarin.Android.Tools.BootstrapTasks.UnzipDirectoryChildren" />
14+
<Target Name="_DownloadItems"
15+
Outputs="@(AndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)');@(AndroidNdkItems->'$(AndroidToolchainCacheDirectory)\%(Identity)')">
16+
<DownloadUri
17+
SourceUris="@(AndroidSdkItem->'$(AndroidUri)/%(Identity)');@(AndroidNdkItem->'$(AndroidUri)/%(Identity)')"
18+
DestinationFiles="@(AndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)');@(AndroidNdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')"
19+
/>
20+
</Target>
21+
<Target Name="_UnzipFiles"
22+
Inputs="@(AndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')"
23+
Outputs="$(AndroidToolchainDirectory)\.stamp-sdk">
24+
<CreateItem
25+
Include="@(AndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)"
26+
Condition=" '%(AndroidSdkItem.HostOS)' == '$(HostOS)' Or '%(AndroidSdkItem.HostOS)' == '' ">
27+
<Output TaskParameter="Include" ItemName="_AndroidSdkItems"/>
28+
</CreateItem>
29+
<CreateItem
30+
Include="@(AndroidNdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)"
31+
Condition=" '%(AndroidSdkItem.HostOS)' == '$(HostOS)' Or '%(AndroidSdkItem.HostOS)' == '' ">
32+
<Output TaskParameter="Include" ItemName="_AndroidNdkItems"/>
33+
</CreateItem>
34+
35+
<RemoveDir Directories="$(AndroidToolchainDirectory)\sdk;$(AndroidToolchainDirectory)\ndk" />
36+
<MakeDir Directories="$(AndroidToolchainDirectory)\sdk;$(AndroidToolchainDirectory)\ndk" />
37+
38+
<UnzipDirectoryChildren
39+
SourceFiles="@(AndroidSdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')"
40+
DestinationFolder="$(AndroidToolchainDirectory)\sdk"
41+
/>
42+
<UnzipDirectoryChildren
43+
SourceFiles="@(AndroidNdkItem->'$(AndroidToolchainCacheDirectory)\%(Identity)')"
44+
DestinationFolder="$(AndroidToolchainDirectory)\ndk"
45+
/>
46+
<Touch
47+
Files="$(AndroidToolchainDirectory)\.stamp-sdk"
48+
AlwaysCreate="True"
49+
/>
50+
</Target>
51+
<ItemGroup>
52+
<_NdkToolchain Include="arm-linux-androideabi-clang">
53+
<Platform>android-4</Platform>
54+
<Arch>arm</Arch>
55+
</_NdkToolchain>
56+
</ItemGroup>
57+
<Target Name="_CreateNdkToolchains"
58+
Condition=" '$(OS)' == 'Unix' "
59+
Inputs="$(AndroidToolchainDirectory)\.stamp-sdk"
60+
Outputs="@(_NdkToolchain->'$(AndroidToolchainDirectory)\.stamp-toolchains-%(Identity)')">
61+
<PropertyGroup>
62+
<_Script>$(AndroidToolchainDirectory)\ndk\build\tools\make-standalone-toolchain.sh</_Script>
63+
<_Install>@(_NdkToolchain->'$(AndroidToolchainDirectory)\toolchains\%(Identity)')</_Install>
64+
<_Arch>@(_NdkToolchain->'%(Arch)')</_Arch>
65+
<_Toolchain>@(_NdkToolchain->'%(Identity)')</_Toolchain>
66+
</PropertyGroup>
67+
<Exec Command="bash &quot;$(_Script)&quot; --platform=%(_NdkToolchain.Platform) &quot;--install-dir=$(_Install)&quot; --arch=$(_Arch) --toolchain=$(_Toolchain)" />
68+
<Touch
69+
Files="@(_NdkToolchain->'$(AndroidToolchainDirectory)\.stamp-toolchains-%(Identity)')"
70+
AlwaysCreate="True"
71+
/>
72+
</Target>
73+
</Project>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<packages>
3+
</packages>

0 commit comments

Comments
 (0)