AnyMath 文档

二元分布

这些笔记是为那些希望编译Julia的二进制分发以在各种平台上分发的人准备的。 我们喜欢用户尽可能广泛地传播Julia,尽可能广泛地尝试各种操作系统和硬件配置。 由于每个平台都有特定的gotchas和流程,为了创建一个可移植的,工作的Julia发行版,我们已经将大部分笔记按操作系统分开。

请注意,虽然Julia的代码是https://github.com/JuliaLang/julia/blob/master/LICENSE.md[MIT-licensed,除了少数例外],由本文描述的技术创建的发行版将获得GPL许可,作为各种依赖库,例如 N.诉讼,诉讼 是GPL许可的。 我们确实希望在未来有一个非GPL的Julia分布。

版本控制和Git

Makefile同时使用 版本 文件和提交哈希和标签从git存储库生成 base/version_git。jl 我们使用的信息来填充初始屏幕和 版本信息() 输出。 如果您出于某种原因不想在构建时使用git存储库,则应该预先生成 base/version_git。jl 文件与:

make -C base version_git.jl.phony

Julia有很多构建依赖关系,我们使用尚未被流行的包管理器包含的修补版本。 这些依赖项通常会在您构建时自动下载,但如果您希望能够在没有internet访问的计算机上构建Julia,则应该使用特殊的make目标创建一个完整的源dist存档

make full-source-dist

这将创建一个julia-version-commit。焦油。gz存档与所有必需的依赖关系。

在git存储库中编译标记版本时,我们不会在初始屏幕中显示分支/提交哈希信息。 您可以使用此行显示最多45个字符的发行说明。 要设置这一行,你必须创建一个Make。用户文件包含:

override TAGGED_RELEASE_BANNER = "my-package-repository build"

目标架构

默认情况下,Julia将其系统映像优化为构建机器的本机架构。 在构建软件包时,这通常不是你想要的,因为它会使Julia在任何具有不兼容Cpu的机器上启动时失败(特别是具有更多受限制指令集的旧机器)。

因此,我们建议您通过 三月 调用时的变量 使,将其设置为您打算支持的基线目标。 这将确定Julia可执行文件和库的目标CPU,以及系统映像(后者也可以使用 JULIA_CPU_目标). X86Cpu的典型有用值是 x86-64核心2 (对于64位构建)和 奔腾4 (对于32位构建)。 不幸的是,目前不支持比Pentium4更早的Cpu(请参阅https://github.com/JuliaLang/julia/issues/7185[本期])。

LLVM支持的CPU目标的完整列表可以通过运行 llc-mattr=帮助.

Linux操作系统

在Linux上, 制作二进制区 创建包含功能齐全的Julia安装的压缩包。 如果您希望创建一个分发包,例如 .黛布,或 .转速/转速,需要一些额外的努力。 查看https://github.com/staticfloat/julia-debian[julia-debian]存储库,用于创建所需的元数据的示例 .黛布 Debian和基于Ubuntu的系统的软件包。 查看https://src.fedoraproject.org/rpms/julia[Fedora软件包]用于基于RPM的发行版。 虽然我们还没有尝试过,https://wiki.debian.org/Alien[Alien]可用于为各种Linux发行版生成Julia包。

Julia支持通过以下方式复盖标准安装目录 前缀 以及调用时可以传递的其他环境变量 使进行安装. 请参阅Make。inc为他们的名单。 德斯迪尔 也可用于强制安装到临时目录中。

默认情况下,Julia加载 $prefix/etc/julia/startup。jl 作为安装范围的初始化文件。 分发管理器可以使用此文件来设置自定义路径或初始化代码。 对于Linux分发包,如果 $prefix 被设置为 /usr,没有 /usr/等 去调查。 这需要通往朱莉娅私人的道路 要更改的目录。 这可以通过 sysconfdir,sysconfdir 构建时使变量。 简单地通过 sysconfdir=/等使 当建筑和朱莉娅将首先检查 /etc/julia/startup。jl 在尝试之前 $prefix/etc/julia/startup。jl.

OS X的

要在OSX上创建二进制发行版,请先构建Julia,然后cd到 contrib/mac/应用程序,并运行 使 用同样的makevars 使 在建造朱莉娅的时候。 然后,这将创建一个 .dmg,dmg 文件在 contrib/mac/应用程序 目录持有一个完全独立的Julia。应用程序。

或者,可以通过调用将Julia构建为框架 使darwinframework 目标及 DARWIN_FRAMEWORK=1 设置。 例如, 使DARWIN_FRAMEWORK=1darwinframework.

窗户

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

关于BLAS和LAPACK的注意事项

Julia默认构建OpenBLAS,其中包括BLAS和LAPACK库。 在32位体系结构上,Julia构建OpenBLAS以使用32位整数,而在64位体系结构上,Julia构建OpenBLAS以使用64位整数(ILP64)。 所有调用BLAS和LAPACK API例程的Julia函数都必须使用正确宽度的整数。

Linux发行版上提供的大多数BLAS和LAPACK发行版,甚至商业实现都提供使用32位Api的库。 在许多情况下,64位API作为单独的库提供。

当使用供应商提供或操作系统提供的库时, 使 选项调用 使用_BLAS64 作为朱莉娅构建的一部分可用。 当做 使USE_BLAS64=0,Julia将调用BLAS和LAPACK假设一个32位API,其中所有整数都是32位宽的,即使在64位架构上也是如此。

Julia使用的其他库,如SuiteSparse也在内部使用BLAS和LAPACK。 Api需要在所有依赖BLAS和LAPACK的库中保持一致。 Julia构建过程将正确构建所有这些库,但是在重写默认值并使用系统提供的库时,必须确保这种一致性。

另请注意,Linux发行版有时会提供多个版本的OpenBLAS,其中一些支持多线程,另一些仅以串行方式工作。 例如,在Fedora中, libopenblasp.so 是线程的,但是 libopenblas.so 不是。 我们建议使用前者以获得最佳性能。 选择名称与默认值不同的OpenBLAS库 libopenblas.so,通过 LIBBLAS=-l$(YOURBLAS)LIBBLASNAME=lib$(YOURBLAS)使,更换 (你的布拉斯) 用你的图书馆的名字。 您还可以添加 .所以.0 如果您希望包在不需要未版本控制的情况下工作,则库的名称 .所以 符号链接。

最后,OpenBLAS包括自己的LAPACK优化版本。 如果你设置 USE_SYSTEM_BLAS=1USE_SYSTEM_LAPACK=1,你也应该设置 LIBLAPACK=-l$(YOURBLAS)LIBLAPACKNAME=lib$(YOURBLAS). 否则,将使用参考LAPACK,性能通常会低得多。

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

点释放101

创建点/补丁版本包括几个不同的步骤。

返回提交

一些拉取请求被标记为"backport pending x.y",例如"backport pending0.6"。 这指定从release-x.y分支标记的下一个后续版本应该在该拉取请求中包含提交。 一旦拉取请求合并到master中,每个提交都应该是https://git-scm.com/docs/git-cherry-pick[樱桃采摘]到一个专门的分支,最终将合并到发布-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副本与origin是最新的。

樱桃采摘承诺

现在我们做实际的反向移植。 在GitHub web UI中查找所有标记为"backport pending x.y"的合并拉取请求。 对于其中的每一个,滚动到底部,它说"someperson merged commit 123abc 进入 师父 XX分钟前"。 请注意,提交名称是一个链接;如果您单击它,您将看到提交的内容。 如果此页面显示 123abc 是一个合并提交,回到PR页面---我们不想合并提交,我们想要实际的提交。 但是,如果这不显示合并提交,则意味着PR被重新合并。 在这种情况下,使用提交的git SHA,列在本页提交旁边。

一旦你有了提交的SHA,就把它选到backport分支上:

git cherry-pick -x -e <sha>

可能存在需要手动解决的冲突。 一旦冲突解决(如果适用),请在提交消息的正文中添加对引入提交的GitHub pull请求的引用。

在backports分支上完成所有相关提交后,将该分支推送到GitHub。

检查性能回归

点版本不应该引入性能回归。 幸运的是,Julia基准测试机器人Nanosoldier可以针对任何分支运行基准测试,而不仅仅是master。 在这种情况下,我们要检查js/backport-x.y与release-x.y的基准测试结果。要做到这一点,请使用对您的backport拉请求的评论将Nanosoldier从他的机器人睡眠中唤醒:

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

这将在release-x.y和js/backport-x.y上运行所有注册的基准测试,并生成结果摘要,标记所有改进和回归。

如果Nanosoldier发现任何回归,请尝试本地验证,并在必要时重新运行Nanosoldier。 如果回归被认为是真实的,而不仅仅是噪音,你必须找到一个master上的提交到backport,如果存在的话修复它,否则你应该确定是什么导致了回归并提交一个补丁(或者让一个知道代码的人提交一个补丁)到master,然后在合并后返回提交。 (或者如果合适,直接向backport分支提交补丁。)

构建测试二进制文件

后端口PR已合并到 释放-x.y 分支,更新Julia的本地克隆,然后使用

git rev-parse origin/release-x.y

保持方便,因为它是您将在buildbot UI中的"修订"字段中输入的内容。

现在,您只需要linux x86-64的二进制文件,因为这是用于运行PackageEvaluator的。 前往https://buildog.julialang.org,提交工作 nuke_linux64,然后排队作业 包装_linux64,提供SHA作为修订。 当打包作业完成后,它将把二进制文件上传到 朱利兰2 AWS上的桶。 检索URL,因为它将用于PackageEvaluator。

检查包装破损

点版本不应该破坏包,可能的例外是使用不打算面向用户的基本内部进行一些严重可疑的黑客攻击的包。 (在这些情况下,也许与包作者有一个词。)

检查在即将到来的新版本中所做的更改是否会破坏包可以使用https://github.com/JuliaCI/PackageEvaluator.jl[PackageEvaluator],通常简称为"PkgEval"。 PkgEval是在GitHub repos和on上填充状态徽章的地方pkg.julialang.org。它通常在Nanosoldier的其中一个非基准测试节点上运行,并使用Vagrant在单独的并行VirtualBox虚拟机中执行其职责。

设置PackageEvaluator

克隆PackageEvaluator并创建一个名为 后端口-x.y.z,并检查出来。 请注意,所需的更改有点hacky和混乱,希望这将在未来版本的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,请找到足够大的机器(例如Nanosoldier节点1),然后运行

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/&ast;.json > summary_release.txt
./summary.sh 0.5AK/&ast;.json >> summary_release.txt
./summary.sh 0.6AK/&ast;.json >> summary_release.txt
./summary.sh 0.4LZ/&ast;.json > summary_backport.txt
./summary.sh 0.5LZ/&ast;.json >> summary_backport.txt
./summary.sh 0.6LZ/&ast;.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

这将写入颜色编码的行到 标准输出. 必须调查所有红色行,因为它们表示由反向端口版本引起的潜在损坏。 应该查看黄色的行,因为这意味着包在一个版本上运行,但由于某种原因而不在另一个版本上运行。 如果您发现您的反向分支导致中断,请使用 git bisect 识别有问题的提交, git恢复 那些提交,并重复这个过程。

将反向端口合并到发布分支中

在你确保了这一点之后

*返回的提交通过了Julia的所有单元测试, *与发布分支相比,向后移植的提交没有引入性能回归,并且 *返回的提交不会破坏任何已注册的包,

然后backport分支就可以合并到release-x.y中了。合并后,从包含已被backport的提交的所有pull请求中删除"backport pending x.y"标签。 请勿从未回传的Pr中删除标签。

Release-x.y分支现在应该包含所有新提交。 我们要对分支做的最后一件事就是调整版本号。 为此,请针对编辑要删除的版本文件的release-x.y提交PR -前期 从版本号。 一旦合并,我们就可以标记了。

标记释放

是时候了! 查看release-x.y分支,并确保分支的本地副本与远程分支是最新的。 在命令行中,运行

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

这会在本地创建标签并将其推送到GitHub。

标记发布后,向release-x.y提交另一个PR,以获取补丁编号并添加 -前期 回到最后。 这表示分支状态反映了x.y系列中下一个点版本的预发布版本。

按照Makefile中的其余说明操作。

签署二进制文件

其中一些步骤将需要安全密码。 要获得适当的密码,请联系Elliot Saba(staticfloat)或Alex Arslan(arslan)。 请注意,必须在该平台上执行每个平台的代码签名(例如,必须在Windows上执行Windows签名等)。).

Linux操作系统

代码签名必须在Linux上手动完成,但它非常简单。 首先获取文件 朱莉娅。钥匙 从CodeSigning文件夹中的 [医]朱利亚 AWS桶。 将此添加到您的GnuPG密钥环使用

gpg --import julia.key

这将需要输入一个密码,你必须从艾略特或亚历克斯获得。 接下来,将密钥的信任级别设置为最大值。 首先输入 石油气 会议:

gpg --edit-key julia

在提示符下,键入 信任,然后当询问信任级别时,提供可用的最大值(可能为5)。 退出GnuPG。

现在,对于构建在buildbots上的每个Linux tarball,请输入

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

这将产生相应的。每个tarball的asc文件。 就这样!

macOS的

代码签名应该在macOS buildbots上自动发生。 但是,重要的是要验证它是否成功。 在运行macOS的系统或虚拟机上,下载。建立在buildbots上的dmg文件。 为了举例,说。dmg文件被称为 朱莉娅-x.y.z-osx。dmg,dmg. 跑

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

请务必注意挂载时列出的已挂载磁盘的名称! 为了举例,我们假设这是 磁盘3. 如果代码签名验证成功退出,则不会从 协同设计 步。 如果它确实成功了,你可以分离。dmg现在:

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

如果你收到这样的信息

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

然后,您需要手动签名。

要手动签名,请首先从 [医]朱利亚 AWS上的桶。 添加的。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实际上是通过双击它来修复的。 如果一切看起来不错,弹出它,然后放下 _固定 来自名称的后缀。 就这样!

窗户

必须在Windows上手动执行签名。 首先从Microsoft网站获取包含必要签名实用程序的Windows10SDK。 我们需要 标志学校 实用程序应该安装在像这样的地方 C:\Program 文件(x86)\Windows套件\10\应用认证套件. 从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中的行延续字符和 密码 是此证书密码的占位符。 像往常一样,联系Elliot或Alex获取密码。 如果没有错误,我们都很好!

上传二进制文件

现在所有内容都已签名,我们需要将二进制文件上传到AWS。 你可以使用像Cyber Duck或 美国焊接学会 命令行实用程序。 二进制文件应该放在 朱利兰2 桶在适当的文件夹。 比如Linux x86-64进去 jang2/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&ast; | grep -v -e sha256 -e md5 -e asc > julia-x.y.z.sha256
md5sum julia-x.y.z&ast; | grep -v -e sha256 -e md5 -e asc > julia-x.y.z.md5

请注意,如果您在macOS上运行这些命令,则会得到非常稍微不同的输出,可以通过查看现有文件重新格式化。 Mac用户还需要使用 md5-r 而不是 md5sum. 上传.md5和.sha256文件到 julialang2/bin/校验和 在AWS上。

确保所有上传文件在AWS上的权限均设置为"Everyone:READ。"

对于我们上传的每个文件,我们需要清除快速缓存,以便网站上的链接指向更新的文件。 作为一个例子:

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

有时这不是必要的,但无论如何都是好的。