Skip to content

Commit 5dc69ae

Browse files
committed
Parallelised the compilation of inlines thus significantly speeding it up.
1 parent 36cf51b commit 5dc69ae

File tree

2 files changed

+91
-60
lines changed

2 files changed

+91
-60
lines changed

CHANGELOG

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
0.7.0 - 5.2.2017
2+
Added:
3+
- Bindings for Qt 5.8.
4+
Fixed:
5+
- Decreased the size of inlines 24 times, from 60 to 2,5 total size.
6+
17
0.6.1 - 17.9.2016
28
Fixed:
39
- Removed all mappings to C# structures because their empty constructors are not correctly wrapped yet.

QtSharp/CompileInlinesPass.cs

+85-60
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using CppSharp.Passes;
77
using CppSharp;
88
using CppSharp.Parser;
9+
using System.Threading;
910

1011
namespace QtSharp
1112
{
@@ -22,71 +23,35 @@ public CompileInlinesPass(string qmake, string make)
2223

2324
public override bool VisitASTContext(ASTContext context)
2425
{
25-
string error;
26-
const string qtVersionVariable = "QT_VERSION";
27-
var qtVersion = ProcessHelper.Run(this.qmake, string.Format("-query {0}", qtVersionVariable), out error);
28-
var qtVersionFile = Path.Combine(this.Context.Options.OutputDir, qtVersionVariable);
29-
var qtVersionFileInfo = new FileInfo(qtVersionFile);
30-
var text = string.Empty;
31-
if (!qtVersionFileInfo.Exists || (text = File.ReadAllText(qtVersionFile)) != qtVersion)
32-
{
33-
File.WriteAllText(qtVersionFile, qtVersion);
34-
qtVersionFileInfo = new FileInfo(qtVersionFile);
35-
}
3626
var dir = Platform.IsMacOS ? this.Context.Options.OutputDir : Path.Combine(this.Context.Options.OutputDir, "release");
27+
var findSymbolsPass = this.Context.TranslationUnitPasses.FindPass<FindSymbolsPass>();
28+
findSymbolsPass.Wait = true;
29+
remainingCompilationTasks = this.Context.Options.Modules.Count;
3730
foreach (var module in this.Context.Options.Modules)
3831
{
3932
var inlines = Path.GetFileName(string.Format("{0}{1}.{2}", Platform.IsWindows ? string.Empty : "lib",
4033
module.InlinesLibraryName, Platform.IsMacOS ? "dylib" : "dll"));
41-
var libFile = Path.Combine(dir, inlines);
42-
var inlinesFileInfo = new FileInfo(libFile);
43-
if (!inlinesFileInfo.Exists || qtVersionFileInfo.LastWriteTimeUtc > inlinesFileInfo.LastWriteTimeUtc)
44-
{
45-
if (!this.CompileInlines(module))
46-
{
47-
continue;
48-
}
49-
}
50-
var parserOptions = new ParserOptions();
51-
parserOptions.AddLibraryDirs(dir);
52-
parserOptions.LibraryFile = inlines;
53-
using (var parserResult = CppSharp.Parser.ClangParser.ParseLibrary(parserOptions))
54-
{
55-
if (parserResult.Kind == ParserResultKind.Success)
56-
{
57-
var nativeLibrary = CppSharp.ClangParser.ConvertLibrary(parserResult.Library);
58-
this.Context.Symbols.Libraries.Add(nativeLibrary);
59-
this.Context.Symbols.IndexSymbols();
60-
parserResult.Library.Dispose();
61-
}
62-
}
34+
this.CompileInlines(module, dir, inlines);
6335
}
6436
return true;
6537
}
6638

67-
private bool CompileInlines(Module module)
39+
private void CompileInlines(Module module, string dir, string inlines)
6840
{
6941
var pro = string.Format("{0}.pro", module.InlinesLibraryName);
7042
var path = Path.Combine(this.Context.Options.OutputDir, pro);
7143
var proBuilder = new StringBuilder();
7244
var qtModules = string.Join(" ", from header in module.Headers
7345
where !header.EndsWith(".h", StringComparison.Ordinal)
7446
select header.Substring("Qt".Length).ToLowerInvariant());
75-
switch (qtModules)
47+
// QtTest is only library which has a "lib" suffix to its module alias for qmake
48+
if (qtModules == "test")
7649
{
77-
// QtTest is only library which has a "lib" suffix to its module alias for qmake
78-
case "test":
79-
qtModules += "lib";
80-
break;
81-
// HACK: work around https://bugreports.qt.io/browse/QTBUG-54030
82-
case "bluetooth":
83-
qtModules += " network";
84-
break;
50+
qtModules += "lib";
8551
}
8652

8753
proBuilder.AppendFormat("QT += {0}\n", qtModules);
8854
proBuilder.Append("CONFIG += c++11\n");
89-
proBuilder.Append("QMAKE_CXXFLAGS += -fkeep-inline-functions\n");
9055
proBuilder.AppendFormat("TARGET = {0}\n", module.InlinesLibraryName);
9156
proBuilder.Append("TEMPLATE = lib\n");
9257
proBuilder.AppendFormat("SOURCES += {0}\n", Path.ChangeExtension(pro, "cpp"));
@@ -95,32 +60,92 @@ private bool CompileInlines(Module module)
9560
proBuilder.Append("LIBS += -loleaut32 -lole32");
9661
}
9762
File.WriteAllText(path, proBuilder.ToString());
63+
// HACK: work around https://bugreports.qt.io/browse/QTBUG-55952
64+
if (module.LibraryName == "Qt3DRender.Sharp")
65+
{
66+
var cpp = Path.ChangeExtension(pro, "cpp");
67+
var unlinkable = new[]
68+
{
69+
"&Qt3DRender::QSortCriterion::tr;",
70+
"&Qt3DRender::QSortCriterion::trUtf8;",
71+
"&Qt3DRender::qt_getEnumMetaObject;"
72+
};
73+
var linkable = (from line in File.ReadLines(cpp)
74+
where unlinkable.All(ul => !line.EndsWith(ul, StringComparison.Ordinal))
75+
select line).ToList();
76+
File.WriteAllLines(cpp, linkable);
77+
}
9878
string error;
99-
// HACK: Clang does not support -fkeep-inline-functions so force compilation with (the real) GCC on OS X
100-
ProcessHelper.Run(this.qmake, string.Format("{0}\"{1}\"", Platform.IsMacOS ? "-spec macx-g++ " : string.Empty, path), out error);
79+
ProcessHelper.Run(this.qmake, $"\"{path}\"", out error);
10180
if (!string.IsNullOrEmpty(error))
10281
{
10382
Console.WriteLine(error);
104-
return false;
83+
return;
10584
}
10685
var makefile = File.Exists(Path.Combine(this.Context.Options.OutputDir, "Makefile.Release")) ? "Makefile.Release" : "Makefile";
107-
if (Platform.IsMacOS)
86+
InvokeCompiler(dir, inlines, makefile);
87+
}
88+
89+
private void InvokeCompiler(string dir, string inlines, string makefile)
90+
{
91+
new Thread(() =>
92+
{
93+
try
94+
{
95+
string error;
96+
ProcessHelper.Run(this.make, string.Format("-j{0} -f {1}", Environment.ProcessorCount + 1, makefile), out error, true);
97+
if (string.IsNullOrEmpty(error))
98+
{
99+
var parserOptions = new ParserOptions();
100+
parserOptions.AddLibraryDirs(dir);
101+
parserOptions.LibraryFile = inlines;
102+
using (var parserResult = CppSharp.Parser.ClangParser.ParseLibrary(parserOptions))
103+
{
104+
if (parserResult.Kind == ParserResultKind.Success)
105+
{
106+
var nativeLibrary = CppSharp.ClangParser.ConvertLibrary(parserResult.Library);
107+
lock (@lock)
108+
{
109+
this.Context.Symbols.Libraries.Add(nativeLibrary);
110+
this.Context.Symbols.IndexSymbols();
111+
}
112+
parserResult.Library.Dispose();
113+
}
114+
}
115+
}
116+
else
117+
{
118+
Console.WriteLine(error);
119+
}
120+
}
121+
finally
122+
{
123+
RemainingCompilationTasks--;
124+
}
125+
}).Start();
126+
}
127+
128+
private int RemainingCompilationTasks
129+
{
130+
get
108131
{
109-
// HACK: Clang does not support -fkeep-inline-functions so force compilation with (the real) GCC on OS X
110-
var makefilePath = Path.Combine(this.Context.Options.OutputDir, makefile);
111-
var script = new StringBuilder(File.ReadAllText(makefilePath));
112-
var xcodePath = XcodeToolchain.GetXcodePath();
113-
script.Replace(Path.Combine(xcodePath, "Contents", "Developer", "usr", "bin", "gcc"), "/usr/local/bin/gcc");
114-
script.Replace(Path.Combine(xcodePath, "Contents", "Developer", "usr", "bin", "g++"), "/usr/local/bin/g++");
115-
File.WriteAllText(makefilePath, script.ToString());
132+
return remainingCompilationTasks;
116133
}
117-
ProcessHelper.Run(this.make, string.Format("-j{0} -f {1}", Environment.ProcessorCount + 1, makefile), out error, true);
118-
if (!string.IsNullOrEmpty(error))
134+
set
119135
{
120-
Console.WriteLine(error);
121-
return false;
136+
if (remainingCompilationTasks != value)
137+
{
138+
remainingCompilationTasks = value;
139+
if (remainingCompilationTasks == 0)
140+
{
141+
var findSymbolsPass = this.Context.TranslationUnitPasses.FindPass<FindSymbolsPass>();
142+
findSymbolsPass.Wait = false;
143+
}
144+
}
122145
}
123-
return true;
124146
}
147+
148+
private int remainingCompilationTasks;
149+
private static readonly object @lock = new object();
125150
}
126151
}

0 commit comments

Comments
 (0)