示例#1
0
        public override bool RunTask()
        {
            Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode);

            if (string.IsNullOrEmpty(AndroidEmbedProfilers) && _Debug)
            {
                AndroidEmbedProfilers = "log";
            }

            var outputFiles = new List <string> ();

            uncompressedFileExtensions = UncompressedFileExtensions?.Split(new char [] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries) ?? new string [0];

            existingEntries.Clear();
            ExecuteWithAbi(SupportedAbis, ApkInputPath, ApkOutputPath);
            outputFiles.Add(ApkOutputPath);
            if (CreatePackagePerAbi && SupportedAbis.Length > 1)
            {
                foreach (var abi in SupportedAbis)
                {
                    existingEntries.Clear();
                    var path = Path.GetDirectoryName(ApkOutputPath);
                    var apk  = Path.GetFileNameWithoutExtension(ApkOutputPath);
                    ExecuteWithAbi(new [] { abi }, String.Format("{0}-{1}", ApkInputPath, abi),
                                   Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                    outputFiles.Add(Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                }
            }

            OutputFiles = outputFiles.Select(a => new TaskItem(a)).ToArray();

            Log.LogDebugTaskItems("  [Output] OutputFiles :", OutputFiles);

            return(!Log.HasLoggedErrors);
        }
示例#2
0
        public override bool Execute()
        {
            Log.LogDebugMessage("BuildApk Task");
            Log.LogDebugMessage("  ApkInputPath: {0}", ApkInputPath);
            Log.LogDebugMessage("  ApkOutputPath: {0}", ApkOutputPath);
            Log.LogDebugMessage("  BundleAssemblies: {0}", BundleAssemblies);
            Log.LogDebugTaskItems("  DalvikClasses:", DalvikClasses);
            Log.LogDebugMessage("  SupportedAbis: {0}", SupportedAbis);
            Log.LogDebugMessage("  UseSharedRuntime: {0}", UseSharedRuntime);
            Log.LogDebugMessage("  Debug: {0}", Debug ?? "no");
            Log.LogDebugMessage("  PreferNativeLibrariesWithDebugSymbols: {0}", PreferNativeLibrariesWithDebugSymbols);
            Log.LogDebugMessage("  EmbedAssemblies: {0}", EmbedAssemblies);
            Log.LogDebugMessage("  AndroidSequencePointsMode: {0}", AndroidSequencePointsMode);
            Log.LogDebugMessage("  CreatePackagePerAbi: {0}", CreatePackagePerAbi);
            Log.LogDebugMessage("  UncompressedFileExtensions: {0}", UncompressedFileExtensions);
            Log.LogDebugTaskItems("  ResolvedUserAssemblies:", ResolvedUserAssemblies);
            Log.LogDebugTaskItems("  ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies);
            Log.LogDebugTaskItems("  NativeLibraries:", NativeLibraries);
            Log.LogDebugTaskItems("  AdditionalNativeLibraryReferences:", AdditionalNativeLibraryReferences);
            Log.LogDebugTaskItems("  BundleNativeLibraries:", BundleNativeLibraries);
            Log.LogDebugTaskItems("  JavaSourceFiles:", JavaSourceFiles);
            Log.LogDebugTaskItems("  JavaLibraries:", JavaLibraries);
            Log.LogDebugTaskItems("  LibraryProjectJars:", LibraryProjectJars);
            Log.LogDebugTaskItems("  AdditionalNativeLibraryReferences:", AdditionalNativeLibraryReferences);

            Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode);

            if (string.IsNullOrEmpty(AndroidEmbedProfilers) && _Debug)
            {
                AndroidEmbedProfilers = "log";
            }

            var outputFiles = new List <string> ();

            uncompressedFileExtensions = UncompressedFileExtensions?.Split(new char [] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries) ?? new string [0];

            ExecuteWithAbi(SupportedAbis, ApkInputPath, ApkOutputPath);
            outputFiles.Add(ApkOutputPath);
            if (CreatePackagePerAbi)
            {
                var abis = SupportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (abis.Length > 1)
                {
                    foreach (var abi in abis)
                    {
                        var path = Path.GetDirectoryName(ApkOutputPath);
                        var apk  = Path.GetFileNameWithoutExtension(ApkOutputPath);
                        ExecuteWithAbi(abi, String.Format("{0}-{1}", ApkInputPath, abi),
                                       Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                        outputFiles.Add(Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                    }
                }
            }

            OutputFiles = outputFiles.Select(a => new TaskItem(a)).ToArray();

            Log.LogDebugTaskItems("  [Output] OutputFiles :", OutputFiles);

            return(!Log.HasLoggedErrors);
        }
示例#3
0
        bool DoExecute()
        {
            Log.LogDebugTaskItems("  Targets:", ResolvedAssemblies);

            AotMode aotMode;
            bool    hasValidAotMode = Aot.GetAndroidAotMode(AndroidAotMode, out aotMode);

            if (!hasValidAotMode)
            {
                Log.LogCodedError("XA3002", Properties.Resources.XA3002, AndroidAotMode);
                return(false);
            }

            // Create a directory to move the original non IL-stripped assemblies.
            string assembliesDir = Path.GetDirectoryName(ResolvedAssemblies.First().ItemSpec);
            string nonstripDir   = Path.Combine(assembliesDir, "non-stripped");

            if (!Directory.Exists(nonstripDir))
            {
                Directory.CreateDirectory(nonstripDir);
            }

            var timestampFileDate = File.GetLastWriteTimeUtc(ApkOutputPath.ItemSpec);

            foreach (var assembly in ResolvedAssemblies)
            {
                string assemblyPath = Path.GetFullPath(assembly.ItemSpec);
                string nonstripPath = Path.Combine(nonstripDir, Path.GetFileName(assemblyPath));

                Log.LogDebugMessage($"Moving {assemblyPath} to {nonstripPath}");

                var srcmodifiedDate = File.GetLastWriteTimeUtc(assemblyPath);

                if (srcmodifiedDate < timestampFileDate)
                {
                    Log.LogDebugMessage($"Skipping strip of IL for {assembly.ItemSpec}. Assembly has already been stripped.");
                    continue;
                }

                File.Copy(assemblyPath, nonstripPath, overwrite: true);

                if (!RunCilStrip(nonstripPath, assemblyPath))
                {
                    Log.LogCodedError("XA3003", Properties.Resources.XA3003, assembly.ItemSpec);
                    return(false);
                }
            }

            return(true);
        }
示例#4
0
        public override bool RunTask()
        {
            Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode);

            var outputFiles = new List <string> ();

            uncompressedFileExtensions = UncompressedFileExtensions?.Split(new char [] { ';', ',' }, StringSplitOptions.RemoveEmptyEntries) ?? new string [0];

            existingEntries.Clear();

            bool debug    = _Debug;
            bool compress = !debug && EnableCompression;
            IDictionary <string, CompressedAssemblyInfo> compressedAssembliesInfo = null;

            if (compress)
            {
                string key = CompressedAssemblyInfo.GetKey(ProjectFullPath);
                Log.LogDebugMessage($"Retrieving assembly compression info with key '{key}'");
                compressedAssembliesInfo = BuildEngine4.UnregisterTaskObjectAssemblyLocal <IDictionary <string, CompressedAssemblyInfo> > (key, RegisteredTaskObjectLifetime.Build);
                if (compressedAssembliesInfo == null)
                {
                    throw new InvalidOperationException($"Assembly compression info not found for key '{key}'. Compression will not be performed.");
                }
            }

            ExecuteWithAbi(SupportedAbis, ApkInputPath, ApkOutputPath, debug, compress, compressedAssembliesInfo);
            outputFiles.Add(ApkOutputPath);
            if (CreatePackagePerAbi && SupportedAbis.Length > 1)
            {
                foreach (var abi in SupportedAbis)
                {
                    existingEntries.Clear();
                    var path = Path.GetDirectoryName(ApkOutputPath);
                    var apk  = Path.GetFileNameWithoutExtension(ApkOutputPath);
                    ExecuteWithAbi(new [] { abi }, String.Format("{0}-{1}", ApkInputPath, abi),
                                   Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)),
                                   debug, compress, compressedAssembliesInfo);
                    outputFiles.Add(Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                }
            }

            OutputFiles = outputFiles.Select(a => new TaskItem(a)).ToArray();

            Log.LogDebugTaskItems("  [Output] OutputFiles :", OutputFiles);

            return(!Log.HasLoggedErrors);
        }
示例#5
0
        bool DoExecute()
        {
            Log.LogDebugTaskItems("  Targets:", ResolvedAssemblies);

            AotMode aotMode;
            bool    hasValidAotMode = Aot.GetAndroidAotMode(AndroidAotMode, out aotMode);

            if (!hasValidAotMode)
            {
                Log.LogCodedError("XA3001", "Invalid AOT mode: {0}", AndroidAotMode);
                return(false);
            }

            // Create a directory to move the original non IL-stripped assemblies.
            string assembliesDir = Path.GetDirectoryName(ResolvedAssemblies.First().ItemSpec);
            string nonstripDir   = Path.Combine(assembliesDir, "non-stripped");

            if (!Directory.Exists(nonstripDir))
            {
                Directory.CreateDirectory(nonstripDir);
            }

            foreach (var assembly in ResolvedAssemblies)
            {
                string assemblyPath = Path.GetFullPath(assembly.ItemSpec);
                string nonstripPath = Path.Combine(nonstripDir, Path.GetFileName(assemblyPath));

                File.Move(assemblyPath, nonstripPath);

                if (!RunCilStrip(nonstripPath, assemblyPath))
                {
                    Log.LogCodedError("XA3001", "Could not strip IL of assembly: {0}", assembly.ItemSpec);
                    return(false);
                }
            }

            return(true);
        }
        public override bool RunTask()
        {
            string toolsZipAlignPath = Path.Combine(AndroidSdkPath, "tools", ZipAlign);
            bool   findZipAlign      = (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath)) && !File.Exists(toolsZipAlignPath);

            var commandLineToolsDir = MonoAndroidHelper.AndroidSdk.GetCommandLineToolsPaths(CommandLineToolsVersion)
                                      .FirstOrDefault() ?? "";

            var lintPaths = new string [] {
                LintToolPath ?? string.Empty,
                commandLineToolsDir,
                Path.Combine(commandLineToolsDir, "bin"),
                Path.Combine(AndroidSdkPath, "tools"),
                Path.Combine(AndroidSdkPath, "tools", "bin"),
            };

            LintToolPath = null;
            foreach (var path in lintPaths)
            {
                if (File.Exists(Path.Combine(path, Lint)))
                {
                    LintToolPath = path;
                    break;
                }
            }

            foreach (var dir in MonoAndroidHelper.AndroidSdk.GetBuildToolsPaths(AndroidSdkBuildToolsVersion))
            {
                Log.LogDebugMessage("Trying build-tools path: {0}", dir);
                if (dir == null || !Directory.Exists(dir))
                {
                    continue;
                }

                var toolsPaths = new string [] {
                    Path.Combine(dir),
                    Path.Combine(dir, "bin"),
                };

                string aapt = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, Aapt)));
                if (string.IsNullOrEmpty(aapt))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", Aapt,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, Aapt))));
                    continue;
                }
                AndroidSdkBuildToolsPath    = Path.GetFullPath(dir);
                AndroidSdkBuildToolsBinPath = Path.GetFullPath(aapt);

                string zipalign = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, ZipAlign)));
                if (findZipAlign && string.IsNullOrEmpty(zipalign))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", ZipAlign,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, ZipAlign))));
                    continue;
                }
                else
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(AndroidSdkBuildToolsPath))
            {
                Log.LogCodedError("XA5205", Properties.Resources.XA5205,
                                  Aapt, AndroidSdkPath, Path.DirectorySeparatorChar, Android);
                return(false);
            }

            ApkSignerJar        = Path.Combine(AndroidSdkBuildToolsBinPath, "lib", ApkSigner);
            AndroidUseApkSigner = File.Exists(ApkSignerJar);

            if (string.IsNullOrEmpty(Aapt2ToolPath))
            {
                var osBinPath = MonoAndroidHelper.GetOSBinPath();
                var aapt2     = Path.Combine(osBinPath, Aapt2);
                if (File.Exists(aapt2))
                {
                    Aapt2ToolPath = osBinPath;
                }
            }

            bool aapt2Installed = !string.IsNullOrEmpty(Aapt2ToolPath) && File.Exists(Path.Combine(Aapt2ToolPath, Aapt2));

            if (aapt2Installed && AndroidUseAapt2)
            {
                if (!GetAapt2Version())
                {
                    AndroidUseAapt2 = false;
                    aapt2Installed  = false;
                    Log.LogCodedWarning("XA0111", Properties.Resources.XA0111);
                }
            }
            if (AndroidUseAapt2)
            {
                if (!aapt2Installed)
                {
                    AndroidUseAapt2 = false;
                    Log.LogCodedWarning("XA0112", Properties.Resources.XA0112);
                }
            }

            if (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath))
            {
                ZipAlignPath = new [] {
                    Path.Combine(AndroidSdkBuildToolsPath),
                    Path.Combine(AndroidSdkBuildToolsBinPath),
                    Path.Combine(AndroidSdkPath, "tools"),
                }
                .Where(p => File.Exists(Path.Combine(p, ZipAlign)))
                .FirstOrDefault();
            }
            if (string.IsNullOrEmpty(ZipAlignPath))
            {
                Log.LogCodedError("XA5205", Properties.Resources.XA5205,
                                  ZipAlign, AndroidSdkPath, Path.DirectorySeparatorChar, Android);
                return(false);
            }

            if (!Validate())
            {
                return(false);
            }

            SequencePointsMode mode;

            if (!Aot.TryGetSequencePointsMode(SequencePointsMode ?? "None", out mode))
            {
                Log.LogCodedError("XA0104", Properties.Resources.XA0104, SequencePointsMode);
            }
            AndroidSequencePointsMode = mode.ToString();

            AndroidApiLevelName = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel(AndroidApiLevel);

            LogOutputs();

            return(!Log.HasLoggedErrors);
        }
示例#7
0
        public override bool RunTask()
        {
            string toolsZipAlignPath = Path.Combine(AndroidSdkPath, "tools", ZipAlign);
            bool   findZipAlign      = (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath)) && !File.Exists(toolsZipAlignPath);

            var lintPaths = new string [] {
                LintToolPath ?? string.Empty,
                Path.Combine(AndroidSdkPath, "tools"),
                Path.Combine(AndroidSdkPath, "tools", "bin"),
            };

            LintToolPath = null;
            foreach (var path in lintPaths)
            {
                if (File.Exists(Path.Combine(path, Lint)))
                {
                    LintToolPath = path;
                    break;
                }
            }

            foreach (var dir in MonoAndroidHelper.AndroidSdk.GetBuildToolsPaths(AndroidSdkBuildToolsVersion))
            {
                Log.LogDebugMessage("Trying build-tools path: {0}", dir);
                if (dir == null || !Directory.Exists(dir))
                {
                    continue;
                }

                var toolsPaths = new string [] {
                    Path.Combine(dir),
                    Path.Combine(dir, "bin"),
                };

                string aapt = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, Aapt)));
                if (string.IsNullOrEmpty(aapt))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", Aapt,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, Aapt))));
                    continue;
                }
                AndroidSdkBuildToolsPath    = Path.GetFullPath(dir);
                AndroidSdkBuildToolsBinPath = Path.GetFullPath(aapt);

                string zipalign = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, ZipAlign)));
                if (findZipAlign && string.IsNullOrEmpty(zipalign))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", ZipAlign,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, ZipAlign))));
                    continue;
                }
                else
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(AndroidSdkBuildToolsPath))
            {
                Log.LogCodedError("XA5205", Properties.Resources.XA5205,
                                  Aapt, AndroidSdkPath, Path.DirectorySeparatorChar, Android);
                return(false);
            }

            ApkSignerJar        = Path.Combine(AndroidSdkBuildToolsBinPath, "lib", ApkSigner);
            AndroidUseApkSigner = File.Exists(ApkSignerJar);

            if (string.IsNullOrEmpty(Aapt2ToolPath))
            {
                var osBinPath = MonoAndroidHelper.GetOSBinPath();
                var aapt2     = Path.Combine(osBinPath, Aapt2);
                if (File.Exists(aapt2))
                {
                    Aapt2ToolPath = osBinPath;
                }
            }

            bool aapt2Installed = !string.IsNullOrEmpty(Aapt2ToolPath) && File.Exists(Path.Combine(Aapt2ToolPath, Aapt2));

            if (aapt2Installed && AndroidUseAapt2)
            {
                if (!GetAapt2Version())
                {
                    AndroidUseAapt2 = false;
                    aapt2Installed  = false;
                    Log.LogCodedWarning("XA0111", Properties.Resources.XA0111);
                }
            }
            if (AndroidUseAapt2)
            {
                if (!aapt2Installed)
                {
                    AndroidUseAapt2 = false;
                    Log.LogCodedWarning("XA0112", Properties.Resources.XA0112);
                }
            }

            if (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath))
            {
                ZipAlignPath = new [] {
                    Path.Combine(AndroidSdkBuildToolsPath),
                    Path.Combine(AndroidSdkBuildToolsBinPath),
                    Path.Combine(AndroidSdkPath, "tools"),
                }
                .Where(p => File.Exists(Path.Combine(p, ZipAlign)))
                .FirstOrDefault();
            }
            if (string.IsNullOrEmpty(ZipAlignPath))
            {
                Log.LogCodedError("XA5205", Properties.Resources.XA5205,
                                  ZipAlign, AndroidSdkPath, Path.DirectorySeparatorChar, Android);
                return(false);
            }

            if (!ValidateApiLevels())
            {
                return(false);
            }

            if (!MonoAndroidHelper.SupportedVersions.FrameworkDirectories.Any(p => Directory.Exists(Path.Combine(p, TargetFrameworkVersion))))
            {
                Log.LogError(
                    subcategory: string.Empty,
                    errorCode: "XA0001",
                    helpKeyword: string.Empty,
                    file: ProjectFilePath,
                    lineNumber: 0,
                    columnNumber: 0,
                    endLineNumber: 0,
                    endColumnNumber: 0,
                    message: Properties.Resources.XA0001,
                    messageArgs: new [] {
                    TargetFrameworkVersion,
                }
                    );
                return(false);
            }

            int apiLevel;

            if (AndroidApplication && int.TryParse(AndroidApiLevel, out apiLevel))
            {
                if (apiLevel < 26)
                {
                    Log.LogCodedWarning("XA0113", Properties.Resources.XA0113, TargetFrameworkVersion, AndroidApiLevel);
                }
                if (apiLevel < 19)
                {
                    Log.LogCodedWarning("XA0117", Properties.Resources.XA0117, TargetFrameworkVersion);
                }
            }

            SequencePointsMode mode;

            if (!Aot.TryGetSequencePointsMode(SequencePointsMode ?? "None", out mode))
            {
                Log.LogCodedError("XA0104", Properties.Resources.XA0104, SequencePointsMode);
            }
            AndroidSequencePointsMode = mode.ToString();

            AndroidApiLevelName = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel(AndroidApiLevel);

            Log.LogDebugMessage($"{nameof (ResolveAndroidTooling)} Outputs:");
            Log.LogDebugMessage($"  {nameof (TargetFrameworkVersion)}: {TargetFrameworkVersion}");
            Log.LogDebugMessage($"  {nameof (AndroidApiLevel)}: {AndroidApiLevel}");
            Log.LogDebugMessage($"  {nameof (AndroidApiLevelName)}: {AndroidApiLevelName}");
            Log.LogDebugMessage($"  {nameof (AndroidSdkBuildToolsPath)}: {AndroidSdkBuildToolsPath}");
            Log.LogDebugMessage($"  {nameof (AndroidSdkBuildToolsBinPath)}: {AndroidSdkBuildToolsBinPath}");
            Log.LogDebugMessage($"  {nameof (ZipAlignPath)}: {ZipAlignPath}");
            Log.LogDebugMessage($"  {nameof (AndroidSequencePointsMode)}: {AndroidSequencePointsMode}");
            Log.LogDebugMessage($"  {nameof (LintToolPath)}: {LintToolPath}");
            Log.LogDebugMessage($"  {nameof (ApkSignerJar)}: {ApkSignerJar}");
            Log.LogDebugMessage($"  {nameof (AndroidUseApkSigner)}: {AndroidUseApkSigner}");
            Log.LogDebugMessage($"  {nameof (AndroidUseAapt2)}: {AndroidUseAapt2}");
            Log.LogDebugMessage($"  {nameof (Aapt2Version)}: {Aapt2Version}");

            return(!Log.HasLoggedErrors);
        }
示例#8
0
        void AddEnvironment(ZipArchive apk)
        {
            var environment = new StringWriter()
            {
                NewLine = "\n",
            };

            if (EnableLLVM)
            {
                environment.WriteLine("mono.llvm=true");
            }

            AotMode aotMode;

            if (AndroidAotMode != null && Aot.GetAndroidAotMode(AndroidAotMode, out aotMode))
            {
                environment.WriteLine("mono.aot={0}", aotMode.ToString().ToLowerInvariant());
            }

            const string defaultLogLevel           = "MONO_LOG_LEVEL=info";
            const string defaultMonoDebug          = "MONO_DEBUG=gen-compact-seq-points";
            const string defaultHttpMessageHandler = "XA_HTTP_CLIENT_HANDLER_TYPE=Xamarin.Android.Net.AndroidClientHandler";
            string       xamarinBuildId            = string.Format("XAMARIN_BUILD_ID={0}", buildId);

            if (Environments == null)
            {
                if (_Debug)
                {
                    environment.WriteLine(defaultLogLevel);
                }
                if (sequencePointsMode != SequencePointsMode.None)
                {
                    environment.WriteLine(defaultMonoDebug);
                }
                environment.WriteLine(xamarinBuildId);
                apk.AddEntry("environment", environment.ToString(),
                             new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
                return;
            }

            bool haveLogLevel           = false;
            bool haveMonoDebug          = false;
            bool havebuildId            = false;
            bool haveHttpMessageHandler = false;

            foreach (ITaskItem env in Environments)
            {
                environment.WriteLine("## Source File: {0}", env.ItemSpec);
                foreach (string line in File.ReadLines(env.ItemSpec))
                {
                    var lineToWrite = line;
                    if (lineToWrite.StartsWith("MONO_LOG_LEVEL=", StringComparison.Ordinal))
                    {
                        haveLogLevel = true;
                    }
                    if (lineToWrite.StartsWith("XAMARIN_BUILD_ID=", StringComparison.Ordinal))
                    {
                        havebuildId = true;
                    }
                    if (lineToWrite.StartsWith("MONO_DEBUG=", StringComparison.Ordinal))
                    {
                        haveMonoDebug = true;
                        if (sequencePointsMode != SequencePointsMode.None && !lineToWrite.Contains("gen-compact-seq-points"))
                        {
                            lineToWrite = line + ",gen-compact-seq-points";
                        }
                    }
                    if (lineToWrite.StartsWith("XA_HTTP_CLIENT_HANDLER_TYPE=", StringComparison.Ordinal))
                    {
                        haveHttpMessageHandler = true;
                    }
                    environment.WriteLine(lineToWrite);
                }
            }

            if (_Debug && !haveLogLevel)
            {
                environment.WriteLine(defaultLogLevel);
            }

            if (sequencePointsMode != SequencePointsMode.None && !haveMonoDebug)
            {
                environment.WriteLine(defaultMonoDebug);
            }

            if (!havebuildId)
            {
                environment.WriteLine(xamarinBuildId);
            }

            if (!haveHttpMessageHandler)
            {
                environment.WriteLine(HttpClientHandlerType == null ? defaultHttpMessageHandler : $"XA_HTTP_CLIENT_HANDLER_TYPE={HttpClientHandlerType.Trim ()}");
            }

            apk.AddEntry("environment", environment.ToString(),
                         new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
        }
示例#9
0
        public override bool Execute()
        {
            Log.LogDebugMessage("BuildApk Task");
            Log.LogDebugMessage("  ApkInputPath: {0}", ApkInputPath);
            Log.LogDebugMessage("  ApkOutputPath: {0}", ApkOutputPath);
            Log.LogDebugMessage("  BundleAssemblies: {0}", BundleAssemblies);
            Log.LogDebugTaskItems("  DalvikClasses:", DalvikClasses);
            Log.LogDebugMessage("  SupportedAbis: {0}", SupportedAbis);
            Log.LogDebugMessage("  UseSharedRuntime: {0}", UseSharedRuntime);
            Log.LogDebugMessage("  Debug: {0}", Debug ?? "no");
            Log.LogDebugMessage("  EmbedAssemblies: {0}", EmbedAssemblies);
            Log.LogDebugMessage("  AndroidAotMode: {0}", AndroidAotMode);
            Log.LogDebugMessage("  AndroidSequencePointsMode: {0}", AndroidSequencePointsMode);
            Log.LogDebugMessage("  CreatePackagePerAbi: {0}", CreatePackagePerAbi);
            Log.LogDebugTaskItems("  Environments:", Environments);
            Log.LogDebugTaskItems("  ResolvedUserAssemblies:", ResolvedUserAssemblies);
            Log.LogDebugTaskItems("  ResolvedFrameworkAssemblies:", ResolvedFrameworkAssemblies);
            Log.LogDebugTaskItems("  NativeLibraries:", NativeLibraries);
            Log.LogDebugTaskItems("  AdditionalNativeLibraryReferences:", AdditionalNativeLibraryReferences);
            Log.LogDebugTaskItems("  BundleNativeLibraries:", BundleNativeLibraries);
            Log.LogDebugTaskItems("  JavaSourceFiles:", JavaSourceFiles);
            Log.LogDebugTaskItems("  JavaLibraries:", JavaLibraries);
            Log.LogDebugTaskItems("  LibraryProjectJars:", LibraryProjectJars);
            Log.LogDebugTaskItems("  AdditionalNativeLibraryReferences:", AdditionalNativeLibraryReferences);
            Log.LogDebugTaskItems("  HttpClientHandlerType:", HttpClientHandlerType);

            Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode);

            var androidDebugServer = GdbPaths.GetAndroidDebugServer(AndroidGdbDebugServer);

            if (!androidDebugServer.HasValue)
            {
                Log.LogError("Unable to determine debug server variant: {0}", AndroidGdbDebugServer);
                return(false);
            }
            debugServer = androidDebugServer.Value;

            if (string.IsNullOrEmpty(AndroidEmbedProfilers) && _Debug)
            {
                AndroidEmbedProfilers = "log";
            }

            var outputFiles = new List <string> ();

            ExecuteWithAbi(SupportedAbis, ApkInputPath, ApkOutputPath);
            outputFiles.Add(ApkOutputPath);
            if (CreatePackagePerAbi)
            {
                var abis = SupportedAbis.Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
                if (abis.Length > 1)
                {
                    foreach (var abi in abis)
                    {
                        var path = Path.GetDirectoryName(ApkOutputPath);
                        var apk  = Path.GetFileNameWithoutExtension(ApkOutputPath);
                        ExecuteWithAbi(abi, String.Format("{0}-{1}", ApkInputPath, abi),
                                       Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                        outputFiles.Add(Path.Combine(path, String.Format("{0}-{1}.apk", apk, abi)));
                    }
                }
            }

            BuildId = buildId.ToString();

            Log.LogDebugMessage("  [Output] BuildId: {0}", BuildId);

            OutputFiles = outputFiles.Select(a => new TaskItem(a)).ToArray();

            Log.LogDebugTaskItems("  [Output] OutputFiles :", OutputFiles);

            return(!Log.HasLoggedErrors);
        }
        public bool RunTask()
        {
            Log.LogDebugMessage("ResolveSdksTask:");
            Log.LogDebugMessage("  AndroidApiLevel: {0}", AndroidApiLevel);
            Log.LogDebugMessage("  AndroidSdkBuildToolsVersion: {0}", AndroidSdkBuildToolsVersion);
            Log.LogDebugMessage($"  {nameof (AndroidSdkPath)}: {AndroidSdkPath}");
            Log.LogDebugMessage($"  {nameof (AndroidNdkPath)}: {AndroidNdkPath}");
            Log.LogDebugMessage($"  {nameof (JavaSdkPath)}: {JavaSdkPath}");
            Log.LogDebugTaskItems("  ReferenceAssemblyPaths: ", ReferenceAssemblyPaths);
            Log.LogDebugMessage("  TargetFrameworkVersion: {0}", TargetFrameworkVersion);
            Log.LogDebugMessage("  UseLatestAndroidPlatformSdk: {0}", UseLatestAndroidPlatformSdk);
            Log.LogDebugMessage("  SequencePointsMode: {0}", SequencePointsMode);
            Log.LogDebugMessage("  LintToolPath: {0}", LintToolPath);

            // OS X:    $prefix/lib/xamarin.android/xbuild/Xamarin/Android
            // Windows: %ProgramFiles(x86)%\MSBuild\Xamarin\Android
            if (string.IsNullOrEmpty(MonoAndroidToolsPath))
            {
                MonoAndroidToolsPath = Path.GetDirectoryName(typeof(ResolveSdks).Assembly.Location);
            }
            MonoAndroidBinPath = MonoAndroidHelper.GetOSBinPath() + Path.DirectorySeparatorChar;

            MonoAndroidHelper.RefreshSupportedVersions(ReferenceAssemblyPaths);
            MonoAndroidHelper.RefreshAndroidSdk(AndroidSdkPath, AndroidNdkPath, JavaSdkPath);

            this.AndroidNdkPath = MonoAndroidHelper.AndroidSdk.AndroidNdkPath;
            this.AndroidSdkPath = MonoAndroidHelper.AndroidSdk.AndroidSdkPath;
            this.JavaSdkPath    = MonoAndroidHelper.AndroidSdk.JavaSdkPath;

            if (!ValidateJavaVersion(TargetFrameworkVersion, AndroidSdkBuildToolsVersion))
            {
                return(false);
            }

            if (string.IsNullOrEmpty(AndroidSdkPath))
            {
                Log.LogCodedError("XA5205", "The Android SDK Directory could not be found. Please set via /p:AndroidSdkDirectory.");
                return(false);
            }

            string toolsZipAlignPath = Path.Combine(AndroidSdkPath, "tools", ZipAlign);
            bool   findZipAlign      = (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath)) && !File.Exists(toolsZipAlignPath);

            var lintPaths = new string [] {
                LintToolPath ?? string.Empty,
                Path.Combine(AndroidSdkPath, "tools"),
                Path.Combine(AndroidSdkPath, "tools", "bin"),
            };

            LintToolPath = null;
            foreach (var path in lintPaths)
            {
                if (File.Exists(Path.Combine(path, Lint)))
                {
                    LintToolPath = path;
                    break;
                }
            }

            foreach (var dir in MonoAndroidHelper.AndroidSdk.GetBuildToolsPaths(AndroidSdkBuildToolsVersion))
            {
                Log.LogDebugMessage("Trying build-tools path: {0}", dir);
                if (dir == null || !Directory.Exists(dir))
                {
                    continue;
                }

                var toolsPaths = new string[] {
                    Path.Combine(dir),
                    Path.Combine(dir, "bin"),
                };

                string aapt = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, Aapt)));
                if (string.IsNullOrEmpty(aapt))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", Aapt,
                                        string.Join(";", toolsPaths.Select(x => Path.Combine(x, Aapt))));
                    continue;
                }
                AndroidSdkBuildToolsPath    = Path.GetFullPath(dir);
                AndroidSdkBuildToolsBinPath = Path.GetFullPath(aapt);

                string zipalign = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, ZipAlign)));
                if (findZipAlign && string.IsNullOrEmpty(zipalign))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", ZipAlign,
                                        string.Join(";", toolsPaths.Select(x => Path.Combine(x, ZipAlign))));
                    continue;
                }
                else
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(AndroidSdkBuildToolsPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      Aapt, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            ApkSignerJar        = Path.Combine(AndroidSdkBuildToolsBinPath, "lib", ApkSigner);
            AndroidUseApkSigner = File.Exists(ApkSignerJar);

            if (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath))
            {
                ZipAlignPath = new[] {
                    Path.Combine(AndroidSdkBuildToolsPath),
                    Path.Combine(AndroidSdkBuildToolsBinPath),
                    Path.Combine(AndroidSdkPath, "tools"),
                }
                .Where(p => File.Exists(Path.Combine(p, ZipAlign)))
                .FirstOrDefault();
            }
            if (string.IsNullOrEmpty(ZipAlignPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      ZipAlign, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            if (!ValidateApiLevels())
            {
                return(false);
            }

            if (!MonoAndroidHelper.SupportedVersions.FrameworkDirectories.Any(p => Directory.Exists(Path.Combine(p, TargetFrameworkVersion))))
            {
                Log.LogError(
                    subcategory:      string.Empty,
                    errorCode:        "XA0001",
                    helpKeyword:      string.Empty,
                    file:             ProjectFilePath,
                    lineNumber:       0,
                    columnNumber:     0,
                    endLineNumber:    0,
                    endColumnNumber:  0,
                    message:          "Unsupported or invalid $(TargetFrameworkVersion) value of '{0}'. Please update your Project Options.",
                    messageArgs:      new[] {
                    TargetFrameworkVersion,
                }
                    );
                return(false);
            }

            SequencePointsMode mode;

            if (!Aot.TryGetSequencePointsMode(SequencePointsMode ?? "None", out mode))
            {
                Log.LogCodedError("XA0104", "Invalid Sequence Point mode: {0}", SequencePointsMode);
            }
            AndroidSequencePointsMode = mode.ToString();

            MonoAndroidHelper.TargetFrameworkDirectories = ReferenceAssemblyPaths;

            AndroidApiLevelName = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel(AndroidApiLevel);

            Log.LogDebugMessage("ResolveSdksTask Outputs:");
            Log.LogDebugMessage("  AndroidApiLevel: {0}", AndroidApiLevel);
            Log.LogDebugMessage("  AndroidApiLevelName: {0}", AndroidApiLevelName);
            Log.LogDebugMessage("  AndroidNdkPath: {0}", AndroidNdkPath);
            Log.LogDebugMessage("  AndroidSdkBuildToolsPath: {0}", AndroidSdkBuildToolsPath);
            Log.LogDebugMessage("  AndroidSdkBuildToolsBinPath: {0}", AndroidSdkBuildToolsBinPath);
            Log.LogDebugMessage("  AndroidSdkPath: {0}", AndroidSdkPath);
            Log.LogDebugMessage("  JavaSdkPath: {0}", JavaSdkPath);
            Log.LogDebugMessage("  JdkVersion: {0}", JdkVersion);
            Log.LogDebugMessage("  MinimumRequiredJdkVersion: {0}", MinimumRequiredJdkVersion);
            Log.LogDebugMessage("  MonoAndroidBinPath: {0}", MonoAndroidBinPath);
            Log.LogDebugMessage("  MonoAndroidToolsPath: {0}", MonoAndroidToolsPath);
            Log.LogDebugMessage("  TargetFrameworkVersion: {0}", TargetFrameworkVersion);
            Log.LogDebugMessage("  ZipAlignPath: {0}", ZipAlignPath);
            Log.LogDebugMessage("  SupportedApiLevel: {0}", SupportedApiLevel);
            Log.LogDebugMessage("  AndroidSequencePointMode: {0}", AndroidSequencePointsMode);
            Log.LogDebugMessage("  LintToolPath: {0}", LintToolPath);

            if (!string.IsNullOrEmpty(CacheFile))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(CacheFile));

                var document = new XDocument(
                    new XDeclaration("1.0", "UTF-8", null),
                    new XElement("Sdk",
                                 new XElement("AndroidApiLevel", AndroidApiLevel),
                                 new XElement("AndroidApiLevelName", AndroidApiLevelName),
                                 new XElement("AndroidNdkPath", AndroidNdkPath),
                                 new XElement("AndroidSdkBuildToolsPath", AndroidSdkBuildToolsPath),
                                 new XElement("AndroidSdkBuildToolsBinPath", AndroidSdkBuildToolsBinPath),
                                 new XElement("AndroidSdkPath", AndroidSdkPath),
                                 new XElement("JavaSdkPath", JavaSdkPath),
                                 new XElement("MonoAndroidBinPath", MonoAndroidBinPath),
                                 new XElement("MonoAndroidToolsPath", MonoAndroidToolsPath),
                                 new XElement("ReferenceAssemblyPaths",
                                              (ReferenceAssemblyPaths ?? new string [0])
                                              .Select(e => new XElement("ReferenceAssemblyPath", e))),
                                 new XElement("TargetFrameworkVersion", TargetFrameworkVersion),
                                 new XElement("ZipAlignPath", ZipAlignPath),
                                 new XElement("MonoAndroidIncludePath", MonoAndroidIncludePath),
                                 new XElement("SupportedApiLevel", SupportedApiLevel),
                                 new XElement("AndroidSequencePointsMode", AndroidSequencePointsMode.ToString()),
                                 new XElement("LintToolPath", LintToolPath)
                                 ));
                document.Save(CacheFile);
            }

            //note: this task does not error out if it doesn't find all things. that's the job of the targets
            return(!Log.HasLoggedErrors);
        }
示例#11
0
        void AddEnvironment()
        {
            var environment = new StringWriter()
            {
                NewLine = "\n",
            };

            if (EnableLLVM)
            {
                WriteEnvironment("mono.llvm", "true");
            }

            AotMode aotMode;

            if (AndroidAotMode != null && Aot.GetAndroidAotMode(AndroidAotMode, out aotMode))
            {
                WriteEnvironment("mono.aot", aotMode.ToString().ToLowerInvariant());
            }

            bool haveLogLevel           = false;
            bool haveMonoDebug          = false;
            bool havebuildId            = false;
            bool haveHttpMessageHandler = false;
            bool haveTlsProvider        = false;
            bool haveMonoGCParams       = false;

            SequencePointsMode sequencePointsMode;

            if (!Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode))
            {
                sequencePointsMode = SequencePointsMode.None;
            }

            foreach (ITaskItem env in Environments ?? new TaskItem[0])
            {
                environment.WriteLine("\t\t// Source File: {0}", env.ItemSpec);
                foreach (string line in File.ReadLines(env.ItemSpec))
                {
                    var lineToWrite = line;
                    if (lineToWrite.StartsWith("MONO_LOG_LEVEL=", StringComparison.Ordinal))
                    {
                        haveLogLevel = true;
                    }
                    if (lineToWrite.StartsWith("MONO_GC_PARAMS=", StringComparison.Ordinal))
                    {
                        haveMonoGCParams = true;
                    }
                    if (lineToWrite.StartsWith("XAMARIN_BUILD_ID=", StringComparison.Ordinal))
                    {
                        havebuildId = true;
                    }
                    if (lineToWrite.StartsWith("MONO_DEBUG=", StringComparison.Ordinal))
                    {
                        haveMonoDebug = true;
                        if (sequencePointsMode != SequencePointsMode.None && !lineToWrite.Contains("gen-compact-seq-points"))
                        {
                            lineToWrite = line + ",gen-compact-seq-points";
                        }
                    }
                    if (lineToWrite.StartsWith("XA_HTTP_CLIENT_HANDLER_TYPE=", StringComparison.Ordinal))
                    {
                        haveHttpMessageHandler = true;
                    }
                    if (lineToWrite.StartsWith("XA_TLS_PROVIDER=", StringComparison.Ordinal))
                    {
                        haveTlsProvider = true;
                    }
                    WriteEnvironmentLine(lineToWrite);
                }
            }

            if (_Debug && !haveLogLevel)
            {
                WriteEnvironment(defaultLogLevel[0], defaultLogLevel[1]);
            }

            if (sequencePointsMode != SequencePointsMode.None && !haveMonoDebug)
            {
                WriteEnvironment(defaultMonoDebug[0], defaultMonoDebug[1]);
            }

            if (!havebuildId)
            {
                WriteEnvironment("XAMARIN_BUILD_ID", buildId.ToString());
            }

            if (!haveHttpMessageHandler)
            {
                if (HttpClientHandlerType == null)
                {
                    WriteEnvironment(defaultHttpMessageHandler[0], defaultHttpMessageHandler[1]);
                }
                else
                {
                    WriteEnvironment("XA_HTTP_CLIENT_HANDLER_TYPE", HttpClientHandlerType.Trim());
                }
            }

            if (!haveTlsProvider)
            {
                if (TlsProvider == null)
                {
                    WriteEnvironment(defaultTlsProvider[0], defaultTlsProvider[1]);
                }
                else
                {
                    WriteEnvironment("XA_TLS_PROVIDER", TlsProvider.Trim());
                }
            }

            if (!haveMonoGCParams)
            {
                if (EnableSGenConcurrent)
                {
                    WriteEnvironment("MONO_GC_PARAMS", "major=marksweep-conc");
                }
                else
                {
                    WriteEnvironment("MONO_GC_PARAMS", "major=marksweep");
                }
            }

            string environmentTemplate;

            using (var sr = new StreamReader(typeof(BuildApk).Assembly.GetManifestResourceStream(EnvironmentFileName))) {
                environmentTemplate = sr.ReadToEnd();
            }

            using (var ms = new MemoryStream()) {
                using (var sw = new StreamWriter(ms)) {
                    sw.Write(environmentTemplate.Replace("//@ENVVARS@", environment.ToString()));
                    sw.Flush();

                    string dest = Path.GetFullPath(Path.Combine(EnvironmentOutputDirectory, EnvironmentFileName));
                    MonoAndroidHelper.CopyIfStreamChanged(ms, dest);
                }
            }

            void WriteEnvironment(string name, string value)
            {
                environment.WriteLine($"\t\t\"{ValidJavaString (name)}\", \"{ValidJavaString (value)}\",");
            }

            void WriteEnvironmentLine(string line)
            {
                if (String.IsNullOrEmpty(line))
                {
                    return;
                }

                string[] nv = line.Split(new char[] { '=' }, 2);
                WriteEnvironment(nv[0].Trim(), nv.Length < 2 ? String.Empty : nv[1].Trim());
            }

            string ValidJavaString(string s)
            {
                return(s.Replace("\"", "\\\""));
            }
        }
示例#12
0
        public override bool Execute()
        {
            string toolsZipAlignPath = Path.Combine(AndroidSdkPath, "tools", ZipAlign);
            bool   findZipAlign      = (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath)) && !File.Exists(toolsZipAlignPath);

            var lintPaths = new string [] {
                LintToolPath ?? string.Empty,
                Path.Combine(AndroidSdkPath, "tools"),
                Path.Combine(AndroidSdkPath, "tools", "bin"),
            };

            LintToolPath = null;
            foreach (var path in lintPaths)
            {
                if (File.Exists(Path.Combine(path, Lint)))
                {
                    LintToolPath = path;
                    break;
                }
            }

            foreach (var dir in MonoAndroidHelper.AndroidSdk.GetBuildToolsPaths(AndroidSdkBuildToolsVersion))
            {
                Log.LogDebugMessage("Trying build-tools path: {0}", dir);
                if (dir == null || !Directory.Exists(dir))
                {
                    continue;
                }

                var toolsPaths = new string [] {
                    Path.Combine(dir),
                    Path.Combine(dir, "bin"),
                };

                string aapt = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, Aapt)));
                if (string.IsNullOrEmpty(aapt))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", Aapt,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, Aapt))));
                    continue;
                }
                AndroidSdkBuildToolsPath    = Path.GetFullPath(dir);
                AndroidSdkBuildToolsBinPath = Path.GetFullPath(aapt);

                string zipalign = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, ZipAlign)));
                if (findZipAlign && string.IsNullOrEmpty(zipalign))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", ZipAlign,
                                        string.Join(Path.PathSeparator.ToString(), toolsPaths.Select(x => Path.Combine(x, ZipAlign))));
                    continue;
                }
                else
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(AndroidSdkBuildToolsPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      Aapt, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            ApkSignerJar        = Path.Combine(AndroidSdkBuildToolsBinPath, "lib", ApkSigner);
            AndroidUseApkSigner = File.Exists(ApkSignerJar);

            if (string.IsNullOrEmpty(Aapt2ToolPath))
            {
                var osBinPath = MonoAndroidHelper.GetOSBinPath();
                var aapt2     = Path.Combine(osBinPath, Aapt2);
                if (File.Exists(aapt2))
                {
                    Aapt2ToolPath = osBinPath;
                }
            }

            bool aapt2Installed = !string.IsNullOrEmpty(Aapt2ToolPath) && File.Exists(Path.Combine(Aapt2ToolPath, Aapt2));

            if (aapt2Installed && AndroidUseAapt2)
            {
                if (!GetAapt2Version())
                {
                    AndroidUseAapt2 = false;
                    aapt2Installed  = false;
                    Log.LogCodedWarning("XA0111", "Could not get the `aapt2` version. Disabling `aapt2` support. Please check it is installed correctly.");
                }
            }
            if (AndroidUseAapt2)
            {
                if (!aapt2Installed)
                {
                    AndroidUseAapt2 = false;
                    Log.LogCodedWarning("XA0112", "`aapt2` is not installed. Disabling `aapt2` support. Please check it is installed correctly.");
                }
            }

            if (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath))
            {
                ZipAlignPath = new [] {
                    Path.Combine(AndroidSdkBuildToolsPath),
                    Path.Combine(AndroidSdkBuildToolsBinPath),
                    Path.Combine(AndroidSdkPath, "tools"),
                }
                .Where(p => File.Exists(Path.Combine(p, ZipAlign)))
                .FirstOrDefault();
            }
            if (string.IsNullOrEmpty(ZipAlignPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      ZipAlign, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            if (!ValidateApiLevels())
            {
                return(false);
            }

            if (!MonoAndroidHelper.SupportedVersions.FrameworkDirectories.Any(p => Directory.Exists(Path.Combine(p, TargetFrameworkVersion))))
            {
                Log.LogError(
                    subcategory: string.Empty,
                    errorCode: "XA0001",
                    helpKeyword: string.Empty,
                    file: ProjectFilePath,
                    lineNumber: 0,
                    columnNumber: 0,
                    endLineNumber: 0,
                    endColumnNumber: 0,
                    message: "Unsupported or invalid $(TargetFrameworkVersion) value of '{0}'. Please update your Project Options.",
                    messageArgs: new [] {
                    TargetFrameworkVersion,
                }
                    );
                return(false);
            }

            int apiLevel;

            if (AndroidApplication && int.TryParse(AndroidApiLevel, out apiLevel))
            {
                if (apiLevel < 26)
                {
                    Log.LogCodedWarning("XA0113", $"Google Play requires that new applications and updates must use a TargetFrameworkVersion of v8.0 (API level 26) or above. You are currently targeting {TargetFrameworkVersion} (API level {AndroidApiLevel}).");
                }
                if (apiLevel < 19)
                {
                    Log.LogCodedWarning("XA0117", $"The TargetFrameworkVersion {TargetFrameworkVersion} is deprecated. Please update it to be v4.4 or higher.");
                }
            }

            SequencePointsMode mode;

            if (!Aot.TryGetSequencePointsMode(SequencePointsMode ?? "None", out mode))
            {
                Log.LogCodedError("XA0104", "Invalid Sequence Point mode: {0}", SequencePointsMode);
            }
            AndroidSequencePointsMode = mode.ToString();

            AndroidApiLevelName = MonoAndroidHelper.SupportedVersions.GetIdFromApiLevel(AndroidApiLevel);

            Log.LogDebugMessage($"{nameof (ResolveAndroidTooling)} Outputs:");
            Log.LogDebugMessage($"  {nameof (TargetFrameworkVersion)}: {TargetFrameworkVersion}");
            Log.LogDebugMessage($"  {nameof (AndroidApiLevel)}: {AndroidApiLevel}");
            Log.LogDebugMessage($"  {nameof (AndroidApiLevelName)}: {AndroidApiLevelName}");
            Log.LogDebugMessage($"  {nameof (AndroidSdkBuildToolsPath)}: {AndroidSdkBuildToolsPath}");
            Log.LogDebugMessage($"  {nameof (AndroidSdkBuildToolsBinPath)}: {AndroidSdkBuildToolsBinPath}");
            Log.LogDebugMessage($"  {nameof (ZipAlignPath)}: {ZipAlignPath}");
            Log.LogDebugMessage($"  {nameof (AndroidSequencePointsMode)}: {AndroidSequencePointsMode}");
            Log.LogDebugMessage($"  {nameof (LintToolPath)}: {LintToolPath}");
            Log.LogDebugMessage($"  {nameof (ApkSignerJar)}: {ApkSignerJar}");
            Log.LogDebugMessage($"  {nameof (AndroidUseApkSigner)}: {AndroidUseApkSigner}");
            Log.LogDebugMessage($"  {nameof (AndroidUseAapt2)}: {AndroidUseAapt2}");
            Log.LogDebugMessage($"  {nameof (Aapt2Version)}: {Aapt2Version}");

            return(!Log.HasLoggedErrors);
        }
示例#13
0
        public override bool Execute()
        {
            Log.LogDebugMessage("ResolveSdksTask:");
            Log.LogDebugMessage("  AndroidApiLevel: {0}", AndroidApiLevel);
            Log.LogDebugMessage("  AndroidSdkBuildToolsVersion: {0}", AndroidSdkBuildToolsVersion);
            Log.LogDebugTaskItems("  ReferenceAssemblyPaths: ", ReferenceAssemblyPaths);
            Log.LogDebugMessage("  TargetFrameworkVersion: {0}", TargetFrameworkVersion);
            Log.LogDebugMessage("  UseLatestAndroidPlatformSdk: {0}", UseLatestAndroidPlatformSdk);
            Log.LogDebugMessage("  SequencePointsMode: {0}", SequencePointsMode);
            Log.LogDebugMessage("  MonoAndroidToolsPath: {0}", MonoAndroidToolsPath);
            Log.LogDebugMessage("  MonoAndroidBinPath: {0}", MonoAndroidBinPath);

            MonoAndroidHelper.InitializeAndroidLogger(Log);

            MonoAndroidHelper.RefreshAndroidSdk(AndroidSdkPath, AndroidNdkPath, JavaSdkPath);
            MonoAndroidHelper.RefreshMonoDroidSdk(MonoAndroidToolsPath, MonoAndroidBinPath, ReferenceAssemblyPaths);

            // OS X:    $prefix/lib/mandroid
            // Windows: %ProgramFiles(x86)%\MSBuild\Xamarin\Android
            this.MonoAndroidToolsPath = MonoDroidSdk.RuntimePath;

            // OS X:    $prefix/bin
            // Windows: %ProgramFiles(x86)%\MSBuild\Xamarin\Android
            this.MonoAndroidBinPath = MonoDroidSdk.BinPath;

            if (this.MonoAndroidBinPath == null)
            {
                Log.LogCodedError("XA0020", "Could not find mandroid!");
                return(false);
            }

            string include;

            if (MonoAndroidToolsPath != null &&
                Directory.Exists(include = Path.Combine(MonoAndroidToolsPath, "include")))
            {
                MonoAndroidIncludePath = include;
            }

            this.AndroidNdkPath = AndroidSdk.AndroidNdkPath;
            this.AndroidSdkPath = AndroidSdk.AndroidSdkPath;
            this.JavaSdkPath    = AndroidSdk.JavaSdkPath;

            if (string.IsNullOrEmpty(AndroidSdkPath))
            {
                Log.LogCodedError("XA5205", "The Android SDK Directory could not be found. Please set via /p:AndroidSdkDirectory.");
                return(false);
            }

            string toolsZipAlignPath = Path.Combine(AndroidSdkPath, "tools", ZipAlign);
            bool   findZipAlign      = (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath)) && !File.Exists(toolsZipAlignPath);

            foreach (var dir in AndroidSdk.GetBuildToolsPaths(AndroidSdkBuildToolsVersion))
            {
                Log.LogDebugMessage("Trying build-tools path: {0}", dir);
                if (dir == null || !Directory.Exists(dir))
                {
                    continue;
                }

                var toolsPaths = new string[] {
                    Path.Combine(dir),
                    Path.Combine(dir, "bin"),
                };

                string aapt = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, Aapt)));
                if (string.IsNullOrEmpty(aapt))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", Aapt,
                                        string.Join(";", toolsPaths.Select(x => Path.Combine(x, Aapt))));
                    continue;
                }
                AndroidSdkBuildToolsPath    = Path.GetFullPath(dir);
                AndroidSdkBuildToolsBinPath = Path.GetFullPath(aapt);

                string zipalign = toolsPaths.FirstOrDefault(x => File.Exists(Path.Combine(x, ZipAlign)));
                if (findZipAlign && string.IsNullOrEmpty(zipalign))
                {
                    Log.LogDebugMessage("Could not find `{0}`; tried: {1}", ZipAlign,
                                        string.Join(";", toolsPaths.Select(x => Path.Combine(x, ZipAlign))));
                    continue;
                }
                else
                {
                    break;
                }
            }

            if (string.IsNullOrEmpty(AndroidSdkBuildToolsPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      Aapt, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            if (string.IsNullOrEmpty(ZipAlignPath) || !Directory.Exists(ZipAlignPath))
            {
                ZipAlignPath = new[] {
                    Path.Combine(AndroidSdkBuildToolsPath),
                    Path.Combine(AndroidSdkBuildToolsBinPath),
                    Path.Combine(AndroidSdkPath, "tools"),
                }
                .Where(p => File.Exists(Path.Combine(p, ZipAlign)))
                .FirstOrDefault();
            }
            if (string.IsNullOrEmpty(ZipAlignPath))
            {
                Log.LogCodedError("XA5205",
                                  string.Format(
                                      "Cannot find `{0}`. Please install the Android SDK Build-tools package with the `{1}{2}tools{2}{3}` program.",
                                      ZipAlign, AndroidSdkPath, Path.DirectorySeparatorChar, Android));
                return(false);
            }

            if (!ValidateApiLevels())
            {
                return(false);
            }

            string frameworksPath = Path.GetDirectoryName(MonoDroidSdk.FrameworkPath);

            if (!Directory.Exists(Path.Combine(frameworksPath, TargetFrameworkVersion)))
            {
                Log.LogError(
                    subcategory:      string.Empty,
                    errorCode:        "XA0001",
                    helpKeyword:      string.Empty,
                    file:             ProjectFilePath,
                    lineNumber:       0,
                    columnNumber:     0,
                    endLineNumber:    0,
                    endColumnNumber:  0,
                    message:          "Unsupported or invalid $(TargetFrameworkVersion) value of '{0}'. Please update your Project Options.",
                    messageArgs:      new[] {
                    TargetFrameworkVersion,
                }
                    );
                return(false);
            }

            SequencePointsMode mode;

            if (!Aot.TryGetSequencePointsMode(SequencePointsMode ?? "None", out mode))
            {
                Log.LogCodedError("XA0104", "Invalid Sequence Point mode: {0}", SequencePointsMode);
            }
            AndroidSequencePointsMode = mode.ToString();


            AndroidApiLevelName = MonoAndroidHelper.GetPlatformApiLevelName(AndroidApiLevel);

            Log.LogDebugMessage("ResolveSdksTask Outputs:");
            Log.LogDebugMessage("  AndroidApiLevel: {0}", AndroidApiLevel);
            Log.LogDebugMessage("  AndroidApiLevelName: {0}", AndroidApiLevelName);
            Log.LogDebugMessage("  AndroidNdkPath: {0}", AndroidNdkPath);
            Log.LogDebugMessage("  AndroidSdkBuildToolsPath: {0}", AndroidSdkBuildToolsPath);
            Log.LogDebugMessage("  AndroidSdkBuildToolsBinPath: {0}", AndroidSdkBuildToolsBinPath);
            Log.LogDebugMessage("  AndroidSdkPath: {0}", AndroidSdkPath);
            Log.LogDebugMessage("  JavaSdkPath: {0}", JavaSdkPath);
            Log.LogDebugMessage("  MonoAndroidBinPath: {0}", MonoAndroidBinPath);
            Log.LogDebugMessage("  MonoAndroidToolsPath: {0}", MonoAndroidToolsPath);
            Log.LogDebugMessage("  MonoAndroidIncludePath: {0}", MonoAndroidIncludePath);
            Log.LogDebugMessage("  TargetFrameworkVersion: {0}", TargetFrameworkVersion);
            Log.LogDebugMessage("  ZipAlignPath: {0}", ZipAlignPath);
            Log.LogDebugMessage("  SupportedApiLevel: {0}", SupportedApiLevel);
            Log.LogDebugMessage("  AndroidSequencePointMode: {0}", AndroidSequencePointsMode);

            if (!string.IsNullOrEmpty(CacheFile))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(CacheFile));

                var document = new XDocument(
                    new XDeclaration("1.0", "UTF-8", null),
                    new XElement("Sdk",
                                 new XElement("AndroidApiLevel", AndroidApiLevel),
                                 new XElement("AndroidApiLevelName", AndroidApiLevelName),
                                 new XElement("AndroidNdkPath", AndroidNdkPath),
                                 new XElement("AndroidSdkBuildToolsPath", AndroidSdkBuildToolsPath),
                                 new XElement("AndroidSdkBuildToolsBinPath", AndroidSdkBuildToolsBinPath),
                                 new XElement("AndroidSdkPath", AndroidSdkPath),
                                 new XElement("JavaSdkPath", JavaSdkPath),
                                 new XElement("MonoAndroidBinPath", MonoAndroidBinPath),
                                 new XElement("MonoAndroidToolsPath", MonoAndroidToolsPath),
                                 new XElement("ReferenceAssemblyPaths",
                                              (ReferenceAssemblyPaths ?? new string [0])
                                              .Select(e => new XElement("ReferenceAssemblyPath", e))),
                                 new XElement("TargetFrameworkVersion", TargetFrameworkVersion),
                                 new XElement("ZipAlignPath", ZipAlignPath),
                                 new XElement("MonoAndroidIncludePath", MonoAndroidIncludePath),
                                 new XElement("SupportedApiLevel", SupportedApiLevel),
                                 new XElement("AndroidSequencePointsMode", AndroidSequencePointsMode.ToString())
                                 ));
                document.Save(CacheFile);
            }

            //note: this task does not error out if it doesn't find all things. that's the job of the targets
            return(!Log.HasLoggedErrors);
        }
        void AddEnvironment()
        {
            bool   usesMonoAOT          = false;
            bool   usesAssemblyPreload  = EnablePreloadAssembliesDefault;
            uint   monoAOTMode          = 0;
            string androidPackageName   = null;
            var    environmentVariables = new Dictionary <string, string> (StringComparer.Ordinal);
            var    systemProperties     = new Dictionary <string, string> (StringComparer.Ordinal);

            AotMode aotMode;

            if (AndroidAotMode != null && Aot.GetAndroidAotMode(AndroidAotMode, out aotMode))
            {
                usesMonoAOT = true;
                monoAOTMode = (uint)aotMode;
            }

            bool haveLogLevel           = false;
            bool haveMonoDebug          = false;
            bool havebuildId            = false;
            bool haveHttpMessageHandler = false;
            bool haveTlsProvider        = false;
            bool haveMonoGCParams       = false;

            SequencePointsMode sequencePointsMode;

            if (!Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode))
            {
                sequencePointsMode = SequencePointsMode.None;
            }

            foreach (ITaskItem env in Environments ?? new TaskItem[0])
            {
                foreach (string line in File.ReadLines(env.ItemSpec))
                {
                    var lineToWrite = line;
                    if (lineToWrite.StartsWith("MONO_LOG_LEVEL=", StringComparison.Ordinal))
                    {
                        haveLogLevel = true;
                    }
                    if (lineToWrite.StartsWith("MONO_GC_PARAMS=", StringComparison.Ordinal))
                    {
                        haveMonoGCParams = true;
                    }
                    if (lineToWrite.StartsWith("XAMARIN_BUILD_ID=", StringComparison.Ordinal))
                    {
                        havebuildId = true;
                    }
                    if (lineToWrite.StartsWith("MONO_DEBUG=", StringComparison.Ordinal))
                    {
                        haveMonoDebug = true;
                        if (sequencePointsMode != SequencePointsMode.None && !lineToWrite.Contains("gen-compact-seq-points"))
                        {
                            lineToWrite = line + ",gen-compact-seq-points";
                        }
                    }
                    if (lineToWrite.StartsWith("XA_HTTP_CLIENT_HANDLER_TYPE=", StringComparison.Ordinal))
                    {
                        haveHttpMessageHandler = true;
                    }
                    if (lineToWrite.StartsWith("XA_TLS_PROVIDER=", StringComparison.Ordinal))
                    {
                        haveTlsProvider = true;
                    }
                    if (lineToWrite.StartsWith("mono.enable_assembly_preload=", StringComparison.Ordinal))
                    {
                        int  idx = lineToWrite.IndexOf('=');
                        uint val;
                        if (idx < lineToWrite.Length - 1 && UInt32.TryParse(lineToWrite.Substring(idx + 1), out val))
                        {
                            usesAssemblyPreload = idx == 1;
                        }
                        continue;
                    }

                    AddEnvironmentVariableLine(lineToWrite);
                }
            }

            if (_Debug && !haveLogLevel)
            {
                AddEnvironmentVariable(defaultLogLevel[0], defaultLogLevel[1]);
            }

            if (sequencePointsMode != SequencePointsMode.None && !haveMonoDebug)
            {
                AddEnvironmentVariable(defaultMonoDebug[0], defaultMonoDebug[1]);
            }

            if (!havebuildId)
            {
                AddEnvironmentVariable("XAMARIN_BUILD_ID", BuildId);
            }

            if (!haveHttpMessageHandler)
            {
                if (HttpClientHandlerType == null)
                {
                    AddEnvironmentVariable(defaultHttpMessageHandler[0], defaultHttpMessageHandler[1]);
                }
                else
                {
                    AddEnvironmentVariable("XA_HTTP_CLIENT_HANDLER_TYPE", HttpClientHandlerType.Trim());
                }
            }

            if (!haveTlsProvider)
            {
                if (TlsProvider == null)
                {
                    AddEnvironmentVariable(defaultTlsProvider[0], defaultTlsProvider[1]);
                }
                else
                {
                    AddEnvironmentVariable("XA_TLS_PROVIDER", TlsProvider.Trim());
                }
            }

            if (!haveMonoGCParams)
            {
                if (EnableSGenConcurrent)
                {
                    AddEnvironmentVariable("MONO_GC_PARAMS", "major=marksweep-conc");
                }
                else
                {
                    AddEnvironmentVariable("MONO_GC_PARAMS", "major=marksweep");
                }
            }

            using (var ms = new MemoryStream()) {
                var utf8Encoding = new UTF8Encoding(false);
                foreach (string abi in SupportedAbis)
                {
                    ms.SetLength(0);
                    NativeAssemblerTargetProvider asmTargetProvider;
                    string asmFileName = Path.Combine(EnvironmentOutputDirectory, $"environment.{abi.ToLowerInvariant ()}.s");
                    switch (abi.Trim())
                    {
                    case "armeabi-v7a":
                        asmTargetProvider = new ARMNativeAssemblerTargetProvider(false);
                        break;

                    case "arm64-v8a":
                        asmTargetProvider = new ARMNativeAssemblerTargetProvider(true);
                        break;

                    case "x86":
                        asmTargetProvider = new X86NativeAssemblerTargetProvider(false);
                        break;

                    case "x86_64":
                        asmTargetProvider = new X86NativeAssemblerTargetProvider(true);
                        break;

                    default:
                        throw new InvalidOperationException($"Unknown ABI {abi}");
                    }

                    var asmgen = new ApplicationConfigNativeAssemblyGenerator(asmTargetProvider, environmentVariables, systemProperties)
                    {
                        IsBundledApp        = IsBundledApplication,
                        UsesMonoAOT         = usesMonoAOT,
                        UsesMonoLLVM        = EnableLLVM,
                        UsesAssemblyPreload = usesAssemblyPreload,
                        MonoAOTMode         = monoAOTMode.ToString().ToLowerInvariant(),
                        AndroidPackageName  = AndroidPackageName,
                    };

                    using (var sw = new StreamWriter(ms, utf8Encoding, bufferSize: 8192, leaveOpen: true)) {
                        asmgen.Write(sw, asmFileName);
                        MonoAndroidHelper.CopyIfStreamChanged(ms, asmFileName);
                    }
                }
            }

            void AddEnvironmentVariable(string name, string value)
            {
                if (Char.IsUpper(name [0]) || !Char.IsLetter(name [0]))
                {
                    environmentVariables [ValidAssemblerString(name)] = ValidAssemblerString(value);
                }
                else
                {
                    systemProperties [ValidAssemblerString(name)] = ValidAssemblerString(value);
                }
            }

            void AddEnvironmentVariableLine(string l)
            {
                string line = l?.Trim();

                if (String.IsNullOrEmpty(line) || line [0] == '#')
                {
                    return;
                }

                string[] nv = line.Split(new char[] { '=' }, 2);
                AddEnvironmentVariable(nv[0].Trim(), nv.Length < 2 ? String.Empty : nv[1].Trim());
            }

            string ValidAssemblerString(string s)
            {
                return(s.Replace("\"", "\\\""));
            }
        }
示例#15
0
        void AddEnvironment()
        {
            bool usesMonoAOT                = false;
            bool usesAssemblyPreload        = EnablePreloadAssembliesDefault;
            bool brokenExceptionTransitions = false;
            var  environmentVariables       = new Dictionary <string, string> (StringComparer.Ordinal);
            var  systemProperties           = new Dictionary <string, string> (StringComparer.Ordinal);

            if (!Enum.TryParse(PackageNamingPolicy, out PackageNamingPolicy pnp))
            {
                pnp = PackageNamingPolicyEnum.LowercaseCrc64;
            }

            AotMode aotMode = AotMode.None;

            if (!string.IsNullOrEmpty(AndroidAotMode) && Aot.GetAndroidAotMode(AndroidAotMode, out aotMode) && aotMode != AotMode.None)
            {
                usesMonoAOT = true;
            }

            bool haveLogLevel           = false;
            bool haveMonoDebug          = false;
            bool havebuildId            = false;
            bool haveHttpMessageHandler = false;
            bool haveTlsProvider        = false;
            bool haveMonoGCParams       = false;

            SequencePointsMode sequencePointsMode;

            if (!Aot.TryGetSequencePointsMode(AndroidSequencePointsMode, out sequencePointsMode))
            {
                sequencePointsMode = SequencePointsMode.None;
            }

            foreach (ITaskItem env in Environments ?? new TaskItem[0])
            {
                foreach (string line in File.ReadLines(env.ItemSpec))
                {
                    var lineToWrite = line;
                    if (lineToWrite.StartsWith("MONO_LOG_LEVEL=", StringComparison.Ordinal))
                    {
                        haveLogLevel = true;
                    }
                    if (lineToWrite.StartsWith("MONO_GC_PARAMS=", StringComparison.Ordinal))
                    {
                        haveMonoGCParams = true;
                    }
                    if (lineToWrite.StartsWith("XAMARIN_BUILD_ID=", StringComparison.Ordinal))
                    {
                        havebuildId = true;
                    }
                    if (lineToWrite.StartsWith("MONO_DEBUG=", StringComparison.Ordinal))
                    {
                        haveMonoDebug = true;
                        if (sequencePointsMode != SequencePointsMode.None && !lineToWrite.Contains("gen-compact-seq-points"))
                        {
                            lineToWrite = line + ",gen-compact-seq-points";
                        }
                    }
                    if (lineToWrite.StartsWith("XA_HTTP_CLIENT_HANDLER_TYPE=", StringComparison.Ordinal))
                    {
                        haveHttpMessageHandler = true;
                    }
                    if (lineToWrite.StartsWith("XA_TLS_PROVIDER=", StringComparison.Ordinal))
                    {
                        haveTlsProvider = true;
                    }
                    if (lineToWrite.StartsWith("mono.enable_assembly_preload=", StringComparison.Ordinal))
                    {
                        int  idx = lineToWrite.IndexOf('=');
                        uint val;
                        if (idx < lineToWrite.Length - 1 && UInt32.TryParse(lineToWrite.Substring(idx + 1), out val))
                        {
                            usesAssemblyPreload = idx == 1;
                        }
                        continue;
                    }
                    if (lineToWrite.StartsWith("XA_BROKEN_EXCEPTION_TRANSITIONS="))
                    {
                        brokenExceptionTransitions = true;
                        continue;
                    }

                    AddEnvironmentVariableLine(lineToWrite);
                }
            }

            if (_Debug && !haveLogLevel)
            {
                AddEnvironmentVariable(defaultLogLevel[0], defaultLogLevel[1]);
            }

            if (sequencePointsMode != SequencePointsMode.None && !haveMonoDebug)
            {
                AddEnvironmentVariable(defaultMonoDebug[0], defaultMonoDebug[1]);
            }

            if (!havebuildId)
            {
                AddEnvironmentVariable("XAMARIN_BUILD_ID", BuildId);
            }

            if (!haveHttpMessageHandler)
            {
                if (HttpClientHandlerType == null)
                {
                    AddEnvironmentVariable(defaultHttpMessageHandler[0], defaultHttpMessageHandler[1]);
                }
                else
                {
                    AddEnvironmentVariable("XA_HTTP_CLIENT_HANDLER_TYPE", HttpClientHandlerType.Trim());
                }
            }

            if (!haveTlsProvider)
            {
                if (TlsProvider == null)
                {
                    AddEnvironmentVariable(defaultTlsProvider[0], defaultTlsProvider[1]);
                }
                else
                {
                    AddEnvironmentVariable("XA_TLS_PROVIDER", TlsProvider.Trim());
                }
            }

            if (!haveMonoGCParams)
            {
                if (EnableSGenConcurrent)
                {
                    AddEnvironmentVariable("MONO_GC_PARAMS", "major=marksweep-conc");
                }
                else
                {
                    AddEnvironmentVariable("MONO_GC_PARAMS", "major=marksweep");
                }
            }

            global::Android.Runtime.BoundExceptionType boundExceptionType;
            if (String.IsNullOrEmpty(BoundExceptionType) || String.Compare(BoundExceptionType, "System", StringComparison.OrdinalIgnoreCase) == 0)
            {
                boundExceptionType = global::Android.Runtime.BoundExceptionType.System;
            }
            else if (String.Compare(BoundExceptionType, "Java", StringComparison.OrdinalIgnoreCase) == 0)
            {
                boundExceptionType = global::Android.Runtime.BoundExceptionType.Java;
            }
            else
            {
                throw new InvalidOperationException($"Unsupported BoundExceptionType value '{BoundExceptionType}'");
            }

            var appConfState = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal <ApplicationConfigTaskState> (ApplicationConfigTaskState.RegisterTaskObjectKey, RegisteredTaskObjectLifetime.Build);

            foreach (string abi in SupportedAbis)
            {
                NativeAssemblerTargetProvider asmTargetProvider = GetAssemblyTargetProvider(abi);
                string baseAsmFilePath = Path.Combine(EnvironmentOutputDirectory, $"environment.{abi.ToLowerInvariant ()}");
                string asmFilePath     = $"{baseAsmFilePath}.s";

                var asmgen = new ApplicationConfigNativeAssemblyGenerator(asmTargetProvider, baseAsmFilePath, environmentVariables, systemProperties)
                {
                    IsBundledApp               = IsBundledApplication,
                    UsesMonoAOT                = usesMonoAOT,
                    UsesMonoLLVM               = EnableLLVM,
                    UsesAssemblyPreload        = usesAssemblyPreload,
                    MonoAOTMode                = aotMode.ToString().ToLowerInvariant(),
                    AndroidPackageName         = AndroidPackageName,
                    BrokenExceptionTransitions = brokenExceptionTransitions,
                    PackageNamingPolicy        = pnp,
                    BoundExceptionType         = boundExceptionType,
                    InstantRunEnabled          = InstantRunEnabled,
                    JniAddNativeMethodRegistrationAttributePresent = appConfState != null ? appConfState.JniAddNativeMethodRegistrationAttributePresent : false,
                };

                using (var sw = MemoryStreamPool.Shared.CreateStreamWriter()) {
                    asmgen.Write(sw);
                    sw.Flush();
                    Files.CopyIfStreamChanged(sw.BaseStream, asmFilePath);
                }
            }

            void AddEnvironmentVariable(string name, string value)
            {
                if (Char.IsUpper(name [0]) || !Char.IsLetter(name [0]))
                {
                    environmentVariables [ValidAssemblerString(name)] = ValidAssemblerString(value);
                }
                else
                {
                    systemProperties [ValidAssemblerString(name)] = ValidAssemblerString(value);
                }
            }

            void AddEnvironmentVariableLine(string l)
            {
                string line = l?.Trim();

                if (String.IsNullOrEmpty(line) || line [0] == '#')
                {
                    return;
                }

                string[] nv = line.Split(new char[] { '=' }, 2);
                AddEnvironmentVariable(nv[0].Trim(), nv.Length < 2 ? String.Empty : nv[1].Trim());
            }

            string ValidAssemblerString(string s)
            {
                return(s.Replace("\"", "\\\""));
            }
        }