Configuring the Environment

Introduction

NMaven is based on the concept of platform capabilities and platform requirements. Examples of platform capabilities include:

  1. Linux (or Windows OS)
  2. Mono 1.1.18 installed, Microsoft 2.0 installed
  3. PHP .NET compiler (from 3rd party)

Platform requirements are those build requirements specified by the developer. Typically, the requirements are given either within the pom.xml or the nmaven-settings.xml file. Examples of platform requirements include:

  1. C# target language
  2. Microsoft SDK
  3. Framework version 2.0
  4. Compact Profile

It is up to NMaven to understand what the developer is asking for (platform requirements) and to determine whether the build machine can support the requirements (with its platform capabilities). If the capabilities match the requirements, NMaven will return an executable (or compiler) that satifies the requirements.

Capability/Requirement Matching

Consider the sequence diagram above. The developer provides the compiler requirements - vendor, vendor version, framework version, language and profile - within the pom.xml build file.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compile-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <vendor>MICROSOFT</vendor>
        <language>C_SHARP</language>
        <frameworkVersion>1.1.4322</frameworkVersion>
        <profile>COMPACT</profile>
    </configuration>
</plugin>

Next, the CompilerMojo class instance creates a CompilerConfig object (2), which contains artifact type (library, module) and key info. The compiler needs the configuration information during execution, but the information is not necessary for NMaven to match the correct compiler.

The CompilerMojo object invokes the NetExecutableFactory.getCompilerExecutableFor method, passing in the CompilerConfig and CompilerRequirement objects as parameters (3). In step (18), the getCompilerExecutableFor method returns a fully initialized CompilerExecutable object. From the CompilerMojo class instance perspective, it simply constructs CompilerConfig and CompilerRequirement objects based on parameters within the pom and gets back a fully initialized CompilerExecutable object from the NetExecutableFactory.

Now let’s dig a little deeper and see what’s going on underneath. The NetExecutableFactory object creates a VendorInfo object (4) and populates the VendorInfo object with information – vendor, vendor version and framework version – from the CompilerRequirement object (5). In short, we have a transfer of specific vendor information from the CompilerRequirement object to the VendorInfo object because the StateMachineProcessor is only concerned with the vendor information, which is the only required information for making a capability match (others are optionally used, if specified, but no attempt is made to infer them if they don't exist).

The StateMachineProcessor fills in the missing vendor info (6, 7) based on a set of rules. Vendor-info may be missing for any number of reasons. For example, a project may compile across multiple vendors (Microsoft/Novell) or framework versions. In this case, the developer may choose to leave say the <vendor/> and <frameworkVersion/> tags within the pom.xml blank. The StateMachineProcessor object uses the ~/.m2/nmaven-settings.xml file (if it exists) to assist in infering the vendor information for the specific build machine. As you can see below, within the nmaven-settings.xml file there is a default setup (which the developer can change).

<nmavenSettings>
  <defaultSetup>
    <vendorName>MICROSOFT</vendorName>
    <vendorVersion>2.0.50727</vendorVersion>
    <frameworkVersion>2.0.50727</frameworkVersion>
  </defaultSetup>
  ...
</nmavenSettings>

There are 23 states of vendor-info and both a start and stop state (for a total of 25 states). The notation is {Vendor, Vendor Version, Framework Version}. For Vendor, M denotes Microsoft, N denotes Novell, G denotes DotGNU and F denotes false (unknown vendor). For Vendor Version and Framework Version, T denotes true (it exists), while F denotes false (does not exist). So NFT means that the NMaven knows that it needs to choose a Novell (MONO) compiler and knows the framework version but not the vendor version.

The 23 vendor-info states are defined below. They are divided between general states, states that can be determined through an nmaven-settings file and states that can be determined without an nmaven-settings file.

STATEDescription
General States
MTTVendor is Microsoft, vendor version exists, framework version exists
MTFVendor is Microsoft, vendor version does not exist, framework version exists
MFTVendor is Microsoft, vendor version does not exist, framework version does not exist
NTTVendor is Novell, vendor version exists, framework version exists
Settings File States
MFFVendor is Microsoft, vendor version does not exist, framework version does not exist
FTFVendor is unknown, vendor version exists, framework version does not exist
FFTVendor is unknown, vendor version does not exist, framework version exists
FTTVendor is unknown, vendor version exists, framework version exists
FFFVendor is unknown, vendor version does not exist, framework version does not exist
NFTVendor is Novell, vendor version does not exist, framework version exists
NTFVendor is Novell, vendor version exists, framework version does not exist
NTTVendor is Novell, vendor version exists, framework version exist
NFFVendor is Novell, vendor version does not exist, framework version does not exist
GFFVendor is GNU vendor version does not exist, framework version does not exist
No Settings File States
MFF_NoSettingsVendor is Microsoft, vendor version does not exist, framework version does not exist
NFT_NoSettingsVendor is Novell, vendor version exists, framework version does not exist
NTF_NoSettingsVendor is Novell, vendor version exists, framework version does not exist
FTF_NoSettingsVendor is unknown, vendor version exists, framework version does not exist
FFT_NoSettingsVendor is unknown, vendor version does not exist, framework version exists
FTT_NoSettingsVendor is unknown, vendor version exists, framework version exists
FFF_NoSettingsVendor is unknown, vendor version does not exist, framework version does not exist
NFF_NoSettingsVendor is Novell, vendor version does not exist, framework version does not exist
GFF_NoSettingsVendor is GNU vendor version does not exist, framework version does not exist

Going back to the sequence diagram, the NetExecutableFactory object fills in the missing vendor information into the CompilerRequirement object (8): we now have a complete CompilerRequirement to use for matching. The NetExecutableFactory object initializes the CompilerContext, passing in the CompilerRequirement and CompilerConfig objects. During initialization, the CompilerContext object invokes CompilerMatcher.matchCompilerCapabilitiesFor(requirement) (10). The CompilerMatcher class instance creates a list of platform capabilities (11) and matches CompilerCapability properties to the CompilerRequirement properties (12). The CompilerMatcher gets the class name of the CompilerExecutable by invoking CompilerRequirement.getPluginClassName() (13). The CompilerMatcher dynamically instatiates and initializes the CompilerExecutable (14).

The CompilerExecutable is returned to the CompilerMojo (16, 17, 18), which then executes the Compiler (19).

For those curious enough, if you add the -X full debug output flag, say "mvn install -X", you will see NMaven write out the states it goes through in choosing the vendor info.

Sample Configuration Files

CSharp2.0:exe:Microsoft

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.ms.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>exe</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

CSharp3.0:exe:Microsoft (on Windows)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.ms.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>exe</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <frameworkVersion>3.0</frameworkVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

CSharp1.1:exe:Microsoft (on Windows)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.ms.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>exe</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <frameworkVersion>1.1.4322</frameworkVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

CSharp1.1:exe:Mono (on Linux)

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.ms.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>exe</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <frameworkVersion>1.1.4322</frameworkVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

VB2.0: library:MS

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.ms.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>library</packaging>
    <version>0.1.0.0</version>
    <name>vb:it-0001</name>

    <build>
        <sourceDirectory>src/main/vb</sourceDirectory>
        <testSourceDirectory>src/test/vb</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                                <language>VB</language>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>

CSharp1.1:module:Mono (on Windows)

You will only need to use the MONO vendor field if you want to build MONO on windows: MONO is the default vendor for other OS's.

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.mono.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>module</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <vendor>MONO</vendor>
                    <frameworkVersion>1.1.4322</frameworkVersion>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

CSharp2.0:library:Mono

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.mono.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>library</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <vendor>MONO</vendor>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

CSharp:library:DotGNU

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.mono.csharp</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>library</packaging>
    <version>0.1.0.0</version>
    <name>csharp: it-0001</name>

    <build>
        <sourceDirectory>src/main/csharp</sourceDirectory>
        <testSourceDirectory>src/test/csharp</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <vendor>DotGNU</vendor>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Nemerle:library:Mono

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.mono.nemerle</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>library</packaging>
    <version>0.1.0.0</version>
    <name>nemerle: it-0001</name>

    <build>
        <sourceDirectory>src/main/nemerle</sourceDirectory>
        <testSourceDirectory>src/test/nemerle</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <language>NEMERLE</language>
                    <vendor>MONO</vendor>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

PHP:library:Mono

To get PHP to run with NMaven, you will need to include mPHPRuntime.dll under each module directory. This is a work around until I create a mavenizer-plugin that will handle non-nmaven generated assemblies.

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.maven.mono.php</groupId>
    <artifactId>it-0001</artifactId>
    <packaging>library</packaging>
    <version>0.1.0.0</version>
    <name>php: it-0001</name>

    <build>
        <sourceDirectory>src/main/php</sourceDirectory>
        <testSourceDirectory>src/test/php</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compile-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <language>PHP</language>
                    <vendor>MONO</vendor>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>