/// <summary> /// Prepares function <see cref="System.Func{ResultT}"/> with specified signature for execution in AOT compiled environment. /// </summary> /// <typeparam name="ResultT">Function result type.</typeparam> public static void RegisterFunc <ResultT>() { if (typeof(AotCompilation).Name == string.Empty) { // ReSharper disable once AssignNullToNotNullAttribute var fn = Expression.Lambda <Func <ResultT> >(default(Expression), default(ParameterExpression[])).CompileAot(); fn.Invoke(); fn.DynamicInvoke(); AotCompiler.Prepare <ResultT>(default(Expression)); } }
/// <summary> /// Prepares function <see cref="System.Func{Arg1T,Arg2T,Arg3T,Arg4T,ResultT}"/> with specified signature for execution in AOT compiled environment. /// </summary> /// <typeparam name="Arg1T">Function's first argument.</typeparam> /// <typeparam name="Arg2T">Function's second argument.</typeparam> /// <typeparam name="Arg3T">Function's third argument.</typeparam> /// <typeparam name="Arg4T">Function's fourth argument.</typeparam> /// <typeparam name="ResultT">Function result type.</typeparam> public static void RegisterFunc <Arg1T, Arg2T, Arg3T, Arg4T, ResultT>() { if (typeof(AotCompilation).Name == string.Empty) { // ReSharper disable once AssignNullToNotNullAttribute var fn = Expression.Lambda <Func <Arg1T, Arg2T, Arg3T, Arg4T, ResultT> >(default(Expression), default(ParameterExpression[])).CompileAot(); fn.Invoke(default(Arg1T), default(Arg2T), default(Arg3T), default(Arg4T)); fn.DynamicInvoke(default(Arg1T), default(Arg2T), default(Arg3T), default(Arg4T)); AotCompiler.Prepare <Arg1T, Arg2T, Arg3T, Arg4T, ResultT>(default(Expression), default(ReadOnlyCollection <ParameterExpression>)); } }
/// <summary> /// Compiles specified expression into <see cref="Func{TArg1, TArg2, TResult}"/> delegate using AOT aware expression compiler. /// </summary> /// <typeparam name="TArg1">First argument type.</typeparam> /// <typeparam name="TArg2">Second argument type.</typeparam> /// <typeparam name="TResult">Result type.</typeparam> /// <param name="expression">An expression syntax tree. Not null.</param> /// <param name="forceAot">True to always use AOT compiler event if environment is JIT and supports dynamic code.</param> /// <returns>A compiled expression.</returns> public static Func <TArg1, TArg2, TResult> CompileAot <TArg1, TArg2, TResult>(this Expression <Func <TArg1, TArg2, TResult> > expression, bool forceAot = false) { if (expression == null) { throw new ArgumentNullException("expression"); } AotCompilation.RegisterFunc <TArg1, TArg2, TResult>(); if (AotCompilation.IsAotRuntime || forceAot) { return(AotCompiler.PrepareFunc <TArg1, TArg2, TResult>(expression.Body, expression.Parameters)); } else { return(expression.Compile()); } }
/// <summary> /// Compiles specified expression into <see cref="Action"/> delegate using AOT aware expression compiler. /// </summary> /// <param name="expression">An expression syntax tree. Not null.</param> /// <param name="forceAot">True to always use AOT compiler event if environment is JIT and supports dynamic code.</param> /// <returns>A compiled expression.</returns> public static Action CompileAot(this Expression <Action> expression, bool forceAot = false) { if (expression == null) { throw new ArgumentNullException("expression"); } AotCompilation.RegisterAction(); if (AotCompilation.IsAotRuntime || forceAot) { return(AotCompiler.PrepareAction(expression.Body)); } else { return(expression.Compile()); } }
public override bool Execute() { Utils.Logger = Log; bool isDevice = Arch.Equals("arm64", StringComparison.InvariantCultureIgnoreCase); if (isDevice && string.IsNullOrEmpty(CrossCompiler)) { throw new ArgumentException("arm64 arch requires CrossCompiler"); } if (!File.Exists(Path.Combine(AppDir, MainLibraryFileName))) { throw new ArgumentException($"MainLibraryFileName='{MainLibraryFileName}' was not found in AppDir='{AppDir}'"); } if (ProjectName.Contains(" ")) { throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces"); } if (UseLlvm && string.IsNullOrEmpty(LlvmPath)) { // otherwise we might accidentally use some random llc/opt from PATH (installed with clang) throw new ArgumentException($"LlvmPath shoun't be empty when UseLlvm is set"); } string[] excludes = new string[0]; if (ExcludeFromAppDir != null) { excludes = ExcludeFromAppDir .Where(i => !string.IsNullOrEmpty(i.ItemSpec)) .Select(i => i.ItemSpec) .ToArray(); } string[] libsToAot = Directory.GetFiles(AppDir, "*.dll") .Where(f => !excludes.Contains(Path.GetFileName(f))) .ToArray(); string binDir = Path.Combine(AppDir, $"bin-{ProjectName}-{Arch}"); if (!string.IsNullOrEmpty(OutputDirectory)) { binDir = OutputDirectory; } Directory.CreateDirectory(binDir); // run AOT compilation only for devices if (isDevice) { if (string.IsNullOrEmpty(CrossCompiler)) { throw new InvalidOperationException("cross-compiler is not set"); } AotCompiler.PrecompileLibraries(CrossCompiler, Arch, !DisableParallelAot, binDir, libsToAot, new Dictionary <string, string> { { "MONO_PATH", AppDir } }, Optimized, UseLlvm, LlvmPath); } // generate modules.m AotCompiler.GenerateLinkAllFile( Directory.GetFiles(binDir, "*.dll.o"), Path.Combine(binDir, "modules.m")); if (GenerateXcodeProject) { XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName, AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, NativeMainSource); if (BuildAppBundle) { if (isDevice && string.IsNullOrEmpty(DevTeamProvisioning)) { // DevTeamProvisioning shouldn't be empty for arm64 builds Utils.LogInfo("DevTeamProvisioning is not set, BuildAppBundle step is skipped."); } else { AppBundlePath = Xcode.BuildAppBundle( Path.Combine(binDir, ProjectName, ProjectName + ".xcodeproj"), Arch, Optimized, DevTeamProvisioning); } } } return(true); }