【问题标题】:Maven building only changed filesMaven 构建只更改了文件
【发布时间】:2013-03-02 13:46:54
【问题描述】:

假设我有如下的模块结构

     Modules
       ->utils
       ->domain
       ->client
       ->services
       ->deploy (this is at the module level)

现在要启动客户端,我需要构建所有模块,i.e utils, domain, client, services,,因为我正在加载所有上述模块的 jar 以最终启动客户端

所有的罐子都在模块部署中组装起来。

我的问题是,例如,如果我更改服务中的任何内容,那么有没有办法在从 deploy maven 运行构建时识别它必须只构建 services 并因此构建它并将其部署在部署文件夹中?

【问题讨论】:

  • 嗨,我有一个疑问。如果您的模块假设服务正在使用最终常量值(final int FOO=5)并且它在域模块中被引用。现在您将常量值更改为 (final int FOO=10) 并且如果您尝试仅部署服务模块,这不会导致域模块出现问题,因为常量值仍将设置为以前的值 (FOO=5 ) 在早期编译期间。为了反映新的最终常量值,我们还需要编译域模块。我们如何处理这个用例?

标签: java maven build continuous-integration


【解决方案1】:

对于 GIT

mvn install -amd -pl $(git status | grep -E "modified:|deleted:|added:" | awk '{print $2}' | cut -f1 -d"/")

在您的 .bashrc 文件中(.bashrc 可以在主目录 ~/.bashrc 中找到,如果不存在则创建它)添加以下函数。

mvn_changed_modules(){
    [ -z "$1" ] && echo "Expected command : mvn_changed_modules (install/build/clean or any maven command)" && exit 0

        modules=$(git status | grep -E "modified:|deleted:|added:" | awk '{print $2}' | cut -f1 -d"/")

                if [  -z "$modules" ];
                then
                        echo "No changes (modified / deleted / added)  found"
                else
                        echo -e "Changed modules are : `echo $modules`\n\n"
                        mvn $1 -amd -pl $modules
                fi
}

**然后在重新启动 bash** (命令提示符)后,您 ** 可以从 ROOT 目录本身使用以下命令**。

smilyface@machine>ProjectRootDir]$ mvn_changed_module install

工作原理
根据问题mvn install -amd -pl services 是“在服务 模块中完成一些更改”时的命令。因此,首先从更改的文件中获取模块名称并将其作为 mvn-install 命令的输入

比如说,下面是修改文件的列表(git status 的输出) -
services/pom.xml
服务/ReadMe.txt
网络/src/java/com/some/Name.java
那么servicesweb就是需要构建/编译/安装的模块名

【讨论】:

  • 就在我在寻找 git 而不是 svn 的时候!不错!
  • 这对我不起作用,因为我的 mvn (3.8.1) 希望 -pl 参数用逗号分隔,我猜。这是在 bash@macos --> mvn install -amd -pl $(git status | grep -E "modified:|deleted:| added:" | awk '{print $2}' | cut -f1 -d "/" | 排序 |uniq| 粘贴 -sd "," -)
  • @ᐅdevrimbaris,我可以用这个更新我的答案吗(对于 mac)?
  • @smilyface 当然,如果它有效:)。
【解决方案2】:

到目前为止发布的问题和答案没有考虑依赖树。如果 utils 模块改变了怎么办?我们需要重建(至少重新测试)它以及依赖它的所有模块。

方法:

【讨论】:

    【解决方案3】:

    在尝试和使用上述建议后,我遇到了以下问题:

    1. Maven 安装(无需清理)仍然需要很长时间,对于几个项目来说,这可能是 10-20 秒的额外时间。
    2. Sebasjm 的解决方案既快速又实用(我使用了几个月),但如果您有多个更改的项目,则一直重建它们(如果您甚至没有更改任何内容)会浪费大量时间

    真正对我有用的是将源修改日期与本地存储库中的 .jar 修改进行比较。如果您只检查 VCS 更改的文件(请参阅 sebasjm 的回答),那么日期比较不会花费明显的时间(对我来说,100 个更改的文件不到 1 秒)。 这种方法的主要好处是只对真正改变的项目进行非常准确的重建。 主要问题是修改日期比较不仅仅是单行脚本。

    对于那些想尝试但懒得自己编写这样的脚本的人分享我的版本:https://github.com/bugy/rebuilder (linux/windows)。 它可以做一些额外有用的事情,但主要思想和中心算法如上所述。

    【讨论】:

    • 一个 git 版本会很棒。
    【解决方案4】:

    我也有同样的挫败感,当时我也写了一个项目 - 可惜它不可用,但我发现有人实现了类似的东西:

    例如 - https://github.com/erickzanardo/maven-watcher

    它使用nodejs 并假设一个maven 项目,但应该可以在windows 和unix 上工作。

    我实现的想法是观察变化,然后编译变化的内容。 - 有点像nodemon

    例如

    • 当 java 文件改变时 - 我编译模块
    • 当类文件或 jar 更改时 - 我会执行其他操作(例如将 jar 复制到 tomcat 下并重新启动 tomcat)

    而且这两者是无关的..所以如果java编译失败,应该没有更新jar文件的原因..而且相当稳定。

    我在一个包含 23K .java 文件的项目中使用了它,并且运行顺利。

    监视过程需要几秒钟才能启动 - 但只有在检测到更改时才会运行,因此整体体验很好。

    我打算添加的下一步类似于您的 SVN 支持 - 列出修改后的文件并将它们用作初始化。

    重要提示 - 如果编译失败,它将在下一次修改时重试。所以如果你修改了多个jar,只要你在写代码,编译就会失败,每次代码更改时它都会重试编译所有内容,直到编译成功。

    如果您愿意,我可以尝试找到我的旧项目,稍微修复一下并发布它..

    【讨论】:

      【解决方案5】:

      如果你只调用“mvn install”而没有“clean”,编译器插件将只编译修改过的类。

      【讨论】:

      • 只使用 mvn compile 我认为没问题,因为您只想运行项目而不是构建战争并且安装需要更多时间。
      • 我认为您误解了我的问题...它只想使用更改的文件构建...我不想重建和复制未更改模块的 jar ..?
      【解决方案6】:

      如果您使用的是 SVN 和 *nix,则从根模块开始

      mvn install -amd -pl $(svn st | colrm 1 8 | sed 's /.*  ' | xargs echo | sed 's- -,:-g' | sed 's ^ : ') 
      

      【讨论】:

      • 有人能简单解释一下这个命令链背后的想法吗?
      • 首先调用$() 中的所有内容:1 svn st 列出所有修改过的项目2 colrm 删除前8 个列3 sed 在第一个斜杠后全部删除 4 xargs echo 取出列表并用逗号分隔(而不是换行符)5 sed 在末尾添加: 使用逗号分隔的项目列表与maven
      • @napster - 根据问题(在此线程中)“mvn install -amd -pl services”是“仅在服务模块中完成一些更改”时的命令。所以获取更改文件的模块名称并将其作为 mvn-install 命令的输入。
      • 试试这个 --> mvn install -amd -pl $(git status | grep "modified:" | awk '{print $2}' | cut -f1 -d"/")
      • 以上是单独修改的。需要修改它以接受添加/修改/种类的所有更改。我会在这里添加它作为答案。
      【解决方案7】:

      在多模块构建中,您可以使用:

      mvn -pl ChangedModule compile
      

      从根模块将只编译给定的ChangedModule。编译器插件只会编译已更改的文件。但是,您更改的模块可能会导致重新编译依赖于 ChangedModule 的其他模块。这可以通过以下方式实现:

      mvn -amd -pl ChangedModule compile
      

      -amd 的意思是也使家属。这将在不通过 mvn install 将整个模块安装到本地存储库的情况下工作。

      【讨论】:

      • 仍然不是我想要的,我需要构建一个 jar,并将其复制到仅包含已更改模块的存储库(部署文件夹)中......
      • 这不能用 Maven 完成。您需要自己编写脚本。或者为此编写一个适当的 Maven 插件。这超出了 Maven 的想法。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 2018-03-28
      • 2013-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多