使用 Maven 构建和部署本机代码
Building and deploying native code using Maven
我花了数年时间尝试将使用本机代码的库部署到 Maven Central。我 运行 遇到以下问题:
- 没有任何好的插件可以使用 Maven 构建本机代码。 native-maven-plugin 是一个非常严格的构建系统,除其他外,它使得调试生成的二进制文件变得困难。您必须手动将 native-maven-plugin 构建系统与用于调试的本机 IDE 同步。
- Maven 没有替换部署的 pom.xml 文件中的变量:MNG-2971, MNG-4223. This meant that libraries had to declare platform-specific dependencies once per Maven profile (as opposed to declaring the dependency once and setting a different classifier per profile); otherwise, anyone who depended on your library had to re-define those same properties in their project file in order to resolve transitive dependencies. See Maven: Using inherited property in dependency classifier causes build failure.
- Jenkins 对 运行 跨不同平台的类似逻辑(例如 "shell" 与 "batch" 任务,以及协调跨多台机器的构建)
虚拟机中的 - 运行 Windows、Linux 和 Mac 太慢且脆弱。即使你让它工作,尝试将 VM 配置为 Jenkins 从站也是一个令人沮丧的教训(你会经常出现间歇性构建错误)。
- Maven Central 需要一个用于特定于平台的工件的主 jar:OSSRH-975
- Sonatype OSS Repository Hosting and maven-release-plugin 假设可以从一台机器上以原子方式发布一个项目,但我需要在不同的机器上构建 OS-specific 位。
我将使用这个 Whosebug 问题来记录我是如何设法克服这些限制的。
以下是我克服上述问题的方法:
- 我使用 CMake 构建本机代码。这个系统的美妙之处在于它为你最喜欢的(原生)生成项目文件IDE。您使用相同的项目文件来编译和调试代码。您不再需要手动同步两个系统。
- Maven 不支持 CMake,所以我构建了自己的插件:https://github.com/cmake-maven-project/cmake-maven-project
- 我手动将特定于平台的依赖项硬编码到每个 Maven 配置文件中,而不是为每个配置文件使用不同的分类器一次定义依赖项。这是更多的工作,但看起来他们不会很快修复 Maven 中的这个错误。
- 我计划在不久的将来调查 http://www.mojohaus.org/flatten-maven-plugin/ and https://github.com/mjiderhamn/promote-maven-plugin 作为替代方案。
- Jenkins pipeline 在跨多台机器编排构建方面做得很好。
- 运行 虚拟机上的 Jenkins slaves 仍然很容易出错,但我已经设法解决了大部分问题。我已经上传了我的 VMWare configuration steps and Jenkins job configuration 来帮助其他人开始。
- 我现在 create an empty JAR file 用于平台特定的工件以抑制 Sonatype 错误。这实际上是 Sonatype 的支持人员推荐的。
- 它 turns out maven-release-plugin 委托给引擎盖下的其他插件。我没有调用它,而是执行以下操作:
- 使用
mvn versions:set
将版本号从 SNAPSHOT 更改为发布并返回。
- 自己标记并提交发布。
- 使用
nexus-staging:rc-open
、nexus-staging:deploy -DstagingProfileId=${stagingProfileId} -DstagingRepositoryId=${stagingRepositoryId}
和 nexus-staging:rc-close
将来自不同平台的工件上传到同一存储库。这称为 Staging Workflow
(在下面引用)。
- 审核后,将存储库发布到 Maven Central。
- 重要提示:不要在
nexus-staging
插件中启用 <autoReleaseAfterClose>
,因为它会在每次部署后关闭暂存存储库,而不是等待所有部署完成。
- 根据 https://issues.sonatype.org/browse/NEXUS-18753 不可能以原子方式释放 SNAPSHOT 工件(没有解决方法)。释放快照时,需要跳过
rc-open
、rc-close
并调用nexus-staging:deploy
而不调用-DstagingProfileId=${stagingProfileId} -DstagingRepositoryId=${stagingRepositoryId}
。每个工件都将上传到单独的存储库中。
请参阅我的 Requirements API 以获取有效的真实示例。
其他需要注意的怪癖:
skipNexusStagingDeployMojo
在最后一个反应器模块中必须为 false(否则不会部署任何工件):https://issues.sonatype.org/browse/NEXUS-12365。最好的解决方法是使用 Maven 配置文件在部署时省略任何你想要的模块(根本不要使用 skipNexusStagingDeployMojo
)
skipLocalStaging
防止将多个工件部署到同一个存储库中:https://issues.sonatype.org/browse/NEXUS-12351
我花了数年时间尝试将使用本机代码的库部署到 Maven Central。我 运行 遇到以下问题:
- 没有任何好的插件可以使用 Maven 构建本机代码。 native-maven-plugin 是一个非常严格的构建系统,除其他外,它使得调试生成的二进制文件变得困难。您必须手动将 native-maven-plugin 构建系统与用于调试的本机 IDE 同步。
- Maven 没有替换部署的 pom.xml 文件中的变量:MNG-2971, MNG-4223. This meant that libraries had to declare platform-specific dependencies once per Maven profile (as opposed to declaring the dependency once and setting a different classifier per profile); otherwise, anyone who depended on your library had to re-define those same properties in their project file in order to resolve transitive dependencies. See Maven: Using inherited property in dependency classifier causes build failure.
- Jenkins 对 运行 跨不同平台的类似逻辑(例如 "shell" 与 "batch" 任务,以及协调跨多台机器的构建) 虚拟机中的
- 运行 Windows、Linux 和 Mac 太慢且脆弱。即使你让它工作,尝试将 VM 配置为 Jenkins 从站也是一个令人沮丧的教训(你会经常出现间歇性构建错误)。
- Maven Central 需要一个用于特定于平台的工件的主 jar:OSSRH-975
- Sonatype OSS Repository Hosting and maven-release-plugin 假设可以从一台机器上以原子方式发布一个项目,但我需要在不同的机器上构建 OS-specific 位。
我将使用这个 Whosebug 问题来记录我是如何设法克服这些限制的。
以下是我克服上述问题的方法:
- 我使用 CMake 构建本机代码。这个系统的美妙之处在于它为你最喜欢的(原生)生成项目文件IDE。您使用相同的项目文件来编译和调试代码。您不再需要手动同步两个系统。
- Maven 不支持 CMake,所以我构建了自己的插件:https://github.com/cmake-maven-project/cmake-maven-project
- 我手动将特定于平台的依赖项硬编码到每个 Maven 配置文件中,而不是为每个配置文件使用不同的分类器一次定义依赖项。这是更多的工作,但看起来他们不会很快修复 Maven 中的这个错误。
- 我计划在不久的将来调查 http://www.mojohaus.org/flatten-maven-plugin/ and https://github.com/mjiderhamn/promote-maven-plugin 作为替代方案。
- Jenkins pipeline 在跨多台机器编排构建方面做得很好。
- 运行 虚拟机上的 Jenkins slaves 仍然很容易出错,但我已经设法解决了大部分问题。我已经上传了我的 VMWare configuration steps and Jenkins job configuration 来帮助其他人开始。
- 我现在 create an empty JAR file 用于平台特定的工件以抑制 Sonatype 错误。这实际上是 Sonatype 的支持人员推荐的。
- 它 turns out maven-release-plugin 委托给引擎盖下的其他插件。我没有调用它,而是执行以下操作:
- 使用
mvn versions:set
将版本号从 SNAPSHOT 更改为发布并返回。 - 自己标记并提交发布。
- 使用
nexus-staging:rc-open
、nexus-staging:deploy -DstagingProfileId=${stagingProfileId} -DstagingRepositoryId=${stagingRepositoryId}
和nexus-staging:rc-close
将来自不同平台的工件上传到同一存储库。这称为Staging Workflow
(在下面引用)。 - 审核后,将存储库发布到 Maven Central。
- 重要提示:不要在
nexus-staging
插件中启用<autoReleaseAfterClose>
,因为它会在每次部署后关闭暂存存储库,而不是等待所有部署完成。 - 根据 https://issues.sonatype.org/browse/NEXUS-18753 不可能以原子方式释放 SNAPSHOT 工件(没有解决方法)。释放快照时,需要跳过
rc-open
、rc-close
并调用nexus-staging:deploy
而不调用-DstagingProfileId=${stagingProfileId} -DstagingRepositoryId=${stagingRepositoryId}
。每个工件都将上传到单独的存储库中。
- 使用
请参阅我的 Requirements API 以获取有效的真实示例。
其他需要注意的怪癖:
skipNexusStagingDeployMojo
在最后一个反应器模块中必须为 false(否则不会部署任何工件):https://issues.sonatype.org/browse/NEXUS-12365。最好的解决方法是使用 Maven 配置文件在部署时省略任何你想要的模块(根本不要使用skipNexusStagingDeployMojo
)skipLocalStaging
防止将多个工件部署到同一个存储库中:https://issues.sonatype.org/browse/NEXUS-12351