Engee 文档

二进制文件的分发

此信息适用于那些希望编译Julia二进制文件以便在各种平台上分发的人。 我们欢迎用户分发Julia,因为它允许您在各种操作系统和所有可能的硬件配置中体验环境。 由于每个平台都有自己的细微差别,必须考虑到这些细微差别才能创建可移植的Julia发行版,因此我们共享了操作系统上的大部分信息。

请注意:虽然Julia代码https://github.com/JuliaLang/julia/blob/master/LICENSE.md [除了少数例外,它是在MIT许可证下分发的],由这里描述的方法创建的分发将在GPL许可证下分发,因为此许可证适用于许多依赖库,例如`SuiteSparse'。 我们希望将来能够在没有GPL许可证的情况下获得Julia发行版。

版本控制和Git

Makefile使用’版本’文件,以及来自Git存储库的哈希和提交标记来创建`base/version_git。jl’文件,其中包含显示在主屏幕和`versioninfo()函数输出中的信息。 如果由于任何原因Git存储库在构建期间不可用,则文件’base/version_git。必须使用以下命令预先创建jl:

make -C base version_git.jl.phony

许多Julia构建依赖关系用于尚未包含在流行的包管理器中的补丁版本。 这些依赖项通常在构建过程中自动加载,但如果您想在没有internet访问权限的计算机上构建Julia,则应该创建一个具有特殊make目的的full-source-dist存档。:

make full-source-dist

结果,将创建一个存档。 朱莉娅-版本-提交。焦油。gz与所有必要的依赖关系。

在Git存储库中编译标记版本时,有关分支和提交的哈希的信息不会显示在主屏幕上。 您可以使用此行显示长达45个字符的发行说明。 要设置此行,请创建一个Make。包含以下说明的用户文件:

override TAGGED_RELEASE_BANNER = "my-package-repository build"

目标架构

默认情况下,Julia会针对构建计算机的计算机体系结构优化系统映像。 这通常不是构建软件包时所需要的,因此Julia将无法在具有不兼容Cpu的计算机上运行(特别是在具有有限指令集的较旧计算机上)。

因此,在调用’make`时,我们建议传递`MARCH’变量,指定要支持的目标基础架构作为其值。 它将确定Julia可执行文件和库以及系统映像(也可以使用`JULIA_CPU_TARGET’指定)的目标Cpu。 对于X86Cpu,典型值为’x86-64`和`core2`(对于64位构建)和`pentium4'(对于32位构建)。 不幸的是,目前不支持比Pentium4更早的Cpu(请参阅https://github.com/JuliaLang/julia/issues/7185 [这个问题])。

LLVM支持的目标Cpu的完整列表可以通过命令"llc-mattr=help"获得。

Linux操作系统

在Linux上,'make binary-dist’命令创建一个包含功能齐全的Julia安装的Tarball存档。 将需要额外的努力来创建分发包,例如,在`。deb’或'。rpm’格式。 为创建`所需的元数据的示例。deb’基于Debian和Ubuntu的系统的软件包,请参阅存储库https://github.com/staticfloat/julia-debian [朱莉娅-debian]。 有关基于RPM的发行版,请参阅https://src.fedoraproject.org/rpms/julia [Fedora软件包]。 要为各种Linux发行版创建Julia包,您可以使用该程序https://wiki.debian.org/Alien [外星人],虽然我们还没有尝试过。

Julia支持使用`prefix`和其他可以在调用`make`和`make install’时传递的环境变量重新定义标准安装目录。 有关列表,请参阅制作。公司 您也可以使用`DESTDIR’强制安装到临时目录中。

默认情况下,Julia下载prefix前缀/etc/julia/startup。jl’作为整个安装的初始化文件。 分发经理可以使用它来设置自定义路径或初始化代码。 如果Linux发行版的`prefix prefix’变量设置为'/usr`,则缺少`/usr/etc’目录。 因此,有必要将路径更改为Julia的私有目录’etc'。 这可以在装配过程中使用make`sysconfdir`变量来完成。 只需在构建期间将`sysconfdir=/etc`传递给`make',Julia将首先检查文件`/etc/julia/startup。jl’然后才--'prefix prefix/etc/julia/startup。jl'。

OS X的

要在OS X中创建二进制发行版,首先构建Julia,然后转到’contrib/mac/app`目录,并使用构建Julia时与`make`命令一起使用的相同变量运行`make`。 结果,a。dmg文件与一个完全独立的Julia。应用程序将在"contrib/mac/app"目录中创建。

此外,Julia可以通过调用`make`构建`darwinframework`和指定变量`DARWIN_FRAMEWORK=1’来构建为框架。 例如,'make DARWIN_FRAMEWORK=1darwinframework'。

窗户

在Windows中创建Julia发行版的说明在https://github.com/JuliaLang/julia/blob/master/doc/src/devdocs/build/windows.md [构建文档的Windows]。

关于BLAS和LAPACK的注意事项

默认情况下,Julia构建OpenBLAS,包括BLAS和LAPACK库。 在32位体系结构上,Julia使用32位整数构建OpenBLAS,在64位体系结构上,它使用64位整数(ILP64)构建。 重要的是,所有调用BLAS和LAPACK API例程的Julia函数都使用正确宽度的整数。

Linux发行版中包含的大多数BLAS和LAPACK发行版,甚至商业实现,都提供使用32位Api的库。 通常,64位API作为单独的库提供。

当使用供应商或操作系统提供的库时,名为"USE_BLAS64"的"make"参数作为Julia构建的一部分可用。 当执行`make USE_BLAS64=0`命令时,Julia调用BLAS和LAPACK,假设使用32位API,其中所有整数都是32位宽,即使在64位架构上也是如此。

Julia使用的其他库,如SuiteSparse,也使用BLAS和LAPACK。 对于依赖于BLAS和LAPACK的所有库,API接口必须一致。 在构建Julia时,所有这些库都正确组装,但是在重新定义默认值和使用系统库时,必须确保这种一致性。

请记住,Linux发行版有时包括多个版本的OpenBLAS,其中一些支持多线程,而其他发行版仅按顺序工作。 例如,在Fedora版本`libopenblasp.so '是多线程的,并且`libopenblas.so ""不。 为了获得最佳性能,我们建议使用第一个选项。 要选择默认库以外的OpenBLAS库(libopenblas.so `),将变量`LIBBLAS=-l$(YOURBLAS)`和`LIBBLASNAME=lib$(YOURBLAS)`传递给`make,在您的库的名称中替换`$(YOURBLAS)。 您还可以将.so.0`添加到库名称中,以便包不需要符号链接`.so`而无需版本。

最后,OpenBLAS包括自己的LAPACK优化版本。 如果设置变量`USE_SYSTEM_BLAS=1`和`USE_SYSTEM_LAPACK=1`,则还必须设置`LIBLAPACK=-l$(YOURBLAS)和`LIBLAPACKNAME=lib$(YOURBLAS)。 否则,将使用LAPACK的参考版本,性能通常会低得多。

从Julia1.7开始,它用于在运行时选择不同的BLAS库。 https://github.com/JuliaLinearAlgebra/libblastrampoline [libblastrampoline]。

发布修改版本的基础知识

修订或纠正问题的创建分几个单独的步骤进行。

修复背孔

一些拉取请求被标记为"backport pending x.y"(x.y backport是预期的),例如"backport pending0.6"。 这意味着来自release-x分支的下一个版本。y,必须在拉取请求中包含提交。 将拉取请求与master分支合并后,来自每个提交的更改应https://git-scm.com/docs/git-cherry-pick [复制]到最终将与release-x.y合并的专用分支。

创建backports的分支

首先,创建一个基于release-x.y的分支。根据Julia约定,如果是个人的,您应该在分支名称之前添加您的首字母。 例如,假设分支的作者是用户Jane Smith。

git fetch origin
git checkout release-x.y
git rebase origin/release-x.y
git checkout -b js/backport-x.y

这可以确保在基于release-x.y的本地副本创建新分支之前,此副本是当前的,并且对应于原始分支。

将更改复制到提交

现在让我们做反向移植。 在GitHub web界面中,查找已执行合并且标记为"backport pending x.y"的所有拉取请求。 对于它们中的每一个,向下滚动到标签"someperson将commit`123ABC`合并为`master`XX分钟前"(有人将commit123ABC与master XX分钟前合并)。 请注意,提交名称是一个链接:如果您点击它,提交的内容将显示。 如果页面显示'123abc’是合并提交,则返回到拉取请求页面。:我们不需要合并提交,而是实际提交。 但是,如果没有显示这是一个合并提交,那么拉请求合并是用压缩执行的。 在这种情况下,请使用此页面上提交旁边指定的提交git SHA值。

收到提交的SHA值后,将其更改复制到backport分支。:

git cherry-pick -x -e <sha>

可能存在需要手动解决的冲突。 解决冲突(如果有)后,在提交消息的文本中添加一个指向GitHub中的拉取请求的链接,其中添加了提交。

将所有必要的提交添加到backport分支后,将此分支发送到GitHub。

检查性能下降

改进的版本不应导致性能下降。 幸运的是,Julia名为Nanosoldier的性能测试机器人允许您为任何分支运行测试,而不仅仅是master。 在这种情况下,我们需要检查js/backport-x测试结果。y与release-x.y相比。要做到这一点,请通过评论反向移植的拉请求来激活Nanosoldier机器人:

@nanosoldier `runbenchmarks(ALL, vs=":release-x.y")`

因此,对于release-x.y和js/backport-x.y,将执行所有注册的性能测试,结果摘要显示所有改进和损伤。

如果Nanosoldier检测到性能下降,请尝试本地检查,然后在必要时重新启动Nanosoldier。 如果看起来确实存在缺陷,则需要在master分支中找到它们关联的提交并将其反向移植。 如果没有这样的提交,您应该确定导致恶化的原因并将修复程序发送给master(或要求理解代码的人执行此操作),然后在合并后返回提交。 (如果适用,您可以直接将修复程序发送到backport分支。)

组装测试二进制文件

在将用于反向移植的拉取请求与`release-x’分支合并之后。y’更新本地Julia克隆,然后使用以下命令获取分支的SHA:

git rev-parse origin/release-x.y

保持这个值方便,因为它需要在构建机器人的用户界面的修订字段中输入。

与此同时,您只需要linux x86-64的二进制文件,因为它们用于运行PackageEvaluator。 进入网站https://buildog.julialang.org ,为`nuke_linux64’提交任务,然后为`package_linux64’排队任务,指定SHA作为修订。 打包任务完成后,二进制文件将被发送到AWS中的’jang2’容器中。 获取Url,因为它将是PackageEvaluator所需要的。

检查包故障

改进的版本不应该破坏包的操作。 唯一可能的例外可能是使用基本模块的内部机制执行极其可疑的操作的包,这些操作不适用于用户。 (在这种情况下,也许你应该与包的作者讨论这种情况。)

您可以使用该工具来检查即将到来的版本中的更改是否会导致软件包出现故障。 https://github.com/JuliaCI/PackageEvaluator.jl [PackageEvaluator],通常缩写为PkgEval。 在GitHub存储库和网站上分配状态标识的是PkgEval。 pkg.julialang.org …​ 该工具通常在其中一个非设计用于性能测试的Nanosoldier节点上运行,并使用Vagrant在并行运行的单独VirtualBox虚拟机上执行其任务。

配置PackageEvaluator

克隆PackageEvaluator,创建’backport-x.y.z’分支并提取它。 请记住,所需的更改是相当复杂和混乱的。 希望情况会在未来版本的PackageEvaluator中发生变化。 的变化将根据样品再现。 https://github.com/JuliaCI/PackageEvaluator.jl/commit/5ba6a3b000e7a3793391d16f695c8704b91d6016 [这种固定]。

配置脚本将Julia版本作为第一个参数,包名称范围作为第二个参数(AK用于名称从A到K的包,LZ用于名称从L到Z的包)。 我们的任务是配置脚本,以便只有两个版本的Julia正在运行:当前版本的x.y和backport版本,每个版本都有三个包范围。

相比之下,链接指示如果第二个参数具有值LZ,则应使用从backport分支编译的二进制文件。 否则,应使用发布分支的(AK)二进制文件。 然后我们使用第一个参数来运行包列表的一部分:a-F表示输入值0.4,G-N表示0.5,O-Z表示0.6。

启动PackageEvaluator

要运行PkgEval,请选择功能足够强大的机器(例如,Nanosoldier1节点),然后运行以下命令:

git clone https://github.com/JuliaCI/PackageEvaluator.jl.git
cd PackageEvaluator.jl/scripts
git checkout backport-x.y.z
./runvagrant.sh

将在scripts/目录中创建多个文件夹。 下面列出了这些文件夹的名称及其内容。

文件夹名称 朱莉娅的版本 包装范围

0.4AK

发行版

A-F

0.4LZ

后港

A-F

0.5AK

发行版

G-N

0.5LZ

后港

G-N

0.6AK

发行版

O-Z

0.6LZ

后港

O-Z

检查结果

之后,使用`。/summary.sh `您可以从同一目录中获得有关结果的摘要报告。 我们将对每个文件夹执行此操作,以按版本获取累积结果。

./summary.sh 0.4AK/*.json > summary_release.txt
./summary.sh 0.5AK/*.json >> summary_release.txt
./summary.sh 0.6AK/*.json >> summary_release.txt
./summary.sh 0.4LZ/*.json > summary_backport.txt
./summary.sh 0.5LZ/*.json >> summary_backport.txt
./summary.sh 0.6LZ/*.json >> summary_backport.txt

现在我们有两个文件,'summary_release。txt’和’summary_backport。txt`,具有两个版本中每个包的PackageEvaluator测试结果(通过或失败)。

为了使它们更容易传输到Julia,我们将它们转换为CSV文件,然后使用DataFrames包处理结果。 要转换为CSV格式,请将每个TXT文件复制到相应的CSV文件中,然后登录Vim并运行`ggVGI"<esc>`后跟`:%s/\。json/",/g'。 (你不必使用Vim,这只是其中一种方法。)现在使用Julia代码处理结果,如下所示。

using DataFrames

release = readtable("summary_release.csv", header=false, names=[:package, :release])
backport = readtable("summary_backport.csv", header=false, names=[:package, :backport])

results = join(release, backport, on=:package, kind=:outer)

for result in eachrow(results)
    a = result[:release]
    b = result[:backport]
    if (isna(a) && !isna(b)) || (isna(b) && !isna(a))
        color = :yellow
    elseif a != b && occursin("pass", b)
        color = :green
    elseif a != b
        color = :red
    else
        continue
    end
    printstyled(result[:package], ": Release ", a, " -> Backport ", b, "\n", color=color)
end

因此,颜色编码的字符串将显示在"stdout"中。 应检查所有红线,因为它们表示由反向端口版本引起的潜在违规。 你也应该注意黄线。:它们意味着一个包在一个版本中执行,但由于某种原因没有在另一个版本中执行。 如果您发现由于backported分支而存在违规,请使用`git bisect`命令识别有问题的提交,为这些提交运行`git revert`命令,并重复该过程。

与发布分支合并反向端口

如果满足以下所有条件:

  • backported提交通过所有Julia单元测试;

  • 由于backported提交,与release分支相比,性能不会下降。;

  • 反向提交不会中断注册包的操作。;

backport分支已准备好与release-x.y合并。合并后,通过所有带有backported提交的拉取请求,并删除标签"backport pending x.y"。 请勿从未回传的拉取请求中删除此标签。

Release-x.y分支现在应该包含所有新提交。 与分支做的最后一件事是调整版本号。 为此,向release-x.y发送拉取请求,该请求修改版本文件,以便从版本号中删除'-pre’元素。 合并后,您可以继续添加标签。

向发行版添加标签

时间到了! 提取release-x分支。y并确保其本地副本与远程副本同步。 在命令提示符下,运行以下命令:

git tag v$(cat VERSION)
git push --tags

因此,标签将在本地创建并发送到GitHub。

将标签添加到release后,将其发送到release-X.y另一个拉取请求以更新修复编号,并再次在末尾添加'-pre’元素。 这意味着分支状态对应于x.y系列中下一个修订版本的初步版本。

按照Makefile中的进一步说明进行操作。

签署二进制文件

下面描述的一些操作将需要安全密码。 要获得它们,请联系Elliot Saba(staticfloat)或Alex Arslan(arslan)。 请注意,必须在该平台上执行针对每个平台的代码签名(例如,必须在Windows上执行针对Windows的签名等)。).

Linux操作系统

在Linux上,代码必须手动签名,但它很容易完成。 首先,得到’朱莉娅。密钥`来自AWS容器`juliasecure’中的CodeSigning文件夹的文件。 使用以下命令将其添加到GnuPG密钥集:

gpg --import julia.key

您需要输入密码,该密码应从Elliot或Alex处获得。 接下来,设置密钥的最大信任级别。 首先’登录’gpg’会话:

gpg --edit-key julia

在命令提示符下,键入"信任",然后,在请求信任级别时,指定可能的最大值(很可能为5)。 注销GnuPG。

现在,对于构建机器人创建的每个Tarball Linux存档,输入以下命令:

gpg -u julia --armor --detach-sig julia-x.y.z-linux-<arch>.tar.gz

因此,将为每个Tarball存档创建相应的ASC文件。 仅此而已!

macOS的

macOS构建机器人应该自动签署代码。 但是,您需要检查是否一切都成功。 下载由macOS系统或虚拟机上的构建机器人创建的DMG文件。 例如,假设DMG文件名为’julia-x.y.z-osx。dmg'。 运行以下命令:

mkdir ./jlmnt
hdiutil mount -readonly -mountpoint ./jlmnt julia-x.y.z-osx.dmg
codesign -v jlmnt/Julia-x.y.app

在连接阶段,记住连接磁盘的名称! 假设它是一个’disk3’磁盘。 如果代码签名验证成功完成,则"代码设计"步骤将不会输出数据。 如果是这样,可以禁用DMG文件。:

hdiutil eject /dev/disk3
rm -rf ./jlmnt

如果您收到如下消息:

Julia-x.y.app:代码对象根本没有签名

代码必须手动签名。

要手动签署代码,请先从AWS’juliasecure’容器中的CodeSigning文件夹中获取OS X证书。 使用Keychain将P12文件添加到您的钥匙串中。应用程序。 有关密钥的密码,请联系Elliot Saba(staticfloat)或Alex Arslan(arslan)。 现在运行以下命令。

hdiutil convert julia-x.y.z-osx.dmg -format UDRW -o julia-x.y.z-osx_writable.dmg
mkdir ./jlmnt
hdiutil mount -mountpoint julia-x.y.z-osx_writable.dmg
codesign -s "AFB379C0B4CBD9DB9A762797FC2AB5460A2B0DBE" --deep jlmnt/Julia-x.y.app

可能会出现以下错误消息:

Julia-x.y.app:不允许使用资源分叉、查找器信息或类似碎屑

在这种情况下,您需要删除额外的属性。:

xattr -cr jlmnt/Julia-x.y.app

之后,尝试再次签署代码。 如果没有错误,请重复检查。 如果现在一切正常,请禁用可写DMG文件并使其再次变为只读。:

hdiutil eject /dev/disk3
rm -rf ./jlmnt
hdiutil convert julia-x.y.z-osx_writable.dmg -format UDZO -o julia-x.y.z-osx_fixed.dmg

通过双击查看生成的DMG文件是否已修复。 如果没有问题,请提取它并从名称中删除`_fixed`后缀。 仅此而已!

窗户

在Windows中,代码是手动签名的。 首先,从Microsoft网站获取带有必要签名工具的WINDOWS10SDK。 我们将需要’SignTool’程序,它应该沿着像’这样的路径安装C:\Program 文件(x86)\Windows套件\10\应用程序认证套件`。 从’juliasecure`中的CodeSigning获取Windows证书文件,并将它们放在可执行目录中。 在Windows中打开CMD窗口,导航(cd)到包含所有文件的目录并运行以下命令:

set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\App Certification Kit;
signtool sign /f julia-windows-code-sign_2017.p12 /p "PASSWORD" ^
   /t http://timestamp.verisign.com/scripts/timstamp.dll ^
   /v julia-x.y.z-win32.exe

请注意,`^'是Windows CMD中的行延续字符,`PASSWORD’是证书密码的占位符。 像往常一样,联系Elliot或Alex获取密码。 如果没有错误,那么一切都很好!

发送二进制文件

现在代码已签名,您需要将二进制文件发送到AWS。 您可以使用Cyberduck等程序或aws命令行程序。 二进制文件必须放在容器’julialang2’中的相应文件夹中。 例如,对于x86-64Linux,这是’xang2/bin/linux/x.y'。 不要忘记删除当前的’julia-x.y-latest-linux-<arch>'文件。焦油。gz’并将其替换为`julia-x.y.z-linux-<arch>的副本。焦油。gz'。

此外,您需要发送所有组装组件的校验和,包括Tarball源代码存档和发布二进制文件。 这样做并不难。

shasum -a 256 julia-x.y.z* | grep -v -e sha256 -e md5 -e asc > julia-x.y.z.sha256
md5sum julia-x.y.z* | grep -v -e sha256 -e md5 -e asc > julia-x.y.z.md5

请记住,如果这些命令在macOS上执行,输出将略有不同。 您可以根据现有文件重新格式化它们。 此外,Mac用户将需要使用’md5-r`而不是’md5sum'。 将MD5和SHA256文件发送到AWS中的`jang2/bin/checksums'。

对于发送到AWS的所有文件,必须设置"All:READ"权限。

对于每个发送的文件,有必要清除Fastly缓存,以便网站上的链接指向发送的文件。 例子::

curl -X PURGE https://julialang-s3.julialang.org/bin/checksums/julia-x.y.z.sha256

有时你可以没有它,但它不会是多余的。