查找多模块 Maven Reactor 项目的根目录

发布于 2024-09-06 14:25:32 字数 2694 浏览 4 评论 0 原文

有没有一种简单的方法可以找到多模块 Maven 项目的根目录,例如 Gradle 的 rootDir


背景:

我想使用 maven-dependency-plugin 将多模块项目的所有子模块中的工件复制到相对于整个项目的根目录的目录。

也就是说,我的布局看起来与此类似,名称已更改:

to-deploy/
my-project/
    module-a/
    module-b/
    more-modules-1/
        module-c/
        module-d/
    more-modules-2/
        module-e/
        module-f/
    ...

并且我希望将所有工件从各自模块的目标目录复制到 my-project/../to-deploy 所以我最终

to-deploy/
    module-a.jar
    module-b.jar
    module-c.jar
    module-d.jar
    module-e.jar
    module-f.jar
my-project/
    ...

可以在每个模块中使用相对路径来完成此操作,如下所示:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>install</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>${project.artifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <outputDirectory>../../to-deploy</outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

但我不想在 元素中指定相对路径。 我更喜欢像 ${reactor.root.directory}/../to-deploy 这样的东西,但我找不到这样的东西。

另外,我希望有某种方法可以继承此 maven-dependency-plugin 配置,这样我就不必为每个模块指定它。

我还尝试从根 pom 继承自定义属性:

<properties>
    <myproject.root>${basedir}</myproject.root>
</properties>

但是当我尝试在模块 POM 中使用 ${myproject.root} 时,${basedir} 将解析到模块的 basedir。

另外,我发现 http://labs.consol.de/lang/de/blog/maven/project-root-path-in-a-maven-multi-module-project/ 建议每个开发人员并且大概持续集成服务器应该在profiles.xml文件中配置根目录,但我不认为这是一个解决方案。

那么有没有一种简单的方法来找到多模块项目的根呢?

Is there an easy way to find the root of a multi-module Maven project, like Gradle's rootDir?


Background:

I want to use the maven-dependency-plugin to copy artifacts from all sub-modules of my multi-module project to a directory that is relative to the root directory of the entire project.

That is, my layout looks similar to this, names changed:

to-deploy/
my-project/
    module-a/
    module-b/
    more-modules-1/
        module-c/
        module-d/
    more-modules-2/
        module-e/
        module-f/
    ...

And i want all the artifacts to be copied from the target-directories of their respective modules to my-project/../to-deploy so i end up with

to-deploy/
    module-a.jar
    module-b.jar
    module-c.jar
    module-d.jar
    module-e.jar
    module-f.jar
my-project/
    ...

I could do it with a relative path in each module, like so:

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy</id>
                    <phase>install</phase>
                    <goals>
                        <goal>copy</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>${project.artifactId}</artifactId>
                                <version>${project.version}</version>
                                <type>jar</type>
                                <outputDirectory>../../to-deploy</outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

But i'd rather not specify a relative path in the <outputDirectory> element.
I'd prefer something like ${reactor.root.directory}/../to-deploy, but i can't find anything like this.

Also, i'd prefer if there was some way to inherit this maven-dependency-plugin configuration so i don't have to specify it for each module.

I also tried inheriting a custom property from the root pom:

<properties>
    <myproject.root>${basedir}</myproject.root>
</properties>

But when i tried to use ${myproject.root} in the module POM's, the ${basedir} would resolve to the basedir of the module.

Also, i found http://labs.consol.de/lang/de/blog/maven/project-root-path-in-a-maven-multi-module-project/ where it's suggested that each developer and presumably the continuous integration server should configure the root directory in a profiles.xml file, but i don't consider it a solution.

So is there an easy way to find the root of a multi-module project?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

漫漫岁月 2024-09-13 14:25:32

使用 ${session.executionRootDirectory}

作为记录,${session.executionRootDirectory} 在 Maven 3.0.3 的 pom 文件中为我工作。该属性将是您正在运行的目录,因此运行父项目,每个模块都可以获取该根目录的路径。

我将使用此属性的插件配置放在父 pom 中,以便它被继承。我在配置文件中使用它,仅当我知道要在父项目上运行 Maven 时才选择该配置文件。这样,当我在子项目上运行 Maven 时,我就不太可能以不希望的方式使用此变量(因为这样该变量将不是父项目的路径)。

例如,

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-artifact</id>
            <phase>package</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <version>${project.version}</version>
                        <type>${project.packaging}</type>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>${session.executionRootDirectory}/target/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

use ${session.executionRootDirectory}

For the record, ${session.executionRootDirectory} works for me in pom files in Maven 3.0.3. That property will be the directory you're running in, so run the parent project and each module can get the path to that root directory.

I put the plugin configuration that uses this property in the parent pom so that it's inherited. I use it in a profile that I only select when I know that I'm going to run Maven on the parent project. This way, it's less likely that I'll use this variable in an undesired way when I run Maven on a child project (because then the variable would not be the path to the parent).

For example,

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-artifact</id>
            <phase>package</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>${project.artifactId}</artifactId>
                        <version>${project.version}</version>
                        <type>${project.packaging}</type>
                    </artifactItem>
                </artifactItems>
                <outputDirectory>${session.executionRootDirectory}/target/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
零時差 2024-09-13 14:25:32

从 Maven 3.3.1 开始,您可以使用 ${maven.multiModuleProjectDirectory} 来实现此目的。
(感谢 https://stackoverflow.com/a/48879554/302789

编辑:这似乎只有在以下情况下才能正常工作您的项目根目录下有一个 .mvn 文件夹。

Since Maven 3.3.1, you can use ${maven.multiModuleProjectDirectory} for this purpose.
(thanks to https://stackoverflow.com/a/48879554/302789)

edit: this seems to only work properly when you have a .mvn folder at the root of your project.

梦纸 2024-09-13 14:25:32

我在项目中使用的方法是覆盖子模块 poms 中的属性。

    root:           <myproject.root>${basedir}</myproject.root>
    moduleA:        <myproject.root>${basedir}/..</myproject.root>
    other/moduleX:  <myproject.root>${basedir}/../..</myproject.root>

这样,您仍然拥有相对路径,但您可以在根模块中定义一次插件,并且您的模块将通过正确替换 myproject.root 来继承它。

Something which I have used in my projects is to override the property in the sub-module poms.

    root:           <myproject.root>${basedir}</myproject.root>
    moduleA:        <myproject.root>${basedir}/..</myproject.root>
    other/moduleX:  <myproject.root>${basedir}/../..</myproject.root>

This way you still have the relative paths, but you can define a plugin once in the root module, and your modules will inherit it with the right substitution for myproject.root.

可遇━不可求 2024-09-13 14:25:32

有一个maven插件可以解决这个特殊问题: directory-maven-plugin

它将分配您的项目到您选择的属性的根路径。请参阅文档中的 highest-basedir 目标。

例如:

<!-- Directory plugin to find parent root directory absolute path -->
<plugin>
  <groupId>org.commonjava.maven.plugins</groupId>
  <artifactId>directory-maven-plugin</artifactId>
  <version>0.1</version>
  <executions>
    <execution>
      <id>directories</id>
      <goals>
        <goal>highest-basedir</goal>
      </goals>
      <phase>initialize</phase>
      <configuration>
        <property>main.basedir</property>
      </configuration>
    </execution>
  </executions>
</plugin>

然后在父/子 pom.xml 中的任何位置使用 ${main.basedir}

There is a maven plugin that solves this particular problem: directory-maven-plugin

It will assign the root path of your project to a property of your choosing. See highest-basedir goal in the docs.

For example:

<!-- Directory plugin to find parent root directory absolute path -->
<plugin>
  <groupId>org.commonjava.maven.plugins</groupId>
  <artifactId>directory-maven-plugin</artifactId>
  <version>0.1</version>
  <executions>
    <execution>
      <id>directories</id>
      <goals>
        <goal>highest-basedir</goal>
      </goals>
      <phase>initialize</phase>
      <configuration>
        <property>main.basedir</property>
      </configuration>
    </execution>
  </executions>
</plugin>

Then use ${main.basedir} anywhere in your parent / child pom.xml.

夜清冷一曲。 2024-09-13 14:25:32

正如其他人所建议的,directory-maven-plugin 是正确的选择。
但是,我发现它最适合 directory-of 目标,如下所述:https://stackoverflow .com/a/37965143/6498617

我更喜欢这样,因为使用 highest-basedir 不适用于具有嵌套多模块 pom 的多模块项目。 directory-of 目标允许您将属性设置为整个项目中任何模块的路径,当然包括根目录。
它也比 ${session.executionRootDirectory} 好得多,因为无论您构建的是根模块还是子模块,也无论您从哪个 mvn 当前工作目录,它总是有效。

As others have suggested, directory-maven-plugin is the way to go.
However, I found it works best with the directory-of goal, as described here: https://stackoverflow.com/a/37965143/6498617.

I prefer that as using highest-basedir didn't work for me with a multi-module project, with nested multi-module poms. The directory-of goal lets you set a property to the path of any module in the whole project, including the root of course.
It is also way better than ${session.executionRootDirectory}, because it always works, regardless of whether you build the root or a sub-module, and irrespective of the current working directory where you mvn from.

香草可樂 2024-09-13 14:25:32

目前,Maven 不提供这样的“根项目目录路径”属性。
“根项目”是指“最顶层”父项目。

请参阅票证并考虑投票:[MNG-7038] Introduce public property to指向(多模块)项目的根目录 - ASF JIRA

Currently, Maven does not provide such the «Root project directory path» property out of the box.
«Root project» means the «topmost» parent project.

Please, refer to the ticket and consider voting for it: [MNG-7038] Introduce public property to point to a root directory of (multi-module) project - ASF JIRA.

温柔女人霸气范 2024-09-13 14:25:32

以下小简介对我有用。我需要这样的 CheckStyle 配置,我将其放入项目根目录的 config 目录中,这样我就可以从主模块和子模块运行它。

<profile>
    <id>root-dir</id>
    <activation>
        <file>
            <exists>${project.basedir}/../../config/checkstyle.xml</exists>
        </file>
    </activation>
    <properties>
        <project.config.path>${project.basedir}/../config</project.config.path>
    </properties>
</profile>

它不适用于嵌套模块,但我确信可以使用具有不同 exists 的多个配置文件对其进行修改。 (我不知道为什么验证标签中应该有“../..”,而重写属性本身只有“..”,但它只能以这种方式工作。)

The following small profile worked for me. I needed such a configuration for CheckStyle, which I put into the config directory in the root of the project, so I can run it from the main module and from submodules.

<profile>
    <id>root-dir</id>
    <activation>
        <file>
            <exists>${project.basedir}/../../config/checkstyle.xml</exists>
        </file>
    </activation>
    <properties>
        <project.config.path>${project.basedir}/../config</project.config.path>
    </properties>
</profile>

It won't work for nested modules, but I'm sure it can be modified for that using several profiles with different exists's. (I have no idea why there should be "../.." in the verification tag and just ".." in the overriden property itself, but it works only in that way.)

一刻暧昧 2024-09-13 14:25:32

我遇到了类似的问题,因为我需要在项目之间复制文件。 Maven 所做的事情是合乎逻辑的,因为它将使安装在存储库中的 pom.xml 远离硬编码值。

我的解决方案是将复制的目录放入 Maven 工件中,然后使用 Ant 提取/复制

I encountered similar problem as i needed to copy files between projects. What Maven does is logical because it will keep the pom.xml installed in repository away from hard coded value.

My solution was to put copied dir in a Maven artifact, then employ Ant to extract/copy

故事未完 2024-09-13 14:25:32

除了使用绝对根路径之外,在某些情况下,我还有另一种方法来解决问题。

使用maven插件combine.children功能,参考:maven插件

我可以编写我的代码:

parent pom:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
          <execution>
              <id>copy-dependencies</id>
              <phase>package</phase>
              <goals>
                  <goal>copy-dependencies</goal>
              </goals>
              <configuration>
                  <includeScope>runtime</includeScope>
                  <outputDirectory combine.children="override">${project.basedir}/to-deploy</outputDirectory>
              </configuration>
          </execution>
      </executions>
    </plugin>
  </plugins>
</build>

或者写在插件管理中,如果parent pom不使用该插件。

子pom:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
          <execution>
              <!--same as parent plugin id-->
              <id>copy-dependencies</id>
              <configuration>
                  <outputDirectory combine.children="override">${project.parent.basedir}/to-deploy</outputDirectory>
              </configuration>
          </execution>
      </executions>
    </plugin>
  </plugins>
</build>

类似的方式
孙子 pom:

<outputDirectory combine.children="override">${project.parent.parent.basedir}/to-deploy</outputDirectory>

Except use absolutely root path, in some case, I have another way to solve the problem.

Use maven plugin combine.children feature, refs: maven plugin

I can write my code:

parent pom:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
          <execution>
              <id>copy-dependencies</id>
              <phase>package</phase>
              <goals>
                  <goal>copy-dependencies</goal>
              </goals>
              <configuration>
                  <includeScope>runtime</includeScope>
                  <outputDirectory combine.children="override">${project.basedir}/to-deploy</outputDirectory>
              </configuration>
          </execution>
      </executions>
    </plugin>
  </plugins>
</build>

or write in plugin management, if parent pom doesn't use this plugin.

child pom:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-dependency-plugin</artifactId>
      <executions>
          <execution>
              <!--same as parent plugin id-->
              <id>copy-dependencies</id>
              <configuration>
                  <outputDirectory combine.children="override">${project.parent.basedir}/to-deploy</outputDirectory>
              </configuration>
          </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Similar way
grandchild pom:

<outputDirectory combine.children="override">${project.parent.parent.basedir}/to-deploy</outputDirectory>
聆听风音 2024-09-13 14:25:32

我不知道找到多模块项目的根的“好”方法。但你也许可以改进一下你当前的方法。

第一种选择是直接在根项目下创建一个附加模块,将所有 EAR 声明为其中的依赖项并使用 dependency:copy-dependencies 将模块的依赖项复制到to-deploy目录(相对)。是的,路径仍然是相对的,但由于依赖插件配置将是集中的,我觉得它并不那么烦人。

第二种选择是使用 Maven Assembly Plugin 而不是 < a href="http://maven.apache.org/plugins/maven-dependency-plugin/" rel="nofollow noreferrer">Maven 依赖插件 使用 dir 格式(这将在目录中创建一个发行版)。这实际上就是我要做的。

I'm not aware of a "nice" way to find the root of a multi-module project. But you can maybe improve a bit your current approach.

A first alternative would be to create an additional module directly under the root project, to declare all EARs as dependencies in it and to use dependency:copy-dependencies to copy the dependencies of the module to the to-deploy directory (relatively). Yes the path would still be relative but since the dependency plugin configuration would be centralized, I don't find it that annoying.

A second alternative would be to use the Maven Assembly Plugin instead of the Maven Dependency Plugin to create a distribution using the dir format (this will create a distribution in a directory). This is actually what I would do.

药祭#氼 2024-09-13 14:25:32

另一个解决方案是使用 ant 任务将“rootdir=${basedir}”写入根项目中的 target/root.properties,然后使用 属性插件 来读回该文件。我自己还没有尝试过,但我想它应该可以工作..?

Another solution would be to use an ant task to write "rootdir=${basedir}" to a target/root.properties in the root project, and then use the Properties Plugin to read that file back in. I haven't tried it myself, but I guess it should work..?

我不咬妳我踢妳 2024-09-13 14:25:32

你可以选择这样的东西。请注意,您必须定义两个配置文件 - 一个将为根目录激活,另一个为子目录激活。显然,这假设孩子们将具有相同的结构,但这可以很容易地适应。

    <profiles>
        <profile>
            <id>root-dir</id>
            <activation>
                <file>
                    <exists>${basedir}/lib</exists>
                </file>
            </activation>
            <properties>
                <project.libdir>${basedir}/lib</project.libdir>
            </properties>
        </profile>
        <profile>
            <id>child-dir</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <project.libdir>${basedir}/../../lib</project.libdir>
            </properties>
        </profile>
    </profiles>

You can go with something like this. Note, that you have to define two profiles - one which will be activated for the root directory and one for children. Obviously this assumes children will have the same structure but this can be easily adapted.

    <profiles>
        <profile>
            <id>root-dir</id>
            <activation>
                <file>
                    <exists>${basedir}/lib</exists>
                </file>
            </activation>
            <properties>
                <project.libdir>${basedir}/lib</project.libdir>
            </properties>
        </profile>
        <profile>
            <id>child-dir</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <project.libdir>${basedir}/../../lib</project.libdir>
            </properties>
        </profile>
    </profiles>
虚拟世界 2024-09-13 14:25:32

这样:在某个父项目的属性中的某个位置,我有稍后需要关联的文件,这就是为什么我在任何地方都需要它的绝对路径。所以,我在groovy的帮助下得到了它:

<properties>    
<source> import java.io.File; 
        String p =project.properties['env-properties-file']; 
        File f = new File(p); 
        if (!f.exists()) 
        { 
           f = new File("../" + p); 
          if (!f.exists()) 
          { 
             f = new File("../../" + p); 
          } 
        } 
        // setting path together with file name in variable xyz_format 
        project.properties['xyz_format'] =f.getAbsolutePath() 
                            + File.separator 
                            + "abc_format.xml"; 
</source>
</properties>   

然后:

  <properties>
     <snapshots>http://localhost:8081/snapshots<snapshots>
     <releases>http://localhost:8081/releases</releases>
     <sonar>jdbc:oracle:thin:sonar/sonar@localhost/XE</sonar>
     <sonar.jdbc.username>sonar</sonar.jdbc.username>
     <format.conf> ${xyz_format}</format.conf>  <---- here is it!
    </properties>

它起作用了!

so that: somewhere in properties of some parent Project I've the file which i need to relate later, what's why i need absolute path on it everywhere. So, i get it with help of groovy:

<properties>    
<source> import java.io.File; 
        String p =project.properties['env-properties-file']; 
        File f = new File(p); 
        if (!f.exists()) 
        { 
           f = new File("../" + p); 
          if (!f.exists()) 
          { 
             f = new File("../../" + p); 
          } 
        } 
        // setting path together with file name in variable xyz_format 
        project.properties['xyz_format'] =f.getAbsolutePath() 
                            + File.separator 
                            + "abc_format.xml"; 
</source>
</properties>   

and then:

  <properties>
     <snapshots>http://localhost:8081/snapshots<snapshots>
     <releases>http://localhost:8081/releases</releases>
     <sonar>jdbc:oracle:thin:sonar/sonar@localhost/XE</sonar>
     <sonar.jdbc.username>sonar</sonar.jdbc.username>
     <format.conf> ${xyz_format}</format.conf>  <---- here is it!
    </properties>

it works!

薔薇婲 2024-09-13 14:25:32

使用 Maven 4(自 4.0.0-beta7 起实施,请参阅 MNG-7038 )您可以使用 project.rootDirectory 变量,其中根目录是通过使用 .mvn 目录或使用新的 pom 属性 root=true< 来定义的/code> 是在新的 pom 模型版本 4.1.0 中与 Maven 4 一起引入的。

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

然后使用该变量,例如

${project.rootDirectory}/exclude-pmd.properties

With Maven 4 (implemented since 4.0.0-beta7, see MNG-7038) you can use the project.rootDirectory variable, where the root directory is definied either by using a .mvn directory or using the new pom attribute root=true which is introduced with the new pom model version 4.1.0 together with Maven 4.

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

and then use the variable, e.g.

<excludeFromFailureFile>${project.rootDirectory}/exclude-pmd.properties</excludeFromFailureFile>

南笙 2024-09-13 14:25:32

对于 Maven 3.6.1,从子项目中,${parent.basedir} 返回父项目的完全限定目录。

With Maven 3.6.1, from a child project, ${parent.basedir} returns the fully qualified directory of the parent project.

蓝戈者 2024-09-13 14:25:32

我有 ${project.parent.basedir} 的父 pom 的根目录。

I've got root directory for parent pom with ${project.parent.basedir}.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文