Пример #1
0
        public override bool Execute()
        {
            try {
                var path = Path.GetFullPath(LockFile);
                var key  = new Tuple <string, string> (nameof(WriteLockFile), path);                // Use the full path as part of the key

                // Check if already registered, for sanity
                var existing = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build) as DeleteFileAfterBuild;
                if (existing == null)
                {
                    if (File.Exists(path))
                    {
                        Log.LogCodedWarning("XA5302", "Two processes may be building this project at once. Lock file exists at path: {0}", path);
                    }
                    else
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                        File.WriteAllText(path, "");
                    }

                    BuildEngine4.RegisterTaskObject(key, new DeleteFileAfterBuild(path), RegisteredTaskObjectLifetime.Build, allowEarlyCollection: false);
                }
                else
                {
                    Log.LogDebugMessage("Lock file was created earlier in the build.");
                }
            } catch (Exception ex) {
                Log.LogDebugMessage($"Exception in {nameof (WriteLockFile)}: {ex}");
            }

            // We want to always continue
            return(true);
        }
Пример #2
0
        public override bool Execute()
        {
            if (LaunchProfiles == null || UserFile == null || FlagFile == null || ProjectDirectory == null)
            {
                Log.LogWarning("MonitorActiveDocument : One or more files missing");
                return(true);
            }

            if (!Directory.Exists(LaunchProfiles))
            {
                Log.LogWarning("LaunchProfiles not created yet");
                return(true);
            }
            try
            {
                if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
                {
                    if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
                    {
                        BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor),
                                                        new ActiveDocumentMonitor(LaunchProfiles, UserFile, FlagFile, ProjectDirectory, services),
                                                        RegisteredTaskObjectLifetime.AppDomain, false);
                    }
                }
                else
                {
                    // NOTE: this means we only support ONE project/launchProfiles per IDE.
                    monitor.Refresh(LaunchProfiles, UserFile, FlagFile, ProjectDirectory);
                }
            }
Пример #3
0
        string GetJvmPath()
        {
            // NOTE: this doesn't need to use GetRegisteredTaskObjectAssemblyLocal()
            // because JavaSdkPath is the key and the value is a string.
            var key    = new Tuple <string, string> (nameof(ResolveJdkJvmPath), JavaSdkPath);
            var cached = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as string;

            if (cached != null)
            {
                Log.LogDebugMessage($"Using cached value for {nameof (JdkJvmPath)}: {cached}");

                return(cached);
            }

            var minVersion = Version.Parse(MinimumSupportedJavaVersion);
            var maxVersion = Version.Parse(LatestSupportedJavaVersion);

            JdkInfo info = MonoAndroidHelper.GetJdkInfo(this.CreateTaskLogger(), JavaSdkPath, minVersion, maxVersion);

            if (info == null)
            {
                return(null);
            }

            var path = info.JdkJvmPath;

            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }

            BuildEngine4.RegisterTaskObject(key, path, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);

            return(path);
        }
Пример #4
0
        string GetJvmPath()
        {
            var key    = new Tuple <string, string> (nameof(ResolveSdks), JavaSdkPath);
            var cached = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as string;

            if (cached != null)
            {
                Log.LogDebugMessage($"Using cached value for {nameof (JdkJvmPath)}: {cached}");

                return(cached);
            }

            Xamarin.Android.Tools.JdkInfo info = null;
            try {
                info = new Xamarin.Android.Tools.JdkInfo(JavaSdkPath);
            } catch {
                info = Xamarin.Android.Tools.JdkInfo.GetKnownSystemJdkInfos(this.CreateTaskLogger()).FirstOrDefault();
            }

            if (info == null)
            {
                return(null);
            }

            var path = info.JdkJvmPath;

            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }

            BuildEngine4.RegisterTaskObject(key, path, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);

            return(path);
        }
Пример #5
0
        public override bool Execute()
        {
            if (string.IsNullOrEmpty(LaunchProfiles) ||
                string.IsNullOrEmpty(UserFile))
            {
                Debug.Fail("Should have gotten something to monitor");
                return(true);
            }

            try
            {
                if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
                {
                    var maxAttempts = 5;
                    for (var i = 1; i <= maxAttempts; i++)
                    {
                        if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
                        {
                            BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor),
                                                            new ActiveDocumentMonitor(LaunchProfiles !, UserFile !,
                                                                                      StartupFiles.Select(x => x.ItemSpec).ToArray(), services),
                                                            RegisteredTaskObjectLifetime.AppDomain, false);

                            return(true);
                        }
                        else
                        {
                            try
                            {
                                BuildEngine4.Yield();
                            }
                            catch (Exception e)
                            {
                                Debug.WriteLine(e);
                            }
                            // Increase the wait time to allow more time between retries
                            Thread.Sleep(200 * i);
                        }
                    }

                    Debug.Fail("Failed to get IServiceProvider to monitor for active document.");
                }
                else
                {
                    // NOTE: this means we only support ONE project/launchProfiles per IDE.
                    monitor.Refresh(LaunchProfiles !, UserFile !,
                                    StartupFiles.Select(x => x.ItemSpec).ToArray());
                }
            }
Пример #6
0
        public override bool Execute()
        {
            var key = s_cacheKeyPrefix + Text;

            var errorReportedSentinel = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build);

            if (errorReportedSentinel != null)
            {
                Log.LogMessage(MessageImportance.Low, Text);
                return(false);
            }

            BuildEngine4.RegisterTaskObject(key, new object(), RegisteredTaskObjectLifetime.Build, allowEarlyCollection: true);
            Log.LogError(Text);
            return(false);
        }
Пример #7
0
        bool GetAapt2Version()
        {
            var sb        = new StringBuilder();
            var aapt2Tool = Path.Combine(Aapt2ToolPath, Aapt2);

            // Try to use a cached value for Aapt2Version
            // NOTE: this doesn't need to use GetRegisteredTaskObjectAssemblyLocal()
            // because the path to aapt2 is in the key and the value is a string.
            var key    = ($"{nameof (ResolveAndroidTooling)}.{nameof (Aapt2Version)}", aapt2Tool);
            var cached = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as string;

            if (!string.IsNullOrEmpty(cached))
            {
                Log.LogDebugMessage($"Using cached value for {nameof (Aapt2Version)}: {cached}");
                Aapt2Version = cached;
                return(true);
            }

            try {
                MonoAndroidHelper.RunProcess(aapt2Tool, "version", (s, e) => {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        sb.AppendLine(e.Data);
                    }
                }, (s, e) => {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        sb.AppendLine(e.Data);
                    }
                }
                                             );
            } catch (Exception ex) {
                Log.LogWarningFromException(ex);
                return(false);
            }
            var versionInfo        = sb.ToString();
            var versionNumberMatch = Aapt2VersionRegex.Match(versionInfo);

            Log.LogDebugMessage($"`{aapt2Tool} version` returned: ```{versionInfo}```");
            if (versionNumberMatch.Success && Version.TryParse(versionNumberMatch.Groups ["version"]?.Value.Replace(":", "."), out Version versionNumber))
            {
                Aapt2Version = versionNumber.ToString();
                BuildEngine4.RegisterTaskObject(key, Aapt2Version, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);
                return(true);
            }
            return(false);
        }
Пример #8
0
        protected override void ExecuteCore()
        {
            const string previewMessageKey = "Microsoft.NET.Build.Tasks.DisplayPreviewMessageKey";

            object messageDisplayed =
                BuildEngine4.GetRegisteredTaskObject(previewMessageKey, RegisteredTaskObjectLifetime.Build);

            if (messageDisplayed == null)
            {
                Log.LogMessage(MessageImportance.High, Strings.UsingPreviewSdkWarning);

                BuildEngine4.RegisterTaskObject(
                    previewMessageKey,
                    new object(),
                    RegisteredTaskObjectLifetime.Build,
                    true);
            }
        }
Пример #9
0
        protected override void ExecuteCore()
        {
            StronglyTypedInputs inputs = GetInputs();

            string cacheKey = inputs.CacheKey();

            ResolvedAssetsCacheEntry results;

            if (s_allowCacheLookup &&
                BuildEngine4?.GetRegisteredTaskObject(
                    cacheKey,
                    RegisteredTaskObjectLifetime.AppDomain /* really "until process exit" */)
                is ResolvedAssetsCacheEntry cacheEntry)
            {
                // NOTE: It's conceivably possible that the user modified the targeting
                //       packs between builds. Since that is extremely rare and the standard
                //       user scenario reads the targeting pack contents over and over without
                //       modification, we're electing not to check for file modification and
                //       returning any cached results that we have.

                results = cacheEntry;
            }
            else
            {
                results = Resolve(inputs, BuildEngine4);

                if (s_allowCacheLookup)
                {
                    BuildEngine4?.RegisterTaskObject(cacheKey, results, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: true);
                }
            }

            foreach (var error in results.Errors)
            {
                Log.LogError(error);
            }

            ReferencesToAdd                  = results.ReferencesToAdd;
            AnalyzersToAdd                   = results.AnalyzersToAdd;
            PlatformManifests                = results.PlatformManifests;
            PackageConflictOverrides         = results.PackageConflictOverrides;
            PackageConflictPreferredPackages = results.PackageConflictPreferredPackages;
            UsedRuntimeFrameworks            = results.UsedRuntimeFrameworks;
        }
        protected Version GetVersionFromTool(string javaExe, Regex versionRegex)
        {
            // NOTE: this doesn't need to use GetRegisteredTaskObjectAssemblyLocal()
            // because the path to java/javac is the key and the value is a System.Version.
            var javaTool = Path.Combine(JavaSdkPath, "bin", javaExe);
            var key      = new Tuple <string, string> (nameof(ValidateJavaVersion), javaTool);
            var cached   = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as Version;

            if (cached != null)
            {
                Log.LogDebugMessage($"Using cached value for `{javaTool} -version`: {cached}");
                JdkVersion = cached.ToString();
                return(cached);
            }

            var sb = new StringBuilder();

            MonoAndroidHelper.RunProcess(javaTool, "-version", (s, e) => {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    sb.AppendLine(e.Data);
                }
            }, (s, e) => {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    sb.AppendLine(e.Data);
                }
            });
            var     versionInfo        = sb.ToString();
            var     versionNumberMatch = versionRegex.Match(versionInfo);
            Version versionNumber;

            if (versionNumberMatch.Success && Version.TryParse(versionNumberMatch.Groups ["version"]?.Value, out versionNumber))
            {
                BuildEngine4.RegisterTaskObject(key, versionNumber, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);
                JdkVersion = versionNumberMatch.Groups ["version"].Value;
                return(versionNumber);
            }
            else
            {
                Log.LogCodedWarning("XA0033", Properties.Resources.XA0033, javaExe, versionInfo);
                return(null);
            }
        }
Пример #11
0
        Version GetVersionFromTool(string javaExe, Regex versionRegex)
        {
            var javaTool = Path.Combine(JavaSdkPath, "bin", javaExe);
            var key      = new Tuple <string, string> (nameof(ValidateJavaVersion), javaTool);
            var cached   = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as Version;

            if (cached != null)
            {
                Log.LogDebugMessage($"Using cached value for `{javaTool} -version`: {cached}");
                JdkVersion = cached.ToString();
                return(cached);
            }

            var sb = new StringBuilder();

            MonoAndroidHelper.RunProcess(javaTool, "-version", (s, e) => {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    sb.AppendLine(e.Data);
                }
            }, (s, e) => {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    sb.AppendLine(e.Data);
                }
            });
            var     versionInfo        = sb.ToString();
            var     versionNumberMatch = versionRegex.Match(versionInfo);
            Version versionNumber;

            if (versionNumberMatch.Success && Version.TryParse(versionNumberMatch.Groups ["version"]?.Value, out versionNumber))
            {
                BuildEngine4.RegisterTaskObject(key, versionNumber, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);
                JdkVersion = versionNumberMatch.Groups ["version"].Value;
                return(versionNumber);
            }
            else
            {
                Log.LogCodedWarning("XA0033", $"Failed to get the Java SDK version as it does not appear to contain a valid version number. `{javaExe} -version` returned: ```{versionInfo}```");
                return(null);
            }
        }
Пример #12
0
        private void ExecuteImpl()
        {
            var globalJsonPath = Path.Combine(RepositoryRoot, "global.json");

            var lastWrite = File.GetLastWriteTimeUtc(globalJsonPath);
            var paths     = Environment.GetEnvironmentVariable("PATH");

            var cachedResult = (CacheEntry)BuildEngine4.GetRegisteredTaskObject(s_cacheKey, RegisteredTaskObjectLifetime.Build);

            if (cachedResult != null && lastWrite == cachedResult.LastWrite && paths == cachedResult.Paths)
            {
                Log.LogMessage(MessageImportance.Low, $"Reused cached value.");
                DotNetPath = cachedResult.Value;
                return;
            }

            var globalJson = File.ReadAllText(globalJsonPath);

            // avoid Newtonsoft.Json dependency
            var match = Regex.Match(globalJson, @"""dotnet""\s*:\s*""([^""]+)""");

            if (!match.Success)
            {
                Log.LogError($"Unable to determine dotnet version from file '{globalJsonPath}'.");
                return;
            }

            var sdkVersion = match.Groups[1].Value;

            var fileName  = (Path.DirectorySeparatorChar == '\\') ? "dotnet.exe" : "dotnet";
            var dotNetDir = paths.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(p => File.Exists(Path.Combine(p, fileName)));

            if (dotNetDir == null || !Directory.Exists(Path.Combine(dotNetDir, "sdk", sdkVersion)))
            {
                Log.LogError($"Unable to find dotnet with SDK version '{sdkVersion}'");
                return;
            }

            DotNetPath = Path.GetFullPath(Path.Combine(dotNetDir, fileName));
            BuildEngine4.RegisterTaskObject(s_cacheKey, new CacheEntry(lastWrite, paths, DotNetPath), RegisteredTaskObjectLifetime.Build, allowEarlyCollection: true);
        }
Пример #13
0
        public override bool Execute()
        {
            var logger = new Logger(Log);

            var sandbox = BuildEngine4.GetRegisteredTaskObject(BuildEngine.ProjectFileOfTaskNode, RegisteredTaskObjectLifetime.Build) as Sanbox;

            if (sandbox == null)
            {
                return(true);
            }

            try
            {
                sandbox.Client.ExecutePostBuildAdaptations(logger);
            }
            catch (Exception e)
            {
                logger.Error($"Assembly adaptation pre build execution failed. Details: {e.GetBaseException().Message}");
            }

            return(!Log.HasLoggedErrors);
        }
Пример #14
0
        public override bool Execute()
        {
            var logger = new Logger(Log);

            var sandbox = BuildEngine4.GetRegisteredTaskObject(BuildEngine.ProjectFileOfTaskNode, RegisteredTaskObjectLifetime.Build) as Sanbox;

            if (sandbox == null)
            {
                return(true);
            }

            CompilesToAdd    = Enumerable.Empty <ITaskItem>().ToArray();
            CompilesToRemove = Enumerable.Empty <ITaskItem>().ToArray();
            if (!Test && Assembly.GetEntryAssembly() == null)
            {
                return(true);
            }

            try
            {
                var replacements = sandbox.Client.ReplaceCompileItems(logger);
                Func <CompileItemReplacement, ITaskItem> selector = r =>
                {
                    return(ItemsCompile.FirstOrDefault(c => string.Equals(c.GetMetadata("FullPath"),
                                                                          r.Source,
                                                                          StringComparison.InvariantCultureIgnoreCase)));
                };

                CompilesToAdd    = replacements.Select(r => new TaskItem(r.Target)).OfType <ITaskItem>().ToArray();
                CompilesToRemove = replacements.Select(selector).ToArray();
            }
            catch (Exception e)
            {
                logger.Error($"Assembly compile replacement failed. Details: {e.GetBaseException().Message}");
            }

            return(!Log.HasLoggedErrors);
        }
Пример #15
0
        string GetJvmPath()
        {
            // NOTE: this doesn't need to use GetRegisteredTaskObjectAssemblyLocal()
            // because JavaSdkPath is the key and the value is a string.
            var key    = new Tuple <string, string> (nameof(ResolveJdkJvmPath), JavaSdkPath);
            var cached = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.AppDomain) as string;

            if (cached != null)
            {
                Log.LogDebugMessage($"Using cached value for {nameof (JdkJvmPath)}: {cached}");

                return(cached);
            }

            JdkInfo info = null;

            try {
                info = new JdkInfo(JavaSdkPath);
            } catch {
                info = JdkInfo.GetKnownSystemJdkInfos(this.CreateTaskLogger()).FirstOrDefault();
            }

            if (info == null)
            {
                return(null);
            }

            var path = info.JdkJvmPath;

            if (string.IsNullOrEmpty(path))
            {
                return(null);
            }

            BuildEngine4.RegisterTaskObject(key, path, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false);

            return(path);
        }
Пример #16
0
        public override bool Execute()
        {
            var logger = new Logger(Log);

            var sandbox = BuildEngine4.GetRegisteredTaskObject(BuildEngine.ProjectFileOfTaskNode, RegisteredTaskObjectLifetime.Build) as Sanbox;

            if (sandbox == null)
            {
                return(true);
            }

            try
            {
                sandbox.Dispose();
                BuildEngine4.UnregisterTaskObject(BuildEngine.ProjectFileOfTaskNode, RegisteredTaskObjectLifetime.Build);
            }
            catch (Exception e)
            {
                logger.Error($"Failure cleanup task failed. Details: {e.GetBaseException().Message}");
            }

            return(!Log.HasLoggedErrors);
        }
Пример #17
0
        public override bool Execute()
        {
            if (LaunchProfiles == null || UserFile == null || FlagFile == null)
            {
                return(true);
            }

            try
            {
                if (BuildEngine4.GetRegisteredTaskObject(nameof(ActiveDocumentMonitor), RegisteredTaskObjectLifetime.AppDomain) is not ActiveDocumentMonitor monitor)
                {
                    if (WindowsInterop.GetServiceProvider() is IServiceProvider services)
                    {
                        BuildEngine4.RegisterTaskObject(nameof(ActiveDocumentMonitor),
                                                        new ActiveDocumentMonitor(LaunchProfiles, UserFile, FlagFile, services),
                                                        RegisteredTaskObjectLifetime.AppDomain, false);
                    }
                }
                else
                {
                    // NOTE: this means we only support ONE project/launchProfiles per IDE.
                    monitor.Refresh(LaunchProfiles, UserFile, FlagFile);
                }
            }
Пример #18
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.GetRegisteredTaskObject(ApplicationConfigTaskState.RegisterTaskObjectKey, RegisteredTaskObjectLifetime.Build) as ApplicationConfigTaskState;

            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();
                    MonoAndroidHelper.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("\"", "\\\""));
            }
        }
Пример #19
0
        public override bool Execute()
        {
            if (!SemanticVersion.TryParse(SdkVersion, out var currentSdkVersion))
            {
                Log.LogError($"Invalid version: {SdkVersion}");
                return(false);
            }

            var      globalJsonPath = Path.Combine(RepositoryRoot, "global.json");
            DateTime lastWrite;

            try
            {
                lastWrite = File.GetLastWriteTimeUtc(globalJsonPath);
            }
            catch (Exception e)
            {
                Log.LogError($"Error accessing file '{globalJsonPath}': {e.Message}");
                return(false);
            }

            var cachedResult = (CacheEntry)BuildEngine4.GetRegisteredTaskObject(s_cacheKey, RegisteredTaskObjectLifetime.Build);

            if (cachedResult != null && lastWrite == cachedResult.LastWrite)
            {
                // Error has already been reported if the current SDK version is not sufficient.
                if (!cachedResult.Success)
                {
                    Log.LogMessage(MessageImportance.Low, $"Previous .NET Core SDK version check failed.");
                }

                return(cachedResult.Success);
            }

            bool execute()
            {
                string globalJson;

                try
                {
                    globalJson = File.ReadAllText(globalJsonPath);
                }
                catch (Exception e)
                {
                    Log.LogError($"Error reading file '{globalJsonPath}': {e.Message}");
                    return(false);
                }

                // avoid Newtonsoft.Json dependency
                var match = Regex.Match(globalJson, $@"""dotnet""\s*:\s*""([^""]+)""");

                if (!match.Success)
                {
                    Log.LogError($"Unable to determine dotnet version from file '{globalJsonPath}'.");
                    return(false);
                }

                var minSdkVersionStr = match.Groups[1].Value;

                if (!SemanticVersion.TryParse(minSdkVersionStr, out var minSdkVersion))
                {
                    Log.LogError($"DotNet version specified in '{globalJsonPath}' is invalid: {minSdkVersionStr}.");
                    return(false);
                }

                if (currentSdkVersion < minSdkVersion)
                {
                    Log.LogError($"The .NET Core SDK version {currentSdkVersion} is below the minimum required version {minSdkVersion}. You can install newer .NET Core SDK from https://www.microsoft.com/net/download.");
                    return(false);
                }

                return(true);
            }

            bool success = execute();

            BuildEngine4.RegisterTaskObject(s_cacheKey, new CacheEntry(lastWrite, success), RegisteredTaskObjectLifetime.Build, allowEarlyCollection: true);
            return(success);
        }
Пример #20
0
        private void AddAssemblies(ZipArchiveEx apk)
        {
            bool   debug              = _Debug;
            bool   compress           = !debug && EnableCompression;
            bool   use_shared_runtime = String.Equals(UseSharedRuntime, "true", StringComparison.OrdinalIgnoreCase);
            string sourcePath;

            AssemblyCompression.AssemblyData             compressedAssembly       = null;
            IDictionary <string, CompressedAssemblyInfo> compressedAssembliesInfo = null;

            if (compress)
            {
                compressedAssembliesInfo = BuildEngine4.GetRegisteredTaskObject(CompressedAssemblyInfo.CompressedAssembliesInfoKey, RegisteredTaskObjectLifetime.Build) as IDictionary <string, CompressedAssemblyInfo>;
            }

            int count = 0;

            foreach (ITaskItem assembly in ResolvedUserAssemblies)
            {
                if (bool.TryParse(assembly.GetMetadata("AndroidSkipAddToPackage"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping {assembly.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' ");
                    continue;
                }
                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogCodedWarning("XA0107", assembly.ItemSpec, 0, Properties.Resources.XA0107, assembly.ItemSpec);
                }

                sourcePath = CompressAssembly(assembly);

                // Add assembly
                AddFileToArchiveIfNewer(apk, sourcePath, GetTargetDirectory(assembly.ItemSpec) + "/" + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);

                // Try to add config if exists
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, config);

                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }

            if (use_shared_runtime)
            {
                return;
            }

            count = 0;
            // Add framework assemblies
            foreach (ITaskItem assembly in ResolvedFrameworkAssemblies)
            {
                if (bool.TryParse(assembly.GetMetadata("AndroidSkipAddToPackage"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping {assembly.ItemSpec} due to 'AndroidSkipAddToPackage' == 'true' ");
                    continue;
                }

                if (MonoAndroidHelper.IsReferenceAssembly(assembly.ItemSpec))
                {
                    Log.LogCodedWarning("XA0107", assembly.ItemSpec, 0, Properties.Resources.XA0107, assembly.ItemSpec);
                }

                sourcePath = CompressAssembly(assembly);
                AddFileToArchiveIfNewer(apk, sourcePath, AssembliesPath + Path.GetFileName(assembly.ItemSpec), compressionMethod: UncompressedMethod);
                var config = Path.ChangeExtension(assembly.ItemSpec, "dll.config");
                AddAssemblyConfigEntry(apk, config);
                // Try to add symbols if Debug
                if (debug)
                {
                    var symbols = Path.ChangeExtension(assembly.ItemSpec, "dll.mdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }

                    symbols = Path.ChangeExtension(assembly.ItemSpec, "pdb");

                    if (File.Exists(symbols))
                    {
                        AddFileToArchiveIfNewer(apk, symbols, AssembliesPath + Path.GetFileName(symbols), compressionMethod: UncompressedMethod);
                    }
                }
                count++;
                if (count == ZipArchiveEx.ZipFlushLimit)
                {
                    apk.Flush();
                    count = 0;
                }
            }

            void EnsureCompressedAssemblyData(string sourcePath, uint descriptorIndex)
            {
                if (compressedAssembly == null)
                {
                    compressedAssembly = new AssemblyCompression.AssemblyData(sourcePath, descriptorIndex);
                }
                else
                {
                    compressedAssembly.SetData(sourcePath, descriptorIndex);
                }
            }

            string CompressAssembly(ITaskItem assembly)
            {
                if (!compress)
                {
                    return(assembly.ItemSpec);
                }

                if (bool.TryParse(assembly.GetMetadata("AndroidSkipCompression"), out bool value) && value)
                {
                    Log.LogDebugMessage($"Skipping compression of {assembly.ItemSpec} due to 'AndroidSkipCompression' == 'true' ");
                    return(assembly.ItemSpec);
                }

                if (compressedAssembliesInfo.TryGetValue(Path.GetFileName(assembly.ItemSpec), out CompressedAssemblyInfo info) && info != null)
                {
                    EnsureCompressedAssemblyData(assembly.ItemSpec, info.DescriptorIndex);
                    AssemblyCompression.CompressionResult result = AssemblyCompression.Compress(compressedAssembly);
                    if (result != AssemblyCompression.CompressionResult.Success)
                    {
                        switch (result)
                        {
                        case AssemblyCompression.CompressionResult.EncodingFailed:
                            Log.LogMessage($"Failed to compress {assembly.ItemSpec}");
                            break;

                        case AssemblyCompression.CompressionResult.InputTooBig:
                            Log.LogMessage($"Input assembly {assembly.ItemSpec} exceeds maximum input size");
                            break;

                        default:
                            Log.LogMessage($"Unknown error compressing {assembly.ItemSpec}");
                            break;
                        }
                        return(assembly.ItemSpec);
                    }
                    return(compressedAssembly.DestinationPath);
                }

                return(assembly.ItemSpec);
            }
        }
Пример #21
0
        public override bool Execute()
        {
            var entry = (RegisterObject)BuildEngine4.GetRegisteredTaskObject(RegisterObject.CacheKey, RegisteredTaskObjectLifetime.Build);

            return(true);
        }
Пример #22
0
        public override bool Execute()
        {
            var key    = (WorkingDirectory, XASourceDirectory, SubmoduleName, GitRemoteName);
            var cached = BuildEngine4.GetRegisteredTaskObject(key, RegisteredTaskObjectLifetime.Build) as string;

            if (!string.IsNullOrEmpty(cached))
            {
                Log.LogMessage(MessageImportance.Normal, "Using cached information from earlier in the build");
                CommitInfo = cached;
                goto outOfHere;
            }

            if (String.IsNullOrEmpty(GitPath?.Trim()))
            {
                GitPath = "git";
            }

            bool   isSubmodule   = !String.IsNullOrEmpty(SubmoduleName);
            string submoduleInfo = isSubmodule ? $" submodule {SubmoduleName}" : String.Empty;

            Log.LogMessage(MessageImportance.Normal, $"Gathering GIT commit info{submoduleInfo} in directory '{WorkingDirectory}'");

            var stdoutLines = new List <string> ();
            var stderrLines = new List <string> ();

            if (!RunGit("log -n 1 --pretty=%D HEAD", stdoutLines, stderrLines))
            {
                goto outOfHere;
            }

            string gitModules = Path.Combine(XASourceDirectory, ".gitmodules");
            string branchFull = stdoutLines [0].Trim();
            string branch;

            if (branchFull.StartsWith("HEAD, ", StringComparison.Ordinal))
            {
                Log.LogMessage(MessageImportance.Low, "  Detached HEAD, branch information available");
                // Detached HEAD with branch information
                // Sample format:
                //
                //    HEAD, origin/master, origin/d16-0-p1, origin/HEAD, master
                //
                branch = branchFull.Substring(6);
            }
            else if (branchFull.StartsWith("HEAD -> ", StringComparison.Ordinal))
            {
                Log.LogMessage(MessageImportance.Low, "  Normal branch");
                // Normal branch
                // Sample format:
                //
                //     HEAD -> bundle-ndk16-fix, origin/pr/1105
                //
                branch = branchFull.Substring(8);
            }
            else if (String.Compare("HEAD", branchFull, StringComparison.Ordinal) == 0)
            {
                Log.LogMessage(MessageImportance.Low, "  Detached HEAD, no branch information");
                // Detached HEAD without branch information
                if (isSubmodule)
                {
                    if (!RunGit($"config -f {gitModules} --get \"submodule.{SubmoduleName}.branch\"", stdoutLines, stderrLines))
                    {
                        goto outOfHere;
                    }
                    branch = stdoutLines [0];
                }
                else
                {
                    Log.LogWarning($"Unable to determine branch name from detached head state in directory {WorkingDirectory}");
                    branch = "unknown";
                }
            }
            else
            {
                Log.LogError($"Unable to parse branch name from: {branchFull}");
                branch = null;
                goto outOfHere;
            }

            int separator = branch.IndexOf(',');

            if (separator >= 0)
            {
                // We choose the first branch from the list
                branch = branch.Substring(0, separator).Trim();
            }

            separator = branch.IndexOf('/');
            if (separator >= 0)
            {
                branch = branch.Substring(separator + 1).Trim();
            }

            if (branch.StartsWith("tag: ", StringComparison.Ordinal))
            {
                branch = branch.Substring(5).Trim();
            }

            if (String.IsNullOrEmpty(branch))
            {
                Log.LogError($"Unsupported branch information format: '{branchFull}'");
                goto outOfHere;
            }

            Log.LogMessage(MessageImportance.Low, $"  Branch: {branch}");
            if (!RunGit("log -n 1 --pretty=%h HEAD", stdoutLines, stderrLines))
            {
                goto outOfHere;
            }
            string commit = stdoutLines [0].Trim();

            Log.LogMessage(MessageImportance.Low, $"  Commit hash: {commit}");

            string url;

            if (isSubmodule)
            {
                if (!RunGit($"config -f {gitModules} --get \"submodule.{SubmoduleName}.url\"", stdoutLines, stderrLines))
                {
                    goto outOfHere;
                }
                url = stdoutLines [0].Trim();
            }
            else
            {
                string remoteName = String.IsNullOrEmpty(GitRemoteName) ? "origin" : GitRemoteName;
                if (!RunGit($"config --local --get \"remote.{remoteName}.url\"", stdoutLines, stderrLines))
                {
                    goto outOfHere;
                }

                url = stdoutLines [0].Trim();
            }
            Log.LogMessage(MessageImportance.Low, $"  Repository URL: {url}");

            string organization;
            string repo;
            bool   urlParsed;

            if (url.StartsWith("git@", StringComparison.Ordinal))
            {
                urlParsed = ParseGitURL(url, out organization, out repo);
            }
            else if (url.StartsWith("https://", StringComparison.Ordinal))
            {
                urlParsed = ParseHttpsURL(url, out organization, out repo);
            }
            else if (url.StartsWith("../../", StringComparison.Ordinal))
            {
                // Special case for monodroid (although it will most likely return the git@ URL anyway)
                urlParsed = ParseRelativePathURL(url, out organization, out repo);
            }
            else
            {
                Log.LogError($"Unknown URL schema in '{url}' for directory '{WorkingDirectory}'");
                goto outOfHere;
            }

            Log.LogMessage(MessageImportance.Low, $"  Organization: {organization}");
            Log.LogMessage(MessageImportance.Low, $"  Repository: {repo}");

            CommitInfo = $"{organization}/{repo}/{branch}@{commit}";
            BuildEngine4.RegisterTaskObject(key, CommitInfo, RegisteredTaskObjectLifetime.Build, allowEarlyCollection: false);

outOfHere:
            return(!Log.HasLoggedErrors);
        }
Пример #23
0
        public override bool RunTask()
        {
            if (InputAssemblies == null)
            {
                return(true);
            }

            var output = new List <ITaskItem> (InputAssemblies.Length);

            foreach (var assemblyItem in InputAssemblies)
            {
                if (!File.Exists(assemblyItem.ItemSpec))
                {
                    Log.LogDebugMessage($"Skipping non-existent dependency '{assemblyItem.ItemSpec}'.");
                    continue;
                }
                using (var pe = new PEReader(File.OpenRead(assemblyItem.ItemSpec))) {
                    var reader = pe.GetMetadataReader();
                    // Check in-memory cache
                    var module = reader.GetModuleDefinition();
                    var key    = (nameof(FilterAssemblies), reader.GetGuid(module.Mvid));
                    var value  = BuildEngine4.GetRegisteredTaskObject(key, Lifetime);
                    if (value is bool isMonoAndroidAssembly)
                    {
                        if (isMonoAndroidAssembly)
                        {
                            Log.LogDebugMessage($"Cached: {assemblyItem.ItemSpec}");
                            output.Add(assemblyItem);
                        }
                        continue;
                    }
                    // Check assembly definition
                    var assemblyDefinition        = reader.GetAssemblyDefinition();
                    var targetFrameworkIdentifier = GetTargetFrameworkIdentifier(assemblyDefinition, reader);
                    if (string.Compare(targetFrameworkIdentifier, TargetFrameworkIdentifier, StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        output.Add(assemblyItem);
                        BuildEngine4.RegisterTaskObject(key, true, Lifetime, AllowEarlyCollection);
                        continue;
                    }
                    // Fallback to looking for a Mono.Android reference
                    if (MonoAndroidHelper.HasMonoAndroidReference(reader))
                    {
                        Log.LogDebugMessage($"Mono.Android reference found: {assemblyItem.ItemSpec}");
                        output.Add(assemblyItem);
                        BuildEngine4.RegisterTaskObject(key, true, Lifetime, AllowEarlyCollection);
                        continue;
                    }
                    // Fallback to looking for *.jar or __Android EmbeddedResource files
                    if (HasEmbeddedResource(reader))
                    {
                        Log.LogDebugMessage($"EmbeddedResource found: {assemblyItem.ItemSpec}");
                        output.Add(assemblyItem);
                        BuildEngine4.RegisterTaskObject(key, true, Lifetime, AllowEarlyCollection);
                        continue;
                    }
                    // Not a MonoAndroid assembly, store false
                    BuildEngine4.RegisterTaskObject(key, false, Lifetime, AllowEarlyCollection);
                }
            }
            OutputAssemblies = output.ToArray();

            return(!Log.HasLoggedErrors);
        }