连续两次运行lein uberjar
,我得到两个不同的版本。经过一些unzip / find / sort / diff shell
魔法之后,我看到它归结为一些Maven文件:更具体地说是 pom.properties 文件。
这是一个差异:
< #Tue Jan 14 07:07:50 CET 2014
---
> #Tue Jan 14 07:07:01 CET 2014
如何使用Leiningen(以及Maven)获得确定性的Clojure构建?
答案 0 :(得分:4)
我有lein-voom(我用Chouser维护的项目)的本地补丁,它将解决此问题,将pom.properties
标头时间修复为VCS(目前只有git)提交时间工作副本完全干净。我希望这个提交能在下周的某个时候完成,不过我还在考虑这个功能的可配置性。
仅凭这一点并不适合稳定的罐子,但这是第一件小事。同样感兴趣的是jar中文件的时间戳,它将改变zip标题。规范化时间戳也应该是直截了当的,但这是一个单独的步骤。
确定性构建对lein-voom很感兴趣,这个项目通常可能是你感兴趣的,因为它允许通过commit sha直接将依赖关系指向特定的源版本,完全避免了工件。
lein-voom非常年轻,文档和CLI非常粗略,但核心功能非常可靠。欢迎在GitHub project上发布问题或解答。答案 1 :(得分:1)
I wrote up an article一会儿用Maven覆盖确定性构建。我在这里提取了重点:
使用程序集插件并将其配置如下:
src/main/assembly/zip.xml
:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>deterministic</id>
<baseDirectory>/</baseDirectory>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<directory>${project.build.directory}/classes</directory>
<outputDirectory>/</outputDirectory>
</fileSet>
</fileSets>
</assembly>
添加你自己的MANIFEST.MF
,记住最后的额外CRLF,否则它将无效。
src/main/resources/META-INF/MANIFEST.MF
:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: yourapp
Build-Jdk: 1.7.0
在pom.xml中添加一些插件:
的pom.xml:
<plugins>
... other plugins ...
<!-- Step 1: Set all timestamps to same value -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>1-touch-classes</id>
<phase>prepare-package</phase>
<configuration>
<target>
<touch datetime="01/01/2000 00:10:00 am">
<fileset dir="target/classes"/>
</touch>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Step 2: Assemble as a ZIP to avoid MANIFEST.MF timestamp -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/zip.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>2-make-assembly</id>
<phase>prepare-package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Step 3: Rename ZIP as JAR -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>3-rename-assembly</id>
<phase>package</phase>
<configuration>
<target>
<move file="${project.build.directory}/${project.build.finalName}-deterministic.zip"
tofile="${project.build.directory}/${project.build.finalName}-deterministic.jar"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
... more plugins ...
</plugins>
这将创建一个确定性JAR,但它仍将依赖于您构建它的JVM和操作系统的确切版本。要克服比特币核心项目使用的you should explore the gitian approach并在VirtualBox环境中强制使用特定的JVM。通过这种方式,多个开发人员可以独立地从源构建,然后签署二进制文件以声明它们是一致的。当达到某个阈值时,代码被认为是确定性的并且可以被释放。