5.4.源代码包文件

Makefile 的第二部分描述了为联编 port 而必须下载的文件, 以及可以在哪里下载这些文件。

5.4.1. DISTNAME

DISTNAME 是软件作者所调用的 Port 的名称。DISTNAME 默认为 ${PORTNAME}-${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX}, 如果没有设置, DISTVERSION 默认为 ${PORTVERSION}, 因此只有在必要时才能覆盖 DISTNAMEDISTNAME 只在两个地方使用。首先, 发行文件列表 (DISTFILES) 默认为 ${DISTNAME}${EXTRACT_SUFX}。第二, 分发文件会被期望解压到名为 WRKSRC 的子目录中, 该目录默认为 work/${DISTNAME}

一些供应商的发行版名称不适合 ${PORTNAME}-${PORTVERSION} 模式, 可以通过设置 DISTVERSIONPREFIXDISTVERSIONDISTVERSIONSUFFIX 来自动处理。PORTVERSION 将自动从 DISTVERSION 派生。

重要

每次只能设置 PORTVERSIONDISTVERSION 中的一个。如果 DISTVERSION 不能派生出正确的 PORTVERSION,就不要使用 DISTVERSION

如果上游的版本方案可以推导出与 ports 兼容的版本方案, 将一些变量设置为上游的版本, 不要使用 DISTVERSION 作为变量名。将 PORTVERSION 设为基于您创建的变量的计算版本, 并相应地设置 DISTNAME

如果上游的版本计划不能轻易地被胁迫为一个与 ports 兼容的值, 则应将 PORTVERSION 设置为一个合理的值, 并将 DISTNAMEPORTNAME 设置为逐字的上游版本。

例11. 手动推导 PORTVERSION

BIND9 使用了一个与 ports 版本不兼容的版本计划 (它的版本中有 -), 并且不能用 DISTVERSION 来导出, 因为在 9.9.9 发布之后, 它将以 9.9.9-P1 的形式发布一个“补丁级别”。DISTVERSION 会把它翻译成 9.9.9.p1, 在 ports 的版本计划中, 这意味着 9.9.9 pre-release 1, 是在 9.9.9 之前而不是之后。因此, PORTVERSION 是由 ISCVERSION 变量手工推导出来的, 以输出 9.9.9p1

使用 pkg-version(8)-t 参数可以检查 ports 框架和 pkg 的版本排序顺序:

% pkg version -t 9.9.9 9.9.9.p1
> ①
% pkg version -t 9.9.9 9.9.9p1
< ②

> 号表示传递给-t的第一个参数大于第二个参数。9.9.9 是在 9.9.9.p1 之后。

< 号表示传递给-t的第一个参数小于第二个参数。9.9.9 是在 9.9.9p1 之前。

在 port Makefile 中,例如 dns/bind99,它是通过以下方式实现的:

PORTNAME=	bind
PORTVERSION=	${ISCVERSION:S/-P/P/:S/b/.b/:S/a/.a/:S/rc/.rc/}
CATEGORIES=	dns net
MASTER_SITES=	ISC/bind9/${ISCVERSION}
PKGNAMESUFFIX=	99
DISTNAME=	${PORTNAME}-${ISCVERSION}

MAINTAINER=	mat@FreeBSD.org
COMMENT=	BIND DNS suite with updated DNSSEC and DNS64
WWW=		https://www.isc.org/bind/

LICENSE=	ISCL

# ISC releases things like 9.8.0-P1 or 9.8.1rc1, which our versioning does not like
ISCVERSION=	9.9.9-P6

ISCVERSION 中定义上游版本, 并加上注释说明为什么需要它。使用 ISCVERSION 来获取一个与 ports 兼容的 PORTVERSION。直接使用 ISCVERSION 来获取正确的 URL 以获取发行文件。直接使用 ISCVERSION 来命名发行文件。

例12. 从 PORTVERSION 推导出 DISTNAME

有时,分发文件的名称与软件的版本几乎没有关系。

comms/kermit 中,只有版本的最后一个元素存在于发行文件中:

PORTNAME=	kermit
PORTVERSION=	9.0.304
CATEGORIES=	comms ftp net
MASTER_SITES=	ftp://ftp.kermitproject.org/kermit/test/tar/
DISTNAME=	cku${PORTVERSION:E}-dev20

:E make(1) 修改器返回变量的后缀,在本例中是 304。发行文件被正确地生成为 cku304-dev20.tar.gz

例13. 异国案例1

有时,软件名称、版本和它的发行文件之间没有关系。

来自 audio/libworkman

PORTNAME=       libworkman
PORTVERSION=    1.4
CATEGORIES=     audio
MASTER_SITES=   LOCAL/jim
DISTNAME=       ${PORTNAME}-1999-06-20

例14. 异国案例2

comms/librs232 中,分布文件是没有版本的,所以需要使用 DIST_SUBDIR

PORTNAME=       librs232
PORTVERSION=    20160710
CATEGORIES=     comms
MASTER_SITES=   http://www.teuniz.net/RS-232/
DISTNAME=       RS-232
DIST_SUBDIR=	${PORTNAME}-${PORTVERSION}

注意

PKGNAMEPREFIXPKGNAMESUFFIX 并不影响 DISTNAME。还需要注意的是, 如果 WRKSRC 等于 ${WRKDIR}/${DISTNAME}, 而原始归档文件的名字不是 ${PORTNAME}-${PORTVERSION}${EXTRACT_SUFX}, 就不要管 DISTNAME 了 -- 只定义 DISTFILESDISTNAMEWRKSRC(可能还有 EXTRACT_SUFX)都要简单。

5.4.2. MASTER_SITES

MASTER_SITES 中记录指向原始压缩包的 FTP/HTTP-URL 的目录部分。不要忘记尾部的斜线 (/)!

如果 make macros 在系统中找不到已经存在的发行文件,它将尝试使用这个规范用 FETCH 抓取发行文件。

建议在这个名单上包括多个站点,最好是来自不同的大陆。这将防止广域网络问题。

重要

MASTER_SITES 不能是空白。它必须指向存放发布文件的实际站点。它不能指向网络档案, 或 FreeBSD 发行文件的缓存站点。这一规则的唯一例外是那些没有任何发行文件的 port。例如, meta-port 没有任何发行文件, 所以 MASTER_SITES 就不需要设置。

5.4.2.1. 使用 MASTER_SITE_* 变量

像 SourceForge (SOURCEFORGE)、GNU (GNU) 或 Perl CPAN (PERL_CPAN) 这样的流行档案都有捷径缩写。MASTER_SITES 可以直接使用它们:

MASTER_SITES=	GNU/make

旧的扩展格式仍然有效,但所有的 port 都已转换为紧凑格式。扩充后的格式看起来像这样:

MASTER_SITES=		${MASTER_SITE_GNU}
MASTER_SITE_SUBDIR=	make

这些值和变量是在 Mk/bsd.sites.mk 中定义的。新的条目经常被添加, 所以在提交 port 之前, 请确保检查这个文件的最新版本。

技巧

对于任何 MASTER_SITE_FOO 变量, 都可以使用速记符 FOO。例如, 使用

MASTER_SITES=	FOO

如果需要 MASTER_SITE_SUBDIR, 请使用这个:

MASTER_SITES=	FOO/bar

注意

有些 MASTER_SITE_* 名称相当长,为了便于使用,我们定义了快捷键:

表3. MASTER_SITE_* 宏的快捷方式

MacroShortcut

PERL_CPAN

CPAN

GITHUB

GH

GITHUB_CLOUD

GHC

LIBREOFFICE_DEV

LODEV

NETLIB

NL

RUBYGEMS

RG

SOURCEFORGE

SF

5.4.2.2. 神奇的 MASTER_SITES

对于具有可预测的目录结构的流行网站,存在几个 “神奇” 的宏。对于这些, 只要使用缩写, 系统就会自动选择一个子目录。对于一个名为 Stardict 的 port, 版本为 1.2.3, 并托管在 SourceForge 上, 添加这一行:

MASTER_SITES=	SF

推断出一个名为 /project/stardict/stardict/1.2.3 的子目录。如果推断的目录不正确,可以覆盖它:

MASTER_SITES=	SF/stardict/WyabdcRealPeopleTTS/${PORTVERSION}

这也可以写成

MASTER_SITES=	SF
MASTER_SITE_SUBDIR=	stardict/WyabdcRealPeopleTTS/${PORTVERSION}

表4. 神奇的 MASTER_SITES

MacroAssumed subdirectory

APACHE_COMMONS_BINARIES

${PORTNAME:S,commons-,,}

APACHE_COMMONS_SOURCE

${PORTNAME:S,commons-,,}

APACHE_JAKARTA

${PORTNAME:S,-,/,}/source

BERLIOS

${PORTNAME:tl}.berlios

CHEESESHOP

source/${DISTNAME:C/(.).*/\1/}/${DISTNAME:C/(.*)-[0-9].*/\1/}

CPAN

${PORTNAME:C/-.*//}

DEBIAN

pool/main/${PORTNAME:C/^((lib)?.).*$/\1/}/${PORTNAME}

FARSIGHT

${PORTNAME}

FESTIVAL

${PORTREVISION}

GCC

releases/${DISTNAME}

GENTOO

distfiles

GIMP

${PORTNAME}/${PORTVERSION:R}/

GH

${GH_ACCOUNT}/${GH_PROJECT}/tar.gz/${GH_TAGNAME}?dummy=/

GHC

${GH_ACCOUNT}/${GH_PROJECT}/

GNOME

sources/${PORTNAME}/${PORTVERSION:C/^([0-9]+\.[0-9]+).*/\1/}

GNU

${PORTNAME}

GNUPG

${PORTNAME}

GNU_ALPHA

${PORTNAME}

HORDE

${PORTNAME}

LODEV

${PORTNAME}

MATE

${PORTVERSION:C/^([0-9]+\.[0-9]+).*/\1/}

MOZDEV

${PORTNAME:tl}

NL

${PORTNAME}

QT

archive/qt/${PORTVERSION:R}

SAMBA

${PORTNAME}

SAVANNAH

${PORTNAME:tl}

SF

${PORTNAME:tl}/${PORTNAME:tl}/${PORTVERSION}

5.4.3. 使用 _GITHUB

如果发行文件来自 GitHub上的一个特定的提交或标签,而该文件并没有正式发布,有一个简单的方法可以自动设置正确的 DISTNAMEMASTER_SITES。这些变量是可用的:

表5. USE_GITHUB 描述

VariableDescriptionDefault

GH_ACCOUNT

Account name of the GitHub user hosting the project

${PORTNAME}

GH_PROJECT

Name of the project on GitHub

${PORTNAME}

GH_TAGNAME

Name of the tag to download (2.0.1, hash, …) Using the name of a branch here is incorrect. It is also possible to use the hash of a commit id to do a snapshot.

${DISTVERSIONPREFIX}${DISTVERSION}${DISTVERSIONSUFFIX}

GH_SUBDIR

When the software needs an additional distribution file to be extracted within ${WRKSRC}, this variable can be used. See the examples in Fetching Multiple Files from GitHub for more information.

(none)

重要

不要使用 GH_TUPLE 作为默认分布文件,因为它没有默认。

例子 15. 简单使用 USE_GITHUB

在试图为 github上的 FreeBSD 用户的 1.2.7 版本的pkg做一个移植时,在https://github.com/freebsd/pkg/,Makefile 最终会是这样的(为了举例,稍作删减):

PORTNAME=	pkg
DISTVERSION=	1.2.7

USE_GITHUB=	yes
GH_ACCOUNT=	freebsd

它将自动把 MASTER_SITES 设为 GH, 而 WRKSRC 设为 ${WRKDIR}/pkg-1.2.7

例16. 更完整地使用 USE_GITHUB

在试图为 github 上的 FreeBSD 用户提供的 pkg 的尖端版本做一个移植时,在 https://github.com/freebsd/pkg/,Makefile 最后看起来是这样的(为了举例,稍作剥离):

PORTNAME=	pkg-devel
DISTVERSION=	1.3.0.a.20140411

USE_GITHUB=	yes
GH_ACCOUNT=	freebsd
GH_PROJECT=	pkg
GH_TAGNAME=	6dbb17b

它将自动把 MASTER_SITES 设为 GH, 而 WRKSRC 设为 ${WRKDIR}/pkg-6dbb17b

20140411GH_TAGNAME 中提到的提交日期,而不是 Makefile 的编辑日期,或者提交日期。

例17. 使用带有 DISTVERSIONPREFIXUSE_GITHUB

有时,GH_TAGNAMEDISTVERSION 略有不同。例如,如果版本是 1.0.2,标签就是 v1.0.2。在这些情况下,可以使用 DISTVERSIONPREFIXDISTVERSIONSUFFIX

PORTNAME=	foo
DISTVERSIONPREFIX=	v
DISTVERSION=	1.0.2

USE_GITHUB=	yes

它将自动把 GH_TAGNAME 设置为 v1.0.2,而 WRKSRC 将保持为 ${WRKDIR}/foo-1.0.2

例18. 当上游不使用版本时使用 USE_GITHUB

如果上游从来没有一个版本,就不要发明一个像 0.11.0 的版本。创建的 port 的 DISTVERSIONgYYYYMMDD ,其中 g 代表 Git,YYYYMMDD 代表 GH_TAGNAME 中引用的提交日期。

PORTNAME=	bar
DISTVERSION=	g20140411

USE_GITHUB=	yes
GH_TAGNAME=	c472d66b

这就形成了一个随时间推移而增加的版本划分方案, 而且还是在版本 0 之前 (关于 pkg-version(8) 的详情, 请参阅 Using pkg-version(8) 来比较版本):

% pkg version -t g20140411 0
<

这意味着,如果上游决定在未来削减版本,就不需要使用 PORTEPOCH 了。

例19. 使用 USE_GITHUB 来访问两个版本之间的承诺

如果软件的当前版本使用了 Git 标签, 而 port 需要更新到一个较新的、 没有标签的中间版本, 可以使用 git-describe(1) 来找出要使用的版本:

% git describe --tags f0038b1
v0.7.3-14-gf0038b1

v0.7.3-14-gf0038b1 可以分成三个部分:

**v0.7.3**

这是请求提交前在提交历史中出现的最后一个 Git 标签。

**-14**

这意味着请求的提交,f0038b1,是 v0.7.3 标签之后的第 14 次提交。

**-gf0038b1**

-g 的意思是 "Git",f0038b1 是这个引用指向的提交哈希值。

PORTNAME=	bar
DISTVERSIONPREFIX=  v
DISTVERSION=	0.7.3-14
DISTVERSIONSUFFIX=  -gf0038b1

USE_GITHUB=	yes

这就创造了一个随着时间推移 (好吧,是随着提交次数的增加) 而增加的版本管理方案, 并且与创建 0.7.4 版本没有冲突。(关于 pkg-version(8) 的细节,请参见使用 pkg-version(8) 来比较版本):

% pkg version -t 0.7.3 0.7.3.14
<
% pkg version -t 0.7.3.14 0.7.4
<

如果请求的提交与一个标签相同,默认会显示一个较短的描述。较长的版本则是等效的:

% git describe --tags c66c71d
v0.7.3

% git describe --tags --long c66c71d
v0.7.3-0-gc66c71d

5.4.3.1. 从GitHub获取多个文件

USE_GITHUB 框架也支持从 GitHub 的不同地方获取多个发布文件。它的工作方式与从多个位置获取多个分发文件或补丁文件非常相似。

多个值被添加到 GH_ACCOUNTGH_PROJECTGH_TAGNAME。每个不同的值都被分配一个组。主值可以没有组,也可以是 :DEFAULT 组。如果一个值与 USE_GITHUB 说明中所列的默认值相同,则可以省略。

GH_TUPLE 也可以在有很多分发文件时使用。它有助于将帐户、项目、tagname 和组的信息放在同一个地方。

对于每个组,都会创建一个 ${WRKSRC_group} 辅助变量,其中包含文件被解压到的目录。${WRKSRC_group} 变量可以用来在解压后移动目录,或添加到 CONFIGURE_ARGS 中,或任何需要的地方,以便软件正确构建。

当心

:group 部分必须只用于一个分发文件。它被用作一个唯一的键,多次使用它将覆盖之前的值。

注意

由于这只是高于 DISTFILESMASTER_SITES 的语法糖, 组名必须遵守《多处分发或多处补丁文件》中列出的对组名的限制。

当从 GitHub 获取多个文件时,有时不会从 GitHub 获取默认的分发文件。要禁止取回默认的分发文件,请设置:

USE_GITHUB=	nodefault

重要

当使用 USE_GITHUB=nodefault 时, Makefile 必须在其顶块中设置 DISTFILES。这个定义应该是:

DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}

例 20. 使用 USE_GITHUB 和多个分发文件

时不时地,需要获取一个以上的发行文件。例如,当上游的 git 仓库使用子模块时。这可以使用 GH_* 变量中的分组轻松完成:

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITHUB=	yes
GH_ACCOUNT=	bar:icons,contrib
GH_PROJECT=	foo-icons:icons foo-contrib:contrib
GH_TAGNAME=	1.0:icons fa579bc:contrib
GH_SUBDIR=	ext/icons:icons

CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

这将从 github 获取三个发布文件。默认的文件来自 foo/foo ,版本为 1.0.2 。第二个文件,包括图标组,来自 bar/foo-icons,版本为 1.0。第三个来自 bar/foo-contrib,使用的是 Git commit fa579bc。分发文件名为 foo-foo-1.0.2_GH0.tar.gzbar-foo-icons-1.0_GH0.tar.gz,以及 bar-foo-contrib-fa579bc_GH0.tar.gz

所有的发行文件都是在 ${WRKDIR} 的各自子目录中解压的。默认文件仍在 ${WRKSRC} 中解压,在本例中是 ${WRKDIR}/foo-1.0.2。每个额外的分发文件都在 ${WRKSRC_group} 中解压。这里,对于图标组,它被称为 ${WRKSRC_icons},包含 ${WRKDIR}/foo-icons-1.0。contrib 组的文件名为 ${WRKSRC_contrib},包含 ${WRKDIR}/foo-contrib-fa579bc

该软件的构建系统希望在其源代码中的 ext/icons 子目录中找到这些图标,因此使用了 GH_SUBDIRGH_SUBDIR 确保 ext 存在,但 ext/icons 并不存在。然后它就这样做:

post-extract:
      @${MV} ${WRKSRC_icons} ${WRKSRC}/ext/icons

例21. 使用 GH_TUPLEUSE_GITHUB 和多个分发文件

这在功能上等同于使用 USE_GITHUB 与多个分发文件, 但使用 GH_TUPLE

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITHUB=	yes
GH_TUPLE=	bar:foo-icons:1.0:icons/ext/icons \
		bar:foo-contrib:fa579bc:contrib

CONFIGURE_ARGS=	--with-contrib=${WRKSRC_contrib}

在前面的例子中,用 bar:icons,contrib 进行了分组。在 GH_TUPLE 中存在一些多余的信息,因为不可能进行分组。

例22. 如何在 Git 子模块中使用 USE_GITHUB

以 GitHub 作为上游仓库的 port 有时会使用子模块。参见 git-submodule(1) 以了解更多信息。

子模块的问题是,每个子模块都是一个独立的资源库。因此,它们都必须被单独获取。

finance/moneymanagerex 为例,其GitHub仓库是https://github.com/moneymanagerex/moneymanagerex/。它在根部有一个 .gitmodules 文件。这个文件描述了这个仓库中使用的所有子模块,并列出了需要的额外仓库。这个文件会告诉你需要哪些额外的存储库:

[submodule "lib/wxsqlite3"]
	path = lib/wxsqlite3
	url = https://github.com/utelle/wxsqlite3.git
[submodule "3rd/mongoose"]
	path = 3rd/mongoose
	url = https://github.com/cesanta/mongoose.git
[submodule "3rd/LuaGlue"]
	path = 3rd/LuaGlue
	url = https://github.com/moneymanagerex/LuaGlue.git
[submodule "3rd/cgitemplate"]
	path = 3rd/cgitemplate
	url = https://github.com/moneymanagerex/html-template.git
[...]

该文件中唯一缺少的信息是用来作为版本的提交哈希值或标签。这些信息可以在克隆版本库后找到:

% git clone --recurse-submodules https://github.com/moneymanagerex/moneymanagerex.git
Cloning into 'moneymanagerex'...
remote: Counting objects: 32387, done.
[...]
Submodule '3rd/LuaGlue' (https://github.com/moneymanagerex/LuaGlue.git) registered for path '3rd/LuaGlue'
Submodule '3rd/cgitemplate' (https://github.com/moneymanagerex/html-template.git) registered for path '3rd/cgitemplate'
Submodule '3rd/mongoose' (https://github.com/cesanta/mongoose.git) registered for path '3rd/mongoose'
Submodule 'lib/wxsqlite3' (https://github.com/utelle/wxsqlite3.git) registered for path 'lib/wxsqlite3'
[...]
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/LuaGlue'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/cgitemplate'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/3rd/mongoose'...
Cloning into '/home/mat/work/freebsd/ports/finance/moneymanagerex/moneymanagerex/lib/wxsqlite3'...
[...]
Submodule path '3rd/LuaGlue': checked out 'c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b'
Submodule path '3rd/cgitemplate': checked out 'cd434eeeb35904ebcd3d718ba29c281a649b192c'
Submodule path '3rd/mongoose': checked out '2140e5992ab9a3a9a34ce9a281abf57f00f95cda'
Submodule path 'lib/wxsqlite3': checked out 'fb66eb230d8aed21dec273b38c7c054dcb7d6b51'
[...]
% cd moneymanagerex
% git submodule status
 c51d11a247ee4d1e9817dfa2a8da8d9e2f97ae3b 3rd/LuaGlue (heads/master)
 cd434eeeb35904ebcd3d718ba29c281a649b192c 3rd/cgitemplate (cd434ee)
 2140e5992ab9a3a9a34ce9a281abf57f00f95cda 3rd/mongoose (6.2-138-g2140e59)
 fb66eb230d8aed21dec273b38c7c054dcb7d6b51 lib/wxsqlite3 (v3.4.0)
[...]

它也可以在 GitHub 上找到。作为子模块的每个子目录都显示为 目录@哈希,例如,mongoose @ 2140e59

虽然从 GitHub 获取信息似乎更直接,但使用 git submodule status 找到的信息将提供更有意义的信息。例如,在这里,lib/wxsqlite3 的提交哈希值 fb66eb2 对应于 v3.4.0。两者可以互换使用,但当一个标签可用时,请使用它。

现在已经收集了所有需要的信息,可以写 Makefile 了(只显示与 GitHub 有关的行):

PORTNAME=	moneymanagerex
DISTVERSIONPREFIX=	v
DISTVERSION=	1.3.0

USE_GITHUB=	yes
GH_TUPLE=	utelle:wxsqlite3:v3.4.0:wxsqlite3/lib/wxsqlite3 \
		moneymanagerex:LuaGlue:c51d11a:lua_glue/3rd/LuaGlue \
		moneymanagerex:html-template:cd434ee:html_template/3rd/cgitemplate \
		cesanta:mongoose:2140e59:mongoose/3rd/mongoose \
		[...]

5.4.4. 使用 _GITLAB

与 GitHub 类似,如果发行文件来自 gitlab.com 或托管 GitLab 软件,这些变量可以使用,可能需要设置。

表6. USE_GITLAB 描述

Variable描述Default

GL_SITE

托管 GitLab 项目的网站名称

https://gitlab.com/

GL_ACCOUNT

主持项目的 GitLab 用户的账户名称

${PORTNAME}

GL_PROJECT

GitLab 上的项目名称

${PORTNAME}

GL_COMMIT

要下载的提交哈希值。必须是完整的 160 位,40 个字符的 sha1 哈希值。这是 GitLab 的一个必要变量。

(none)

GL_SUBDIR

当软件需要在 ${WRKSRC} 内解压额外的分发文件时,可以使用这个变量。更多信息请参见从GitLab获取多个文件中的例子。

(none)

例23. 简单使用 USE_GITLAB

当我们试图从 gitlab.com 上的 accounts-sso 用户那里为 libsignon-glib 的 1.14 版做一个移植时, 在 https://gitlab.com/accounts-sso/libsignon-glib/, Makefile 最终会变成这样, 用于获取发行文件:

PORTNAME=	libsignon-glib
DISTVERSION=	1.14

USE_GITLAB=	yes
GL_ACCOUNT=	accounts-sso
GL_COMMIT=	e90302e342bfd27bc8c9132ab9d0ea3d8723fd03

它将自动把 MASTER_SITES 设置为 gitlab.com,WRKSRC 设置为 ${WRKDIR}/libsignon-glib-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03-e90302e342bfd27bc8c9132ab9d0ea3d8723fd03

例24. 更完整地使用 USE_GITLAB

更完整的使用方法是,如果 port 没有版本管理,而 foobar 来自自已托管的 GitLab 网站上的项目 bar 的 foo 用户 https://gitlab.example.com/,那么 Makefile 最后看起来是这样的,用于获取分发文件:

PORTNAME=	foobar
DISTVERSION=	g20170906

USE_GITLAB=	yes
GL_SITE=	https://gitlab.example.com
GL_ACCOUNT=	foo
GL_PROJECT=	bar
GL_COMMIT=	9c1669ce60c3f4f5eb43df874d7314483fb3f8a6

它的 MASTER_SITES 设置为 "https://gitlab.example.com",WRKSRC 设置为 ${WRKDIR}/bar-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6-9c1669ce60c3f4f5eb43df874d7314483fb3f8a6

技巧

20170906GL_COMMIT 中提到的提交日期, 而不是 Makefile 被编辑的日期, 或提交到 FreeBSD Ports 的日期。

注意

GL_SITE 的协议、 Port 和 webroot 都可以在同一个变量中修改。

5.4.4.1. 从 GitLab 获取多个文件

USE_GITLAB 框架还支持从 GitLab 和 GitLab 托管的网站的不同地方获取多个分发文件。它的工作方式与从多个地点获取多个分发文件或补丁文件以及从 GitLab 获取多个文件非常相似。

多个值被添加到 GL_SITEGL_ACCOUNTGL_PROJECTGL_COMMIT。每个不同的值都被分配一个组。 USE_GITLAB 说明。

GL_TUPLE 也可以在有很多分发文件的时候使用。它有助于将网站、账户、项目、提交和组的信息放在同一个地方。

对于每个组,都会创建一个 ${WRKSRC_group} 辅助变量,其中包含文件被解压到的目录。${WRKSRC_group} 变量可以用来在解压后移动目录,或添加到 CONFIGURE_ARGS 中,或任何需要的地方,以便软件正确构建。

当心

:group 部分必须只用于一个分发文件。它被用作一个唯一的键,多次使用它将覆盖之前的值。

注意

由于这只是高于 DISTFILESMASTER_SITES 的语法糖, 组名必须遵守《多处分发或多处补丁文件》中列出的对组名的限制。

当使用GitLab获取多个文件时,有时不会从GitLab站点获取默认的分发文件。要禁止取回默认的分发文件,请设置:

USE_GITLAB=	nodefault

重要

当使用 USE_GITLAB=nodefault 时,Makefile 必须在其顶块中设置 DISTFILES。这个定义应该是:

DISTFILES=    ${DISTNAME}${EXTRACT_SUFX}

例25. 使用 USE_GITLAB 和多个分布文件

这在功能上等同于使用多分布文件的 USE_GITLAB,但使用 GL_TUPLE

PORTNAME=	foo
DISTVERSION=	1.0.2

USE_GITLAB=	yes
GL_COMMIT=	c189207a55da45305c884fe2b50e086fcad4724b
GL_TUPLE=	https://gitlab.example.com:9434/gitlab:bar:foo-icons:ae7368cab1ca7ca754b38d49da064df87968ffe4:icons/ext/icons \
		bar:foo-contrib:9e4dd76ad9b38f33fdb417a4c01935958d5acd2a:contrib

CONFIGURE_ARGS= --with-contrib=${WRKSRC_contrib}

在前面的例子中,用 bar:icons,contrib 进行了分组。在 GL_TUPLE 中存在一些多余的信息,因为不可能进行分组。

5.4.5. EXTRACT_SUFX

如果有一个分发文件,并且它使用了一个奇怪的后缀来表示压缩机制,请设置 EXTRACT_SUFX

例如,如果发行文件被命名为 foo.tar.gzip,而不是更正常的 foo.tar.gz,就写:

DISTNAME=	foo
EXTRACT_SUFX=	.tar.gzip

USES=tar[:xxx]USES=lhaUSES=zip 会根据需要自动将 EXTRACT_SUFX 设置为最常见的档案扩展名,更多细节见使用 USES 宏。如果这些都没有设置,那么 EXTRACT_SUFX 默认为 .tar.gz

注意

由于 EXTRACT_SUFX 只在 DISTFILES 中使用,所以只需设置其中一个。

5.4.6. DISTFILES

有时, 要下载的文件的名字与 port 的名字并不相像。例如, 它可能被称为 source.tar.gz 或类似的。在其他情况下, 应用程序的源代码可能在几个不同的档案中, 所有这些都必须下载。

如果是这种情况,将 DISTFILES 设置为必须下载的所有文件的空格分隔列表。

DISTFILES=	source1.tar.gz source2.tar.gz

如果没有明确设置,DISTFILES 默认为 ${DISTNAME}${EXTRACT_SUFX}

5.4.7. EXTRACT_ONLY

如果只有部分 DISTFILES 必须被解压--例如,其中一个是源代码,而另一个是未压缩的文档——在 EXTRACT_ONLY 中列出必须被解压的文件名。

DISTFILES=	source.tar.gz manual.html
EXTRACT_ONLY=	source.tar.gz

当没有一个 DISTFILES 需要被解压时,将 EXTRACT_ONLY 设置为空字符串。

EXTRACT_ONLY=

5.4.8. PATCHFILES

如果 port 需要一些可以通过 FTP 或 HTTP 获得的额外补丁, 则应将 PATCHFILES 设为文件名, 而 PATCH_SITES 则是包含这些文件的目录的 URL (格式与 MASTER_SITES 相同)。

如果补丁因为包含一些额外的路径名, 而不是相对于源代码树的顶端 (即 WRKSRC), 则应相应地设置 PATCH_DIST_STRIP。例如, 如果补丁中的所有路径名在文件名前面都有一个额外的 foozolix-1.0/, 则设置 PATCH_DIST_STRIP=-p1

不要担心补丁被压缩;如果文件名以 .Z.gz.bz2.xz 结尾,它们会被自动解压缩。

如果补丁是和其他一些文件, 例如文档, 一起以压缩的 tar 包形式发布的, 则不可能使用 PATCHFILES。如果是这种情况, 应把补丁的名称和压缩包的位置加入到 DISTFILESMASTER_SITES。然后, 使用 EXTRA_PATCHES 来指向这些文件, bsd.port.mk 会自动应用它们。特别是, 不要把补丁文件复制到 ${PATCHDIR}。那个目录可能是不可写的。

技巧

如果有多个补丁,并且它们需要混合的带状参数值,可以在 PATCHFILES 中的补丁名称旁边加上,例如

PATCHFILES=	patch1 patch2:-p1

这与主站点的分组功能并不冲突,添加一个组也可以:

PATCHFILES=	patch2:-p1:source2

注意

到那时,这个压缩包已经和普通的源代码一起被解压了,所以如果是普通的压缩压缩包,就没有必要明确地解压它。如果手动解压,要特别注意不要覆盖该目录中已经存在的东西。另外,不要忘了在预清洁目标中添加一个删除复制的补丁的命令。

5.4.9. 多处分发或来自多处的补丁文件

(考虑到这是一个有点 "高级的话题";刚开始接触本文件的人可能希望跳过这一部分)。

这一节有关于被称为 MASTER_SITES:nMASTER_SITES_NN 的抓取机制的信息。我们将把这种机制称为 MASTER_SITES:n

首先介绍一下背景。OpenBSD 在 DISTFILESPATCHFILES 里有一个很好的功能,允许文件和补丁被后缀上 :n 标识符。这里,n 可以是任何包含 [0-9a-zA-Z_] 的词,并表示一个组的名称。比如说:

DISTFILES=	alpha:0 beta:1

在 OpenBSD 中, 分发文件 alpha 将与变量 MASTER_SITES0 相关联, 而不是我们常见的 MASTER_SITESbetaMASTER_SITES1 相关联。

这是一个非常有趣的功能,可以减少对正确下载网站的无休止的搜索。

试想一下,DISTFILES 中的 2 个文件和 MASTER_SITES 中的 20 个站点,这些站点慢得要命,其中 MASTER_SITES 中的所有站点都携带了 beta,而 alpha 只能在第 20 个站点中找到。如果维护者事先知道这一点,那么检查所有的网站就太浪费了,不是吗?对于那个可爱的周末来说,这不是一个好的开始!

现在你有了这个想法,想象一下更多的 DISTFILES 和更多的 MASTER_SITES。当然,我们的 "distfiles survey meister" 会感谢这将带来的网络压力的缓解。

在接下来的章节中,我们将介绍这个想法在 FreeBSD 上的实现。我们对 OpenBSD 的概念进行了一些改进。

重要

组名中不能有破折号(-),事实上,它们不能有 [a-zA-Z0-9_] 范围以外的任何字符。这是因为,虽然 make(1) 可以接受含有破折号的变量名,但 sh(1) 却不行。

5.4.9.1. 简化信息

这一节介绍了如何快速准备从不同的站点和子目录中获取多个发布文件和补丁的细粒度。我们在这里描述了一个简化的 MASTER_SITES:n 的用法。这对大多数情况来说已经足够了。更详细的信息可以在详细信息中找到。

有些应用程序由多个分发文件组成,必须从一些不同的网站下载。例如,Ghostscript 由程序的核心部分组成,然后是大量的驱动文件,这些文件的使用取决于用户的打印机。其中一些驱动文件是与核心文件一起提供的,但其他许多驱动文件必须从各种不同的网站下载。

为了支持这一点, DISTFILES 中的每个条目后面都可以有一个冒号和一个 "组名" 。在 MASTER_SITES 中列出的每个站点后面都有一个冒号,以及表示从这个站点下载的发行文件的组。

例如, 考虑一个应用程序, 它的源代码被分成两部分, source1.tar.gzsource2.tar.gz, 它们必须从两个不同的站点下载。这个 port 的 Makefile 将包括诸如 Simplified Use of MASTER_SITES:n with One File Per Site 等行。

例26. 简化的 MASTER_SITES:n 的使用,每个站点只有一个文件

MASTER_SITES=	ftp://ftp1.example.com/:source1 \
		http://www.example.com/:source2
DISTFILES=	source1.tar.gz:source1 \
		source2.tar.gz:source2

多个发行文件可以有相同的组。继续前面的例子, 假设有第三个发行文件, source3.tar.gz, 是从 ftp.example2.com 下载的。那么 Makefile 就会写成这样: 简化 MASTER_SITES:n 的使用, 每个站点有一个以上的文件。

例 27. 简化 MASTER_SITES:n 的使用,每个站点有多于一个的文件

MASTER_SITES=	ftp://ftp.example.com/:source1 \
		http://www.example.com/:source2
DISTFILES=	source1.tar.gz:source1 \
		source2.tar.gz:source2 \
		source3.tar.gz:source2

5.4.9.2. 详细资料

好了, 前面的例子没有反映出新 Port 的需求?在这一节中, 我们将详细解释细粒度的获取机制 MASTER_SITES:n 如何工作, 以及如何使用它。

  1. 元素可以用 :n 作为后缀,其中 n 是 [^:,]+,也就是说,n 在概念上可以是任何字母数字字符串,但我们现在将它限制在 [a-zA-Z_] [0-9a-zA-Z_]+

​ 此外,字符串匹配是区分大小写的;也就是说,nN 是不同的。

​ 然而,这些词不能用于后缀的目的,因为它们产生了特殊的含义:defaultallALL(它们在内部被用于第 ii 项)。此外,DEFAULT 是一个特殊用途的词(查看第 3 项)。

  1. 后缀为 :n 的元素属于 n 组,:m 属于 m 组,以此类推。

  2. 没有后缀的元素是无组的,它们都属于特殊组 DEFAULT。任何后缀为 DEFAULT 的元素,都是多余的,除非一个元素同时属于 DEFAULT 和其他组(请查看第 5 项)。

​ 这些例子是等价的,但第一个例子是首选:

  ```shell-session
  MASTER_SITES=	alpha
  ```
MASTER_SITES=	alpha:DEFAULT
  1. 组不是排他性的,一个元素可以同时属于几个不同的组,一个组既可以有几个不同的元素,也可以没有。

  2. 当一个元素同时属于几个组时,使用逗号运算符(,

    我们可以在一个后缀中一次性列出几个组,而不是重复几次,每次都用不同的后缀。例如,:m,n,o 标记一个属于 mno 组的元素。

    所有这些例子都是等价的,但最后一个例子是首选:

    MASTER_SITES=	alpha alpha:SOME_SITE
    MASTER_SITES=	alpha:DEFAULT alpha:SOME_SITE
    MASTER_SITES=	alpha:SOME_SITE,DEFAULT
    MASTER_SITES=	alpha:DEFAULT,SOME_SITE
  3. 一个给定组中的所有站点都会根据 MASTER_SORT_AWK 进行排序。MASTER_SITESPATCH_SITES 中的所有组也会被排序。

  4. 组的语义可以根据这个语法在 MASTER_SITESPATCH_SITESMASTER_SITE_SUBDIRPATCH_SITE_SUBDIRDISTFILESPATCHFILES 等任何一个变量中使用:

    a. 所有 MASTER_SITESPATCH_SITESMASTER_SITE_SUBDIRPATCH_SITE_SUBDIR 元素都必须以正斜线 / 字符来结束。如果有任何元素属于任何组, 则组的后缀 :n 必须紧跟在终止符 / 之后。MASTER_SITES:n 机制依赖于终结符 / 的存在, 以避免将 :n 是元素的有效部分的元素与 :n 表示组 n 的元素混淆。出于兼容性的考虑, 由于之前在 MASTER_SITE_SUBDIRPATCH_SITE_SUBDIR 元素中不需要 / 终结符, 如果紧随其后的后缀字符不是 /, 那么 :n 将被视为元素的有效部分, 而不是组后缀, 即使元素后缀为 :n。请参见 MASTER_SITE_SUBDIRMASTER_SITES:n 的详细用法 和 MASTER_SITES:n 与逗号操作符、 多个文件、多个站点和多个子目录的详细用法。

例子 28. MASTER_SITES:nMASTER_SITE_SUBDIR 中的详细用法

MASTER_SITE_SUBDIR=	old:n new/:NEW
  • 组内目录 DEFAULT → old:n

  • 组内目录 NEW → new

例29. 带逗号操作符的 MASTER_SITES:n 的详细用法, 多个文件、多个站点和多个子目录

MASTER_SITES=	http://site1/%SUBDIR%/ http://site2/:DEFAULT \
		http://site3/:group3 http://site4/:group4 \
		http://site5/:group5 http://site6/:group6 \
		http://site7/:DEFAULT,group6 \
		http://site8/%SUBDIR%/:group6,group7 \
		http://site9/:group8
DISTFILES=	file1 file2:DEFAULT file3:group3 \
		file4:group4,group5,group6 file5:grouping \
		file6:group7
MASTER_SITE_SUBDIR=	directory-trial:1 directory-n/:groupn \
		directory-one/:group6,DEFAULT \
		directory

前面的例子导致了这种细粒度的取材。网站是按照它们将被使用的确切顺序排列的。

  • file1 将被取自

  • MASTER_SITE_OVERRIDE

  • http://site1/directory-trial:1/

  • http://site1/directory-one/

  • http://site1/directory/

  • http://site2/

  • http://site7/

  • MASTER_SITE_BACKUP

  • file2 将和 file1 一样被取走,因为它们都属于同一个组。

  • MASTER_SITE_OVERRIDE

  • http://site1/directory-trial:1/

  • http://site1/directory-one/

  • http://site1/directory/

  • http://site2/

  • http://site7/

  • MASTER_SITE_BACKUP

  • file3 将被取自

  • MASTER_SITE_OVERRIDE

  • http://site3/

  • MASTER_SITE_BACKUP

  • file4 将被取自

  • MASTER_SITE_OVERRIDE

  • http://site4/

  • http://site5/

  • http://site6/

  • http://site7/

  • http://site8/directory-one/

  • MASTER_SITE_BACKUP

  • file5 将被取自

  • MASTER_SITE_OVERRIDE

  • MASTER_SITE_BACKUP

  • file6 将被取自

  • MASTER_SITE_OVERRIDE

  • http://site8/

  • MASTER_SITE_BACKUP

  1. 我如何将 bsd.sites.mk 的一个特殊宏分组,例如 SourceForge(SF)?

    这已经被尽可能地简化了。参见 MASTER_SITES:n 与 SourceForge (SF) 的详细用法。

例30. MASTER_SITES:n 与 SourceForge (SF) 的详细用法

MASTER_SITES=	http://site1/ SF/something/1.0:sourceforge,TEST
DISTFILES=	something.tar.gz:sourceforge

something.tar.gz 将从 SourceForge 的所有站点获取。

  1. 我如何将其与 PATCH* 一起使用?

    所有的例子都是在 MASTER* 的情况下完成的, 但对于 PATCH* 来说, 它们的工作原理是完全一样的, 这一点可以在简化 MASTER_SITES:nPATCH_SITES 的使用中看到。

例31. 简化了 MASTER_SITES:nPATCH_SITES 的使用。

PATCH_SITES=	http://site1/ http://site2/:test
PATCHFILES=	patch1:test

5.4.9.3. 对 Port 来说,什么会发生变化?什么没有?

Ⅰ. 所有当前的 Port 都保持不变。MASTER_SITES:n 功能代码只有在有元素后缀为 :n 的情况下才会根据上述语法规则被激活, 特别是如第 7 项所示。

Ⅱ. Port 目标保持不变: checksum, makesum, patch, configure, build, 等等。除了 do-fetchfetch-listmaster-sitespatch-sites 这些明显的例外。

  • do-fetch: 部署新的分组后缀 DISTFILESPATCHFILES, 并在 MASTER_SITESPATCH_SITES 中使用匹配的组元素, 这些组元素在 MASTER_SITE_SUBDIRPATCH_SITE_SUBDIR 中都使用。检查 MASTER_SITES:n 的详细使用情况, 包括逗号操作符、 多个文件、 多个站点和多个子目录。

  • fetch-list: 和以前的 fetch-list 一样工作,例外的是,它和 do-fetch 一样分组。

  • master-sitespatch-sites:(与旧版本不兼容)只返回 DEFAULT 组的元素;事实上,它们分别执行目标 master-sites-defaultpatch-sites-default

此外, 使用 master-sites-all 或 patch-sites-all 的目标比直接检查 MASTER_SITES 或 PATCH_SITES 更为可取。另外, 直接检查并不保证在未来的版本中能够正常工作。请查看 B 项, 以了解关于这些新的 port 目标的更多信息。

Ⅲ. 新的 Ports 目标

a. 有 master-sites-npatch-sites-n 两个目标, 它们将分别列出 MASTER_SITESPATCH_SITES 中各自的 n 组的元素。例如, master-sites-DEFAULTpatch-sites-DEFAULT 都会返回 DEFAULT 组的元素, 以及 test 组的 master-sites-testpatch-sites-test, 以及其他的元素。

b. 有一些新的目标 master-sites-allpatch-sites-all, 它们完成了旧的 master-sitespatch-sites 的工作。它们会返回所有组的元素, 就像它们都属于同一个组一样, 但需要注意的是, 它列出的 MASTER_SITE_BACKUPMASTER_SITE_OVERRIDE 数量与 DISTFILESPATCHFILES 中定义的组一样多; 对于 master-sites-allpatch-sites-all 而言, 它们分别列出了 MASTER_SITE_BACKUPMASTER_SITE_OVERRIDE

5.4.10. DIST_SUBDIR

不要让 port 扰乱 /usr/ports/distfiles。如果这个 port 需要获取大量的文件, 或包含的文件名称可能与其它 port 冲突 (例如, Makefile), 则应将 DIST_SUBDIR 设置为 port 的名称 (${PORTNAME}${PKGNAMEPREFIX}${PORTNAME} 都可以)。这将把 DISTDIR 从默认的 /usr/ports/distfiles 改为 /usr/ports/distfiles/${DIST_SUBDIR}, 并在实际上把这个 port 所需要的所有东西都放到这个子目录里。

它还会查看备份主站点上的同名子目录,网址是:http://distcache.FreeBSD.org(在 Makefile 中明确设置 DISTDIR 不会实现这一点,所以请使用 DIST_SUBDIR)。

注意

这并不影响 Makefile 中定义的 MASTER_SITES

最后更新于

FreeBSD 中文社区