6
6
using CppSharp . Passes ;
7
7
using CppSharp ;
8
8
using CppSharp . Parser ;
9
+ using System . Threading ;
9
10
10
11
namespace QtSharp
11
12
{
@@ -22,71 +23,35 @@ public CompileInlinesPass(string qmake, string make)
22
23
23
24
public override bool VisitASTContext ( ASTContext context )
24
25
{
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
- }
36
26
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 ;
37
30
foreach ( var module in this . Context . Options . Modules )
38
31
{
39
32
var inlines = Path . GetFileName ( string . Format ( "{0}{1}.{2}" , Platform . IsWindows ? string . Empty : "lib" ,
40
33
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 ) ;
63
35
}
64
36
return true ;
65
37
}
66
38
67
- private bool CompileInlines ( Module module )
39
+ private void CompileInlines ( Module module , string dir , string inlines )
68
40
{
69
41
var pro = string . Format ( "{0}.pro" , module . InlinesLibraryName ) ;
70
42
var path = Path . Combine ( this . Context . Options . OutputDir , pro ) ;
71
43
var proBuilder = new StringBuilder ( ) ;
72
44
var qtModules = string . Join ( " " , from header in module . Headers
73
45
where ! header . EndsWith ( ".h" , StringComparison . Ordinal )
74
46
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" )
76
49
{
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" ;
85
51
}
86
52
87
53
proBuilder . AppendFormat ( "QT += {0}\n " , qtModules ) ;
88
54
proBuilder . Append ( "CONFIG += c++11\n " ) ;
89
- proBuilder . Append ( "QMAKE_CXXFLAGS += -fkeep-inline-functions\n " ) ;
90
55
proBuilder . AppendFormat ( "TARGET = {0}\n " , module . InlinesLibraryName ) ;
91
56
proBuilder . Append ( "TEMPLATE = lib\n " ) ;
92
57
proBuilder . AppendFormat ( "SOURCES += {0}\n " , Path . ChangeExtension ( pro , "cpp" ) ) ;
@@ -95,32 +60,92 @@ private bool CompileInlines(Module module)
95
60
proBuilder . Append ( "LIBS += -loleaut32 -lole32" ) ;
96
61
}
97
62
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
+ }
98
78
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 ) ;
101
80
if ( ! string . IsNullOrEmpty ( error ) )
102
81
{
103
82
Console . WriteLine ( error ) ;
104
- return false ;
83
+ return ;
105
84
}
106
85
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
108
131
{
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 ;
116
133
}
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
119
135
{
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
+ }
122
145
}
123
- return true ;
124
146
}
147
+
148
+ private int remainingCompilationTasks ;
149
+ private static readonly object @lock = new object ( ) ;
125
150
}
126
151
}
0 commit comments