2
2
using System . Collections . Generic ;
3
3
using System . Diagnostics ;
4
4
using System . IO ;
5
- using System . Threading ;
6
5
7
6
using Microsoft . Build . Framework ;
8
- using Microsoft . Build . Utilities ;
9
-
10
- using Xamarin . Android . Tools ;
11
7
using Microsoft . Android . Build . Tasks ;
12
8
13
9
namespace Xamarin . Android . Tasks
@@ -16,13 +12,6 @@ public class CompileNativeAssembly : AsyncTask
16
12
{
17
13
public override string TaskPrefix => "CNA" ;
18
14
19
- sealed class Config
20
- {
21
- public string AssemblerPath ;
22
- public string AssemblerOptions ;
23
- public string InputSource ;
24
- }
25
-
26
15
[ Required ]
27
16
public ITaskItem [ ] Sources { get ; set ; }
28
17
@@ -37,124 +26,34 @@ sealed class Config
37
26
38
27
public override System . Threading . Tasks . Task RunTaskAsync ( )
39
28
{
40
- return this . WhenAll ( GetAssemblerConfigs ( ) , RunAssembler ) ;
29
+ var context = new NativeAssemblerCompilation . AssemblerRunContext (
30
+ Log ,
31
+ Path . GetFullPath ( WorkingDirectory ) ,
32
+ registerForCancellation : RegisterForCancellation ,
33
+ cancel : Cancel
34
+ ) ;
35
+
36
+ return this . WhenAll (
37
+ GetAssemblerConfigs ( ) ,
38
+ ( NativeAssemblerCompilation . AssemblerConfig config ) => NativeAssemblerCompilation . RunAssembler ( context , config )
39
+ ) ;
41
40
}
42
41
43
- void RunAssembler ( Config config )
42
+ void RegisterForCancellation ( Process proc )
44
43
{
45
- var stdout_completed = new ManualResetEvent ( false ) ;
46
- var stderr_completed = new ManualResetEvent ( false ) ;
47
- var psi = new ProcessStartInfo ( ) {
48
- FileName = config . AssemblerPath ,
49
- Arguments = config . AssemblerOptions ,
50
- UseShellExecute = false ,
51
- RedirectStandardOutput = true ,
52
- RedirectStandardError = true ,
53
- CreateNoWindow = true ,
54
- WindowStyle = ProcessWindowStyle . Hidden ,
55
- WorkingDirectory = WorkingDirectory ,
56
- } ;
57
-
58
- string assemblerName = Path . GetFileName ( config . AssemblerPath ) ;
59
- LogDebugMessage ( $ "[LLVM llc] { psi . FileName } { psi . Arguments } ") ;
60
-
61
- var stdoutLines = new List < string > ( ) ;
62
- var stderrLines = new List < string > ( ) ;
63
-
64
- using ( var proc = new Process ( ) ) {
65
- proc . OutputDataReceived += ( s , e ) => {
66
- if ( e . Data != null ) {
67
- OnOutputData ( assemblerName , s , e ) ;
68
- stdoutLines . Add ( e . Data ) ;
69
- } else
70
- stdout_completed . Set ( ) ;
71
- } ;
72
-
73
- proc . ErrorDataReceived += ( s , e ) => {
74
- if ( e . Data != null ) {
75
- OnErrorData ( assemblerName , s , e ) ;
76
- stderrLines . Add ( e . Data ) ;
77
- } else
78
- stderr_completed . Set ( ) ;
79
- } ;
80
-
81
- proc . StartInfo = psi ;
82
- proc . Start ( ) ;
83
- proc . BeginOutputReadLine ( ) ;
84
- proc . BeginErrorReadLine ( ) ;
85
- CancellationToken . Register ( ( ) => { try { proc . Kill ( ) ; } catch ( Exception ) { } } ) ;
86
- proc . WaitForExit ( ) ;
87
-
88
- if ( psi . RedirectStandardError )
89
- stderr_completed . WaitOne ( TimeSpan . FromSeconds ( 30 ) ) ;
90
-
91
- if ( psi . RedirectStandardOutput )
92
- stdout_completed . WaitOne ( TimeSpan . FromSeconds ( 30 ) ) ;
93
-
94
- if ( proc . ExitCode != 0 ) {
95
- var sb = MonoAndroidHelper . MergeStdoutAndStderrMessages ( stdoutLines , stderrLines ) ;
96
- LogCodedError ( "XA3006" , Properties . Resources . XA3006 , Path . GetFileName ( config . InputSource ) , sb . ToString ( ) ) ;
97
- Cancel ( ) ;
44
+ CancellationToken . Register ( ( ) => {
45
+ try {
46
+ proc . Kill ( ) ;
47
+ } catch ( Exception ) {
98
48
}
99
- }
49
+ } ) ;
100
50
}
101
51
102
- static readonly List < string > llcArguments = new ( ) {
103
- "-O2" ,
104
- "--debugger-tune=lldb" , // NDK uses lldb now
105
- "--debugify-level=location+variables" ,
106
- "--fatal-warnings" ,
107
- "--filetype=obj" ,
108
- "--relocation-model=pic" ,
109
- } ;
110
-
111
- static readonly List < string > llvmMcArguments = new ( ) {
112
- "--assemble" ,
113
- "--filetype=obj" ,
114
- "-g" ,
115
- } ;
116
-
117
- IEnumerable < Config > GetAssemblerConfigs ( )
52
+ IEnumerable < NativeAssemblerCompilation . AssemblerConfig > GetAssemblerConfigs ( )
118
53
{
119
- const string llcOptions =
120
- "-O2 " +
121
- "--debugger-tune=lldb " + // NDK uses lldb now
122
- "--debugify-level=location+variables " +
123
- "--fatal-warnings " +
124
- "--filetype=obj " +
125
- "--relocation-model=pic" ;
126
- string llcPath = Path . Combine ( AndroidBinUtilsDirectory , "llc" ) ;
127
-
128
54
foreach ( ITaskItem item in Sources ) {
129
- // We don't need the directory since our WorkingDirectory is where all the sources are
130
- string sourceFile = Path . GetFileName ( item . ItemSpec ) ;
131
- string outputFile = QuoteFileName ( Path . ChangeExtension ( sourceFile , ".o" ) ) ;
132
- string executableDir = Path . GetDirectoryName ( llcPath ) ;
133
- string executableName = MonoAndroidHelper . GetExecutablePath ( executableDir , Path . GetFileName ( llcPath ) ) ;
134
-
135
- yield return new Config {
136
- InputSource = item . ItemSpec ,
137
- AssemblerPath = Path . Combine ( executableDir , executableName ) ,
138
- AssemblerOptions = $ "{ llcOptions } -o={ outputFile } { QuoteFileName ( sourceFile ) } ",
139
- } ;
55
+ yield return NativeAssemblerCompilation . GetAssemblerConfig ( AndroidBinUtilsDirectory , item , stripFilePaths : true ) ;
140
56
}
141
57
}
142
-
143
- void OnOutputData ( string assemblerName , object sender , DataReceivedEventArgs e )
144
- {
145
- LogDebugMessage ( $ "[{ assemblerName } stdout] { e . Data } ") ;
146
- }
147
-
148
- void OnErrorData ( string assemblerName , object sender , DataReceivedEventArgs e )
149
- {
150
- LogMessage ( $ "[{ assemblerName } stderr] { e . Data } ", MessageImportance . High ) ;
151
- }
152
-
153
- static string QuoteFileName ( string fileName )
154
- {
155
- var builder = new CommandLineBuilder ( ) ;
156
- builder . AppendFileNameIfNotNull ( fileName ) ;
157
- return builder . ToString ( ) ;
158
- }
159
58
}
160
59
}
0 commit comments