Question

I'm currently rewriting my OSS project netlib-java to be as easy to use as possible by both devs and end users.

However, as part of the maven-native setup, I seem to need a separate pom.xml for each native binary that I want to create. The large majority of these files are actually identical across platforms.

How can I reduce the boilerplate of my native build files?, e.g.:

(Almost everything is shared between OS targets, except the name of the output file, the compiler flags, and the target platform for javah).

Some other smaller, but related, questions:

  • I only want to distribute bundled jars, how can I turn off the jnilib (etc) deploys and instead deploy a jar using the default classifier (I can create a native classifier jar, but this is awkward for end users to include).
  • Obviously I'll never be able to build the whole project in one go (as there are several OS native targets). However, Maven insists on trying to compile things if they are modules. How can I set up a dependency tree / workflow such that end users only need to depend on one project which pulls in all the native jars?
Was it helpful?

Solution

maven's inheritance-feature could reduce your boilerplate-code a great deal. To keep things simple I've omitted the javah and other JNI-stuff and just created two C-projects and a common parent-project. Directory-structure is like this:

+-NativeParent
! !
! +-src/main/native
! +-pom.xml
+-NativeTest1
! !
! +-pom.xml
+-NativeTest2
  !
  +-pom.xml

NativeParent contains all source code and the pom.xml contains almost all definitions:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

   <groupId>test</groupId>
   <artifactId>nativeParent</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>pom</packaging>

    <name>parent-pom</name>

    <modules>
        <module>../NativeTest1</module>
        <module>../NativeTest2</module>
    </modules>

    <dependencies>
    </dependencies>



   <build>
     <plugins>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>native-maven-plugin</artifactId>
         <extensions>true</extensions>
         <configuration>

           <sources>
             <source>
               <directory>../NativeParent/src/main/native</directory> 
               <fileNames>
                 <fileName>krbwinclient.c</fileName>
               </fileNames>
             </source>          
           </sources>

           <linkerStartOptions>
             <linkerStartOption>-Wl,--kill-at</linkerStartOption>
             <linkerStartOption>-shared</linkerStartOption>
           </linkerStartOptions>
           <linkerEndOptions>
            <linkerEndOption>-lSecur32</linkerEndOption>
            <linkerEndOption>-lOle32</linkerEndOption>
           </linkerEndOptions>
         </configuration>
         </plugin>

         </plugins>
    </build>

</project>

NativeTest1's and NativeTest2's poms can be pretty lean as they only have to define properties diffeing from the parent-pom.

NativeTest1:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

    <parent>
       <groupId>test</groupId>
       <artifactId>nativeParent</artifactId>
       <version>0.0.1-SNAPSHOT</version>
    </parent>

   <groupId>test</groupId>
   <artifactId>native1</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>so</packaging>

   <build>
    <finalName>native1.so</finalName>
     <plugins>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>native-maven-plugin</artifactId>
         <extensions>true</extensions>
         <configuration>
           <compilerStartOptions>
             <compilerStartOption>-Wl,--add-stdcall-alias</compilerStartOption>
             <compilerStartOption>-DBUILD_SO</compilerStartOption>
           </compilerStartOptions>

         </configuration>
         </plugin>

         </plugins>
    </build>

</project>

And NativeTest2:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

    <parent>
       <groupId>test</groupId>
       <artifactId>nativeParent</artifactId>
       <version>0.0.1-SNAPSHOT</version>
    </parent>

   <groupId>test</groupId>
   <artifactId>native2</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>dll</packaging>

   <build>
    <finalName>native1.so</finalName>
     <plugins>
       <plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>native-maven-plugin</artifactId>
         <extensions>true</extensions>
         <configuration>
           <compilerStartOptions>
             <compilerStartOption>-Wl,--add-stdcall-alias</compilerStartOption>
             <compilerStartOption>-DBUILD_DLL</compilerStartOption>
           </compilerStartOptions>

         </configuration>
         </plugin>

         </plugins>
    </build>

</project>

The only things different are package-type, target-name and the compile-options, but most of the configuration is taken from the parent-pom.

Pay attention that there is only one compilerStartOption-Property, so altough you can use several equally named attributes in the child-pom you will lose all equally-named entries from the parent-pom.

I hope this is the kind of thing you were looking for - it's still a bit of boilerplate-code but it is greatly reduced.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top