Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Builds for different platforms the Maven way

I have a project with a submodule a:jar which needs a different set of dependencies, depending for which platform it is compiled. The code is the same for all platforms. E.g. on Android the httpcomponents library is already bundled with the OS, whereas I have to include it for builds for J2SE environments. I also have another submodule, which assembles several submodules and their dependencies into an archive. How can I reliably configure the assembly submodule, to take all the submodules compiled for the respective platform, and their dependencies appropriate for that platform?

I tried using profiles to create a:jar:android and a:jar:j2se. However, declaring a dependency on one of these would result in strange dependencies in the assembly. I.e., the dependency:tree of the assembly project would sometimes include the dependencies on a:jar:j2se (doesn't matter whether I declared to use the a:jar:android or a:jar:j2se in the assembly), and sometimes the other. It changed (often) after I updated the jars of a in the local repository. Switching in the assembly project uses also profiles.

I could solve that by applying the same dependencies to the assembly project's profiles as are needed by the individual submodules profile. But as I have to repeat myself in the POMs, there is probably a more maven-y way to achieve that. As I am quite new to maven, I wonder what it is? I don't want to duplicate the code (that would even be more repeating as the code stays the same) and I don't like to duplicate parts of the POM as changing them due to version upgrades can get complicated.

Some concrete material: Dependencies from a:jar's POM:

  <dependencies>
    .....
    <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpmime</artifactId>
      <version>4.0.1</version>
      <scope>compile</scope>
      <!-- Exclusion in the common part, they are provided in the profiles from different sources -->
      <exclusions>
        <exclusion>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
        </exclusion>
        ....
      </exclusions>
    </dependency>
  </dependencies>
  <profiles>
    <profile>
      <id>android</id>
      <dependencies>
        <dependency>
          <groupId>com.google.android</groupId>
          <artifactId>android</artifactId>
          <version>1.6_r2</version>
          <scope>provided</scope>
        </dependency>   
      </dependencies>
    </profile>
    <profile>
      <id>java</id>
      <dependencies>
        <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.0.1</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>commons-codec</groupId>
          <artifactId>commons-codec</artifactId>
          <version>1.3</version>
          <scope>compile</scope>
        </dependency>
      </dependencies>
    </profile>
  </profiles>

The assembly project (which uses the Maven Assembly Plugin) profiles:

  <profiles>
    <profile>
      <id>android</id>     
      <dependencies>
        <dependency>
          <groupId>a</groupId>
          <artifactId>a</artifactId>
          <version>${project.version}</version>
          <classifier>android</classifier>
          <type>jar</type>
        </dependency>
        <!-- Duplicate --> 
        <dependency>
          <groupId>com.google.android</groupId>
          <artifactId>android</artifactId>
          <version>1.6_r2</version>
          <scope>provided</scope>
        </dependency>   
        <!-- Duplicate --> 
      </dependencies>
    </profile>
    <profile>
      <id>java</id>
      <dependencies>
        <!-- Duplicate -->
        <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.0.1</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>commons-codec</groupId>
          <artifactId>commons-codec</artifactId>
          <version>1.3</version>
          <scope>compile</scope>
        </dependency>
        <!-- /Duplicate --> 
        <dependency>
          <groupId>a</groupId>
          <artifactId>a</artifactId>
          <version>${project.version}</version>
          <classifier>java</classifier>
         <type>jar</type>
        </dependency>
      </dependencies>
    </profile>
  </profiles>

I'd like to get rid of the marked dependency declarations.

like image 401
Stephan Avatar asked Oct 09 '22 20:10

Stephan


2 Answers

There are several solutions:

  1. These submodule's dependencies could be declared "provided", in this case in a project you include the dependency to the submodule along with explicit dependencies which a platform doesn't have.

  2. Use <exclusions> for unnecessary dependencies.

  3. Using (1) or (2) above create yet another "structural" submodules a-android:pom a-j2se:pom which just describe dependencies, and use these modules from your projects.

like image 76
kan Avatar answered Oct 18 '22 04:10

kan


You can add a maven profile to pom and activate each profile based on the OS. Profile activation does support such an options. Then in each OS-specific profile you can list optional dependencies. Here is an article on profiles -> http://maven.apache.org/guides/introduction/introduction-to-profiles.html

In your case it would be something like this:

<profiles>
  <profile>
    <activation>
      <os>
        <family>Windows</family>
      </os>
    </activation>
    <dependencies>
      ... specific dependencies for Windows
    </dependencies>
    <plugins>
      ... specific build plugins for Windows
    </plugins>
  </profile>
  <profile>
    <activation>
      <os>
        <family>unix</family>
      </os>
    </activation>
    <dependencies>
      ... specific dependencies for unix
    </dependencies>
    <plugins>
      ... specific build plugins for unix
    </plugins>
  </profile>
  <dependencies>
    ... Common dependencies
  <dependencies>
  <plugins>
    ... Common build plugins
  </plugins>
</profiles>
like image 35
Alexander Pogrebnyak Avatar answered Oct 18 '22 03:10

Alexander Pogrebnyak