void CompileClang(IEnumerable <string> files)
        {
            var xcodePath = XcodeToolchain.GetXcodeToolchainPath();
            var clangBin  = Path.Combine(xcodePath, "usr/bin/clang");
            var monoPath  = ManagedToolchain.FindMonoPath();

            var args = new List <string> {
                $"-D{DLLExportDefine}",
                "-framework CoreFoundation",
                $"-I\"{monoPath}/include/mono-2.0\"",
                $"-L\"{monoPath}/lib/\" -lmonosgen-2.0",
                string.Join(" ", files.ToList())
            };

            switch (Options.GeneratorKind)
            {
            case GeneratorKind.ObjectiveC:
                args.Add("-ObjC");
                args.Add("-lobjc");
                break;

            case GeneratorKind.CPlusPlus:
                args.Add("-x c++");
                break;
            }

            var invocation = string.Join(" ", args);

            Invoke(clangBin, invocation);
        }
        bool CompileClangMac(IEnumerable <string> files)
        {
            var xcodePath = XcodeToolchain.GetXcodeToolchainPath();
            var clangBin  = Path.Combine(xcodePath, "usr/bin/clang");
            var monoPath  = ManagedToolchain.FindMonoPath();

            var args = new List <string> {
                $"-D{DLLExportDefine}",
                "-framework CoreFoundation",
                $"-I\"{monoPath}/include/mono-2.0\"",
                $"-L\"{monoPath}/lib/\" -lmonosgen-2.0",
                string.Join(" ", files.ToList())
            };

            var sysroot = Path.Combine(XcodeToolchain.GetXcodeIncludesFolder(), "../..");

            args.Add($"-isysroot {sysroot}");

            if (Options.Compilation.Target == CompilationTarget.SharedLibrary)
            {
                var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]);
                var libName    = $"lib{name}.dylib";
                var outputPath = Path.Combine(Options.OutputDir, libName);
                args.Add($"-dynamiclib -install_name {libName} -o {outputPath}");
            }

            switch (Options.GeneratorKind)
            {
            case GeneratorKind.ObjectiveC:
                args.Add("-ObjC");
                args.Add("-lobjc");
                break;

            case GeneratorKind.CPlusPlus:
                args.Add("-x c++");
                break;
            }

            var invocation = string.Join(" ", args);
            var output     = Invoke(clangBin, invocation);

            return(output.ExitCode == 0);
        }
        bool CompileClangLinux(IEnumerable <string> files)
        {
            var clangBin = Path.Combine("/usr/bin/clang");
            var monoPath = ManagedToolchain.FindMonoPath();

            var args = new List <string> {
                $"-D{DLLExportDefine}",
                $"-D_REENTRANT -I/usr/lib/pkgconfig/../../include/mono-2.0",
                $"-L/usr/lib/pkgconfig/../../lib -lmono-2.0 -lm -lrt -ldl -lpthread",
                string.Join(" ", files.ToList())
            };

            if (Options.Compilation.Target == CompilationTarget.SharedLibrary)
            {
                var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]);
                var libName    = $"lib{name}.so";
                var outputPath = Path.Combine(Options.OutputDir, libName);
                args.Add($"-shared -fPIC -install_name {libName} -o {outputPath}");
            }

            switch (Options.GeneratorKind)
            {
            case GeneratorKind.ObjectiveC:
                args.Add("-ObjC");
                args.Add("-lobjc");
                break;

            case GeneratorKind.CPlusPlus:
                args.Add("-x c++");
                break;
            }

            var invocation = string.Join(" ", args);
            var output     = Invoke(clangBin, invocation);

            return(output.ExitCode == 0);
        }
        void CompileMSVC(IEnumerable <string> files)
        {
            List <ToolchainVersion> vsSdks;

            MSVCToolchain.GetVisualStudioSdks(out vsSdks);

            if (vsSdks.Count == 0)
            {
                throw new Exception("Visual Studio SDK was not found on your system.");
            }

            ToolchainVersion vsSdk;

            if (Options.Compilation.VsVersion == VisualStudioVersion.Latest)
            {
                vsSdk = vsSdks.LastOrDefault();
            }
            else
            {
                var exactVersion = vsSdks.Where(vs => (int)vs.Version == (int)Options.Compilation.VsVersion)
                                   .Cast <ToolchainVersion?>().SingleOrDefault();
                if (!exactVersion.HasValue)
                {
                    throw new Exception($"Visual Studio SDK version {Options.Compilation.VsVersion} was not found on your system.");
                }

                vsSdk = exactVersion.Value;
            }

            var clBin = String.Empty;

            if ((int)vsSdk.Version == (int)VisualStudioVersion.VS2017)
            {
                var clFiles = System.IO.Directory.EnumerateFiles(Path.Combine(vsSdk.Directory, @"..\..\VC\Tools\MSVC"), "cl.exe", SearchOption.AllDirectories);
                clBin = clFiles.Where(s => s.Contains(@"x86\cl.exe")).First();
            }
            else
            {
                clBin = Path.GetFullPath(Path.Combine(vsSdk.Directory, "..", "..", "VC", "bin", "cl.exe"));
            }

            Diagnostics.Debug($"VS path {vsSdk.Directory}");

            var monoPath = ManagedToolchain.FindMonoPath();
            var output   = Path.Combine(Options.OutputDir, Options.LibraryName ??
                                        Path.GetFileNameWithoutExtension(Project.Assemblies[0]));

            var args = new List <string> {
                "/nologo",
                $"-D{DLLExportDefine}",
                $"-I\"{monoPath}\\include\\mono-2.0\"",
                string.Join(" ", files.Select(file => "\"" + Path.GetFullPath(file) + "\"")),
                $"\"{GetSgenLibPath(monoPath)}\"",
                Options.Compilation.CompileSharedLibrary ? "/LD" : string.Empty,
                $"/Fe{output}"
            };

            var invocation = string.Join(" ", args);

            var vsVersion = (VisualStudioVersion)(int)vsSdk.Version;
            var includes  = MSVCToolchain.GetSystemIncludes(vsVersion);

            var winSdks = new List <ToolchainVersion>();

            MSVCToolchain.GetWindowsKitsSdks(out winSdks);

            var libParentPath = Directory.GetParent(Directory.EnumerateDirectories(Path.Combine(winSdks.Last().Directory, "lib"), "um", SearchOption.AllDirectories).First());
            var libPaths      = libParentPath.EnumerateDirectories();

            Dictionary <string, string> envVars = null;

            if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("INCLUDE")))
            {
                envVars            = new Dictionary <string, string>();
                envVars["INCLUDE"] = string.Join(";", includes);

                var clLib = Path.GetFullPath(
                    Path.Combine(vsSdk.Directory, "..", "..", "VC", "lib"));
                envVars["LIB"] = clLib + ";" + string.Join(";", libPaths.Select(path => Path.Combine(path.FullName, "x86")));
            }

            Invoke(clBin, invocation, envVars);
        }
        void CompileNDK(IEnumerable <string> files)
        {
            RefreshAndroidSdk();

            var monoPath = ManagedToolchain.FindMonoPath();
            var name     = Path.GetFileNameWithoutExtension(Project.Assemblies[0]);
            var libName  = $"lib{name}.so";
            var ndkPath  = AndroidSdk.AndroidNdkPath;

            //NOTE: "arm64-v8a" doesn't compile at the moment
            foreach (var abi in new[] { "armeabi", "armeabi-v7a", "x86", "x86_64" })
            {
                string            extra = string.Empty;
                AndroidTargetArch targetArch;
                switch (abi)
                {
                case "armeabi":
                    targetArch = AndroidTargetArch.Arm;
                    break;

                case "armeabi-v7a":
                    targetArch = AndroidTargetArch.Arm;
                    extra      = " -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16";
                    break;

                case "arm64-v8a":
                    targetArch = AndroidTargetArch.Arm64;
                    break;

                case "x86":
                    targetArch = AndroidTargetArch.X86;
                    extra      = " -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32";
                    break;

                case "x86_64":
                    targetArch = AndroidTargetArch.X86_64;
                    extra      = " -march=x86-64 -mtune=intel -msse4.2 -mpopcnt -m64";
                    break;

                default:
                    throw new NotImplementedException();
                }

                var clangBin      = NdkUtil.GetNdkClangBin(Path.Combine(ndkPath, "toolchains"), targetArch);
                var systemInclude = NdkUtil.GetNdkPlatformIncludePath(ndkPath, targetArch, 24); //NOTE: 24 should be an option?
                var monoDroidPath = Path.Combine(MonoDroidSdk.BinPath, "..", "lib", "xbuild", "Xamarin", "Android", "lib", abi);
                var abiDir        = Path.Combine(Options.OutputDir, "android", "jni", abi);
                var output        = Path.Combine(abiDir, libName);

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

                var args = new List <string> {
                    $"--sysroot=\"{systemInclude}\"{extra}",
                    $"-D{DLLExportDefine}",
                    $"-I\"{monoPath}/include/mono-2.0\"",
                    $"-L\"{monoDroidPath}\" -lmonosgen-2.0",
                    string.Join(" ", files.ToList()),
                    "--std=c99",
                    $"-shared -o {output}",
                };

                var invocation = string.Join(" ", args);
                Invoke(clangBin, invocation);
            }
        }
        void CreateJar()
        {
            var executableSuffix = Platform.IsWindows ? ".exe" : string.Empty;
            var jar        = $"{Path.Combine(GetJavaSdkPath(), "bin", "jar" + executableSuffix)}";
            var classesDir = Path.Combine(Options.OutputDir, "classes");
            var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]);

            var args = new List <string> {
                "cf",
                Path.Combine(Options.OutputDir, name + ".jar"),
                $"-C {classesDir} ."
            };

            // On desktop Java, we need a few more files included
            if (Options.Compilation.Platform == TargetPlatform.MacOS)
            {
                //Copy native libs
                var platformDir = Path.Combine(classesDir, "darwin");
                if (!Directory.Exists(platformDir))
                {
                    Directory.CreateDirectory(platformDir);
                }

                var libName = $"lib{name}.dylib";
                var output  = Path.Combine(Options.OutputDir, libName);
                File.Copy(output, Path.Combine(platformDir, libName), true);

                //Copy .NET assemblies
                var assembliesDir = Path.Combine(classesDir, "assemblies");
                if (!Directory.Exists(assembliesDir))
                {
                    Directory.CreateDirectory(assembliesDir);
                }

                foreach (var assembly in Project.Assemblies)
                {
                    File.Copy(assembly, Path.Combine(assembliesDir, Path.GetFileName(assembly)), true);
                }

                //Copy any referenced assemblies such as mscorlib.dll
                List <string> referencedAssemblies = new List <string>();
                foreach (var assembly in Assemblies)
                {
                    foreach (var reference in assembly.GetReferencedAssemblies())
                    {
                        if (!referencedAssemblies.Contains(reference.Name))
                        {
                            referencedAssemblies.Add(reference.Name);
                        }
                    }
                }

                var monoPath = ManagedToolchain.FindMonoPath();
                foreach (var reference in referencedAssemblies)
                {
                    var referencePath = Path.Combine(monoPath, "lib", "mono", "4.5", reference + ".dll");
                    if (File.Exists(referencePath))
                    {
                        File.Copy(referencePath, Path.Combine(assembliesDir, reference + ".dll"), true);
                    }
                }
            }

            //Embed JNA into our jar file
            using (var stream = File.OpenRead(Path.Combine(FindDirectory("external"), "jna", "jna-4.4.0.jar")))
                using (var zip = new ZipArchive(stream))
                {
                    foreach (var entry in zip.Entries)
                    {
                        //Skip META-INF
                        if (entry.FullName.StartsWith("META-INF", StringComparison.Ordinal))
                        {
                            continue;
                        }

                        var entryPath = Path.Combine(classesDir, entry.FullName);

                        if (string.IsNullOrEmpty(entry.Name))
                        {
                            if (!Directory.Exists(entryPath))
                            {
                                Directory.CreateDirectory(entryPath);
                            }
                        }
                        else
                        {
                            //NOTE: *.so files on Android will be packaged in a different way
                            if (Options.Compilation.Platform == TargetPlatform.Android && entry.Name.EndsWith(".so", StringComparison.Ordinal))
                            {
                                continue;
                            }

                            using (var zipEntryStream = entry.Open())
                                using (var fileStream = File.Create(entryPath))
                                {
                                    zipEntryStream.CopyTo(fileStream);
                                }
                        }
                    }
                }

            var invocation = string.Join(" ", args);

            Invoke(jar, invocation);
        }
        bool CompileNDK(IEnumerable <string> files)
        {
            var monoPath = Path.Combine(ManagedToolchain.FindMonoPath(), "include", "mono-2.0");
            var name     = Path.GetFileNameWithoutExtension(Project.Assemblies[0]);
            var libName  = $"lib{name}.so";
            var ndkPath  = AndroidSdk.AndroidNdkPath;

            foreach (var abi in new[] { "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64" })
            {
                string            extra = string.Empty;
                AndroidTargetArch targetArch;
                switch (abi)
                {
                case "armeabi":
                    targetArch = AndroidTargetArch.Arm;
                    break;

                case "armeabi-v7a":
                    targetArch = AndroidTargetArch.Arm;
                    extra      = " -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16";
                    break;

                case "arm64-v8a":
                    targetArch = AndroidTargetArch.Arm64;
                    break;

                case "x86":
                    targetArch = AndroidTargetArch.X86;
                    extra      = " -march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32";
                    break;

                case "x86_64":
                    targetArch = AndroidTargetArch.X86_64;
                    extra      = " -march=x86-64 -mtune=intel -msse4.2 -mpopcnt -m64";
                    break;

                default:
                    throw new NotImplementedException();
                }

                var clangBin      = NdkUtil.GetNdkClangBin(Path.Combine(ndkPath, "toolchains"), targetArch);
                var systemInclude = NdkUtil.GetNdkPlatformIncludePath(ndkPath, targetArch, XamarinAndroid.ApiLevel);
                var monoDroidPath = Path.Combine(XamarinAndroid.LibraryPath, abi);
                var abiDir        = Path.Combine(Options.OutputDir, "android", "jni", abi);
                var outputPath    = Path.Combine(abiDir, libName);

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

                var args = new List <string> {
                    $"--sysroot=\"{systemInclude}\"{extra}",
                    "-fdiagnostics-color",
                    $"-D{DLLExportDefine}",
                    $"-I\"{monoPath}\"",
                    $"-L\"{monoDroidPath}\" -lmonosgen-2.0 -lmono-android.release",
                    string.Join(" ", files.ToList()),
                    "--std=c99",
                    $"-shared -o {outputPath}",
                };

                var invocation = string.Join(" ", args);
                var output     = Invoke(clangBin, invocation);
                if (output.ExitCode != 0)
                {
                    return(false);
                }
            }
            return(true);
        }
        bool CreateJar()
        {
            var executableSuffix = Platform.IsWindows ? ".exe" : string.Empty;
            var jar        = Path.Combine(XamarinAndroid.JavaSdkPath, "bin", "jar" + executableSuffix);
            var classesDir = Path.Combine(Options.OutputDir, "classes");
            var name       = Path.GetFileNameWithoutExtension(Project.Assemblies[0]).Replace('-', '_');

            var args = new List <string> {
                "cf",
                Path.Combine(Options.OutputDir, name + ".jar"),
                $"-C {classesDir} ."
            };

            // On desktop Java, we need a few more files included
            if (Options.Compilation.Platform != TargetPlatform.Android)
            {
                //Copy native libs
                var platformDir = Path.Combine(classesDir, GetJnaPlatformDir());
                if (!Directory.Exists(platformDir))
                {
                    Directory.CreateDirectory(platformDir);
                }

                var libName = (Options.Compilation.Platform == TargetPlatform.Windows) ?
                              $"{name}.dll" : $"lib{name}.dylib";
                var libFile = Path.Combine(Options.OutputDir, libName);
                if (File.Exists(libFile))
                {
                    var outputFile = Path.Combine(platformDir, libName);
                    File.Copy(libFile, outputFile, true);
                }

                //Copy .NET assemblies
                var assembliesDir = Path.Combine(classesDir, "assemblies");
                if (!Directory.Exists(assembliesDir))
                {
                    Directory.CreateDirectory(assembliesDir);
                }

                foreach (var assembly in Project.Assemblies)
                {
                    File.Copy(assembly, Path.Combine(assembliesDir, Path.GetFileName(assembly)), true);
                }

                //Copy any referenced assemblies such as mscorlib.dll
                List <string> referencedAssemblies = new List <string>();
                foreach (var assembly in Assemblies)
                {
                    foreach (var reference in assembly.GetReferencedAssemblies())
                    {
                        if (!referencedAssemblies.Contains(reference.Name))
                        {
                            referencedAssemblies.Add(reference.Name);
                        }
                    }
                }

                var monoPath = ManagedToolchain.FindMonoPath();
                foreach (var reference in referencedAssemblies)
                {
                    var referencePath = Path.Combine(monoPath, "lib", "mono", "4.5", reference + ".dll");
                    if (File.Exists(referencePath))
                    {
                        File.Copy(referencePath, Path.Combine(assembliesDir, reference + ".dll"), true);
                    }
                }

                // Copy the Mono runtime shared library to the JAR file
                var libDir = (Options.Compilation.Platform == TargetPlatform.Windows) ?
                             "bin" : "lib";
                libName = (Options.Compilation.Platform == TargetPlatform.Windows) ?
                          "mono-2.0-sgen.dll" : "libmonosgen-2.0.dylib";

                var monoLib = Path.Combine(monoPath, libDir, libName);
                File.Copy(monoLib, Path.Combine(platformDir, libName), true);
            }

            //Embed JNA into our jar file
            //  If on Android, we do not need any native libraries
            var jnaJar = Path.Combine(FindDirectory("external"), "jna", "jna-4.4.0.jar");
            var filter = Options.Compilation.Platform == TargetPlatform.Android ?
                         entry => entry.Name.EndsWith(".class", StringComparison.Ordinal) :
                         default(Func <ZipArchiveEntry, bool>);

            XamarinAndroidBuild.ExtractJar(jnaJar, classesDir, filter);

            //Embed mono.android.jar into our jar file
            if (Options.Compilation.Platform == TargetPlatform.Android)
            {
                var monoAndroidJar = XamarinAndroid.FindAssembly("mono.android.jar");
                XamarinAndroidBuild.ExtractJar(monoAndroidJar, classesDir);

                //Look for other JAR file dependencies from the user's assemblies
                foreach (var assembly in Assemblies)
                {
                    var intermediateDir = Path.Combine(Options.OutputDir, XamarinAndroidBuild.IntermediateDir, Path.GetFileNameWithoutExtension(assembly.Location));
                    if (Directory.Exists(intermediateDir))
                    {
                        foreach (var dependency in Directory.GetFiles(intermediateDir, "*.jar", SearchOption.AllDirectories))
                        {
                            XamarinAndroidBuild.ExtractJar(dependency, classesDir);
                        }
                    }
                }
            }

            var invocation = string.Join(" ", args);
            var output     = Invoke(jar, invocation);

            return(output.ExitCode == 0);
        }
Beispiel #9
0
        void CompileCode()
        {
            var files = GetOutputFiles("c");

            switch (Options.Language)
            {
            case GeneratorKind.ObjectiveC:
                files = files.Concat(GetOutputFiles("mm"));
                break;

            case GeneratorKind.CPlusPlus:
                files = files.Concat(GetOutputFiles("cpp"));
                break;
            }

            const string exportDefine = "MONO_M2N_DLL_EXPORT";

            if (Platform.IsWindows)
            {
                List <ToolchainVersion> vsSdks;
                MSVCToolchain.GetVisualStudioSdks(out vsSdks);

                if (vsSdks.Count == 0)
                {
                    throw new Exception("Visual Studio SDK was not found on your system.");
                }

                var vsSdk = vsSdks.FirstOrDefault();
                var clBin = Path.GetFullPath(
                    Path.Combine(vsSdk.Directory, "..", "..", "VC", "bin", "cl.exe"));

                var monoPath = ManagedToolchain.FindMonoPath();
                var output   = Options.LibraryName ??
                               Path.GetFileNameWithoutExtension(Options.Project.Assemblies[0]);
                output = Path.Combine(Options.OutputDir, output);
                var invocation = string.Format(
                    "/nologo /D{0} -I\"{1}\\include\\mono-2.0\" {2} \"{1}\\lib\\monosgen-2.0.lib\" {3} {4}",
                    exportDefine, monoPath, string.Join(" ", files.ToList()),
                    Options.CompileSharedLibrary ? "/LD" : string.Empty,
                    output);

                var vsVersion = (VisualStudioVersion)(int)vsSdk.Version;
                var includes  = MSVCToolchain.GetSystemIncludes(vsVersion);

                Dictionary <string, string> envVars = null;
                if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("INCLUDE")))
                {
                    envVars            = new Dictionary <string, string>();
                    envVars["INCLUDE"] = string.Join(";", includes);

                    var clLib = Path.GetFullPath(
                        Path.Combine(vsSdk.Directory, "..", "..", "VC", "lib"));
                    envVars["LIB"] = clLib;
                }

                InvokeCompiler(clBin, invocation, envVars);

                return;
            }
            else if (Platform.IsMacOS)
            {
                var xcodePath = XcodeToolchain.GetXcodeToolchainPath();
                var clangBin  = Path.Combine(xcodePath, "usr/bin/clang");
                var monoPath  = ManagedToolchain.FindMonoPath();

                var invocation = string.Format(
                    "-D{0} -framework CoreFoundation -I\"{1}/include/mono-2.0\" " +
                    "-L\"{1}/lib/\" -lmonosgen-2.0 {2}",
                    exportDefine, monoPath, string.Join(" ", files.ToList()));

                InvokeCompiler(clangBin, invocation);

                return;
            }

            throw new NotImplementedException();
        }
        void CompileMSVC(IEnumerable <string> files)
        {
            List <ToolchainVersion> vsSdks;

            MSVCToolchain.GetVisualStudioSdks(out vsSdks);

            if (vsSdks.Count == 0)
            {
                throw new Exception("Visual Studio SDK was not found on your system.");
            }

            ToolchainVersion vsSdk;

            if (Options.VsVersion == VisualStudioVersion.Latest)
            {
                vsSdk = vsSdks.LastOrDefault();
            }
            else
            {
                var exactVersion = vsSdks.Where(vs => (int)vs.Version == (int)Options.VsVersion)
                                   .Cast <ToolchainVersion?>().SingleOrDefault();
                if (!exactVersion.HasValue)
                {
                    throw new Exception($"Visual Studio SDK version {Options.VsVersion} was not found on your system.");
                }

                vsSdk = exactVersion.Value;
            }

            var clBin = Path.GetFullPath(
                Path.Combine(vsSdk.Directory, "..", "..", "VC", "bin", "cl.exe"));

            var monoPath = ManagedToolchain.FindMonoPath();
            var output   = Path.Combine(Options.OutputDir, Options.LibraryName ??
                                        Path.GetFileNameWithoutExtension(Project.Assemblies[0]));

            var args = new List <string> {
                "/nologo",
                $"-D{DLLExportDefine}",
                $"-I\"{monoPath}\\include\\mono-2.0\"",
                string.Join(" ", files.Select(file => Path.GetFullPath(file))),
                $"\"{monoPath}\\lib\\monosgen-2.0.lib\"",
                Options.CompileSharedLibrary ? "/LD" : string.Empty,
                $"/Fe{output}"
            };

            var invocation = string.Join(" ", args);

            var vsVersion = (VisualStudioVersion)(int)vsSdk.Version;
            var includes  = MSVCToolchain.GetSystemIncludes(vsVersion);

            Dictionary <string, string> envVars = null;

            if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("INCLUDE")))
            {
                envVars            = new Dictionary <string, string>();
                envVars["INCLUDE"] = string.Join(";", includes);

                var clLib = Path.GetFullPath(
                    Path.Combine(vsSdk.Directory, "..", "..", "VC", "lib"));
                envVars["LIB"] = clLib;
            }

            Invoke(clBin, invocation, envVars);
        }