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.Collections;
26 import java.util.Iterator;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Vector;
30
31 import org.apache.maven.artifact.Artifact;
32 import org.apache.maven.execution.MavenSession;
33 import org.apache.maven.plugin.MojoExecutionException;
34 import org.apache.maven.plugin.MojoFailureException;
35 import org.apache.maven.plugins.annotations.Component;
36 import org.apache.maven.plugins.annotations.LifecyclePhase;
37 import org.apache.maven.plugins.annotations.Mojo;
38 import org.apache.maven.plugins.annotations.Parameter;
39 import org.apache.maven.plugins.annotations.ResolutionScope;
40 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
41 import org.apache.tools.ant.BuildException;
42 import org.apache.tools.ant.Project;
43 import org.codehaus.plexus.util.FileUtils;
44 import org.codehaus.plexus.util.StringUtils;
45
46 import com.github.maven_nar.cpptasks.CCTask;
47 import com.github.maven_nar.cpptasks.CUtil;
48 import com.github.maven_nar.cpptasks.CompilerDef;
49 import com.github.maven_nar.cpptasks.LinkerDef;
50 import com.github.maven_nar.cpptasks.OutputTypeEnum;
51 import com.github.maven_nar.cpptasks.RuntimeType;
52 import com.github.maven_nar.cpptasks.SubsystemEnum;
53 import com.github.maven_nar.cpptasks.types.LibrarySet;
54 import com.github.maven_nar.cpptasks.types.LinkerArgument;
55 import com.github.maven_nar.cpptasks.types.SystemLibrarySet;
56
57
58
59
60
61
62
63 @Mojo(name = "nar-compile", defaultPhase = LifecyclePhase.COMPILE, requiresProject = true,
64 requiresDependencyResolution = ResolutionScope.COMPILE)
65 public class NarCompileMojo extends AbstractCompileMojo {
66
67
68
69
70 @Parameter(property = "nar.embedManifest", defaultValue = "true")
71 protected boolean embedManifest = true;
72
73
74
75
76 @Component
77 protected MavenSession session;
78
79 private void copyInclude(final Compiler c) throws IOException, MojoExecutionException, MojoFailureException {
80 if (c == null) {
81 return;
82 }
83 c.copyIncludeFiles(
84 getMavenProject(),
85 getLayout().getIncludeDirectory(getTargetDirectory(), getMavenProject().getArtifactId(),
86 getMavenProject().getVersion()));
87 }
88
89 private void createLibrary(final Project antProject, final Library library)
90 throws MojoExecutionException, MojoFailureException {
91 getLog().debug("Creating Library " + library);
92
93 final CCTask task = new CCTask();
94 task.setCommandLogLevel(this.commandLogLevel);
95 task.setProject(antProject);
96
97 task.setDecorateLinkerOptions(this.decorateLinkerOptions);
98
99
100 final SubsystemEnum subSystem = new SubsystemEnum();
101 subSystem.setValue(library.getSubSystem());
102 task.setSubsystem(subSystem);
103
104
105 task.setMaxCores(getMaxCores(getAOL()));
106
107
108 final OutputTypeEnum outTypeEnum = new OutputTypeEnum();
109 final String type = library.getType();
110 outTypeEnum.setValue(type);
111 task.setOuttype(outTypeEnum);
112
113
114 task.setLinkCPP(library.linkCPP());
115
116
117 task.setLinkFortran(library.linkFortran());
118 task.setLinkFortranMain(library.linkFortranMain());
119
120
121 File outDir;
122 if (type.equals(Library.EXECUTABLE)) {
123 outDir = getLayout().getBinDirectory(getTargetDirectory(), getMavenProject().getArtifactId(),
124 getMavenProject().getVersion(), getAOL().toString());
125 } else {
126 outDir = getLayout().getLibDirectory(getTargetDirectory(), getMavenProject().getArtifactId(),
127 getMavenProject().getVersion(), getAOL().toString(), type);
128 }
129 outDir.mkdirs();
130
131
132
133 final File outFile = new File(outDir, getOutput(getAOL(), type));
134 getLog().debug("NAR - output: '" + outFile + "'");
135 task.setOutfile(outFile);
136
137
138 File objDir = new File(getTargetDirectory(), "obj");
139 objDir = new File(objDir, getAOL().toString());
140 objDir.mkdirs();
141 task.setObjdir(objDir);
142
143
144 task.setFailonerror(failOnError(getAOL()));
145 task.setLibtool(useLibtool(getAOL()));
146
147
148 final RuntimeType runtimeType = new RuntimeType();
149 runtimeType.setValue(getRuntime(getAOL()));
150 task.setRuntime(runtimeType);
151
152
153
154
155
156
157 if (getIdl() != null) {
158 final CompilerDef idl = getIdl().getCompiler(Compiler.MAIN, null);
159 if (idl != null) {
160 task.addConfiguredCompiler(idl);
161 task.createIncludePath().setPath(objDir.getPath());
162
163 }
164 }
165 if (getMessage() != null) {
166 final CompilerDef mc = getMessage().getCompiler(Compiler.MAIN, null);
167 if (mc != null) {
168 task.addConfiguredCompiler(mc);
169 task.createIncludePath().setPath(objDir.getPath());
170
171 }
172 }
173 if (getResource() != null) {
174 final CompilerDef res = getResource().getCompiler(Compiler.MAIN, null);
175 if (res != null) {
176 task.addConfiguredCompiler(res);
177 }
178 }
179
180
181
182
183
184
185 if (getCpp() != null) {
186 final CompilerDef cpp = getCpp().getCompiler(Compiler.MAIN, null);
187 if (cpp != null) {
188 task.addConfiguredCompiler(cpp);
189 }
190 }
191
192
193 if (getC() != null) {
194 final CompilerDef c = getC().getCompiler(Compiler.MAIN, null);
195 if (c != null) {
196 task.addConfiguredCompiler(c);
197 }
198 }
199
200
201 if (getFortran() != null) {
202 final CompilerDef fortran = getFortran().getCompiler(Compiler.MAIN, null);
203 if (fortran != null) {
204 task.addConfiguredCompiler(fortran);
205 }
206 }
207
208
209
210 final File jniDirectory = getJavah().getJniDirectory();
211 if (jniDirectory.exists()) {
212 task.createIncludePath().setPath(jniDirectory.getPath());
213 }
214
215
216 getJava().addIncludePaths(task, type);
217
218 getMsvc().configureCCTask(task);
219
220 final List<NarArtifact> dependencies = getNarArtifacts();
221
222 for (final Object element : dependencies) {
223
224 final NarArtifact narDependency = (NarArtifact) element;
225 final String binding = getBinding(library, narDependency);
226 getLog().debug("Looking for " + narDependency + " found binding " + binding);
227 if (!binding.equals(Library.JNI)) {
228 final File unpackDirectory = getUnpackDirectory();
229 final File include = getLayout().getIncludeDirectory(unpackDirectory, narDependency.getArtifactId(),
230 narDependency.getBaseVersion());
231 getLog().debug("Looking for include directory: " + include);
232 if (include.exists()) {
233 task.createIncludePath().setPath(include.getPath());
234 } else {
235
236
237
238
239 getLog().warn(String.format("Unable to locate %1$s lib include path '%2$s'", binding, include));
240 }
241 }
242 }
243
244
245 final LinkerDef linkerDefinition = getLinker().getLinker(this, task, getOS(), getAOL().getKey() + ".linker.", type);
246 task.addConfiguredLinker(linkerDefinition);
247
248
249
250
251 final boolean skipDepLink = linkerDefinition.isSkipDepLink();
252 if (((type.equals(Library.SHARED) || type.equals(Library.JNI) || type.equals(Library.EXECUTABLE))) && !skipDepLink) {
253
254 final List depLibOrder = getDependencyLibOrder();
255 List depLibs = dependencies;
256
257
258
259 if (depLibOrder != null && !depLibOrder.isEmpty()) {
260 final List tmp = new LinkedList();
261
262 for (final Object aDepLibOrder : depLibOrder) {
263 final String depToOrderName = (String) aDepLibOrder;
264
265 for (final Iterator j = depLibs.iterator(); j.hasNext(); ) {
266 final NarArtifact dep = (NarArtifact) j.next();
267 final String depName = dep.getGroupId() + ":" + dep.getArtifactId();
268
269 if (depName.equals(depToOrderName)) {
270 tmp.add(dep);
271 j.remove();
272 }
273 }
274 }
275
276 tmp.addAll(depLibs);
277 depLibs = tmp;
278 }
279
280 for (final Object depLib : depLibs) {
281 final NarArtifact dependency = (NarArtifact) depLib;
282
283
284
285
286 final String binding = dependency.getNarInfo().getBinding(getAOL(), Library.NONE);
287 getLog().debug("Using Binding: " + binding);
288 AOL aol = getAOL();
289 aol = dependency.getNarInfo().getAOL(getAOL());
290 getLog().debug("Using Library AOL: " + aol.toString());
291
292 if (!binding.equals(Library.JNI) && !binding.equals(Library.NONE) && !binding.equals(Library.EXECUTABLE)) {
293 final File unpackDirectory = getUnpackDirectory();
294
295 final File dir = getLayout()
296 .getLibDirectory(unpackDirectory, dependency.getArtifactId(), dependency.getBaseVersion(), aol.toString(),
297 binding);
298
299 getLog().debug("Looking for Library Directory: " + dir);
300 if (dir.exists()) {
301 final LibrarySet libSet = new LibrarySet();
302 libSet.setProject(antProject);
303
304
305 final String libs = dependency.getNarInfo().getLibs(getAOL());
306 if (libs != null && !libs.equals("")) {
307 getLog().debug("Using LIBS = " + libs);
308 libSet.setLibs(new CUtil.StringArrayBuilder(libs));
309 libSet.setDir(dir);
310 task.addLibset(libSet);
311 }
312 } else {
313 getLog().debug("Library Directory " + dir + " does NOT exist.");
314 }
315
316
317
318 final String options = dependency.getNarInfo().getOptions(getAOL());
319 if (options != null && !options.equals("")) {
320 getLog().debug("Using OPTIONS = " + options);
321 final LinkerArgument arg = new LinkerArgument();
322 arg.setValue(options);
323 linkerDefinition.addConfiguredLinkerArg(arg);
324 }
325
326 final String sysLibs = dependency.getNarInfo().getSysLibs(getAOL());
327 if (sysLibs != null && !sysLibs.equals("")) {
328 getLog().debug("Using SYSLIBS = " + sysLibs);
329 final SystemLibrarySet sysLibSet = new SystemLibrarySet();
330 sysLibSet.setProject(antProject);
331
332 sysLibSet.setLibs(new CUtil.StringArrayBuilder(sysLibs));
333 task.addSyslibset(sysLibSet);
334 }
335 }
336 }
337 }
338
339
340 getJava().addRuntime(task, getJavaHome(getAOL()), getOS(), getAOL().getKey() + ".java.");
341
342
343 try {
344 task.execute();
345 } catch (final BuildException e) {
346 throw new MojoExecutionException("NAR: Compile failed", e);
347 }
348
349
350
351 if ((isEmbedManifest() || getLinker().isGenerateManifest()) && getOS().equals(OS.WINDOWS)
352 && getLinker().getName().equals("msvc") && !getLinker().getVersion(this).startsWith("6.")) {
353 final String[] env = new String[] {
354 "PATH=" + getMsvc().getPathVariable().getValue()
355 };
356 final String libType = library.getType();
357 if (Library.JNI.equals(libType) || Library.SHARED.equals(libType) || Library.EXECUTABLE.equals(libType)) {
358 Vector<String> commandlineArgs = new Vector<>();
359 commandlineArgs.add("/manifest");
360 getManifests(outFile.getPath(), commandlineArgs);
361 if (commandlineArgs.size() == 1) {
362 if (isEmbedManifest())
363 getLog().warn("Embed manifest requested, no source manifests to embed, no manifest generated");
364 } else {
365 if (Library.JNI.equals(libType) || Library.SHARED.equals(libType)) {
366 String dll = outFile.getPath() + ".dll";
367 if (isEmbedManifest()) {
368 commandlineArgs.add("/outputresource:" + dll + ";#2");
369 } else {
370 commandlineArgs.add("/out:" + dll + ".manifest");
371 }
372 } else
373 {
374 String exe = outFile.getPath() + ".exe";
375 if (isEmbedManifest()) {
376 commandlineArgs.add("/outputresource:" + exe + ";#1");
377 } else {
378 commandlineArgs.add("/out:" + exe + ".manifest");
379 }
380 }
381 String[] commandlineArgsArray = commandlineArgs.toArray(new String[0]);
382 String mtexe = "mt.exe";
383 if (getMsvc().compareVersion( getMsvc().getWindowsSdkVersion(),"7.0")<0 && getLinker().getVersion(this).startsWith("8.")) {
384 File mtexeFile = new File(getMsvc().getToolPath(), mtexe);
385 if (mtexeFile.exists())
386 mtexe = mtexeFile.getAbsolutePath();
387 } else {
388 File mtexeFile = new File(getMsvc().getSDKToolPath(), mtexe);
389 if (mtexeFile.exists())
390 mtexe = mtexeFile.getAbsolutePath();
391 }
392 int result = NarUtil.runCommand(mtexe, commandlineArgsArray, null, null, getLog());
393 if (result != 0) {
394 throw new MojoFailureException("MT.EXE failed with exit code: " + result);
395 }
396 }
397 }
398 }
399 if( getOS().equals(OS.WINDOWS) && Library.STATIC.equals(library.getType()) ){
400 getLog().debug( "Copy static pdbs from intermediat dir to " + task.getOutfile().getParentFile() );
401 try {
402 NarUtil.copyDirectoryStructure(task.getObjdir(), task.getOutfile().getParentFile(), "**/*.pdb", NarUtil.DEFAULT_EXCLUDES );
403 } catch (IOException e) {
404 getLog().info( "Failed to copy pdbs from " + task.getObjdir() + "\nexception" + e.getMessage() );
405 }
406 }
407 }
408
409
410
411
412
413
414 @Override
415 protected ScopeFilter getArtifactScopeFilter() {
416 return new ScopeFilter(Artifact.SCOPE_COMPILE, null);
417 }
418
419 private List getSourcesFor(final Compiler compiler) throws MojoFailureException, MojoExecutionException {
420 if (compiler == null) {
421 return Collections.emptyList();
422 }
423
424 try {
425 final List files = new ArrayList();
426 final List srcDirs = compiler.getSourceDirectories();
427 for (final Object srcDir : srcDirs) {
428 final File dir = (File) srcDir;
429 if (dir.exists()) {
430 files.addAll(FileUtils.getFiles(dir, StringUtils.join(compiler.getIncludes().iterator(), ","), null));
431 }
432 }
433 return files;
434 } catch (final IOException e) {
435 return Collections.emptyList();
436 }
437 }
438
439 @Override
440 public final void narExecute() throws MojoExecutionException, MojoFailureException {
441
442
443 getTargetDirectory().mkdirs();
444
445
446 int noOfSources = 0;
447 noOfSources += getSourcesFor(getCpp()).size();
448 noOfSources += getSourcesFor(getC()).size();
449 noOfSources += getSourcesFor(getFortran()).size();
450 if (noOfSources > 0) {
451 getLog().info("Compiling " + noOfSources + " native files");
452 for (final Library library : getLibraries()) {
453 createLibrary(getAntProject(), library);
454 }
455 } else {
456 getLog().info("Nothing to compile");
457 }
458
459 try {
460
461 copyInclude(getCpp());
462 copyInclude(getC());
463 copyInclude(getFortran());
464 } catch (final IOException e) {
465 throw new MojoExecutionException("NAR: could not copy include files", e);
466 }
467
468 getNarInfo().writeToDirectory(this.classesDirectory);
469 }
470
471 public boolean isEmbedManifest() {
472 return embedManifest;
473 }
474
475 private void getManifests(String generated, Vector<String> manifests) {
476
477
478
479 if (getLinker().isGenerateManifest())
480 manifests.add(generated + ".manifest");
481 }
482
483 }