建设"来源"与Maven

时间:2017-12-13 18:31:42

标签: maven maven-2

要点: 我想知道如何构建包含多个Maven项目的Maven应用程序,其中包含从只读源和所有输出到给定(临时)文件夹的所有输入,而不会破坏IDE(Netbeans)支持。所提议的解决方案都不适用于我,所以我要求详细解释我的问题尽可能好。

详细信息: 很长一段时间以来,我试图将我的Maven构建集成到我们的生产性建筑环境中,这有很多要求:

  • 无法访问互联网(所有输入必须受版本控制)
  • 源树是只读的
  • 所有构建工件必须位于构建目录
  • 之下
  • 定义良好的工具链(在版本控制下或在只读虚拟机中)
  • 图书馆不知道哪个应用程序使用它们(即"没有父POM")
  • 支持开发周期,最好是IDE(Netbeans),可选
  • 支持开发周期,最好是逐步工作, 可选的

这类似于Out-of-tree build with maven. Is it possible?以及与maven构建目录相关的其他问题,但不幸的是,所提出的解决方案都不适用于此。

我有"中央存储库"通过" file:" URL以及"本地存储库"在(临时)构建目录下面,但我没有找到任何方法来拥有专家#34; target"构建目录下的目录,不会破坏任何其他内容。

我有几个共享一些库的应用程序。对于每个图书馆,我都有自己的父母POM" (违反DRY原则,因为我找不到更好的方法)。每个都包含应用程序和特定于环境的设置,例如distributionManagement存储库路径,该路径使用${env.variable}定义,以允许构建工具注入系统和应用程序特定值。提供默认值是为了让使用Netbeans的开发人员感到满意。

不幸的是,这对构建目录不起作用。

我可以在Maven: How to change path to target directory from command line?中设置构建目录。然后,由一个父POM构建的所有类文件(所有库和应用程序)将被放入同一个目录中。 Maven可以运行一次并运行 - 但在以后的运行中它将失败!至少单元测试失败,因为Maven(surefire)将找到所有项目的所有测试,而不仅仅是Maven当前正在处理的测试。因此,它会在构建库A时尝试从应用程序运行单元测试(在我的情况下失败,因为它还需要库B,而库A中没有作为依赖项提供)。

我也试过像"-DbuildDirectory=$BUILDDIR/maven-target/\${project.name}"这样的结构。这适用于编译源,但同样不适用于测试。尽管Maven(3.1.1)在存储文件时正确评估${project.name},但它将字面(!)传递给类路径,因此在编译单元测试时,java没有找到测试对象("错误:找不到符号")。将符号链接${project.name}设置为正确的名称当然只适用于一个项目(例如库A),因为我发现无法从pom.xml中更改它。

目前我最接近的方法是使用全局目标目录并在每次构建之前清理它,但显然这在使用此构建系统进行开发时很糟糕(在没有IDE的情况下逐步工作)。

现在我甚至考虑使用填充值从构建系统生成pom.xml文件,并将所有源复制到构建树。这应该适用于我们定义的发布版本,但在正常开发期间(使用IDE)会感到不舒服。

有没有诀窍,或者这对Maven来说真的不可能吗?

已编辑以回答问题

非常感谢您花时间处理我的问题/帮助请求!我尽可能清楚地回答。

队友建议增加所有这些的动力:

即使互联网发生变化,也应该可以在十年或二十年内复制任何版本。

  

为什么需要更改" target"?

的值

由于源树是只读的,因此Maven无法在其默认位置创建目录。可写的构建目录可用,但在源代码树之外。

  

Maven不会写入/ src,所以没问题

"源树"没有引用" src"构建过程的源/输入中的文件夹,但是整个结构 - 包括POM文件,资源甚至二进制库(如果需要)。所以包含src的目录也包含pom.xml,属于只读的VCS控制"源树"。

  

您能举例说明一些与标准项目布局不兼容的事情吗?

这种只读源树的一个不同示例可能是:在CD-R上刻录整个项目结构(带有库的应用程序)并确保" mvn编译测试包部署"的工作原理。

(只读源树需求的一个动机是确保构建过程不会意外(或有意)操纵源代码,这可能导致重复次数自动更改构建工件,从而破坏可重复性。)

  

使用存储库管理器

据我所知,存储库管理器是一种通常在主机上运行的复杂服务。我认为使用文件URL而不是这种复杂的服务可以减少依赖关系。请注意,整个存储库必须是版本控制的,因此无论如何自动更新都不能工作,但据我所知,存储库管理器的优势。

  

你使用依赖jar&#39>

是的,当然。库和应用程序依赖于几个JAR。甚至Maven依赖于几个JAR,例如编译器插件。

  

如果您的请求声明您需要自己构建所有依赖项?

实际上,我担心情况会是这样,是的,我很清楚,不幸的是,这将是巨大的努力。即使使用Debian软件包,这也很难实现,并且他们付出了很多努力来实现它。不幸的是,目前我还没有看到建立这些图书馆的现实机会。

  

" ...所有构建工件必须位于构建目录下面#34; - 您能详细解释一下吗?

构建过程应该创建给定构建目录下的所有文件,例如/tmp/$USER/build/$PROJECTNAME/$PROJECTVERSION/$APPLICATION/$VARIANT/。构建系统可以在其下创建任意结构,但不应该在此之外更改任何内容。此树中的文件列表定义为输出(构建结果)并从那里获取。通常会将某些二进制文件或ZIP文件复制到版本控制系统。 有些人称之为"树木构建","构建源代码"或类似的。

  

定义良好的工具链

我们的想法是拥有一个虚拟机映像(在版本控制下),为每个构建创建一个动态的"克隆"其中,安装所需的工具链(来自版本控制),例如构建工具,Maven安装及其存储库,可以访问要构建的源的特定版本(例如,以只读ClearCase视图的形式) ),运行构建脚本入口点脚本,收集创建的输出(例如一些" release.zip"" buildlogs.zip")最后丢弃整个虚拟机,包括其所有内容。当然工具链可以完全预先安装在图像中,但实际上并没有这样做(是的,我们也使用Docker)。

  

对于影响分析,了解谁在使用哪个库非常重要?

是的,这肯定是非常的。但是,消息来源应该从中抽象出来,并且通常会这样做。例如,JUnit的作者不要'知道每个人都在使用它。我们喜欢同时在几个项目中使用库,所以我们不能提到父POM,因为有多个父POM。

我希望这次我能够更好地解释。

编辑#2回答新问题

再次感谢您抽出宝贵的时间来完成这篇长篇文章!我希望这次能够解释最后遗漏的部分,并说清楚。我认为有些问题似乎是对要求的评论。我担心我们会陷入讨论中。

  

在maven中,您有一个目录结构,如:

root
+- pom.xml
+- src
     

根目录受版本控制。所以我不理解以下内容:

     
    

"源树"没有引用" src"内的文件夹     构建过程的源/输入,但整个结构 -

  
root
+- pom.xml
+- src
    +-- ...
+- target
    +-- ...

我添加了target"结构以更好地说明问题。如您所说,根目录受版本控制,因此是只读的。因此,root/pom.xmlroot/srcroot本身是只读的。

当Maven尝试创建root/target时,会收到错误(Read-only file system),因为root及其所有子文件夹都是只读的。

这里甚至父文件夹都受版本控制,如果是ClearCase,还有更多的其他只读父目录,但我认为这并不重要。

  

我们正在谈论工件的terra字节....它们必须备份但不检查版本控制。

这超出了范围,但我尽力回答。 我现在正在处理的一个ClearCase实例具有2.2 TB,所以tera字节完全正确。例如,如果标准要求版本之间的所有更改都可追溯,则备份可能还不够。但是我认为这超出了我的问题范围。

  

文件库存储库运行不正常,需要复制到您使用它的每台计算机上,这是一种安装到许多计算机的网络文件系统的麻烦。存储库管理器基于http(s)工作,其处理起来要简单得多..

我认为这超出了范围,与我的问题无关,但无论如何我都试着回答。 问题是,为了重现性,您需要将此http(s)的所有内容存档一段时间,并保持其运行。有历史,因为它可能需要重现一个五岁的州。当然,互联网上可能无法提供所需的软件包(请记住Codehaus.org吗?)。具有挑战性的任务。

  

存储库管理器更加简单并保持约定

不幸的是,它不符合要求,或者需要很高的价格(管理额外的虚拟机以及存储包的版本控制)。

  

自己构建所有依赖项我认为这根本不值得付出努力。我没有真正的优势

我认为这些要求并不少见(https://en.wikipedia.org/wiki/Source_code_escrow),但我担心我们会脱离主题并开始讨论要求。

  

如果JUnit团队可以从maven中心访问请求(可以这样做),他们可以看到谁正在使用JUnit

我认为它偏离主题,但JUnit开发人员应该如何能够了解所有"我的"使用JUnit的项目?

  

与父母的关系在哪里?

对不起,如果我引起混淆,这只是一个旁注。我认为这超出了我的提问范围。不过,我会尽力回答。

为了避免冗余,Maven中的一种方法是使用父POM并从中继承。例如,您可以在父POM中定义distributionManagement并使库POM继承它。如果您有项目特定的distributionManagement要求,则需要项目特定的父POM文件。如果两个项目共享一个相同的库,那么两个项目POM中的哪一个应该由库继承(作为父项)?在聚合器POM中设置distributionManagement不起作用,因为它没有传播。

编辑#3解释只读

你好@JF Meier
谢谢你的评论。

只读意味着无法写入,因此Maven无法创建目标目录。因此,javac无法存储类文件和编译中止。

也许它太抽象了,所以让我举一个完整的实例:

cat pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>test</groupId>
    <artifactId>mavenproject1</artifactId>
    <version>1.0-SNAPSHOT</version>
</project>

cat src/main/java/Hello.java

public class HelloWorld {
    public static void main(String[] args) { System.out.println("Hello, World!"); }
}

现在复制&amp;从贝壳粘贴(我剪了几条无聊的线条):

steffen@node1:/view/dev_test_project_v1/vobs/playground/steffen/minimal_pom $ mvn compile
[...]
[ERROR] Failure executing javac, but could not parse the error:
javac: directory not found: /view/dev_test_project_v1/vobs/playground/steffen/minimal_pom/target/classes

这是一个问题。我必须纠正一个小细节,它不会显示Read-only file sytem错误,我认为是一个错误,但在strace中我们可以看到它:

21192 mkdir("/view/dev_test_project_v1/vobs/playground/steffen/minimal_pom/target/classes", 0777) = -1 ENOENT (No such file or directory)
21192 mkdir("/view/dev_test_project_v1/vobs/playground/steffen/minimal_pom/target", 0777) = -1 EROFS (Read-only file system)
21192 mkdir("/view/dev_test_project_v1/vobs/playground/steffen/minimal_pom/target", 0777) = -1 EROFS (Read-only file system)

这会导致javac: directory not found错误。

它是只读的:

steffen@node1:/view/dev_test_project_v1/vobs/playground/steffen/minimal_pom $ mkdir -p target/classes
mkdir: cannot create directory ‘target’: Read-only file system

mkdir工具正确显示错误消息。

4 个答案:

答案 0 :(得分:1)

不是答案..

首先,您需要无法访问互联网。好的,这可以通过使用存储库管理器来完成。这是企业环境中Maven和其他构建工具的默认设置。

你使用依赖jar(库?)?

如果您的请求声明您需要自己构建所有依赖项?这将是一项巨大的努力,因此意味着您需要拥有组织内所有库的所有源代码,并且您需要维护它们的所有更新/更改。(极大的努力)。

我不了解您的要求:

  

源树是只读的

如果您有版本控制系统,通常存储库具有身份验证,这意味着您可以控制某人是否能够提交(写入)...

  

..所有构建工件必须位于构建目录下..

你能详细解释一下吗?

以下我可以理解:

  

定义良好的工具链(在版本控制下或在只读虚拟机中)

通常使用您使用的工具链定义环境(当然应该检查版本控制)。

  

图书馆不知道哪个应用程序使用它们(即&#34;没有父POM&#34;)

父母的使用并不意味着图书馆不知道谁在使用图书馆?但除此之外,我不明白这个要求?对于影响分析,了解谁在使用哪个库非常重要?

你提到你已经通过文件协议配置了中央仓库,我无法推荐......此外target目录是Maven的惯例......我没有看到任何优势改变这个?有什么问题?

答案 1 :(得分:1)

因此,根据您的更新,我在此处添加了另一个更新:

  

为什么需要更改“目标”的值?

     

因为源树是只读的,所以Maven无法创建   目录在其默认位置。可写的构建目录是   可用,但在源代码树之外。

您似乎误解了target目录的想法,或者您误解了Maven的工作方式。

target目录旨在包含 NOT 检查到源代码管理中的所有生成/编译的内容。或者换句话说,target目录在签入期间默认被忽略,并且永远不会被检查到版本控制中。

  

Maven不会写入/ src,所以没问题

在maven中,您有一个目录结构,如:

root
+- pom.xml
+- src
    +-- ...

根目录受版本控制。所以我不明白以下几点:

  

“source tree”不引用其中的“src”文件夹   构建过程的源/输入,但整个结构 -   如果需要,包括POM文件,资源甚至二进制库。所以   包含src的目录也包含pom.xml并且属于   只读VCS控制的“源树”。

来到下一点:

  

据我所知,存储库管理器通常是一项复杂的服务   在主机上运行。我认为使用文件URL而不是这么复杂   service使依赖项保持较小。请注意整个   存储库必须受版本控制,因此需要自动更新   反正一定不行,但据我所知,是一个优点   存储库管理器。

整个存储库应该受版本控制。听起来你没有在企业环境中使用真实版本的经验。我们正在讨论工件的terra字节....它们必须备份但不检查版本控制。

原因很简单,因为每个工件都是由它的坐标唯一定义的groupId,artifactId,version。

除了你提出的论点,设置的复杂性比你想象的要简单。除此之外,文件库存储库不能很好地工作,需要复制到您使用它的每台机器上,这是一种麻烦,有一种安装到许多机器的网络文件系统。存储库管理器基于http(s)工作,其处理起来要简单得多..

来到下一点:

  

构建过程应该创建给定构建下的所有文件   目录,例如   的/ tmp / $ USER /建设/ $ PROJECTNAME / $ PROJECTVERSION / $应用/ $ VARIANT /.

Maven在target目录中执行此操作..

  

构建系统可以在其下创建任意结构,但是   不应该在此之外改变任何东西。其中的文件列表   此树被定义为输出(构建结果)并从那里获取。   通常会将某些二进制文件或ZIP文件复制到版本控制   系统。有人称之为“树外构建”,“构建源代码”或   类似。

正如我之前提到的产生的工件,我不建议将它们置于版本控制之下,因为存储库管理器更简单并保持约定......

回到你自己构建所有依赖关系的观点,我认为这根本不值得付出努力。我没有真正的优势...特别是因为您可以从Maven存储库(或您组织内部自己的存储库管理器)中使用基于正确坐标的所有工件... ...

下一点:

  

是的,这肯定是非常的。但是,消息来源应该是抽象的   从它,通常做。例如,JUnit的作者不知道   每个人都在使用它。

如果JUnit团队可以从maven中心访问请求(可以这样做),他们可以看到谁正在使用JUnit。通过使用存储库管理器的访问日志并提取用法,这在组织内部更加简单信息...

我不明白的是:

  

我们喜欢在几个库中使用库   项目同时进行,所以我们不能提到父POM,因为   有多个父POM。

这在Maven中称为简单依赖。与父母pom的关系在哪里?你似乎误解了/或者不明白Maven是如何工作的?

答案 2 :(得分:0)

让我在khmarbaise的回答中添加以下内容。

我不会在十年内看到你的&#34;可重现的&#34;标准Maven结构的问题。你只是:

  1. 查看版本控制系统中的源到空目录。
  2. 在此目录中使用Maven构建项目。
  3. 将结果部署到您想要的任何位置。
  4. 版本控制系统中的源不会更改,每次都会完全相同。您只需要确保只在依赖项中使用发行版本(而不是SNAPSHOT版本),这样Nexus / Artifactory每次都会为您提供相同的工件。

答案 3 :(得分:0)

使用Maven并且没有Internet

的树外构建

如果其他人面临类似的要求,我会以一个例子的形式描述我的解决方案。我理解并乐意接受大多数人肯定不希望这个或根本不需要&#34;树外&#34;用Maven构建。这对于像我这样没有其他选择的极少数人来说。

所以这不适合&#34;普通的Maven构建&#34;,但仅适用于问题中描述的特定要求(没有互联网访问,除了/ tmp文件夹之外的所有内容都是只读的)。这样的配置可以是从VW模板运行的虚拟机中的构建系统,由Jenkins作业动态实例化。

  

关于ClearCase的一个词

     

此方法不是特定于ClearCase的,但该示例使用ClearCase路径。

     

以下示例使用挂载到toolchain_view的只读ClearCase视图/view/toolchain_view/(包含Maven,所有Java包和其他构建工具)和只读源代码视图(包含应用程序)可在下面&#34; / view / steffen_hellojava_source_view /&#34;。而不是&#34; / view / toolchain_view /&#34;,有人可以使用&#34; / opt / vendor / name / toolchain / version /&#34;或者使用任何其他版本控制系统,因此这种方法不是特定于ClearCase的。

     

对于那些不了解ClearCase的人:该视图的行为类似于NFS文件系统,其中服务器根据版本描述选择文件内容。文件内容本身位于名为Versioned Object Base(VOB)的数据库中。使用所谓的配置规范(CS),某人可以定义哪个内容版本以选择规则的形式显示哪个文件(元素)(例如通过LABEL选择)。例如:

---[ toolchain-1_4_7_0.cs ]---------------------------------------->8=======
element /vobs/playvob/toolchain/...                  TOOLCHAIN_VERSION_1_4_7_0
# TOOLCHAIN_VERSION_1_4_7_0 automatically also selects:
# element /vobs/playvob/toolchain/3p/maven/...       TOOLCHAIN_MAVEN_3_1_1_0
# element /vobs/playvob/toolchain/3p/maven-repo/...  TOOLCHAIN_MAVENREPO_1_0_1_0
# element /vobs/playvob/toolchain/3p/java/...        TOOLCHAIN_JAVA_1_7_0_U60
=======8<-------------------------------------------------------------------
     

现在是一个ClearCase视图,例如&#34; toolchain_view&#34;可以创建和配置使用这些选择规则cleartool -tag toolchain_view -setcs toolchain-1_4_7_0.cs。在示例中,它以/view/toolchain_view/挂载,前缀为元素(文件)路径。

配置Maven

现在我们需要将Maven配置为

  • 将我们的文件结构/view/toolchain_view/vobs/playvob/toolchain/3p/maven-repo/仅用作中央存储库
  • 将本地存储库存储在/tmp
  • 下方
  • target以下的/tmp目录

前两个可以在Maven设置文件中配置,但显然最后一个似乎需要在POM文件中进行特定更改。

mvn_settings.xml

这里摘录了Maven的--global-settings文件。我把它压缩了一下。必不可少的是两个中央存储库使用file:/// URL,并将其强制执行为唯一的镜像:

<!-- Automatically generated by toolchain creator scripts.
     This sets the maven-repo version to the correct value, for example
     toolchain version 1.4.7.0 defines Maven repo version 1.0.1. -->
<settings ...>
  <localRepository>${env.MAVEN_LOCAL_REPO}</localRepository>
  <profiles>
    <profile>
      <id>1</id>
      <activation><activeByDefault>true</activeByDefault></activation>
      <repositories><repository>
        <id>3rdparty</id><name>third party repo</name>
        <url>file:///view/toolchain_view/vobs/playvob/toolchain/3p/maven-repo/</url>
        <snapshots><enabled>true</enabled><updatePolicy>never</updatePolicy></snapshots>
        <releases><enabled>true</enabled><updatePolicy>never</updatePolicy></releases>
      </repository></repositories>
      <pluginRepositories><pluginRepository>
        <id>3rdparty</id><name>third party repo</name>
        <url>file:///view/toolchain_view/vobs/playvob/toolchain/3p/maven-repo/</url>
        <snapshots><enabled>true</enabled><updatePolicy>never</updatePolicy></snapshots>
        <releases><enabled>true</enabled><updatePolicy>never</updatePolicy></releases>
      </pluginRepository></pluginRepositories>
    </profile>
  </profiles>
  <!-- Unfortunately **required** for file-based "central repository": -->
  <mirrors><mirror>
    <id>dehe_repo_1.0.1</id><name>Vendor Name Central 1.0.1</name>
    <url>file:///view/toolchain_view/vobs/playvob/toolchain/3p/maven-repo/</url>
    <mirrorOf>*,!3rdparty</mirrorOf>
  </mirror></mirrors>
</settings>

为了简化部署,我们可以使用包含版本号的路径,例如/opt/vendor/name/toolchain/1.4.7.0/mvn_settings.xml,这些路径可以由自己的Debian软件包提供。

通过设置环境变量将localRepository指向特定于构建的(临时)目录,允许在所有内容都是只读时进行构建,但临时目录除外,这是&#34; out-of-tree&# 34;生成。

使用IDE(Netbeans)构建时,我们也可以使用此设置文件,但通常不这样做会更舒服。但是,在这种情况下,有人必须注意不要意外添加依赖项。如果这些未包含在固定的Maven Repo中,则构建系统上的编译将会中断。

hellojava / pom.xml的

为了支持树外构建,我们还需要将target文件夹移出只读源树(通常它们是在pom.xmlsrc旁边创建的Java包目录,它本身受版本控制,因此在这里是只读的)。这是通过使用两个属性实现的:buildDirectorydeployDirectory。默认的buildDirectory是普通的target文件夹,因此当不设置buildDirectory时,Maven会正常构建。这很好,因为我们不需要IDE(Netbeans)的特定POM文件。

Surefire生成单元测试报告,当然也需要转到我们的构建目录。

<project>
    ...
    <properties>
        <project.skipTests>false</project.skipTests>
        <project.testFailureIgnore>false</project.testFailureIgnore>
        <buildDirectory>${project.basedir}/target</buildDirectory>
        <deployDirectory>defaultDeploy</deployDirectory>
    </properties>
    ...
    <build>
        <!-- https://stackoverflow.com/a/3908061 -->
        <directory>${buildDirectory}/hellojava</directory>
        <!-- https://stackoverflow.com/a/6733858/9095109 -->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.12.4</version>
                <configuration>
                    <skipTests>${project.skipTests}</skipTests>
                    <testFailureIgnore>${project.testFailureIgnore}</testFailureIgnore>
                    <workingDirectory>${project.build.directory}/test-run</workingDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
    ...
    <distributionManagement>
        <repository>
            <id>build-integration</id>
            <name>Deployment Repository</name>
            <url>file:///${deployDirectory}</url>
        </repository>
    </distributionManagement>
    ...
</project>

全部放在一起

现在必须通过命令行参数设置此POM文件中属性的值,并且必须配置MAVEN_LOCAL_REPO,例如:

#!/bin/bash
# Normally in a wrapper which is automatically generated by toolchain creator.
# The path to the pom.xml and build directories then of course are parameters.
export JAVA_HOME="/view/toolchain_view/vobs/playvob/toolchain/3p/java/"
export PATH="/view/toolchain_view/vobs/playvob/toolchain/bin:$PATH"
# or: export PATH="/opt/vendor/name/toolchain/1.4.7.0/bin:$PATH"
: ${MAVEN_LOCAL_REPO:="$HOME/.m2/repository"}
: ${MAVEN_OPTS:="-XX:PermSize=64m -XX:MaxPermSize=192m"}

export MAVEN_LOCAL_REPO="/tmp/steffen-build/hellojava/mavenbuild/repo"
/view/toolchain_view/vobs/playvob/toolchain/3p/maven/bin/mvn -e \
     --global-settings /view/toolchain_view/vobs/playvob/toolchain/mvn_settings.xml \
     -DbuildDirectory=/tmp/steffen-build/hellojava/mavenbuild/target/ \
     -DdeployDirectory=/tmp/steffen-build/hellojava/mavenbuild/output/ \
     -Dproject.skipTests \
     -f /view/steffen_hellojava_source_view/hellojava/pom.xml \
     compile package deploy

现在/tmp可以是&#34;只读系统上的RAM磁盘&#34;。所有工件都写在专用构建目录下。我们可以在DVD或只读NFS存档服务器上拥有工具链和完整的源代码树,并且仍然可以编译它,而无需访问Internet。即使Maven Central已被重命名或其他任何内容,这仍应在20年内有效。

当然,包装器脚本可以隐藏所有细节。就我而言,它们集成在基于cmake的构建系统中,顶级构建目录由Jenkins作业配置。

检查要求

对于原始问题的每个要求,我们可以检查这种方法是否符合它:

  • 无法访问互联网(所有输入必须受版本控制)
    • 好的,&#34; downlading&#34;来自file:///
  • 源树是只读的
    • 好的,适用于只读/view
  • 所有构建工件必须位于构建目录下
    • 确定,通过设置MAVEN_LOCAL_REPO
    • 配置Maven Local Repository
  • 定义良好的工具链(在版本控制下或在只读虚拟机中)
    • 好的,在/view//opt,所有版本都是&#34;固定&#34; (固定)
  • 图书馆不知道哪个应用程序使用它们(即&#34;没有父POM&#34;)
    • 好的,但不好,因为需要调整所有POM文件
  • 支持开发周期,最好是与IDE(Netbeans)一起使用,可选
    • 好的,相同的POM文件适用于IDE
  • 支持开发周期,最好是逐步工作,可选
    • 好的,只要保留了构建树和本地存储库,Maven就会逐步工作

因此满足了所有(非常具体的)输入要求。好。所以这实现了没有Internet的树外构建。