public override bool VisitASTContext(ASTContext context) { string error; const string qtVersionVariable = "QT_VERSION"; var qtVersion = ProcessHelper.Run(this.qmake, string.Format("-query {0}", qtVersionVariable), out error); var qtVersionFile = Path.Combine(this.Context.Options.OutputDir, qtVersionVariable); var qtVersionFileInfo = new FileInfo(qtVersionFile); var text = string.Empty; if (!qtVersionFileInfo.Exists || (text = File.ReadAllText(qtVersionFile)) != qtVersion) { File.WriteAllText(qtVersionFile, qtVersion); qtVersionFileInfo = new FileInfo(qtVersionFile); } var dir = Platform.IsMacOS ? this.Context.Options.OutputDir : Path.Combine(this.Context.Options.OutputDir, "release"); foreach (var module in this.Context.Options.Modules) { var inlines = Path.GetFileName(string.Format("{0}{1}.{2}", Platform.IsWindows ? string.Empty : "lib", module.InlinesLibraryName, Platform.IsMacOS ? "dylib" : "dll")); var libFile = Path.Combine(dir, inlines); var inlinesFileInfo = new FileInfo(libFile); if (!inlinesFileInfo.Exists || qtVersionFileInfo.LastWriteTimeUtc > inlinesFileInfo.LastWriteTimeUtc) { if (!this.CompileInlines(module)) { continue; } } var parserOptions = new ParserOptions(); parserOptions.AddLibraryDirs(dir); parserOptions.LibraryFile = inlines; using (var parserResult = CppSharp.Parser.ClangParser.ParseLibrary(parserOptions)) { if (parserResult.Kind == ParserResultKind.Success) { var nativeLibrary = CppSharp.ClangParser.ConvertLibrary(parserResult.Library); this.Context.Symbols.Libraries.Add(nativeLibrary); this.Context.Symbols.IndexSymbols(); parserResult.Library.Dispose(); } } } return(true); }
private void CompileMakefile(GenerateSymbolsPass.SymbolsCodeEventArgs e) { var pro = $"{e.Module.SymbolsLibraryName}.pro"; var path = Path.Combine(e.OutputDir, pro); var proBuilder = new StringBuilder(); var qtModules = string.Join(" ", from header in e.Module.Headers where !header.EndsWith(".h", StringComparison.Ordinal) select header.Substring("Qt".Length).ToLowerInvariant()); // QtTest is only library which has a "lib" suffix to its module alias for qmake if (qtModules == "test") { qtModules += "lib"; } proBuilder.Append($"QT += {qtModules}\n"); proBuilder.Append("CONFIG += c++11\n"); proBuilder.Append($"TARGET = {e.Module.SymbolsLibraryName}\n"); proBuilder.Append("TEMPLATE = lib\n"); proBuilder.Append($"SOURCES += {Path.ChangeExtension(pro, "cpp")}\n"); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { proBuilder.Append("LIBS += -loleaut32 -lole32"); } File.WriteAllText(path, proBuilder.ToString()); int error; string errorMessage; ProcessHelper.Run(this.qtInfo.QMake, $"\"{path}\"", out error, out errorMessage); if (!string.IsNullOrEmpty(errorMessage)) { Console.WriteLine(errorMessage); return; } var makefile = File.Exists(Path.Combine(e.OutputDir, "Makefile.Release")) ? "Makefile.Release" : "Makefile"; e.CustomCompiler = this.qtInfo.Make; e.CompilerArguments = $"-f {makefile}"; e.OutputDir = Platform.IsMacOS ? e.OutputDir : Path.Combine(e.OutputDir, "release"); }
public override bool VisitLibrary(ASTContext library) { bool result = base.VisitLibrary(library); string pro = string.Format("{0}.pro", this.Driver.Options.InlinesLibraryName); string path = Path.Combine(this.Driver.Options.OutputDir, pro); StringBuilder proBuilder = new StringBuilder(); proBuilder.Append("QMAKE_CXXFLAGS += -fkeep-inline-functions -std=c++0x\n"); proBuilder.AppendFormat("TARGET = {0}\n", this.Driver.Options.InlinesLibraryName); proBuilder.Append("TEMPLATE = lib\n"); proBuilder.AppendFormat("SOURCES += {0}\n", Path.ChangeExtension(pro, "cpp")); File.WriteAllText(path, proBuilder.ToString()); string error; ProcessHelper.Run(this.qmake, string.Format("\"{0}\"", path), out error, this.Driver.Options.OutputDir); if (!string.IsNullOrEmpty(error)) { Console.WriteLine(error); return(false); } ProcessHelper.Run(this.make, "-f Makefile.Release", out error, this.Driver.Options.OutputDir); if (!string.IsNullOrEmpty(error)) { Console.WriteLine(error); return(false); } var parserOptions = new ParserOptions(); parserOptions.addLibraryDirs(Path.Combine(this.Driver.Options.OutputDir, "release")); parserOptions.FileName = Path.GetFileName(string.Format("lib{0}.a", Path.GetFileNameWithoutExtension(pro))); var parserResult = ClangParser.ParseLibrary(parserOptions); if (parserResult.Kind == ParserResultKind.Success) { var nativeLibrary = CppSharp.ClangParser.ConvertLibrary(parserResult.Library); this.Driver.Symbols.Libraries.Add(nativeLibrary); this.Driver.Symbols.IndexSymbols(); } return(result); }
private bool CompileInlines(Module module) { var pro = string.Format("{0}.pro", module.InlinesLibraryName); var path = Path.Combine(this.Context.Options.OutputDir, pro); var proBuilder = new StringBuilder(); var qtModules = string.Join(" ", from header in module.Headers where !header.EndsWith(".h", StringComparison.Ordinal) select header.Substring("Qt".Length).ToLowerInvariant()); switch (qtModules) { // QtTest is only library which has a "lib" suffix to its module alias for qmake case "test": qtModules += "lib"; break; // HACK: work around https://bugreports.qt.io/browse/QTBUG-54030 case "bluetooth": qtModules += " network"; break; } proBuilder.AppendFormat("QT += {0}\n", qtModules); proBuilder.Append("CONFIG += c++11\n"); proBuilder.Append("QMAKE_CXXFLAGS += -fkeep-inline-functions\n"); proBuilder.AppendFormat("TARGET = {0}\n", module.InlinesLibraryName); proBuilder.Append("TEMPLATE = lib\n"); proBuilder.AppendFormat("SOURCES += {0}\n", Path.ChangeExtension(pro, "cpp")); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { proBuilder.Append("LIBS += -loleaut32 -lole32"); } File.WriteAllText(path, proBuilder.ToString()); string error; // HACK: Clang does not support -fkeep-inline-functions so force compilation with (the real) GCC on OS X ProcessHelper.Run(this.qmake, string.Format("{0}\"{1}\"", Platform.IsMacOS ? "-spec macx-g++ " : string.Empty, path), out error); if (!string.IsNullOrEmpty(error)) { Console.WriteLine(error); return(false); } var makefile = File.Exists(Path.Combine(this.Context.Options.OutputDir, "Makefile.Release")) ? "Makefile.Release" : "Makefile"; if (Platform.IsMacOS) { // HACK: Clang does not support -fkeep-inline-functions so force compilation with (the real) GCC on OS X var makefilePath = Path.Combine(this.Context.Options.OutputDir, makefile); var script = new StringBuilder(File.ReadAllText(makefilePath)); var xcodePath = XcodeToolchain.GetXcodePath(); script.Replace(Path.Combine(xcodePath, "Contents", "Developer", "usr", "bin", "gcc"), "/usr/local/bin/gcc"); script.Replace(Path.Combine(xcodePath, "Contents", "Developer", "usr", "bin", "g++"), "/usr/local/bin/g++"); File.WriteAllText(makefilePath, script.ToString()); } ProcessHelper.Run(this.make, string.Format("-j{0} -f {1}", Environment.ProcessorCount + 1, makefile), out error, true); if (!string.IsNullOrEmpty(error)) { Console.WriteLine(error); return(false); } return(true); }
private void CompileMakefile(GenerateInlinesPass.InlinesCodeEventArgs e) { var pro = $"{e.Module.InlinesLibraryName}.pro"; var path = Path.Combine(e.OutputDir, pro); var proBuilder = new StringBuilder(); var qtModules = string.Join(" ", from header in e.Module.Headers where !header.EndsWith(".h", StringComparison.Ordinal) select header.Substring("Qt".Length).ToLowerInvariant()); // QtTest is only library which has a "lib" suffix to its module alias for qmake if (qtModules == "test") { qtModules += "lib"; } proBuilder.Append($"QT += {qtModules}\n"); proBuilder.Append("CONFIG += c++11\n"); proBuilder.Append($"TARGET = {e.Module.InlinesLibraryName}\n"); proBuilder.Append("TEMPLATE = lib\n"); proBuilder.Append($"SOURCES += {Path.ChangeExtension(pro, "cpp")}\n"); if (Environment.OSVersion.Platform == PlatformID.Win32NT) { proBuilder.Append("LIBS += -loleaut32 -lole32"); } File.WriteAllText(path, proBuilder.ToString()); // HACK: work around https://bugreports.qt.io/browse/QTBUG-55952 if (e.Module.LibraryName == "Qt3DRender.Sharp") { var cpp = Path.ChangeExtension(pro, "cpp"); var unlinkable = new[] { "&Qt3DRender::QSortCriterion::tr;", "&Qt3DRender::QSortCriterion::trUtf8;", "&Qt3DRender::qt_getEnumMetaObject;" }; var linkable = (from line in File.ReadLines(cpp) where unlinkable.All(ul => !line.EndsWith(ul, StringComparison.Ordinal)) select line).ToList(); File.WriteAllLines(cpp, linkable); } if (e.Module.LibraryName == "QtGui.Sharp") { var cpp = Path.ChangeExtension(pro, "cpp"); var unlinkable = new[] { "_CoreBackend", "_DeprecatedBackend", }; var linkable = (from line in File.ReadLines(cpp) where unlinkable.All(ul => !line.Contains(ul)) select line).ToList(); File.WriteAllLines(cpp, linkable); } int error; string errorMessage; ProcessHelper.Run(this.qtInfo.QMake, $"\"{path}\"", out error, out errorMessage); if (!string.IsNullOrEmpty(errorMessage)) { Console.WriteLine(errorMessage); return; } var makefile = File.Exists(Path.Combine(e.OutputDir, "Makefile.Release")) ? "Makefile.Release" : "Makefile"; e.CustomCompiler = this.qtInfo.Make; e.CompilerArguments = $"-f {makefile}"; e.OutputDir = Platform.IsMacOS ? e.OutputDir : Path.Combine(e.OutputDir, "release"); }