1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.github.maven_nar;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29
30 import org.apache.maven.plugin.MojoExecutionException;
31 import org.apache.maven.plugin.MojoFailureException;
32 import org.apache.maven.plugins.annotations.Parameter;
33 import org.apache.maven.project.MavenProject;
34 import org.codehaus.plexus.util.StringUtils;
35
36 import com.github.maven_nar.cpptasks.CUtil;
37 import com.github.maven_nar.cpptasks.CompilerDef;
38 import com.github.maven_nar.cpptasks.CompilerEnum;
39 import com.github.maven_nar.cpptasks.OptimizationEnum;
40 import com.github.maven_nar.cpptasks.types.CompilerArgument;
41 import com.github.maven_nar.cpptasks.types.ConditionalFileSet;
42 import com.github.maven_nar.cpptasks.types.DefineArgument;
43 import com.github.maven_nar.cpptasks.types.DefineSet;
44
45
46
47
48
49
50 public abstract class Compiler {
51
52 public static final String MAIN = "main";
53
54 public static final String TEST = "test";
55
56
57
58
59
60
61 @Parameter
62 private String name;
63
64
65
66
67 @Parameter
68 private String prefix;
69
70
71
72
73 @Parameter
74 private String toolPath;
75
76
77
78
79 @Parameter(defaultValue = "${basedir}/src/main", required = true)
80 private File sourceDirectory;
81
82
83
84
85 @Parameter(defaultValue = "${basedir}/src/test", required = true)
86 private File testSourceDirectory;
87
88
89
90
91 @Parameter(required = true)
92 private Set<String> includes = new HashSet<>();
93
94
95
96
97 @Parameter(required = true)
98 private Set<String> excludes = new HashSet<>();
99
100
101
102
103 @Parameter(required = true)
104 private Set<String> testIncludes = new HashSet<>();
105
106
107
108
109 @Parameter(required = true)
110 private Set<String> testExcludes = new HashSet<>();
111
112 @Parameter(defaultValue = "false", required = false)
113 private boolean ccache = false;
114
115
116
117
118 @Parameter(required = true)
119 private boolean debug = false;
120
121
122
123
124 @Parameter(defaultValue = "true", required = true)
125 private boolean exceptions = true;
126
127
128
129
130 @Parameter(defaultValue = "true", required = true)
131 private boolean rtti = true;
132
133
134
135
136
137
138 @Parameter(defaultValue = "none", required = true)
139 private String optimize = "none";
140
141
142
143
144
145 @Parameter(required = true)
146 private boolean multiThreaded = false;
147
148
149
150
151 @Parameter
152 private List<String> defines;
153
154
155
156
157
158
159 @Parameter
160 private String defineSet;
161
162
163
164
165 @Parameter(required = true)
166 private boolean clearDefaultDefines;
167
168
169
170
171 @Parameter
172 private List<String> undefines;
173
174
175
176
177
178
179 @Parameter
180 private String undefineSet;
181
182
183
184
185 @Parameter
186 private boolean clearDefaultUndefines;
187
188
189
190
191 @Parameter
192 private List<IncludePath> includePaths;
193
194
195
196
197 @Parameter
198 private List<IncludePath> testIncludePaths;
199
200
201
202
203 @Parameter
204 private List<String> systemIncludePaths;
205
206
207
208
209
210 @Parameter
211 private List<String> options;
212
213
214
215
216
217 @Parameter
218 private List<String> testOptions;
219
220
221
222
223
224 @Parameter
225 private String optionSet;
226
227
228
229
230 @Parameter(required = true)
231 private boolean clearDefaultOptions;
232
233
234
235
236 @Parameter
237 private String compileOrder;
238 private AbstractCompileMojo mojo;
239
240 protected Compiler() {
241 }
242
243
244
245
246
247
248
249 private String cleanDefineValue(final String value) {
250 return value.replaceAll("\r", "").replaceAll("\n", "");
251 }
252
253 public final void copyIncludeFiles(final MavenProject mavenProject, final File targetDirectory) throws IOException {
254 for (final IncludePath includePath : getIncludePaths("dummy")) {
255 if (includePath.exists()) {
256 NarUtil.copyDirectoryStructure(includePath.getFile(), targetDirectory, includePath.getIncludes(),
257 NarUtil.DEFAULT_EXCLUDES);
258 }
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 public final CompilerDef getCompiler(final String type, final String output)
279 throws MojoFailureException, MojoExecutionException {
280 final String name = getName();
281 if (name == null) {
282 return null;
283 }
284
285 final CompilerDef compilerDef = new CompilerDef();
286 compilerDef.setProject(this.mojo.getAntProject());
287 final CompilerEnum compilerName = new CompilerEnum();
288 compilerName.setValue(name);
289 compilerDef.setName(compilerName);
290
291
292 if (this.toolPath != null) {
293 compilerDef.setToolPath(this.toolPath);
294 } else if ("msvc".equalsIgnoreCase( this.mojo.getLinker().getName())){
295 mojo.getMsvc().setToolPath(compilerDef,getLanguage());
296 }
297
298
299 compilerDef.setCompilerPrefix(this.prefix);
300 compilerDef.setCcache(this.ccache);
301 compilerDef.setDebug(this.debug);
302 compilerDef.setExceptions(this.exceptions);
303 compilerDef.setRtti(this.rtti);
304 compilerDef.setMultithreaded(this.mojo.getOS().equals("Windows") || this.multiThreaded);
305
306
307 final OptimizationEnum optimization = new OptimizationEnum();
308 optimization.setValue(this.optimize);
309 compilerDef.setOptimize(optimization);
310
311
312 if (this.options != null) {
313 for (final String string : this.options) {
314 final CompilerArgument arg = new CompilerArgument();
315 arg.setValue(string);
316 compilerDef.addConfiguredCompilerArg(arg);
317 }
318 }
319
320 if (this.optionSet != null) {
321
322 final String[] opts = this.optionSet.split("\\s");
323
324 for (final String opt : opts) {
325
326 final CompilerArgument arg = new CompilerArgument();
327
328 arg.setValue(opt);
329 compilerDef.addConfiguredCompilerArg(arg);
330 }
331 }
332
333 compilerDef.setClearDefaultOptions(this.clearDefaultOptions);
334 if (!this.clearDefaultOptions) {
335 final String optionsProperty = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(
336 getPrefix() + "options");
337 if (optionsProperty != null) {
338 final String[] option = optionsProperty.split(" ");
339 for (final String element : option) {
340 final CompilerArgument arg = new CompilerArgument();
341 arg.setValue(element);
342 compilerDef.addConfiguredCompilerArg(arg);
343 }
344 }
345 }
346
347
348 if (this.defines != null) {
349 final DefineSet ds = new DefineSet();
350 for (final String string : this.defines) {
351 final DefineArgument define = new DefineArgument();
352 final String[] pair = string.split("=", 2);
353 define.setName(pair[0]);
354 define.setValue(pair.length > 1 ? cleanDefineValue(pair[1]) : null);
355 ds.addDefine(define);
356 }
357 compilerDef.addConfiguredDefineset(ds);
358 }
359
360 if (this.defineSet != null) {
361
362 final String[] defList = this.defineSet.split(",");
363 final DefineSet defSet = new DefineSet();
364
365 for (final String element : defList) {
366
367 final String[] pair = element.trim().split("=", 2);
368 final DefineArgument def = new DefineArgument();
369
370 def.setName(pair[0]);
371 def.setValue(pair.length > 1 ? cleanDefineValue(pair[1]) : null);
372
373 defSet.addDefine(def);
374 }
375
376 compilerDef.addConfiguredDefineset(defSet);
377 }
378
379 if (!this.clearDefaultDefines) {
380 final DefineSet ds = new DefineSet();
381 final String defaultDefines = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(
382 getPrefix() + "defines");
383 if (defaultDefines != null) {
384 ds.setDefine(new CUtil.StringArrayBuilder(defaultDefines));
385 }
386 compilerDef.addConfiguredDefineset(ds);
387 }
388
389
390 if (this.undefines != null) {
391 final DefineSet us = new DefineSet();
392 for (final String string : this.undefines) {
393 final DefineArgument undefine = new DefineArgument();
394 final String[] pair = string.split("=", 2);
395 undefine.setName(pair[0]);
396 undefine.setValue(pair.length > 1 ? pair[1] : null);
397 us.addUndefine(undefine);
398 }
399 compilerDef.addConfiguredDefineset(us);
400 }
401
402 if (this.undefineSet != null) {
403
404 final String[] undefList = this.undefineSet.split(",");
405 final DefineSet undefSet = new DefineSet();
406
407 for (final String element : undefList) {
408
409 final String[] pair = element.trim().split("=", 2);
410 final DefineArgument undef = new DefineArgument();
411
412 undef.setName(pair[0]);
413 undef.setValue(pair.length > 1 ? pair[1] : null);
414
415 undefSet.addUndefine(undef);
416 }
417
418 compilerDef.addConfiguredDefineset(undefSet);
419 }
420
421 if (!this.clearDefaultUndefines) {
422 final DefineSet us = new DefineSet();
423 final String defaultUndefines = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(
424 getPrefix() + "undefines");
425 if (defaultUndefines != null) {
426 us.setUndefine(new CUtil.StringArrayBuilder(defaultUndefines));
427 }
428 compilerDef.addConfiguredDefineset(us);
429 }
430
431
432 for (final IncludePath includePath : getIncludePaths(type)) {
433
434
435 if (!includePath.exists()) {
436 throw new MojoFailureException("NAR: Include path not found: " + includePath);
437 }
438 compilerDef.createIncludePath().setPath(includePath.getPath());
439 }
440
441
442 if (this.systemIncludePaths != null) {
443 for (final String path : this.systemIncludePaths) {
444 compilerDef.createSysIncludePath().setPath(path);
445 }
446 }
447
448
449 final List<File> srcDirs = getSourceDirectories(type);
450 final Set<String> includeSet = getIncludes(type);
451 final Set<String> excludeSet = getExcludes(type);
452
453
454 for (final Object o : this.mojo.getTests()) {
455 final Test test = (Test) o;
456 if (!test.getName().equals(output)) {
457 excludeSet.add("**/" + test.getName() + ".*");
458 }
459 }
460
461 for (final File srcDir : srcDirs) {
462 this.mojo.getLog().debug("Checking for existence of " + getLanguage() + " source directory: " + srcDir);
463 if (srcDir.exists()) {
464 if (this.compileOrder != null) {
465 compilerDef.setOrder(Arrays.asList(StringUtils.split(this.compileOrder, ", ")));
466 }
467
468 final ConditionalFileSet fileSet = new ConditionalFileSet();
469 fileSet.setProject(this.mojo.getAntProject());
470 fileSet.setIncludes(StringUtils.join(includeSet.iterator(), ","));
471 fileSet.setExcludes(StringUtils.join(excludeSet.iterator(), ","));
472 fileSet.setDir(srcDir);
473 compilerDef.addFileset(fileSet);
474 }
475 }
476
477 if (type.equals(TEST)) {
478 if (this.testSourceDirectory.exists()) {
479 compilerDef.setWorkDir(this.testSourceDirectory);
480 }
481 } else {
482 if (this.sourceDirectory.exists()) {
483 compilerDef.setWorkDir(this.sourceDirectory);
484 }
485 }
486 return compilerDef;
487 }
488
489 public final Set<String> getExcludes() throws MojoFailureException, MojoExecutionException {
490 return getExcludes("main");
491 }
492
493 protected final Set<String> getExcludes(final String type) throws MojoFailureException, MojoExecutionException {
494 final Set<String> result = new HashSet<>();
495 if (type.equals(TEST) && !this.testExcludes.isEmpty()) {
496 result.addAll(this.testExcludes);
497 } else if (!this.excludes.isEmpty()) {
498 result.addAll(this.excludes);
499 } else {
500 final String defaultExcludes = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(
501 getPrefix() + "excludes");
502 if (defaultExcludes != null) {
503 final String[] exclude = defaultExcludes.split(" ");
504 for (final String element : exclude) {
505 result.add(element.trim());
506 }
507 }
508 }
509
510 return result;
511 }
512
513 protected final List<IncludePath> getIncludePaths(final String type) {
514 List<IncludePath> includeList = type.equals(TEST) ? this.testIncludePaths : this.includePaths;
515
516 if (includeList != null && includeList.size() != 0) {
517 return includeList;
518 }
519
520 includeList = new ArrayList<>();
521 for (final File file2 : getSourceDirectories(type)) {
522
523
524 final File file = new File(file2, "include");
525 if (file.isDirectory()) {
526 final IncludePath includePath = new IncludePath();
527 includePath.setPath(file.getPath());
528 includeList.add(includePath);
529 }
530 }
531 return includeList;
532 }
533
534 public final Set<String> getIncludes() throws MojoFailureException, MojoExecutionException {
535 return getIncludes("main");
536 }
537
538 protected final Set<String> getIncludes(final String type) throws MojoFailureException, MojoExecutionException {
539 final Set<String> result = new HashSet<>();
540 if (!type.equals(TEST) && !this.includes.isEmpty()) {
541 result.addAll(this.includes);
542 } else if (type.equals(TEST) && !this.testIncludes.isEmpty()) {
543 result.addAll(this.testIncludes);
544 } else {
545 final String defaultIncludes = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(
546 getPrefix() + "includes");
547 if (defaultIncludes != null) {
548 final String[] include = defaultIncludes.split(" ");
549 for (final String element : include) {
550 result.add(element.trim());
551 }
552 }
553 }
554 return result;
555 }
556
557 protected abstract String getLanguage();
558
559 public String getName() throws MojoFailureException, MojoExecutionException {
560
561 if (this.name == null) {
562 this.name = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(getPrefix() + "compiler");
563 }
564 if (this.prefix == null) {
565 this.prefix = NarProperties.getInstance(this.mojo.getMavenProject()).getProperty(getPrefix() + "prefix");
566 }
567 return this.name;
568 }
569
570 protected final String getPrefix() throws MojoFailureException, MojoExecutionException {
571 return this.mojo.getAOL().getKey() + "." + getLanguage() + ".";
572 }
573
574 public final List<File> getSourceDirectories() {
575 return getSourceDirectories("dummy");
576 }
577
578 private List<File> getSourceDirectories(final String type) {
579 final List<File> sourceDirectories = new ArrayList<>();
580 final File baseDir = this.mojo.getMavenProject().getBasedir();
581
582 if (type.equals(TEST)) {
583 if (this.testSourceDirectory == null) {
584 this.testSourceDirectory = new File(baseDir, "/src/test");
585 }
586 if (this.testSourceDirectory.exists()) {
587 sourceDirectories.add(this.testSourceDirectory);
588 }
589
590 for (final Object element : this.mojo.getMavenProject().getTestCompileSourceRoots()) {
591 final File extraTestSourceDirectory = new File((String) element);
592 if (extraTestSourceDirectory.exists()) {
593 sourceDirectories.add(extraTestSourceDirectory);
594 }
595 }
596 } else {
597 if (this.sourceDirectory == null) {
598 this.sourceDirectory = new File(baseDir, "src/main");
599 }
600 if (this.sourceDirectory.exists()) {
601 sourceDirectories.add(this.sourceDirectory);
602 }
603
604 for (final Object element : this.mojo.getMavenProject().getCompileSourceRoots()) {
605 final File extraSourceDirectory = new File((String) element);
606 if (extraSourceDirectory.exists()) {
607 sourceDirectories.add(extraSourceDirectory);
608 }
609 }
610 }
611
612 if (this.mojo.getLog().isDebugEnabled()) {
613 for (final File file : sourceDirectories) {
614 this.mojo.getLog().debug("Added to sourceDirectory: " + file.getPath());
615 }
616 }
617 return sourceDirectories;
618 }
619
620
621
622
623
624 public final CompilerDef getTestCompiler(final String type, final String output)
625 throws MojoFailureException, MojoExecutionException {
626 final CompilerDef compiler = getCompiler(type, output);
627 if (compiler != null && this.testOptions != null) {
628 for (final String string : this.testOptions) {
629 final CompilerArgument arg = new CompilerArgument();
630 arg.setValue(string);
631 compiler.addConfiguredCompilerArg(arg);
632 }
633 }
634 return compiler;
635 }
636
637 public final void setAbstractCompileMojo(final AbstractCompileMojo mojo) {
638 this.mojo = mojo;
639 }
640
641 @Override
642 public String toString() {
643 return NarUtil.prettyMavenString(this);
644 }
645 }