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); }
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); }