mavenmaven-assembly-plugin

Running exec-maven-plugin after maven-assembly-plugin but before package phase executes


We have an assembly folder that includes our application launcher executable (thin wrapper that uses JNI to launch the Java runtime with our main class). We compile the assembly into an NSIS installer using nsis-maven-plugin. We then sign the installer executable (this is under Windows, so we do this using Microsoft's SignTool.exe). We've been doing this for years, works great.

Now we would like to also sign the application launcher executable.

So we need to:

  1. Use the assembly to set up the target folder
  2. Sign the launcher exe (that got copied to the target folder)
  3. Create the nsis installer exe
  4. Sign the installer exe

Here's how we have the plugins configured:

Here's a slightly redacted version of my <plugins>:

    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            ... unrelated stuff
        </plugin>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>

            <executions>
                <execution>
                    <id>bundle-project-sources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <configuration>
                        <descriptors>
                            <descriptor>${basedir}/src/main/assembly/assembly.xml</descriptor>
                        </descriptors>
                        <appendAssemblyId>false</appendAssemblyId>
                    </configuration>
                </execution>
            </executions>


        </plugin>
        
        
        <plugin> <!-- Sign the installer -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.2.1</version>
            <executions>

                <execution>
                    <id>sign-launcher</id>
                    <phase>pre-package</phase>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                    <configuration>
                        <executable>${deployment.windowskit.path}\signtool.exe</executable>
                        <arguments>
                            <argument>sign</argument>
                            <argument>/f</argument>
                            <argument>${deployment.resources.signature.location}</argument>
                            <argument>/fd</argument>
                            <argument>certHash</argument>
                            <argument>/p</argument>
                            <argument>${deployment.resources.signature.secret}</argument>
                            <argument>${project.build.directory}\${project.build.finalName}\AppFolder\Launcher.exe</argument>
                        </arguments>
                    </configuration>                        
                </execution>                    
                <execution>
                    <id>exec</id>
                    <phase>package</phase>
                    <goals>
                        <goal>exec</goal>
                    </goals>
                    <configuration>
                        <executable>${deployment.windowskit.path}\signtool.exe</executable>
                        <arguments>
                            <argument>sign</argument>
                            <argument>/f</argument>
                            <argument>${deployment.resources.signature.location}</argument>
                            <argument>/fd</argument>
                            <argument>certHash</argument>
                            <argument>/p</argument>
                            <argument>${deployment.resources.signature.secret}</argument>
                            <argument>${project.build.directory}\${project.build.finalName}.exe</argument>
                        </arguments>
                    </configuration>                        
                </execution>
            </executions>

        </plugin>

        <plugin> <!-- NSIS plugin for producing nsis installer -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>nsis-maven-plugin</artifactId>
            <version>1.0-alpha-1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>generate-headerfile</goal>
                        <goal>make</goal>
                    </goals>
                    <configuration>
                        <makensisBin>${package.nsisbinpath}</makensisBin> <!-- specify this in your settings.xml! -->

                        <scriptFile>target/${project.build.finalName}\Setup.nsi</scriptFile>
                        <outputFile>${project.build.finalName}.exe</outputFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        
        <plugin> <!-- Deploy to scp production server -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>properties-maven-plugin</artifactId>
            ... unrelated stuff
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-antrun-plugin</artifactId>
            ... unrelated stuff
        </plugin>
        <plugin> <!-- skip the regular deploy plugin - we don't want this build winding up in Nexus -->
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-deploy-plugin</artifactId>
            ... unrelated stuff
        </plugin>
        
    </plugins>          

If I set the phase for the sign-launcher execution to 'package', the NSIS install build happens before the launcher exe is signed. If I set the phase to 'pre-package', the launcher exe hasn't been copied to the target folder by the Assembly plugin yet when SignTool is called.

What I need is the following execution order

  1. Assembly plugin
  2. exec-maven-plugin - sign the launcher
  3. nsis-maven-plugin
  4. exec-maven-plugin - sign the installer

Any suggestions on how to get the exec-maven-plugin to run right after the Assembly plugin?


A few updates: I noticed that the phase in the Maven documentation is "prepare-package", not "pre-package". Changing that does note make a difference.

According to this post: Changing the order of maven plugins execution - ordering of executions in the same phase is controlled by the order they appear in the POM.

But I have a single plugin that needs one execution to happen before another plugin (the nsis build plugin) and one execution to happen after that plugin...

I've tried inserting the plugin exec-maven-plugin twice, but that doesn't work either.


Solution

  • Huge shout out to @Andrey B. Panfilov for suggestion and example of using the mojo-executor-maven-plugin to get fine grained control over the build process. Our pom is ugly now, but it works :-)

    In case anyone else needs this, here's the full working example (note we had to split the nsis plugings goals into two separate execution. Also had to make sure we only include configuration properties specific to each of those goals):

                <plugin>
                    <groupId>org.twdata.maven</groupId>
                    <artifactId>mojo-executor-maven-plugin</artifactId>
                    <version>2.4.1</version>
                    <executions>
                    
                        <execution>
                            <id>assembly</id>
                            <phase>package</phase>
                            <goals>
                                <goal>execute-mojo</goal>
                            </goals>
                            <configuration>
                                <plugin>
                                    <artifactId>maven-assembly-plugin</artifactId>
                                </plugin>
                                <goal>single</goal>
                                <configuration>
                                    <descriptors>
                                        <descriptor>${basedir}/src/main/assembly/assembly.xml</descriptor>
                                    </descriptors>
                                    <appendAssemblyId>false</appendAssemblyId>
                                </configuration>
                                
                            </configuration>
                        </execution>
                        
                        <execution>
                            <id>exec-maven-plugin-sign-launcher</id>
                            <phase>package</phase>
                            <goals>
                                <goal>execute-mojo</goal>
                            </goals>
                            <configuration>
                                <plugin> <!-- Sign the launcher -->
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>exec-maven-plugin</artifactId>
                                    <version>3.5.0</version>
                                </plugin>           
                                <goal>exec</goal>
                                <configuration>
                                    <executable>${deployment.windowskit.path}\signtool.exe</executable>
                                    <arguments>
                                        <argument>sign</argument>
                                        <argument>/f</argument>
                                        <argument>${deployment.resources.signature.location}</argument>
                                        <argument>/fd</argument>
                                        <argument>certHash</argument>
                                        <argument>/p</argument>
                                        <argument>${deployment.resources.signature.secret}</argument>
                                        <argument>${project.build.directory}\${project.build.finalName}\AppFolder\Launcher.exe</argument>
                                    </arguments>
                                </configuration>                        
                            </configuration>
                        </execution>
    
                        <execution>
                            <id>nsis-maven-plugin-generate-headerfile</id>
                            <phase>package</phase>
                            <goals>
                                <goal>execute-mojo</goal>
                            </goals>
                            <configuration>
                                <plugin> <!-- NSIS plugin for producing nsis installer -->
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>nsis-maven-plugin</artifactId>
                                    <version>1.0-alpha-1</version>
                                </plugin>
                                <goal>generate-headerfile</goal>
                                <configuration>
                                </configuration>
                            </configuration>
                        </execution>
    
                        <execution>
                            <id>nsis-maven-plugin-make</id>
                            <phase>package</phase>
                            <goals>
                                <goal>execute-mojo</goal>
                            </goals>
                            <configuration>
                                <plugin> <!-- NSIS plugin for producing nsis installer -->
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>nsis-maven-plugin</artifactId>
                                    <version>1.0-alpha-1</version>
                                </plugin>
                                <goal>make</goal>
                                <configuration>
                                    <makensisBin>${package.nsisbinpath}</makensisBin> <!-- specify this in your settings.xml! -->
                                    <scriptFile>target/${project.build.finalName}\Setup.nsi</scriptFile>
                                    <outputFile>${project.build.finalName}.exe</outputFile>
                                </configuration>
                            </configuration>
                        </execution>
                        
                        <execution>
                            <id>exec-maven-plugin-sign-installer</id>
                            <phase>package</phase>
                            <goals>
                                <goal>execute-mojo</goal>
                            </goals>
                            <configuration>
                                <plugin> <!-- Sign the launcher -->
                                    <groupId>org.codehaus.mojo</groupId>
                                    <artifactId>exec-maven-plugin</artifactId>
                                    <version>3.5.0</version>
                                </plugin>           
                                <goal>exec</goal>
                                <configuration>
                                    <executable>${deployment.windowskit.path}\signtool.exe</executable>
                                    <arguments>
                                        <argument>sign</argument>
                                        <argument>/f</argument>
                                        <argument>${deployment.resources.signature.location}</argument>
                                        <argument>/fd</argument>
                                        <argument>certHash</argument>
                                        <argument>/p</argument>
                                        <argument>${deployment.resources.signature.secret}</argument>
                                        <argument>${project.build.directory}\${project.build.finalName}.exe</argument>
                                    </arguments>
                                </configuration>                        
                            </configuration>
                        </execution>
                        
                        
                    </executions>
                </plugin>