View Javadoc
1   package org.codehaus.mojo.natives.plugin;
2   
3   /*
4    * The MIT License
5    *
6    * Copyright (c) 2004, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
9    * associated documentation files (the "Software"), to deal in the Software without restriction,
10   * including without limitation the rights to use, copy, modify, merge, publish, distribute,
11   * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
12   * furnished to do so, subject to the following conditions:
13   *
14   * The above copyright notice and this permission notice shall be included in all copies or
15   * substantial portions of the Software.
16   *
17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
18   * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20   * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22   */
23  
24  import java.io.File;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.List;
28  
29  import org.apache.maven.plugin.MojoExecutionException;
30  import org.apache.maven.plugins.annotations.Component;
31  import org.apache.maven.plugins.annotations.LifecyclePhase;
32  import org.apache.maven.plugins.annotations.Mojo;
33  import org.apache.maven.plugins.annotations.Parameter;
34  import org.codehaus.mojo.natives.NativeBuildException;
35  import org.codehaus.mojo.natives.NativeSources;
36  import org.codehaus.mojo.natives.compiler.Compiler;
37  import org.codehaus.mojo.natives.compiler.CompilerConfiguration;
38  import org.codehaus.mojo.natives.manager.CompilerManager;
39  import org.codehaus.mojo.natives.manager.NoSuchNativeProviderException;
40  
41  /**
42   * Compile source files into native object files
43    */
44  @Mojo(name = "compile", defaultPhase = LifecyclePhase.COMPILE)
45  public class NativeCompileMojo
46      extends AbstractNativeMojo
47  {
48  
49      /**
50       * Compiler Provider Type
51       * @since 1.0-alpha-2
52       */
53      @Parameter(defaultValue = "generic", required = true)
54      private String compilerProvider;
55  
56      /**
57       * Use this field to override object file extension. The default extensions are .obj and .o on Windows and Unix
58       * respectively
59       * @since 1.0-alpha-2
60       */
61      @Parameter
62      private String objectFileExtension;
63  
64      /**
65       * Use this field to override provider specific compiler executable
66       * @since 1.0-alpha-2
67       */
68      @Parameter
69      private String compilerExecutable;
70  
71      /**
72       * Compiler options
73       * @since 1.0-alpha-2
74       */
75      @Parameter
76      private List compilerStartOptions;
77  
78      /**
79       * Compiler options
80       * @since 1.0-alpha-2
81       */
82      @Parameter
83      private List compilerMiddleOptions;
84  
85      /**
86       * Compiler options
87       * @since 1.0-alpha-2
88       */
89      @Parameter
90      private List compilerEndOptions;
91  
92      /**
93       * Javah OS name. ${jdkIncludePath} and ${jdkIncludePath}/${javaOS} are added to system include path when this field
94       * is set
95       * @since 1.0-alpha-2
96       */
97      @Parameter
98      private String javahOS;
99  
100     /**
101      * JDK native include directory
102      * @since 1.0-alpha-2
103      */
104     @Parameter(defaultValue="${java.home}/../include")
105     private File jdkIncludePath;
106 
107     /**
108      * Array of NativeSources containing include directories and source files.
109      * @since 1.0-alpha-2
110      */
111     @Parameter
112     protected NativeSources[] sources = new NativeSources[0];
113 
114     /**
115      * Compiler output files ( .o, .obj, etc) location
116      * @since 1.0-alpha-4
117      */
118     @Parameter(defaultValue="${project.build.directory}/objs", required = true)
119     protected File compilerOutputDirectory;
120 
121     /**
122      * Number of parallel compilation threads
123      *
124      * @since 1.0-alpha-4
125      */
126     @Parameter(defaultValue = "1")
127     protected int numberOfConcurrentCompilation;
128 
129     @Component
130     private CompilerManager manager;
131 
132     public void execute()
133         throws MojoExecutionException
134     {
135 
136         Compiler compiler;
137 
138         try
139         {
140             compiler = this.manager.getCompiler( this.compilerProvider );
141         }
142         catch ( NoSuchNativeProviderException pe )
143         {
144             throw new MojoExecutionException( pe.getMessage() );
145         }
146 
147         if ( this.javahOS != null )
148         {
149             this.addJavaHIncludePaths();
150         }
151 
152         this.addAdditionalIncludePath();
153 
154         CompilerConfiguration config = this.createProviderConfiguration();
155 
156         List objectFiles;
157         try
158         {
159             objectFiles = compiler.compile( config, NativeSources.getAllSourceFiles( this.sources ) );
160         }
161         catch ( NativeBuildException e )
162         {
163             throw new MojoExecutionException( e.getMessage(), e );
164         }
165 
166         this.saveCompilerOutputFilePaths( objectFiles );
167 
168     }
169 
170     private void addJavaHIncludePaths()
171     {
172         List sourceArray = new ArrayList( Arrays.asList( this.sources ) );
173 
174         NativeSources jdkIncludeSource = new NativeSources();
175 
176         jdkIncludeSource.setDirectory( this.jdkIncludePath );
177 
178         jdkIncludeSource.setDependencyAnalysisParticipation( false );
179 
180         sourceArray.add( jdkIncludeSource );
181 
182         File jdkOsIncludeDir = new File( this.jdkIncludePath, this.javahOS );
183 
184         NativeSources jdkIncludeOsSource = new NativeSources();
185 
186         jdkIncludeOsSource.setDirectory( jdkOsIncludeDir );
187 
188         jdkIncludeOsSource.setDependencyAnalysisParticipation( false );
189 
190         sourceArray.add( jdkIncludeOsSource );
191 
192         this.sources = (NativeSources[]) sourceArray.toArray( new NativeSources[sourceArray.size()] );
193 
194     }
195 
196     /**
197      * Pickup additional source paths that previous phases added to source root Note: we intentionally ignore the first
198      * item of source root ( ie ${project.build.directory}/classes since this plugin never use it.
199      */
200     private void addAdditionalIncludePath()
201         throws MojoExecutionException
202     {
203         List additionalIncludePaths = project.getCompileSourceRoots();
204 
205         boolean includeDependencyFound = this.getPluginContext().get( AbstractNativeMojo.INCZIP_FOUND ) != null;
206 
207         if ( !includeDependencyFound )
208         {
209             if ( additionalIncludePaths == null || additionalIncludePaths.size() < 2 )
210             {
211                 return;
212             }
213         }
214 
215         if ( this.sources == null )
216         {
217             return;
218         }
219 
220         List sourceArray = new ArrayList( Arrays.asList( this.sources ) );
221 
222         if ( additionalIncludePaths.size() > 1 )
223         {
224             for ( int i = 1; i < additionalIncludePaths.size(); ++i )
225             {
226                 File genIncludeDir = new File( additionalIncludePaths.get( i ).toString() );
227 
228                 NativeSources genIncludeSource = new NativeSources();
229 
230                 genIncludeSource.setDirectory( genIncludeDir );
231 
232                 sourceArray.add( genIncludeSource );
233             }
234         }
235 
236         if ( includeDependencyFound )
237         {
238             NativeSources dependencyIncludeSource = new NativeSources();
239             dependencyIncludeSource.setDependencyAnalysisParticipation( false );
240             dependencyIncludeSource.setDirectory( this.dependencyIncludeDirectory );
241 
242             sourceArray.add( dependencyIncludeSource );
243         }
244 
245         this.sources = (NativeSources[]) sourceArray.toArray( new NativeSources[sourceArray.size()] );
246 
247     }
248 
249     /*
250      * use protected scope for unit test purpose
251      */
252     protected CompilerConfiguration createProviderConfiguration()
253         throws MojoExecutionException
254     {
255         this.config = new CompilerConfiguration();
256         config.setWorkingDirectory( this.workingDirectory );
257         config.setExecutable( this.compilerExecutable );
258         config.setStartOptions( removeEmptyOptions( this.compilerStartOptions ) );
259         config.setMiddleOptions( removeEmptyOptions( this.compilerMiddleOptions ) );
260         config.setEndOptions( removeEmptyOptions( this.compilerEndOptions ) );
261         config.setIncludePaths( NativeSources.getIncludePaths( this.sources ) );
262         config.setSystemIncludePaths( NativeSources.getSystemIncludePaths( this.sources ) );
263         config.setOutputDirectory( this.compilerOutputDirectory );
264         config.setObjectFileExtension( this.objectFileExtension );
265         config.setEnvFactory( this.getEnvFactory() );
266         config.setNumberOfConcurrentCompilation( numberOfConcurrentCompilation );
267 
268         return config;
269     }
270 
271     // //////////////////////////////////// UNIT TEST HELPERS ////////////////////////////////
272 
273     /**
274      * For unittest only
275      */
276     private CompilerConfiguration config;
277 
278     /**
279      * Internal only for test harness purpose
280      *
281      * @return
282      */
283     protected CompilerConfiguration getCompilerConfiguration()
284     {
285         return this.config;
286     }
287 }