diff --git a/Documentation/DevelopmentTips.md b/Documentation/DevelopmentTips.md index 05557888972..980f6c20a7c 100644 --- a/Documentation/DevelopmentTips.md +++ b/Documentation/DevelopmentTips.md @@ -116,6 +116,17 @@ to hold file locks on output assemblies containing MSBuild tasks. Until there is for this, it might be more advisable to use an editor like Visual Studio Code and build via the command-line. +Windows also requires `xabuild.exe` in place of the `tools/scripts/xabuild` script used +on other platforms. + +So a command on macOS such as: + + $ tools/scripts/xabuild /t:SignAndroidPackage tests/locales/Xamarin.Android.Locale-Tests/Xamarin.Android.Locale-Tests.csproj + +Would be run on Windows as: + + > bin\Debug\bin\xabuild.exe /t:SignAndroidPackage tests\locales\Xamarin.Android.Locale-Tests\Xamarin.Android.Locale-Tests.csproj + # Unit Tests The `xamarin-android` repo contains several unit tests: diff --git a/Xamarin.Android.sln b/Xamarin.Android.sln index 5a3063da2d8..de7cd92d43f 100644 --- a/Xamarin.Android.sln +++ b/Xamarin.Android.sln @@ -105,6 +105,8 @@ Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "netstandard", "src\netstand EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "setup-windows", "tools\setup-windows\setup-windows.csproj", "{73DF9E10-E933-4222-B8E1-F4536FFF9FAD}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "xabuild", "tools\xabuild\xabuild.csproj", "{B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android", "src\Mono.Android\Mono.Android.csproj", "{66CF299A-CE95-4131-BCD8-DB66E30C4BF7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android.Export", "src\Mono.Android.Export\Mono.Android.Export.csproj", "{B8105878-D423-4159-A3E7-028298281EC6}" @@ -531,6 +533,18 @@ Global {1E5501E8-49C1-4659-838D-CC9720C5208F}.XAIntegrationDebug|Any CPU.Build.0 = Debug|Any CPU {1E5501E8-49C1-4659-838D-CC9720C5208F}.XAIntegrationRelease|Any CPU.ActiveCfg = Release|Any CPU {1E5501E8-49C1-4659-838D-CC9720C5208F}.XAIntegrationRelease|Any CPU.Build.0 = Release|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Debug|AnyCPU.Build.0 = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Release|AnyCPU.ActiveCfg = Release|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.Release|AnyCPU.Build.0 = Release|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationDebug|AnyCPU.ActiveCfg = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationDebug|AnyCPU.Build.0 = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationRelease|AnyCPU.ActiveCfg = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationRelease|AnyCPU.Build.0 = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationDebug|Any CPU.ActiveCfg = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationDebug|Any CPU.Build.0 = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationRelease|Any CPU.ActiveCfg = Debug|Any CPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D}.XAIntegrationRelease|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {8FF78EB6-6FC8-46A7-8A15-EBBA9045C5FA} = {E351F97D-EA4F-4E7F-AAA0-8EBB1F2A4A62} @@ -585,6 +599,7 @@ Global {B8105878-D423-4159-A3E7-028298281EC6} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {04E3E11E-B47D-4599-8AFC-50515A95E715} {1E5501E8-49C1-4659-838D-CC9720C5208F} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483} + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D} = {864062D3-A415-4A6F-9324-5820237BA058} EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index 0c09691041f..d37a8283740 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -10,11 +10,6 @@ namespace Xamarin.ProjectTools { public class Builder : IDisposable { - const string fixed_osx_xbuild_path = "/Library/Frameworks/Mono.framework/Commands"; - const string fixed_linux_xbuild_path = "/usr/bin"; - const string xbuildapp = "xbuild"; - const string msbuildapp = "msbuild"; - public bool IsUnix { get; set; } public bool RunningMSBuild { get; set; } public LoggerVerbosity Verbosity { get; set; } @@ -23,18 +18,6 @@ public class Builder : IDisposable public string BuildLogFile { get; set; } public bool ThrowOnBuildFailure { get; set; } - string GetUnixBuildExe () - { - RunningMSBuild = false; - var tooldir = Directory.Exists (fixed_osx_xbuild_path) ? fixed_osx_xbuild_path : fixed_linux_xbuild_path; - string path = Path.Combine (tooldir, xbuildapp); - if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("USE_MSBUILD"))) { - path = Path.Combine (tooldir, msbuildapp); - RunningMSBuild = true; - } - return File.Exists (path) ? path : msbuildapp; - } - string GetVisualStudio2017Directory () { var editions = new [] { @@ -54,38 +37,20 @@ string GetVisualStudio2017Directory () return null; } - string GetWindowsBuildExe () - { - RunningMSBuild = true; - - //First try environment variable - string msbuildExe = Environment.GetEnvironmentVariable ("XA_MSBUILD_EXE"); - if (!string.IsNullOrEmpty (msbuildExe) && File.Exists (msbuildExe)) - return msbuildExe; - - //Next try VS 2017, MSBuild 15.0 - var visualStudioDirectory = GetVisualStudio2017Directory (); - if (!string.IsNullOrEmpty(visualStudioDirectory)) { - msbuildExe = Path.Combine (visualStudioDirectory, "MSBuild", "15.0", "Bin", "MSBuild.exe"); - - if (File.Exists (msbuildExe)) - return msbuildExe; - } - - //Try older than VS 2017, MSBuild 14.0 - msbuildExe = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86), "MSBuild", "14.0", "Bin", "MSBuild.exe"); - if (File.Exists (msbuildExe)) - return msbuildExe; - - //MSBuild 4.0 last resort - return Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Windows), "Microsoft.NET", "Framework", "v4.0.30319", "MSBuild.exe"); - } - - public string MSBuildExe { + public string XABuildExe { get { - return IsUnix - ? GetUnixBuildExe () - : GetWindowsBuildExe (); + if (IsUnix) { + if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("USE_MSBUILD"))) { + RunningMSBuild = true; + } + return Path.GetFullPath (Path.Combine (Root, "..", "..", "tools", "scripts", "xabuild")); + } + + #if DEBUG + return Path.GetFullPath (Path.Combine (Root, "..", "..", "bin", "Debug", "bin", "xabuild.exe")); + #else + return Path.GetFullPath (Path.Combine (Root, "..", "..", "bin", "Release", "bin", "xabuild.exe")); + #endif } } @@ -200,57 +165,22 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] buildLogFullPath, Verbosity.ToString ().ToLower ()); var start = DateTime.UtcNow; - var homeDirectory = Environment.GetFolderPath (Environment.SpecialFolder.Personal); - var androidSdkToolPath = Path.Combine (homeDirectory, "android-toolchain"); - var sdkPath = Environment.GetEnvironmentVariable ("ANDROID_SDK_PATH"); - if (String.IsNullOrEmpty (sdkPath)) - sdkPath = GetPathFromRegistry ("AndroidSdkDirectory"); - if (String.IsNullOrEmpty (sdkPath)) - sdkPath = Path.GetFullPath (Path.Combine (androidSdkToolPath, "sdk")); - var ndkPath = Environment.GetEnvironmentVariable ("ANDROID_NDK_PATH"); - if (String.IsNullOrEmpty (ndkPath)) - ndkPath = GetPathFromRegistry ("AndroidNdkDirectory"); - if (String.IsNullOrEmpty (ndkPath)) - ndkPath = Path.GetFullPath (Path.Combine (androidSdkToolPath, "ndk")); - StringBuilder args = new StringBuilder (); - var psi = new ProcessStartInfo (MSBuildExe); - if (IsUnix) { - if (Directory.Exists (sdkPath)) { - args.AppendFormat ("/p:AndroidSdkDirectory=\"{0}\" ", sdkPath); - } - if (Directory.Exists (ndkPath)) { - args.AppendFormat ("/p:AndroidNdkDirectory=\"{0}\" ", ndkPath); - } - var outdir = Path.GetFullPath (Path.Combine (FrameworkLibDirectory, "..", "..")); - var targetsdir = Path.Combine (FrameworkLibDirectory, "xbuild"); - args.AppendFormat (" {0} ", logger); + var args = new StringBuilder (); + var psi = new ProcessStartInfo (XABuildExe); + args.AppendFormat ("{0} /t:{1} {2} /p:UseHostCompilerIfAvailable=false /p:BuildingInsideVisualStudio=true", + QuoteFileName(Path.Combine (Root, projectOrSolution)), target, logger); - if (Directory.Exists (targetsdir)) { - psi.EnvironmentVariables ["TARGETS_DIR"] = targetsdir; - psi.EnvironmentVariables ["MSBuildExtensionsPath"] = targetsdir; - } - if (Directory.Exists (outdir)) { - var frameworksPath = Path.Combine (outdir, "lib", "xamarin.android", "xbuild-frameworks"); - psi.EnvironmentVariables ["MONO_ANDROID_PATH"] = outdir; - args.AppendFormat ("/p:MonoDroidInstallDirectory=\"{0}\" ", outdir); - psi.EnvironmentVariables ["XBUILD_FRAMEWORK_FOLDERS_PATH"] = frameworksPath; - if (RunningMSBuild) - args.AppendFormat ($"/p:TargetFrameworkRootPath={frameworksPath} "); - } - args.AppendFormat ("/t:{0} {1} /p:UseHostCompilerIfAvailable=false /p:BuildingInsideVisualStudio=true", target, QuoteFileName (Path.Combine (Root, projectOrSolution))); - } - else { - args.AppendFormat ("{0} /t:{1} {2} /p:UseHostCompilerIfAvailable=false /p:BuildingInsideVisualStudio=true", - QuoteFileName(Path.Combine (Root, projectOrSolution)), target, logger); - } if (parameters != null) { foreach (var param in parameters) { args.AppendFormat (" /p:{0}", param); } } + if (RunningMSBuild) { + psi.EnvironmentVariables ["MSBUILD"] = "msbuild"; + } if (environmentVariables != null) { foreach (var kvp in environmentVariables) { - psi.EnvironmentVariables[kvp.Key] = kvp.Value; + psi.EnvironmentVariables [kvp.Key] = kvp.Value; } } psi.Arguments = args.ToString (); diff --git a/tools/scripts/xabuild b/tools/scripts/xabuild index 3b9f41abcbb..b9c1509127e 100755 --- a/tools/scripts/xabuild +++ b/tools/scripts/xabuild @@ -43,7 +43,7 @@ if [ -z "$MSBUILD" ] ; then fi if [ -z "$CONFIGURATION" ]; then - for p in "$*"; do + for p in "$@"; do case $p in /property:Configuration=*| \ /p:Configuration=*| \ @@ -82,6 +82,11 @@ else exit 1 fi +if [[ "$MSBUILD" == "msbuild" ]] ; then + exec mono "$prefix/bin/xabuild.exe" "$@" + exit $? +fi + for t in "$TARGETS_DIR" "$prefix/lib/mono/xbuild" "$xa_prefix/xbuild" ; do if [ -z "$t" -o ! -d "$t" ]; then continue diff --git a/tools/xabuild/App.config b/tools/xabuild/App.config new file mode 100644 index 00000000000..bd95ffefcd5 --- /dev/null +++ b/tools/xabuild/App.config @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tools/xabuild/Properties/AssemblyInfo.cs b/tools/xabuild/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..88ca841df73 --- /dev/null +++ b/tools/xabuild/Properties/AssemblyInfo.cs @@ -0,0 +1,26 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("xabuild")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("Microsoft Corporation")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/tools/xabuild/SymbolicLink.cs b/tools/xabuild/SymbolicLink.cs new file mode 100644 index 00000000000..ed80fd1f8a5 --- /dev/null +++ b/tools/xabuild/SymbolicLink.cs @@ -0,0 +1,46 @@ +using System; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using Mono.Unix; + +namespace Xamarin.Android.Build +{ + static class SymbolicLink + { + public static bool Create (string source, string target) + { + if (!Directory.Exists (source)) { + if (Environment.OSVersion.Platform == PlatformID.Win32NT) { + //NOTE: attempt with and without the AllowUnprivilegedCreate flag, seems to fix Windows Server 2016 + if (!CreateSymbolicLink (source, target, SymbolLinkFlag.Directory | SymbolLinkFlag.AllowUnprivilegedCreate) && + !CreateSymbolicLink (source, target, SymbolLinkFlag.Directory)) { + var error = new Win32Exception ().Message; + Console.Error.WriteLine ($"Unable to create symbolic link from `{source}` to `{target}`: {error}"); + return false; + } + } else { + try { + var fileInfo = new UnixFileInfo (target); + fileInfo.CreateSymbolicLink (source); + } catch (Exception exc) { + Console.Error.WriteLine ($"Unable to create symbolic link from `{source}` to `{target}`: {exc.Message}"); + return false; + } + } + } + + return true; + } + + enum SymbolLinkFlag { + File = 0, + Directory = 1, + AllowUnprivilegedCreate = 2, + } + + [DllImport ("kernel32.dll")] + [return: MarshalAs (UnmanagedType.I1)] + static extern bool CreateSymbolicLink (string lpSymlinkFileName, string lpTargetFileName, SymbolLinkFlag dwFlags); + } +} diff --git a/tools/xabuild/XABuild.cs b/tools/xabuild/XABuild.cs new file mode 100644 index 00000000000..374703f6fd5 --- /dev/null +++ b/tools/xabuild/XABuild.cs @@ -0,0 +1,103 @@ +using Microsoft.Build.CommandLine; +using System; +using System.IO; +using System.Xml; + +namespace Xamarin.Android.Build +{ + class XABuild + { + [MTAThread] + static int Main () + { + var paths = new XABuildPaths (); + if (!Directory.Exists (paths.XamarinAndroidBuildOutput)) { + Console.WriteLine ($"Unable to find Xamarin.Android build output at {paths.XamarinAndroidBuildOutput}"); + return 1; + } + + //Create a custom xabuild.exe.config + CreateConfig (paths); + + //Create link to .NETFramework and .NETPortable directory + foreach (var dir in Directory.GetDirectories(paths.SystemProfiles)) { + var name = Path.GetFileName(dir); + if (!SymbolicLink.Create(Path.Combine(paths.FrameworksDirectory, name), dir)) { + return 1; + } + } + + return MSBuildApp.Main (); + } + + static void CreateConfig (XABuildPaths paths) + { + var xml = new XmlDocument (); + xml.Load (paths.MSBuildConfig); + + var toolsets = xml.SelectSingleNode ("configuration/msbuildToolsets/toolset"); + SetProperty (toolsets, "VsInstallRoot", paths.VsInstallRoot); + SetProperty (toolsets, "MSBuildToolsPath", paths.MSBuildBin); + SetProperty (toolsets, "MSBuildToolsPath32", paths.MSBuildBin); + SetProperty (toolsets, "MSBuildToolsPath64", paths.MSBuildBin); + SetProperty (toolsets, "MSBuildExtensionsPath", paths.MSBuildExtensionsPath); + SetProperty (toolsets, "MSBuildExtensionsPath32", paths.MSBuildExtensionsPath); + SetProperty (toolsets, "RoslynTargetsPath", Path.Combine (paths.MSBuildBin, "Roslyn")); + SetProperty (toolsets, "AndroidSdkDirectory", paths.AndroidSdkDirectory); + SetProperty (toolsets, "AndroidNdkDirectory", paths.AndroidNdkDirectory); + SetProperty (toolsets, "MonoAndroidToolsDirectory", paths.MonoAndroidToolsDirectory); + SetProperty (toolsets, "TargetFrameworkRootPath", paths.FrameworksDirectory + Path.DirectorySeparatorChar); //NOTE: Must include trailing \ + + var projectImportSearchPaths = toolsets.SelectSingleNode ("projectImportSearchPaths"); + var searchPaths = projectImportSearchPaths.SelectSingleNode ($"searchPaths[@os='{paths.SearchPathsOS}']") as XmlElement; + + //NOTE: on Linux, the searchPaths XML element does not exist, so we have to create it + if (searchPaths == null) { + searchPaths = xml.CreateElement ("searchPaths"); + searchPaths.SetAttribute ("os", paths.SearchPathsOS); + + var property = xml.CreateElement ("property"); + property.SetAttribute ("name", "MSBuildExtensionsPath"); + property.SetAttribute ("value", ""); + searchPaths.AppendChild (property); + + property = xml.CreateElement ("property"); + property.SetAttribute ("name", "MSBuildExtensionsPath32"); + property.SetAttribute ("value", ""); + searchPaths.AppendChild (property); + + property = xml.CreateElement ("property"); + property.SetAttribute ("name", "MSBuildExtensionsPath64"); + property.SetAttribute ("value", ""); + searchPaths.AppendChild (property); + + projectImportSearchPaths.AppendChild (searchPaths); + } + + foreach (XmlNode property in searchPaths.SelectNodes ("property[starts-with(@name, 'MSBuildExtensionsPath')]/@value")) { + property.Value = string.Join (";", paths.ProjectImportSearchPaths); + } + + xml.Save (paths.XABuildConfig); + } + + /// + /// If the value exists, sets value attribute, else creates the element + /// + static void SetProperty (XmlNode toolsets, string name, string value) + { + if (string.IsNullOrEmpty (value)) + return; + + var valueAttribute = toolsets.SelectSingleNode ($"property[@name='{name}']/@value"); + if (valueAttribute != null) { + valueAttribute.Value = value; + } else { + var property = toolsets.OwnerDocument.CreateElement ("property"); + property.SetAttribute ("name", name); + property.SetAttribute ("value", value); + toolsets.PrependChild (property); + } + } + } +} diff --git a/tools/xabuild/XABuildPaths.cs b/tools/xabuild/XABuildPaths.cs new file mode 100644 index 00000000000..98e06c49b62 --- /dev/null +++ b/tools/xabuild/XABuildPaths.cs @@ -0,0 +1,153 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Xamarin.Android.Build +{ + /// + /// Various paths needed by xabuild.exe + /// + class XABuildPaths + { + public bool IsWindows { get; private set; } + + public bool IsMacOS { get; private set; } + + public bool IsLinux { get; private set; } + + /// + /// Directory to xabuild.exe + /// + public string XABuildDirectory { get; private set; } + + /// + /// Path to xabuild.exe.config, on Unix it seems to use MSBuild.dll.config instead + /// + public string XABuildConfig { get; private set; } + + /// + /// The build output directory of Xamarin.Android, which is a submodule in this repo. Assumes it is already built. + /// + public string XamarinAndroidBuildOutput { get; private set; } + + /// + /// $(VsInstallRoot), normally C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise + /// + public string VsInstallRoot { get; private set; } + + /// + /// Path to MSBuild directory + /// + public string MSBuildPath { get; private set; } + + /// + /// Path to directory of MSBuild.exe + /// + public string MSBuildBin { get; private set; } + + /// + /// Path to MSBuild's App.config file + /// + public string MSBuildConfig { get; private set; } + + /// + /// Path to the system directory containing .NETPortable and .NETFramework + /// + public string SystemProfiles { get; private set; } + + /// + /// Our default $(MSBuildExtensionPath) which should be the "xbuild" directory in the Xamarin.Android build output + /// + public string MSBuildExtensionsPath { get; private set; } + + /// + /// Array of search paths for MSBuildExtensionsPath + /// + public string [] ProjectImportSearchPaths { get; private set; } + + /// + /// The xbuild-frameworks directory inside the Xamarin.Android build output + /// + public string FrameworksDirectory { get; private set; } + + /// + /// Search paths for MSBuildExtensionsPath are specified by an "os" attribute + /// NOTE: Values are "windows", "osx", or "unix" + /// + public string SearchPathsOS { get; set; } + + public string MonoAndroidToolsDirectory { get; private set; } + + public string AndroidSdkDirectory { get; private set; } + + public string AndroidNdkDirectory { get; private set; } + + public XABuildPaths () + { + IsWindows = Environment.OSVersion.Platform == PlatformID.Win32NT; + IsMacOS = !IsWindows && IsDarwin (); + IsLinux = !IsWindows && !IsMacOS; + XABuildDirectory = Path.GetDirectoryName (GetType ().Assembly.Location); + XamarinAndroidBuildOutput = Path.GetFullPath (Path.Combine (XABuildDirectory, "..")); + + string programFiles = Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86); + string userProfile = Environment.GetFolderPath (Environment.SpecialFolder.UserProfile); + string prefix = Path.Combine (XamarinAndroidBuildOutput, "lib", "xamarin.android"); + + if (IsWindows) { + foreach (var edition in new [] { "Enterprise", "Professional", "Community", "BuildTools" }) { + var vsInstall = Path.Combine (programFiles, "Microsoft Visual Studio", "2017", edition); + if (Directory.Exists (vsInstall)) { + VsInstallRoot = vsInstall; + break; + } + } + if (VsInstallRoot == null) + VsInstallRoot = programFiles; + + MSBuildPath = Path.Combine (VsInstallRoot, "MSBuild"); + MSBuildBin = Path.Combine (MSBuildPath, "15.0", "Bin"); + MSBuildConfig = Path.Combine (MSBuildBin, "MSBuild.exe.config"); + ProjectImportSearchPaths = new [] { MSBuildPath, "$(MSBuildProgramFiles32)\\MSBuild" }; + SystemProfiles = Path.Combine (programFiles, "Reference Assemblies", "Microsoft", "Framework"); + XABuildConfig = Path.Combine (XABuildDirectory, "xabuild.exe.config"); + SearchPathsOS = "windows"; + } else { + string mono = IsMacOS ? "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono" : "/usr/lib/mono"; + MSBuildPath = Path.Combine (mono, "msbuild"); + MSBuildBin = Path.Combine (MSBuildPath, "15.0", "bin"); + MSBuildConfig = Path.Combine (MSBuildBin, "MSBuild.dll.config"); + ProjectImportSearchPaths = new [] { MSBuildPath, Path.Combine (mono, "xbuild") }; + SystemProfiles = Path.Combine (mono, "xbuild-frameworks"); + XABuildConfig = Path.Combine (XABuildDirectory, "MSBuild.dll.config"); + SearchPathsOS = IsMacOS ? "osx" : "unix"; + } + + FrameworksDirectory = Path.Combine (prefix, "xbuild-frameworks"); + MSBuildExtensionsPath = Path.Combine (prefix, "xbuild"); + MonoAndroidToolsDirectory = Path.Combine (prefix, "xbuild", "Xamarin", "Android"); + AndroidSdkDirectory = Path.Combine (userProfile, "android-toolchain", "sdk"); + AndroidNdkDirectory = Path.Combine (userProfile, "android-toolchain", "ndk"); + } + + [DllImport ("libc")] + static extern int uname (IntPtr buf); + + static bool IsDarwin () + { + IntPtr buf = IntPtr.Zero; + try { + buf = Marshal.AllocHGlobal (8192); + if (uname (buf) == 0) { + string os = Marshal.PtrToStringAnsi (buf); + return os == "Darwin"; + } + } catch { + } finally { + if (buf != IntPtr.Zero) + Marshal.FreeHGlobal (buf); + } + return false; + } + } +} diff --git a/tools/xabuild/packages.config b/tools/xabuild/packages.config new file mode 100644 index 00000000000..3accbcc35a9 --- /dev/null +++ b/tools/xabuild/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tools/xabuild/xabuild.csproj b/tools/xabuild/xabuild.csproj new file mode 100644 index 00000000000..bf618db7ecc --- /dev/null +++ b/tools/xabuild/xabuild.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {B7A457E6-9CB6-43F6-BFD6-14D5397FB98D} + Exe + Xamarin.Android.Build + xabuild + v4.6 + 512 + + <_MSBuildExtension Condition=" '$(OS)' == 'Windows_NT' ">exe + <_MSBuildExtension Condition=" '$(OS)' != 'Windows_NT' ">dll + <_MSBuildToolsPath Condition=" !$(MSBuildToolsPath.Contains('xbuild')) ">$(MSBuildToolsPath) + <_MSBuildToolsPath Condition=" $(MSBuildToolsPath.Contains('xbuild')) ">$([System.IO.Path]::GetFullPath ('$(MSBuildToolsPath)\..\..\..\msbuild\15.0\bin')) + + + x86 + true + full + false + ..\..\bin\Debug\bin + DEBUG;TRACE + prompt + 4 + + + x86 + pdbonly + true + ..\..\bin\Release\bin + TRACE + prompt + 4 + + + + ..\..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll + + + $(_MSBuildToolsPath)\MSBuild.$(_MSBuildExtension) + + + $(_MSBuildToolsPath)\Microsoft.Build.Tasks.Core.dll + + + $(_MSBuildToolsPath)\Microsoft.Build.Utilities.Core.dll + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file