Quantcast

POM inheritance breaks build

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

POM inheritance breaks build

cowwoc
Hi,

I've posted a simple testcase at http://stackoverflow.com/questions/4171222/maven-depending-on-inheriting-artifact-causes-build-error that demonstrates how POM inheritance causes builds to break.

Given three POM files:

    * C depends on B.
    * B inherits from A.
    * I can build A and B
    * C fails to resolve properties defined in A or B, and as a result fails to locate its transitive dependencies. The build breaks.

Please help!

Thanks,
Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Depending on POM using inheritance breaks build

cowwoc
Hi,

   I'm getting a build error when my project depends on a POM that uses inheritance. Given three POM files:

    * C depends on B.
    * B inherits from A.
    * I can build A and B
    * C fails to build because of its dependency on B.

The full source-code and build output is included below for your review.

Here is A's POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.foo</groupId>
    <artifactId>A</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>A</name>
    <repositories>
        <repository>
            <id>foo releases</id>
            <name>libs-releases-local</name>
            <layout>default</layout>
            <url>http://foo.net/artifactory/libs-releases-local</url>
        </repository>
    </repositories>
    <dependencies>
        <dependency>
            <groupId>org.eclipse.swt</groupId>
            <artifactId>swt</artifactId>
            <classifier>${swt.classifier}</classifier>
            <version>3.6.1</version>
        </dependency>
    </dependencies>
    <profiles>
        <profile>
            <id>windows-x86</id>
            <properties>
                <swt.classifier>win32-x86</swt.classifier>
            </properties>
        </profile>
    </profiles>
</project>

Here is B's POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.foo</groupId>
        <artifactId>A</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../A</relativePath>
    </parent>
    <artifactId>B</artifactId>
    <packaging>jar</packaging>
    <name>B</name>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classifier>${swt.classifier}</classifier>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <profiles>
        <profile>
            <id>windows-x86</id>
            <properties>
                <swt.classifier>win32-x86</swt.classifier>
            </properties>
        </profile>
    </profiles>
</project>

Here is C's POM:

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.amayagaming</groupId>
    <artifactId>C</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>C</name>
    <dependencies>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>B</artifactId>
            <version>${project.version}</version>
            <classifier>win32-x86</classifier>
        </dependency>
    </dependencies>
</project>

Here is the build output from C:

------------------------------------------------------------------------
Building C
   task-segment: [install]
------------------------------------------------------------------------
[compiler:compile]
Nothing to compile - all classes are up to date
Downloading: http://foo.net/artifactory/libs-releases-local/org/eclipse/swt/swt/3.6.1/swt-3.6.1-${swt.classifier}.jar
[WARNING] Unable to get resource 'org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1' from repository foo releases (http://foo.net/artifactory/libs-releases-local): Error transferring file: foo.net
Downloading: http://repo1.maven.org/maven2/org/eclipse/swt/swt/3.6.1/swt-3.6.1-${swt.classifier}.jar
Unable to find resource 'org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1' in repository central (http://repo1.maven.org/maven2)
------------------------------------------------------------------------
[ERROR]BUILD ERROR
------------------------------------------------------------------------
Failed to resolve artifact.

Missing:
----------
1) org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1


Please help!

Thanks,
Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Depending on POM using inheritance breaks build

Benjamin Bentmann
cowwoc wrote:

>      <dependencies>
>          <dependency>
>              <groupId>org.eclipse.swt</groupId>
>              <artifactId>swt</artifactId>
>              <classifier>${swt.classifier}</classifier>
>              <version>3.6.1</version>
>          </dependency>
>      </dependencies>
>      <profiles>
>          <profile>
>              <id>windows-x86</id>
>              <properties>
>                  <swt.classifier>win32-x86</swt.classifier>
>              </properties>
>          </profile>
>      </profiles>

Looks like http://jira.codehaus.org/browse/MNG-1388


Benjamin

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Depending on POM using inheritance breaks build

cowwoc
Benjamin Bentmann wrote
What do you recommend I do to work around this problem?
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Depending on POM using inheritance breaks build

Wayne Fay
> What do you recommend I do to work around this problem?

Don't use the ${swt.classifier} for now...

You may notice it was reported 5 years ago so if you actually want it
fixed, you'll probably need to help on MNG-1388.

Wayne

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Depending on POM using inheritance breaks build

cowwoc
Wayne Fay wrote
> What do you recommend I do to work around this problem?

Don't use the ${swt.classifier} for now...

You may notice it was reported 5 years ago so if you actually want it
fixed, you'll probably need to help on MNG-1388.
How do you deal with artifacts that need a different native library depending on the build platform without the use of ${swt.classifier}?

Thanks,
Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: Depending on POM using inheritance breaks build

Eric Haszlakiewicz
>-----Original Message-----
>From: cowwoc [mailto:[hidden email]]
>
>Wayne Fay wrote:
>>
>>> What do you recommend I do to work around this problem?
>>
>> Don't use the ${swt.classifier} for now...
>>
>> You may notice it was reported 5 years ago so if you actually want it
>> fixed, you'll probably need to help on MNG-1388.
>>
>
>How do you deal with artifacts that need a different native library
>depending on the build platform without the use of ${swt.classifier}?

This feels to me like the old problem that there is no distinction between the pom file used to control the build, and the pom file that describes the artifact.  
In a general sense, the properties that exist at the time that an artifact gets created (in this case swt.classifier, which was set by a profile) aren't remembered in the deployed artifact.

The workaround I've seen suggested for this is to throw another layer of indirection in there and have a separate pom for each possible value of your variable.  
In your case, I think you'd split project B into a B-windows-x86/pom.xml, B-whateverelse/pom.xml, etc... modules that each refer to the swt.classifier with a fixed value.  
Then you'd need to set up an overall pom.xml that lists different modules based on the profile,
and you'll probably want some kind of common pom that all of the sub-modules depend on to pull in all the other normal dependencies.
Obviously, this doesn't work well if you have more than just one variable you're dealing with,
and it seems (to me anyway) to be an unnecessary complex and confusing way to set things up,
but supposedly that's the "maven way".

eric
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: Depending on POM using inheritance breaks build

cowwoc
Eric Haszlakiewicz wrote
>-----Original Message-----
>From: cowwoc [mailto:cowwoc@bbs.darktech.org]
>
>Wayne Fay wrote:
>>
>>> What do you recommend I do to work around this problem?
>>
>> Don't use the ${swt.classifier} for now...
>>
>> You may notice it was reported 5 years ago so if you actually want it
>> fixed, you'll probably need to help on MNG-1388.
>>
>
>How do you deal with artifacts that need a different native library
>depending on the build platform without the use of ${swt.classifier}?

This feels to me like the old problem that there is no distinction between the pom file used to control the build, and the pom file that describes the artifact.  
In a general sense, the properties that exist at the time that an artifact gets created (in this case swt.classifier, which was set by a profile) aren't remembered in the deployed artifact.

The workaround I've seen suggested for this is to throw another layer of indirection in there and have a separate pom for each possible value of your variable.  
In your case, I think you'd split project B into a B-windows-x86/pom.xml, B-whateverelse/pom.xml, etc... modules that each refer to the swt.classifier with a fixed value.  
Then you'd need to set up an overall pom.xml that lists different modules based on the profile,
and you'll probably want some kind of common pom that all of the sub-modules depend on to pull in all the other normal dependencies.
Obviously, this doesn't work well if you have more than just one variable you're dealing with,
and it seems (to me anyway) to be an unnecessary complex and confusing way to set things up,
but supposedly that's the "maven way".
Dear god, that's terrible! I don't want to have to maintain 8 different POM files (the number of platforms I support) per variable. Is there an easier workaround?

PS: Eric is quite right in that the built artifact should remember/hard-code the values used to build it. Anyone who depends on it should use the hard-coded values.

Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: Depending on POM using inheritance breaks build

Eric Haszlakiewicz

>Dear god, that's terrible! I don't want to have to maintain 8 different POM
>files (the number of platforms I support) per variable. Is there an easier
>workaround?

One thing I've been thinking about, but never actually tried, is to set up a wrapper maven build that has all the various variables, and use resource filtering (or perhaps the maven-replacer-plugin) to generate the real pom.xml file based on a template.  Then kick off real build using that generated pom.xml (which could be integrated into the wrapper pom with maven-exec-plugin).
Resource filtering looks like it might be convenient since it uses the same syntax (${foo}) for text replacement, but I suggested maven-replacer-plugin too, since you might want to explicitly distinguish between variables that get replaced and those that don't and using the plugin lets you define a custom token to do the search and replace on.

One snag in all of this is going to be that you can't really use the classifier to distinguish between the artifacts anymore b/c I believe every artifact with the same groupId:artifactId:version ends up with a single pom file, even if there are files with multiple different classifiers.

eric
---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

RE: Depending on POM using inheritance breaks build

cowwoc
In reply to this post by Eric Haszlakiewicz
Eric Haszlakiewicz wrote
>-----Original Message-----
>From: cowwoc [mailto:cowwoc@bbs.darktech.org]
>
>Wayne Fay wrote:
>>
>>> What do you recommend I do to work around this problem?
>>
>> Don't use the ${swt.classifier} for now...
>>
>> You may notice it was reported 5 years ago so if you actually want it
>> fixed, you'll probably need to help on MNG-1388.
>>
>
>How do you deal with artifacts that need a different native library
>depending on the build platform without the use of ${swt.classifier}?

This feels to me like the old problem that there is no distinction between the pom file used to control the build, and the pom file that describes the artifact.  
In a general sense, the properties that exist at the time that an artifact gets created (in this case swt.classifier, which was set by a profile) aren't remembered in the deployed artifact.

The workaround I've seen suggested for this is to throw another layer of indirection in there and have a separate pom for each possible value of your variable.  
In your case, I think you'd split project B into a B-windows-x86/pom.xml, B-whateverelse/pom.xml, etc... modules that each refer to the swt.classifier with a fixed value.  
Then you'd need to set up an overall pom.xml that lists different modules based on the profile,
and you'll probably want some kind of common pom that all of the sub-modules depend on to pull in all the other normal dependencies.
Obviously, this doesn't work well if you have more than just one variable you're dealing with,
and it seems (to me anyway) to be an unnecessary complex and confusing way to set things up,
but supposedly that's the "maven way".

eric
Gentlemen,

Does any of you care to comment on this problem? Is this convoluted approach really the best available way of solving the problem?

Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

Zac Thompson
In reply to this post by cowwoc
I posted a reply to this on stackoverflow, since that's where you
included more details.  The bottom line was that the properties are
*not* defined in A or B, only in *profiles* in A and B.  And there's
the rub: those profiles do not apply when building C, and the property
is not defined anywhere in C's pom.

On Sat, Nov 13, 2010 at 11:42 AM, cowwoc <[hidden email]> wrote:

>
> Hi,
>
> I've posted a simple testcase at
> http://stackoverflow.com/questions/4171222/maven-depending-on-inheriting-artifact-causes-build-error
> that demonstrates how POM inheritance causes builds to break.
>
> Given three POM files:
>
>    * C depends on B.
>    * B inherits from A.
>    * I can build A and B
>    * C fails to resolve properties defined in A or B, and as a result fails
> to locate its transitive dependencies. The build breaks.
>
> Please help!
>
> Thanks,
> Gili

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

cowwoc
Hi Zac,

I added:

                <properties>
                        <swt.classifier>win32-x86</swt.classifier>
                </properties>

to project C but Maven still complains:

Failed to execute goal on project C: Could not resolve dependencies for project com.foo:C:jar:1.0-SNAPSHOT: Failure to find org.eclipse.swt:swt:jar:${swt.classifier}:3.6.1 in [...] was cached in the local repository, resolution will not be reattempted until the update interval of amaya.dependencies has elapsed or updates are forced -> [Help 1]

I don't think property resolution is working as you expect it. I am using Maven 3.0.1.

Gili

Zac Thompson wrote
I posted a reply to this on stackoverflow, since that's where you
included more details.  The bottom line was that the properties are
*not* defined in A or B, only in *profiles* in A and B.  And there's
the rub: those profiles do not apply when building C, and the property
is not defined anywhere in C's pom.

On Sat, Nov 13, 2010 at 11:42 AM, cowwoc <cowwoc@bbs.darktech.org> wrote:
>
> Hi,
>
> I've posted a simple testcase at
> http://stackoverflow.com/questions/4171222/maven-depending-on-inheriting-artifact-causes-build-error
> that demonstrates how POM inheritance causes builds to break.
>
> Given three POM files:
>
>    * C depends on B.
>    * B inherits from A.
>    * I can build A and B
>    * C fails to resolve properties defined in A or B, and as a result fails
> to locate its transitive dependencies. The build breaks.
>
> Please help!
>
> Thanks,
> Gili

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

Jörg Schaible-3
cowwoc wrote:

>
> Hi Zac,
>
> I added:
>
> <properties>
> <swt.classifier>win32-x86</swt.classifier>
> </properties>

You can define this property in your settings.xmll in the appropriate
profile.

- Jörg


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

cowwoc
Jörg Schaible-3 wrote
cowwoc wrote:

>
> Hi Zac,
>
> I added:
>
> <properties>
> <swt.classifier>win32-x86</swt.classifier>
> </properties>

You can define this property in your settings.xmll in the appropriate
profile.

- Jörg
Jörg,

Isn't one of the main selling points of Maven the ability to include transitive dependencies with little effort? Now you're telling me that not only do I have to explicitly deal with each transitive dependency, I also have to tell all my developers to modify their settings.xml file. One person at a time.

... Is this as good as it gets? ... Really?! Surely there is a better way?

Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

Jörg Schaible-3
Hi Gili,

cowwoc wrote:

>
>
> Jörg Schaible-3 wrote:
>>
>> cowwoc wrote:
>>
>>>
>>> Hi Zac,
>>>
>>> I added:
>>>
>>> <properties>
>>> <swt.classifier>win32-x86</swt.classifier>
>>> </properties>
>>
>> You can define this property in your settings.xmll in the appropriate
>> profile.
>>
>> - Jörg
>>
>
> Jörg,
>
> Isn't one of the main selling points of Maven the ability to include
> transitive dependencies with little effort? Now you're telling me that not
> only do I have to explicitly deal with each transitive dependency, I also
> have to tell all my developers to modify their settings.xml file. One
> person at a time.
>
> ... Is this as good as it gets? ... Really?! Surely there is a better way?

The point is that it is platform dependent - the platform your developer is
using. A profile should not be used to define dependencies - at least if
those should be transitively inherited. It simply does not work in the way
most people assume. It is not inherited anyway, therefore you have to define
it already twice (in A and B). This does not scale also.

What you might try is to define a swt pom (or package type pom) for all
platforms like:

...
  <groupId>com.eclipse</groupId>
  <artifactId>swt-generic</artifactId>
  <version>3.6.1</version>
  <packaging>pom</packaging>

  <profiles>
    <profile>
      <id>win32</id>
      <dependencies>
        <groupId>com.eclipse</groupId>
        <artifactId>swt</artifactId>
        <version>3.6.1</version>
        <classifier>win32-x86</classifier>
      </dependencies>
    </profile>
    ...
  </profiles>

and refer that everywhere you need it as provided:

..
    <dependency>
      <groupId>com.eclipse</groupId>
      <artifactId>swt-generic</artifactId>
      <version>3.6.1</version>
      <type>pom</type>
      <scope>provided</scope>
    </dependency>
..

Your developers may actually set their default in the settings.xml:

  <activeProfiles>
    <activeProfile>win32</activeProfile>
    ...
  </activeProfiles>
  <profiles>
    <profile>
      <id>win32</id>
    </profile>
    ...
  </profiles>

The provided scope prevents that a special one is taken and you have to
select the appropriate one(s) when packaging your app e.g. with the assembly
plugin.

- Jörg


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

cowwoc
Jörg Schaible-3 wrote
The point is that it is platform dependent - the platform your developer is
using. A profile should not be used to define dependencies - at least if
those should be transitively inherited. It simply does not work in the way
most people assume. It is not inherited anyway, therefore you have to define
it already twice (in A and B). This does not scale also.

What you might try is to define a swt pom (or package type pom) for all
platforms like:

...
  <groupId>com.eclipse</groupId>
  <artifactId>swt-generic</artifactId>
  <version>3.6.1</version>
  <packaging>pom</packaging>

  <profiles>
    <profile>
      <id>win32</id>
      <dependencies>
        <groupId>com.eclipse</groupId>
        <artifactId>swt</artifactId>
        <version>3.6.1</version>
        <classifier>win32-x86</classifier>
      </dependencies>
    </profile>
    ...
  </profiles>

and refer that everywhere you need it as provided:

..
    <dependency>
      <groupId>com.eclipse</groupId>
      <artifactId>swt-generic</artifactId>
      <version>3.6.1</version>
      <type>pom</type>
      <scope>provided</scope>
    </dependency>
..

Your developers may actually set their default in the settings.xml:

  <activeProfiles>
    <activeProfile>win32</activeProfile>
    ...
  </activeProfiles>
  <profiles>
    <profile>
      <id>win32</id>
    </profile>
    ...
  </profiles>

The provided scope prevents that a special one is taken and you have to
select the appropriate one(s) when packaging your app e.g. with the assembly
plugin.
Hi Jörg,

I followed your instructions but I don't understand how:

  <activeProfiles>
    <activeProfile>win32</activeProfile>
    ...
  </activeProfiles>
  <profiles>
    <profile>
      <id>win32</id>
    </profile>
    ...
  </profiles>

leads to the inclusion of the Windows-specific SWT library. It doesn't seem to activate the "win32" profile in the SWT project. Any ideas?

Gili
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: POM inheritance breaks build

cowwoc
cowwoc wrote
Jörg Schaible-3 wrote
The point is that it is platform dependent - the platform your developer is
using. A profile should not be used to define dependencies - at least if
those should be transitively inherited. It simply does not work in the way
most people assume. It is not inherited anyway, therefore you have to define
it already twice (in A and B). This does not scale also.

What you might try is to define a swt pom (or package type pom) for all
platforms like:

...
  <groupId>com.eclipse</groupId>
  <artifactId>swt-generic</artifactId>
  <version>3.6.1</version>
  <packaging>pom</packaging>

  <profiles>
    <profile>
      <id>win32</id>
      <dependencies>
        <groupId>com.eclipse</groupId>
        <artifactId>swt</artifactId>
        <version>3.6.1</version>
        <classifier>win32-x86</classifier>
      </dependencies>
    </profile>
    ...
  </profiles>

and refer that everywhere you need it as provided:

..
    <dependency>
      <groupId>com.eclipse</groupId>
      <artifactId>swt-generic</artifactId>
      <version>3.6.1</version>
      <type>pom</type>
      <scope>provided</scope>
    </dependency>
..

Your developers may actually set their default in the settings.xml:

  <activeProfiles>
    <activeProfile>win32</activeProfile>
    ...
  </activeProfiles>
  <profiles>
    <profile>
      <id>win32</id>
    </profile>
    ...
  </profiles>

The provided scope prevents that a special one is taken and you have to
select the appropriate one(s) when packaging your app e.g. with the assembly
plugin.
Hi Jörg,

I followed your instructions but I don't understand how:

  <activeProfiles>
    <activeProfile>win32</activeProfile>
    ...
  </activeProfiles>
  <profiles>
    <profile>
      <id>win32</id>
    </profile>
    ...
  </profiles>

leads to the inclusion of the Windows-specific SWT library. It doesn't seem to activate the "win32" profile in the SWT project. Any ideas?

Gili
I should clarify: I can see how <activeProfile> causes the SWT project to build correctly (generating a Windows JAR file). What I can't see is how to get that JAR file to show up as a dependency in the project that depends on SWT.

One final complication: is there a way for me to define ${swt.classifier} in the SWT project and have it  show in the child project? My first use-case is to include SWT as a normal dependency. My second use-case is to use maven-unpack-plugin to download and unpack the JAR file. To do the latter, I need the classifier name in the child project.

Thanks,
Gili
Loading...