FreeBSD Port 开发者手册
FreeBSD 中文社区
  • FreeBSD Port 开发者手册翻译项目
  • 编辑日志
  • 译者说明
  • FreeBSD Port 开发者手册
    • FreeBSD Port 开发者手册
  • 第1章 简介
    • 1.1.简介
  • 第2章 制作新的 port
    • 2.1.制作新的 port
  • 第3章 简单的 port
    • 3.1.编写 Makefile
    • 3.2.编写描述文件
    • 3.3.创建校验和文件
    • 3.4.测试 port
    • 3.5.用 portlint 来检查 port
    • 3.6.提交新的 port
  • 第4章 复杂的 Port
    • 4.1 Port 工作原理
    • 4.2.获取源代码
    • 4.3.修改 port
    • 4.4.打补丁
    • 4.5.配置
    • 4.6.处理用户输入
  • 第5章 配置 Makefile
    • 5.1.原始来源
    • 5.2.命名
    • 5.3.归类
    • 5.4.源代码包文件
    • 5.5.维护者(MAINTAINER)
    • 5.6.一句话说明(COMMENT)
    • 5.7.项目网站
    • 5.8.许可证
    • 5.9.PORTSCOUT
    • 5.10.依赖
    • 5.11.从属 port 和 MASTERDIR
    • 5.12.man 手册
    • 5.13.info 文件
    • 5.14.Makefile 参数
    • 5.15.特殊的工作目录
    • 5.16.解决冲突
    • 5.17.安装文件
    • 5.18. 使用 BINARY_ALIAS 来重命名命令,而不是在编译中打补丁
  • 第6章 特殊情况
    • 第6章 特殊情况
  • 第7章 Flavors
    • 7.1.Flavors 简介
    • 7.2.使用 FLAVORS
    • 7.3.USES=php 和 Flavors
    • 7.4.USES=python 和 Flavors
    • 7.5.USES=lua 和 Flavors
  • 第8章 高级 pkg-plist 实践
    • 8.1.根据 make 变量对 pkg-plist 进行修改
    • 8.2.空目录
    • 8.3.配置文件
    • 8.4.动态与静态软件包列表
    • 8.5.自动创建软件包列表
    • 8.6.用关键词扩展软件包列表
  • 第9章 pkg-*
    • 9.1.pkg-message(安装二进制包时显示的消息文件)
    • 9.2.pkg-install、pkg-pre-install 和 pkg-post-install(安装二进制包时执行的脚本文件)
    • 9.3.pkg-deinstall、pkg-pre-deinstall 和 pkg-post-deinstall(卸载时执行的脚本文件)
    • 9.4.修改 pkg-* 文件的名字
    • 9.5.使用 SUB_FILES 和 SUB_LIST
  • 第10章 测试 port
    • 10.1.运行 make describe
    • 10.2.运行 make test
    • 10.3.Portclippy / Portfmt
    • 10.4.Portlint
    • 10.5.Port 工具
    • 10.6.PREFIX 和 DESTDIR
    • 10.7.Poudriere
    • 10.8.调试 port
  • 第11章 升级 port
    • 11.1.使用 Git 制作补丁
    • 11.2.UPDATING 和 MOVED
  • 第12章 安全
    • 12.1.安全为何如此重要
    • 12.2.修复安全漏洞
    • 12.3.向社区通报情况
  • 第13章 该做什么和不该做什么
    • 第13章 该做什么和不该做什么
  • 第14章 一个简单的 port
    • 第14章 一个简单的 port
  • 第15章 在 Port Makefile 中变量的顺序
    • 第15章 在 Port Makefile 中变量的顺序
  • 第16章 保持更新
    • 第16章 保持更新
  • 第17章 使用 USES 宏
    • 第17章 使用 USES 宏
  • 第18章 __FreeBSD_version 的值
    • 第18章 __FreeBSD_version 的值
由 GitBook 提供支持
在本页
  • 4.4.1. 补丁的一般规则
  • 4.4.2. 手动生成补丁
  • 4.4.3. 简单自动替换
  • 4.4.4. 条件性打补丁

这有帮助吗?

在GitHub上编辑
导出为 PDF
  1. 第4章 复杂的 Port

4.4.打补丁

最后更新于2天前

这有帮助吗?

FreeBSD 中文社区

在准备 Port 时,可以使用 记录已添加或修改的文件,稍后将这些差异提供给 。对典型文件进行此操作时,需要在进行任何更改之前保存原始文件的副本,并使用 .orig 后缀。

% cp file file.orig

在所有更改完成后,cd 回到 Port 目录。使用 make makepatch 生成更新的补丁文件,并将其存储在 files 目录中。

技巧

使用 BINARY_ALIAS 在构建过程中替代硬编码命令,避免修改构建文件。有关更多信息,请参阅 。

4.4.1. 补丁的一般规则

补丁文件存储在 PATCHDIR 中,通常是 files/,从这里它们会被自动应用。所有补丁必须相对于 WRKSRC。通常 WRKSRC 是 WRKDIR 的子目录,即提取 distfile 的目录。使用 make -V WRKSRC 查看实际路径。补丁名称需要遵循以下规则:

  • 避免多个补丁修改同一个文件。例如,patch-foobar.c 和 patch-foobar.c2 都修改 ${WRKSRC}/foobar.c,这样会使补丁变得脆弱且难以调试。

  • 在创建补丁文件名时,将每个下划线 (_) 替换为两个下划线 (__),将每个斜杠 (/) 替换为一个下划线 (_)。例如,要修补名为 src/freeglut_joystick.c 的文件,对应的补丁应命名为 patch-src_freeglut__joystick.c。不要使用像 patch-aa 或 patch-ab 这样的命名方式。始终在补丁名称中使用路径和文件名。使用 make makepatch 可以自动生成正确的名称。

  • 如果更改相关,补丁可以修改多个文件,并且补丁名称应适当命名。例如,patch-add-missing-stdlib.h。

  • 补丁名称只能使用字符 [-+._a-zA-Z0-9]。特别地,不要使用 :: 作为路径分隔符,应使用 _ 代替。

尽量减少补丁中的非功能性空白字符更改。在开源世界中,项目常常共享大量代码基础,但遵循不同的样式和缩进规则。当从一个项目中提取出一个工作功能并修复另一个项目中的类似问题时,请小心:结果补丁可能充满了非功能性更改。这不仅增加了 Ports 仓库的大小,还使得很难确定到底是哪个问题导致了错误,或者具体修改了哪些内容。

如果必须删除文件,请在 post-extract 目标中进行,而不是作为补丁的一部分。

4.4.2. 手动生成补丁

注意

通常不需要手动创建补丁。自动生成补丁,如本节前述,通常是首选方法。然而,有时可能需要手动补丁。

补丁保存为名为 patch-* 的文件,其中 * 表示被修补的文件路径名,例如 patch-Imakefile 或 patch-src-config.h。不以 patch- 开头的补丁文件名将不会被自动应用。

% diff -u file.orig file > patch-pathname-file
% diff -u -N newfile.orig newfile > patch-pathname-newfile

4.4.3. 简单自动替换

post-patch:
	@${REINPLACE_CMD} -e 's|/usr/local|${PREFIX}|g' ${WRKSRC}/Makefile

重要

在移植软件时,源文件中常常使用 CR/LF 换行符约定。这可能会导致进一步打补丁时出现问题、编译警告或脚本执行错误(例如 /bin/sh^M not found)。要快速将所有文件从 CR/LF 转换为仅 LF,可以在 Port 的 Makefile 中添加以下内容:

USES=	dos2unix

可以指定要转换的特定文件列表:

USES=	dos2unix
DOS2UNIX_FILES=	util.c util.h
USES=	dos2unix
DOS2UNIX_REGEX=	.*\.([ch]|cpp)

类似的选项是 DOS2UNIX_GLOB,它会对其中列出的每个元素运行 find。

USES=	dos2unix
DOS2UNIX_GLOB=	*.c *.cpp *.h

可以设置转换的基础目录。这在存在多个 distfile 且其中几个文件需要进行行结束符转换时非常有用。

USES=	dos2unix
DOS2UNIX_WRKSRC=	${WRKDIR}

4.4.4. 条件性打补丁

有些 Ports 需要在特定的 FreeBSD 版本或启用/禁用某个选项时才应用补丁。条件性补丁通过将补丁文件的完整路径添加到 EXTRA_PATCHES 中来指定。条件性补丁的文件名通常以 extra- 开头,虽然这不是必须的。然而,它们的文件名 不能 以 patch- 开头。如果以 patch- 开头,框架将无条件地应用它们,这对条件性补丁来说是不可取的。

示例 1. 针对特定 FreeBSD 版本应用补丁

.include <bsd.port.options.mk>

# 在此之前打上 iconv const 限定符
.if ${OPSYS} == FreeBSD && ${OSVERSION} < 1100069
EXTRA_PATCHES=	${PATCHDIR}/extra-patch-fbsd10
.endif

.include <bsd.port.mk>

示例 2. 可选地应用补丁

OPTIONS_DEFINE=	  FOO BAR
FOO_EXTRA_PATCHES=  ${PATCHDIR}/extra-patch-foo
BAR_EXTRA_PATCHES_OFF=	${PATCHDIR}/extra-patch-bar.c \
		${PATCHDIR}/extra-patch-bar.h

示例 3. 使用 EXTRA_PATCHES 与目录

有时,某个功能需要多个补丁,在这种情况下,可以将 EXTRA_PATCHES 指向一个目录,它将自动应用该目录中所有名为 patch-* 的文件。

在 ${PATCHDIR} 中创建一个子目录,并将补丁文件移入其中。例如:

% ls -l files/foo-patches
-rw-r--r--  1 root  wheel    350 Jan 16 01:27 patch-Makefile.in
-rw-r--r--  1 root  wheel   3084 Jan 18 15:37 patch-configure.ac

然后将以下内容添加到 Makefile 中:

OPTIONS_DEFINE=	FOO
FOO_EXTRA_PATCHES=	${PATCHDIR}/foo-patches

框架将会使用该目录中所有名为 patch-* 的文件。

修改文件后,使用 记录原始文件和修改后文件之间的差异。-u 选项使 生成“统一”格式的差异,这是首选格式。

当为新添加的文件生成补丁时,使用 -N 告诉 将不存在的原始文件视为空文件:

使用 的递归选项 (-r) 生成补丁是可以的,但请检查生成的补丁,确保其中没有不必要的内容。特别是,当两个备份文件、使用 Imake 或 GNU configure 的 Makefile 之间的差异是没有必要的,并且应该删除。如果需要编辑 configure.in 并运行 autoconf 以重新生成 configure,不要对 configure 进行差异比较(它通常会变得很大,达到几千行!)。相反,定义 USES=autoreconf,并对 configure.in 进行差异比较。

可以通过 Port 的 Makefile 直接使用 的原地模式进行简单的替换。这对于需要使用变量值的更改非常有用:

仅使用 来替换变量内容。必须使用补丁文件而不是 来替换静态内容。

使用 DOS2UNIX_REGEX 可以跨子目录转换一组文件。其参数是一个与 兼容的正则表达式。有关格式的更多信息,请参阅 。此选项对于转换所有具有特定扩展名的文件非常有用。例如,转换所有源代码文件,而保持二进制文件不变:

当一个 需要补丁时,可以使用 opt_EXTRA_PATCHES 和 opt_EXTRA_PATCHES_OFF 使补丁依赖于 opt 选项。有关更多信息,请参阅 。

diff(1)
patch(1)
使用 BINARY_ALIAS 重命名命令,而不是修改构建
diff(1)
diff(1)
diff(1)
diff(1)
sed(1)
sed(1)
sed(1)
find(1)
re_format(7)
选项
通用变量替换