GNU软件编码标准风格(3)
Author:Onceday Date: 2024年1月21日
漫漫长路,才刚刚开始…
本文主要翻译自《GNU编码标准》(GNU Coding Standards)一文。
参考文档:
- Linux kernel coding style — The Linux Kernel documentation
- GNU Coding Standards - GNU Project - Free Software Foundation
7. 整体软件配置框架
发布不仅仅是把源文件打包成一个tar文件,然后放到FTP上。您应该对软件进行设置,以便可以将其配置为在各种系统上运行。您的
7.1 配置应该如何工作
每个GNU发行版都应该附带一个名为configure的shell脚本。这个脚本给出了参数,这些参数描述了你想要编译程序的机器和系统的类型。configure脚本必须记录配置选项,以便它们影响编译。
这里的描述是GNU包中配置脚本的接口规范。许多软件包使用GNU Autoconf(参见Autoconf的“介绍”部分)或GNU Automake(参见Automake的“介绍”部分)实现它,但您不必使用这些工具。你可以用任何你喜欢的方式实现它,例如,通过使configure成为一个完全不同的配置系统的包装器。
配置脚本的另一种操作方式是从标准名称(如config.h)链接到所选系统的适当配置文件。如果使用这种技术,发行版不应该包含一个名为config.h的文件。这样人们就无法在没有配置的情况下构建程序。
configure可以做的另一件事是编辑Makefile。如果这样做,发行版不应该包含名为Makefile的文件。相反,它应该包含一个Makefile文件。其中包含用于编辑的输入。同样,这样做是为了让人们在不先配置程序的情况下无法构建程序。
如果configure确实写入Makefile,那么Makefile应该有一个名为Makefile,它导致configure重新运行,设置与上次设置相同的配置。应将configure读取的文件列为依赖项
Makefile。
从configure脚本输出的所有文件都应该在开头有注释,说明它们是使用configure自动生成的。这样用户就不会想要手工编辑它们。
配置脚本应该编写一个名为config的文件。状态,描述上次配置程序时指定了哪些配置选项。该文件应该是一个shell脚本,如果运行,将重新创建相同的配置。
配置脚本应该接受一个形式为
如果用户没有指定
通常,支持
此外,
--prefix --exec-prefix --bindir --sbindir --libexecdir --sysconfdir --sharedstatedir --localstatedir --runstatedir --libdir --includedir --oldincludedir --datarootdir --datadir --infodir --localedir --mandir --docdir --htmldir --dvidir --pdfdir --psdir
configure脚本还应该接受一个参数,该参数指定要为其构建程序的系统类型。这个参数应该是这样的:
cpu-company-system
例如,基于athlon的
configure脚本需要能够解码如何描述机器的所有可能的替代方案。因此,
配置脚本还应该采用选项
configure --build=i686-pc-linux-gnu <==>configure i686-pc-linux-gnu
当没有通过选项或参数指定构建类型时,配置脚本通常应该使用shell脚本配置[config.guess](https://git.savannah.gnu.org/ cgit/config.git/plain/config.guess)来猜测它。
其他选项允许更详细地指定机器上存在的软件或硬件,包括或排除包的可选部分,或调整某些工具或参数的名称:
-
--enable-feature[=parameter] ,配置包以构建和安装一个名为feature的可选用户级工具。这允许用户选择要包含哪些可选特性。如果它是默认构建的,那么给出一个可选参数’ no '应该会忽略功能。
--enable 选项不应该导致一个功能取代另一个功能。——enable 选项不应该用一个有用的行为替换另一个有用的行为。--enable 的唯一正确用法是用于是否构建程序的一部分或排除它。 -
--with-package ,这个包将被安装,所以将这个包配置为与package一起工作。package的可能值包括gnu-as (或gas ),gnu-ld ,gnu-libc ,gdb ,x 和x-toolkit 。不要使用--with 选项来指定文件名,以便查找某些文件。这超出了--with 选项的范围。 -
variable=value ,将变量variable的值设置为value。这用于覆盖构建过程中命令或参数的默认值。例如,用户可以发出
configure CFLAGS=-g CXXFLAGS=-g 来使用调试信息而不使用默认优化进行构建。指定变量作为配置参数,如下所示:
./configure CC=gcc
比在环境变量中设置它们更可取:
CC=gcc ./configure
因为它有助于稍后使用
config.status 重新创建相同的配置。但是,这两种方法都应该得到支持。
所有配置脚本都应该接受所有的“细节”选项和变量设置,无论它们是否对手头的特定包产生任何影响。特别是,它们应该接受以
您将注意到
执行部分编译过程的包可能支持交叉编译。在这种情况下,程序的主机和目标机器可能不同。
configure脚本通常应该将指定类型的系统同时视为主机和目标,从而生成一个适用于它所运行的同一类型机器的程序。
要编译一个程序,使其在不同于构建类型的主机类型上运行,请使用配置选项
要配置一个交叉编译器、交叉汇编器,或者其他什么,你应该指定一个不同于主机的目标,使用配置选项
./configure --host=hosttype --target=targettype
目标器类型通常默认为主机类型。交叉操作没有意义的程序不需要接受
有些程序有自动配置自己的方法。如果您的程序被设置为这样做,那么您的configure脚本可以简单地忽略它的大部分参数。
7.2 makefile的通用约定
本节描述为GNU程序编写makefile的约定。使用Automake将帮助您编写遵循这些约定的Makefile。有关可移植makefile的更多信息,请参阅Autoconf中的posix和“portable Make”部分。
每个Makefile都应该包含这一行:
SHELL = /bin/sh
以避免在SHELL变量可能从环境中继承的系统上出现问题。(这从来都不是GNU make的问题)。
不同的make程序有不兼容的后缀列表和隐式规则,这有时会造成混淆或错误行为。因此,只使用特定Makefile中需要的后缀显式设置后缀列表是个好主意,如下所示:
.SUFFIXES: .SUFFIXES: .c .o
第一行清除了后缀列表,第二行引入了可能受此Makefile中隐式规则约束的所有后缀。
不要这么认为
foo.1 : foo.man sedscript sed -f sedscript foo.man > foo.1
将在构建目录不是源目录时失败,因为foo.Man和sedscript在源目录中。
当使用GNU make时,依靠
foo.o : bar.c $(CC) -I. -I$(srcdir) $(CFLAGS) -c bar.c -o foo.o
应该写成:
foo.o : bar.c $(CC) -I. -I$(srcdir) $(CFLAGS) -c $< -o $@
以允许
foo.1 : foo.man sedscript sed -f $(srcdir)/sedscript $(srcdir)/foo.man > $@
GNU发行版通常包含一些不是源文件的文件,例如Info文件,以及来自
但是,如果一个文件没有出现在发行版中,那么Makefile不应该把它放在源目录中,因为在一般情况下构建程序不应该以任何方式修改源目录。
尝试使构建和安装目标,至少(以及它们的所有子目标)在并行make中正确工作。
7.3 Makefiles中的实用程序
编写Makefile命令(以及任何shell脚本,如configure)以在sh下运行(包括传统的Bourne shell和posix shell),而不是csh。不要使用ksh或bash的任何特殊特性,或者传统Bourne sh中不广泛支持的posix特性。
用于构建和安装的configure脚本和Makefile规则不应该直接使用任何实用程序,除了这些:
awk cat cmp cp diff echo egrep expr false grep install-info ln ls mkdir mv printf pwd rm rmdir sed sleep sort tar test touch tr true
压缩程序,如gzip,可以在dist规则中使用。
一般来说,坚持使用这些程序广泛支持的(通常是posix指定的)选项和特性。例如,不要使用
有关已知不兼容性的列表,请参阅Autoconf中的“Portable Shell”部分。
避免在makefiles中创建符号链接是一个好主意,因为一些文件系统不支持符号链接。
用于构建和安装的Makefile规则也可以使用编译器和相关程序,但应该通过make变量来实现,以便用户可以替换其他选项。
以下是我们指的一些程序:
ar bison cc flex install ld ldconfig lex make makeinfo ranlib texi2dvi yacc
使用以下make变量来运行这些程序:
$(AR) $(BISON) $(CC) $(FLEX) $(INSTALL) $(LD) $(LDCONFIG) $(LEX) $(MAKE) $(MAKEINFO) $(RANLIB) $(TEXI2DVI) $(YACC)
当您使用
如果使用符号链接,则应该为没有符号链接的系统实现回退。可以通过Make变量使用的其他实用程序有:
chgrp chmod chown mknod
在Makefile部分(或脚本)中使用其他实用程序是可以的,这些实用程序仅适用于您知道存在这些实用程序的特定系统。
7.4 用于指定命令的变量
makefile应该为覆盖某些命令、选项等提供变量。特别是,您应该通过变量运行大多数实用程序。因此,如果你使用Bison,有一个名为
文件管理实用程序(如ln、rm、mv等)不需要以这种方式通过变量引用,因为用户不需要用其他程序替换它们。
每个程序名称变量都应该带有一个选项变量,用于向程序提供选项。在
在任何运行预处理器的编译命令中使用
如果必须使用C编译器选项来正确编译某些文件,请不要将它们包含在
相反,安排将必要的选项传递给独立于
CFLAGS = -g ALL_CFLAGS = -I. $(CFLAGS) .c.o: $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
一定要在
将
每个
然后,它应该使用这些变量作为实际安装的命令,分别用于可执行文件和不可执行文件。这些变量的最小使用如下:
$(INSTALL_PROGRAM) foo $(bindir)/foo $(INSTALL_DATA) libfoo.a $(libdir)/libfoo.a
不过,最好在目标文件上支持
$(INSTALL_PROGRAM) foo bar baz $(bindr)
7.5 支持分阶段安装
DESTDIR是一个附加在每个已安装目标文件前的变量,如下所示:
$(INSTALL_PROGRAM) foo $(DESTDIR)$(bindir)/foo $(INSTALL_DATA) libfoo.a $(DESTDIR)$(libdir)/libfoo.a
DESTDIR变量由用户在make命令行中指定为绝对文件名。例如:
make DESTDIR=/tmp/stage install
应该只在安装
如果你的安装步骤正常安装
那么上面示例中调用的安装命令,将对应安装
以这种方式将变量DESTDIR添加到每个目标,提供了分阶段安装,其中安装的文件不会直接放置到预期的位置,而是被复制到临时位置(DESTDIR)。但是,已安装的文件保持其相对目录结构,并且不会修改任何嵌入的文件名。
你根本不应该在Makefile中设置DESTDIR的值,然后在默认情况下将这些文件安装到预期的位置。此外,指定DESTDIR不应该以任何方式改变软件的操作,因此它的值不应该包含在任何文件内容中。
DESTDIR支持通常用于包创建。对于想要了解给定包将安装在何处的用户,以及允许通常没有权限安装到受保护区域的用户在获得这些权限之前进行构建和安装,这也很有帮助。最后,它还可以用于诸如
7.6 安装目录变量
安装目录应该始终由变量命名,因此很容易在非标准位置安装。下面描述了这些变量的标准名称以及它们在GNU包中应该具有的值。它们基于标准的文件系统布局,它的变体在GNU/Linux和其他现代操作系统中使用。
安装程序在调用make(例如,
所有的安装目录及其父目录都应该在安装之前创建(如果需要的话)。
前两个变量设置了安装的根目录。所有其他安装目录都应该是这两个目录之一的子目录,并且不应该直接安装到这两个目录中。
-
prefix ,用于构造下面列出的变量的默认值的前缀。prefix 的默认值为/usr/local 。当构建完整的GNU系统时,前缀将为空,/usr 将是到/ 的符号链接。(如果您使用Autoconf,请将其写为@prefix@ )。使用不同的prefix值运行“make install”不会重新编译该程序。
-
exec_prefix ,在构造下面列出的一些变量的默认值时使用的前缀。exec_prefix的默认值应该是$(prefix) ,(如果你使用Autoconf,把它写成@exec_prefix@ )。通常,
$(exec_prefix) 用于包含特定于机器的文件(例如可执行文件和子例程库)的目录,而$(prefix) 直接用于其他目录。
使用不同的exec_prefix 值运行make install 不会重新编译程序。
可执行程序安装在以下目录之一:
bindir ,用户可以运行的可执行程序的安装目录。这通常应该是/usr/local/bin ,但是写成$(exec_prefix)/bin 。(如果你使用的是Autoconf,把它写成@bindir@ )。sbindir ,用于安装可从shell运行的可执行程序的目录,但通常只对系统管理员有用。这通常应该是/usr/local/sbin ,但是写成$(exec_prefix)/sbin 。(如果你正在使用自动配置,写为@sbindir@ )。libexecdir ,用于安装由其他程序而非用户运行的可执行程序的目录。这个目录通常应该是/usr/local/libexec ,但是可以写成$(exec_prefix)/libexec 。如果你使用Autoconf,把它写成@libexecdir@ ,libexecdir 的定义对所有包都是一样的,所以您应该将数据安装在它的子目录中。大多数包将它们的数据安装在$(libexecdir)/package-name/ 下,也可能在它的其他子目录中,比如$(libexecdir)/package-name/machine/version 。
程序在执行过程中使用的数据文件分为两类:
- 有些文件通常由程序修改,其他的则通常不会被修改(尽管用户可以编辑其中的一些)。
- 有些文件是独立于体系结构的,可以由站点上的所有机器共享,有些是依赖于体系结构的,只能由相同类型和操作系统的机器共享,其他可能永远不会在两台机器之间共享。
这就产生了六种不同的可能性。然而,除了目标文件和库之外,我们不鼓励使用与体系结构相关的文件。使其他数据文件与体系结构无关要简单得多,而且通常并不难。
下面是Makefiles应该用来指定存放这些不同类型文件的目录的变量:
(1)
(2)
这通常应该是
(3)
邮件和网络配置文件、
不要在此目录下安装可执行文件(它们可能属于
(4)
这通常应是
(5)
(6)
此外,除非在重新启动时,否则不应该清理这个目录,而一般的
如果您的程序有特定类型的文件,这些变量指定用于安装这些文件的目录。每个GNU包都应该有Info文件,因此每个程序都需要
(1)
因此,以这种方式安装头文件只对GCC有用。有时这不是问题,因为有些库实际上只打算与GCC一起工作。但有些库旨在与其他编译器一起工作。它们应该在两个地方安装头文件,一个由
(2)
Makefile命令应该检查
因此,如果您的Foo包提供了一个头文件
(3)
(4)
(5)
(5)
(6)
lispdir=’${datarootdir}/emacs/site-lisp’ AC_SUBST(lispdir)
(7)
unix风格的手册页是安装在以下其中一个:
(1)
(2)
(3)
不要让任何GNU软件的主要文档成为手册页。用Texinfo写一个手册。手册页只是为在Unix上运行GNU软件的人准备的,它只是一个次要的应用程序。
(1)
(2)
(3)
如果包需要在手册的多个部分中安装手册页,请使用这些名称而不是
最后,你应该设置以下变量:
(1)
例如下面实例:
# Common prefix for installation directories. # NOTE: This directory must exist when you start the install. prefix = /usr/local datarootdir = $(prefix)/share datadir = $(datarootdir) exec_prefix = $(prefix) # Where to put the executable for the command ’gcc’. bindir = $(exec_prefix)/bin # Where to put the directories used by the compiler. libexecdir = $(exec_prefix)/libexec # Where to put the Info files. infodir = $(datarootdir)/info
如果您的程序将大量文件安装到一个标准用户指定的目录中,那么将它们分组到该程序特定的子目录中可能会很有用。
如果您这样做,您应该编写安装规则来创建这些子目录。
不要期望用户在上面列出的任何变量的值中包含子目录名。为安装目录设置一组统一的变量名是为了使用户能够为几个不同的GNU包指定完全相同的值。为了使这一点有用,必须设计所有的包,以便在用户这样做时能够合理地工作。
有时,并非所有这些变量都可以在当前版本的
7.7 用户标准目标
所有GNU程序都应该在它们的makefile文件中有以下目标:
(1)
默认情况下,Make规则应该与
(2)
安装可执行文件时不要剥离它们。这有助于以后可能需要的最终调试,现在磁盘空间很便宜,动态加载器通常确保在正常执行期间不加载调试部分。需要剥离二进制文件的用户可以调用install-strip目标来实现。
如果可能的话,编写安装目标规则,以便它不会修改构建程序的目录中的任何内容,前提是刚刚完成了
如果要安装的文件还不存在,那么这些命令应该创建这些文件所在的所有目录。这包括作为变量
在安装手册页的任何命令之前使用
安装Info文件的方法是使用
下面是一个安装Info文件的示例规则,它还尝试处理一些其他情况,例如
do-install-info: foo.info installdirs $(NORMAL_INSTALL) # Prefer an info file in . to one in srcdir. if test -f foo.info; then d=.; else d="$(srcdir)"; fi; $(INSTALL_DATA) $$d/foo.info "$(DESTDIR)$(infodir)/foo.info" # Run install-info only if it exists. # Use ’if’ instead of just prepending ’-’ to the # line so we notice real errors from install-info. # Use ’$(SHELL) -c’ because some shells do not # fail gracefully when there is an unknown command. $(POST_INSTALL) if $(SHELL) -c ’install-info --version’ >/dev/null 2>&1; then install-info --dir-file="$(DESTDIR)$(infodir)/dir $(DESTDIR)$(infodir)/foo.info"; else true; fi
在编写安装目标时,必须将所有命令分为三类:普通命令(
(3)
当您有许多文档文件要安装时,我们建议您通过安排这些目标安装在适当的安装目录(如
请使这些安装格式化(
(4)
(5)
install-strip: $(MAKE) INSTALL_PROGRAM=’$(INSTALL_PROGRAM) -s’ install
但是,如果包安装脚本以及真正的可执行文件,安装条带目标不能仅仅引用安装目标;它必须剥离可执行文件,但不剥离脚本。
通常我们不建议剥离可执行程序,除非您确定程序没有错误。然而,安装一个剥离的可执行文件以供实际执行,同时将未剥离的可执行文件保存在其他地方,以防出现错误,这是合理的。
(6)
没有必要删除用
(7)
(8)
(9)
我们说“几乎所有”的原因是,运行命令
为了帮助用户了解这一点,用于特殊的维护人员清理目标的命令应该以以下两个命令开头:
@echo ’This command is intended for maintainers to use; it’ @echo ’deletes files that may need special tools to rebuild.’
(10)
(11)
info: foo.info foo.info: foo.texi chap1.texi chap2.texi $(MAKEINFO) $(srcdir)/foo.texi
您必须在Makefile中定义变量MAKEINFO。它应该运行makeinfo程序,它是Texinfo发行版的一部分。
通常,GNU发行版附带Info文件,这意味着Info文件存在于源目录中。因此,info文件的Make规则应该在源目录中更新它。当用户构建包时,Make通常不会更新Info文件,因为它们已经是最新的了。
(12)
下面是一个从
dvi: foo.dvi foo.dvi: foo.texi chap1.texi chap2.texi $(TEXI2DVI) $(srcdir)/foo.texi
您必须在Makefile中定义变量
下面是另一个例子,这是从Texinfo生成HTML:
html: foo.html foo.html: foo.texi chap1.texi chap2.texi $(TEXI2HTML) $(srcdir)/foo.texi
同样,您将在Makefile中定义变量
(13)
例如,GCC版本1.40的发行tar文件解压缩到名为
最简单的方法是创建一个适当命名的子目录,使用ln或cp在其中安装适当的文件,然后对该子目录进行tar。使用gzip压缩tar文件。实际发布文件的1.40版本GCC命名为
dist目标应该显式依赖于发行版中的所有非源文件,以确保它们在发行版中是最新的。
(14)
以下目标建议作为常规名称,用于它们有用的程序:
(1)
(2)
# Make sure all installation directories (e.g. $(bindir)) # actually exist by making them if necessary. installdirs: mkinstalldirs $(srcdir)/mkinstalldirs $(bindir) $(datadir) $(libdir) $(infodir) $(mandir)
或者,如果您希望支持DESTDIR(强烈建议):
# Make sure all installation directories (e.g. $(bindir)) # actually exist by making them if necessary. installdirs: mkinstalldirs $(srcdir)/mkinstalldirs $(DESTDIR)$(bindir) $(DESTDIR)$(datadir) $(DESTDIR)$(libdir) $(DESTDIR)$(infodir) $(DESTDIR)$(mandir)
此规则不应修改执行编译的目录。它应该只创建安装目录。
7.8 安装命令类别
在编写安装目标时,必须将所有命令分为三类:普通命令、安装前命令和安装后命令。
-
普通命令将文件移动到适当的位置,并设置其模式。它们不能修改任何文件,除了那些完全来自它们所属的包的文件。
-
安装前和安装后的命令可能会修改其他文件;特别是,它们可以编辑全局配置文件或数据库。
-
安装前命令通常在正常命令之前执行,安装后命令通常在正常命令之后执行。
安装后命令最常见的用法是运行
大多数程序不需要任何预安装命令,但我们有这个功能,以防万一需要它。
要将安装规则中的命令划分为这三个类别,请在其中插入类别行。类别行指定后面命令的类别。
类别行由制表符和对特殊Make变量的引用以及末尾的可选注释组成。你可以使用三个变量,每个类别一个,变量名指定类别。在普通执行中,类别行是无操作的,因为这三个Make变量通常是未定义的(您不应该在makefile中定义它们)。
下面是三个可能的分类行,每个都有一个解释其含义的注释:
$(PRE_INSTALL) # Pre-install commands follow. $(POST_INSTALL) # Post-install commands follow. $(NORMAL_INSTALL) # Normal commands follow.
如果在安装规则的开头不使用类别行,那么在第一个类别行出现之前,所有命令都被分类为正常。如果不使用任何类别行,则所有命令都被分类为正常。以下是要卸载的类别行:
$(PRE_UNINSTALL) # Pre-uninstall commands follow. $(POST_UNINSTALL) # Post-uninstall commands follow. $(NORMAL_UNINSTALL) # Normal commands follow.
通常,将使用预卸载命令从Info目录中删除条目。如果安装或卸载目标有任何作为安装子例程的依赖项,那么您应该用一个类别行启动每个依赖项的命令,并且也用一个类别行启动主目标的命令。这样,无论实际运行的是哪个依赖项,您都可以确保每个命令都被放置在正确的类别中。
安装前和安装后的命令不应该运行任何程序,除了这些:
[ basename bash cat chgrp chmod chown cmp cp dd diff echo egrep expand expr false fgrep find getopt grep gunzip gzip hostname install install-info kill ldconfig ln ls md5sum mkdir mkfifo mknod mv printenv pwd rm rmdir sed sort tee test touch true uname xargs yes
以这种方式区分命令的原因是为了制作二进制包。通常,二进制包包含所有需要安装的可执行文件和其他文件,并且有自己的安装方法,因此不需要运行正常的安装命令。但是安装二进制包确实需要执行安装前和安装后命令。
构建二进制包的程序通过提取安装前和安装后命令来工作。下面是提取预安装命令的一种方法(需要
make -s -n install -o all PRE_INSTALL=pre-install POST_INSTALL=post-install NORMAL_INSTALL=normal-install | gawk -f pre-install.awk
其中文件预安装。Awk可以包含以下内容:
$0 ~ /^(normal-install|post-install)[ ]*$/ {on = 0} on {print $0} $0 ~ /^pre-install[ ]*$/ {on = 1}
7.9 制作发布
您应该用一对版本号来标识每个版本,一个主要版本和一个次要版本。我们不反对使用两个以上的数字,但你不太可能真的需要它们。将
构建和安装程序不应该修改发行版中包含的任何文件。这意味着以任何方式构成程序一部分的所有文件必须分为源文件和非源文件。源文件是由人类编写的,永远不会自动更改;非源文件是由Makefile控制下的程序从源文件生成的。
发行版应该包含一个名为README的文件,其中包含软件包的总体概述:
- 包的名称。
- 包的版本号,或指在包中可以找到版本的位置。
- 对包装功能的一般描述。
- 对文件INSTALL的引用,其中应该包含对安装过程的解释。
- 任何不寻常的顶级目录或文件的简要解释,或其他提示读者找到他们的方式在源代码。
- 对包含复制条件的文件的引用。如果使用了
GNU GPL ,应该在一个名为“COPYING”的文件中。如果使用GNU LGPL ,它应该在一个名为copy.lesser 的文件中。
当然,所有的源文件都必须在发行版中。在发行版中包含非源文件以及生成它们的源文件是可以的,只要它们与生成它们的源文件是最新的,并且与机器无关,这样发行版的正常构建就永远不会修改它们。我们通常包含Autoconf、Automake、Bison、flex、TEX和makeinfo生成的非源文件;这有助于避免发行版之间不必要的依赖,这样用户就可以安装他们喜欢的任何版本的软件包。不要轻易地诱导对其他软件的新依赖。
可能在构建和安装程序时被实际修改的非源文件不应该包含在发行版中。因此,如果要发布非源文件,在发布新版本时一定要确保它们是最新的。
确保发行版中的所有文件都是全球可读的,并且目录是全局可读(world-readable)和全局可搜索(world-searchable)(八进制模式755)。我们过去常常建议发行版中的所有目录都是全局可写的(八进制模式777),因为旧版本的tar在以非特权用户提取存档时将无法处理。但是,在创建存档时,这很容易导致安全问题,所以现在我们建议不要这样做。
不要在发行版中包含任何符号链接。如果tar文件包含符号链接,那么人们甚至无法在不支持符号链接的系统上解压缩它。另外,不要为不同目录中的一个文件使用多个名称,因为某些文件系统无法处理这种情况,这会阻止解压缩发行版。
尽量确保所有的文件名在
在您的发行版中包含
8. 引用非自由软件和文档
8.1 自由软件的道德思想
GNU程序不应该推荐、促进或授予使用任何非自由程序的合法性。专有软件是一个社会和道德问题,我们的目标是结束这个问题。我们不能阻止一些人编写专有程序,或者阻止其他人使用它们,但是我们可以而且应该拒绝向新的潜在客户宣传它们,或者拒绝给公众留下它们存在是合法的印象。
自由软件的GNU定义可以在GNU网站上找到,自由文档的定义可以在https://www.gnu.org/philosophy/free-doc.html找到。本文档中使用的术语“free”和“non-free”是指那些定义。
重要许可证的列表以及它们是否符合免费的条件见https://www.gnu.org/licenses/license-list.html。如果不清楚一个许可证是否符合自由的条件,请写信给[email protected]询问GNU工程。我们会回答,如果许可证是重要的,我们会将其添加到列表中。
当一个非自由的程序或系统是众所周知的,您可以顺便提到它,这是无害的,因为可能想要使用它的用户可能已经知道它了。例如,解释如何在一些广泛使用的非自由操作系统上构建您的包,或者如何与一些广泛使用的非自由程序一起使用它,在首先解释如何在GNU系统上使用它之后,这是很好的。
但是,您应该只提供必要的信息,以帮助那些已经使用非自由软件的人与它一起使用您的程序,不要提供或引用任何关于专有程序的进一步信息,也不要暗示专有程序增强了您的程序,或者它的存在在任何方面都是一件好事。目标应该是已经在使用专有程序的人将得到他们需要的关于如何与它一起使用您的自由程序的建议,而那些还没有使用专有程序的人将看不到任何可能导致他们对它感兴趣的东西。
你不应该为非自由程序推荐任何非自由的附加组件,但是可以提到帮助它与你的程序一起工作的免费附加组件,以及如何安装免费附加组件,即使这需要运行一些非自由程序。
如果一个非自由程序或系统在您的程序领域中是模糊的,您的程序不应该提及或支持它,因为这样做会倾向于普及非自由程序,而不是普及您的程序。(如果想要使用您的程序的人通常不知道Foobar的存在,那么您就不能指望在Foobar的用户中为您的程序找到许多其他用户)。
有时一个程序本身是自由软件,但它依赖于一个非自由平台来运行。例如,过去很多Java程序依赖于一些非自由的Java库。(见https://www.gnu.org/philosophy/java-trap.html)。推荐或推广这样一个节目就是推广它所需要的其他节目;因此,法官提到前者就好像提到后者一样。出于这个原因,我们小心翼翼地在自由软件目录中列出Java程序:我们希望避免推广非自由的Java库。
Java不再有这个问题,但总的原则将保持不变: 不推荐、推广或合法化依赖于非自由软件运行的程序。
一些自由软件强烈鼓励使用非自由软件。一个典型的例子就是mplayer。它本身就是自由软件,自由代码可以处理某些类型的文件。
然而,mplayer建议使用非免费的编解码器来处理其他类型的文件,并且安装mplayer的用户很可能会同时安装这些编解码器。实际上,推荐mplayer是为了促进非自由编解码器的使用。
因此,你不应该推荐那些强烈鼓励使用非自由软件的程序。这就是为什么我们没有在自由软件目录中列出mplayer。
GNU软件包不应该让用户参考任何自由软件的非自由文档。可以包含在自由操作系统中的自由文档对于完成GNU系统或任何自由操作系统是必不可少的,因此鼓励它是优先考虑的; 推荐使用我们不允许包含的文档会破坏社区产生我们可以包含的文档的动力。因此GNU软件包不应该推荐非自由文档。
相比之下,在一个程序的注释中引用期刊文章和教科书来解释它是如何工作的是可以的,即使它们是非自由的。这是因为我们不会在GNU系统中包含这些东西,即使它们是免费的,它们超出了软件发行版需要包含的范围。
引用描述或推荐非自由程序的网站是在推广该程序,因此请不要链接(或提及名称)包含此类材料的网站。这个策略特别适用于GNU软件包的网页。
那么链接链呢?点击几乎任何网站的链接都可能最终导致非自由软件的推广;这是网络固有的特性。我们是这样对待的。
你不应该参考
但是,如果
如果一个网页需要用户运行该程序才能使用该网页,那么它会以一种隐式但特别强烈的方式推荐该程序。许多页面包含
如果不运行非自由
极端的情况是那些依赖非免费
相反,请从页面中引用摘录来说明你的观点,或者找另一个地方引用这些信息。
8.2 GNU Free Documentation License
原文请参考standards.pdf (gnu.org)第8章内容。
Appendix A GNU Free Documentation License Version 1.3, 3 November 2008 Copyright c 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. https://fsf.org/ Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
0. 前序(PREAMBLE)
本许可证的目的是使手册、教科书或其他功能和有用的文档在自由的意义上是自由的:确保每个人都有有效的自由来复制和重新发布它,无论是否修改它,无论是商业还是非商业。其次,本许可证为作者和出版者保留了一种获得作品荣誉的方式,同时不被认为对其他人所做的修改负责。
本许可证是一种"copyleft”,这意味着文档的衍生作品本身必须在同样的意义上是自由的。它是对GNU通用公共版的补充许可证,这是一个为自由软件设计的copyleft许可证。
我们设计本许可证是为了将它用于自由软件的手册,因为自由软件需要自由的文档:一个自由的程序应该附带提供与该软件相同的自由的手册。但本许可证并不局限于软件手册;它可以用于任何文本工作,无论主题或是否作为印刷书籍出版。我们主要将此授权推荐给以指导或参考为目的的作品。
1. 效力与定义(APPLICABILITY AND DEFINITIONS)
本许可证适用于任何媒介上的任何手册或其他作品,只要该作品包含版权所有者发布的声明,说明它可以根据本许可证的条款进行分发。这样的通知授予在此所述条件下使用该作品的全球性、免版税、无限期的许可。下文的“文件”是指任何此类手册或作品。任何公众成员都是被许可人,并被称为“您”。如果您以版权法下需要许可的方式复制、修改或分发作品,则表示您接受该许可。
文件的“修改版本”是指包含文件或其部分内容的任何作品,无论是逐字复制,还是经过修改和/或翻译成另一种语言。
“次要部分”是文档的命名附录或前端内容部分,专门处理文档的发布者或作者与文档总体主题(或相关事项)的关系,并且不包含任何可以直接属于该总体主题的内容。(因此,如果文件的一部分是数学教科书,第二部分可能不解释任何数学。)这种关系可以是与主题或相关事项的历史联系,也可以是关于它们的法律、商业、哲学、伦理或政治立场。
“不变章节”是某些次要章节,其标题被指定为在声明文档已经发布的通知中,是那些不变章节在本许可证下。如果一个章节不符合上述二级的定义,那么它就是二级的不允许被指定为不变式。文档可以不包含不变量部分。如果文档没有标识任何不变节,那么就没有。
“封面文本”是列出的某些短段落的文本,作为前封面文本或封底文本,在声明文件根据本许可证发布的通知中。封面文字最多可以有5个单词,封底文字最多可以有25个单词。
文件的“透明”副本是指一种机器可读的副本,以一种公众可获得的格式表示,这种格式适用于使用通用文本编辑器或(对于由像素组成的图像)通用绘画程序或(对于绘图)某些广泛使用的绘图编辑器直接修改文档,并且适用于输入文本格式化器或自动翻译为适合输入文本格式化器的各种格式。以透明文件格式制作的副本,其标记(或没有标记)已被安排以阻止或阻止读者的后续修改,则不是透明的。如果用于大量文本,图像格式就不是透明的。非“透明”的副本称为“不透明”。
透明副本的合适格式示例包括没有标记的纯ASCII、Texinfo输入格式、LaTEX输入格式、使用公开可用DTD的SGML或XML,以及为人为修改而设计的符合标准的简单HTML、PostScript或PDF。透明图像格式的例子包括PNG、XCF和JPG。不透明格式包括只能由专有文字处理器读取和编辑的专有格式、DTD和/或处理工具通常不可用的SGML或XML,以及由某些文字处理器生成的仅用于输出目的的机器生成的HTML、PostScript或PDF。
对于印刷书籍,“扉页”是指扉页本身,以及用于清晰地容纳本许可证要求出现在扉页上的材料的下列页面。对于没有标题页的作品,“标题页”是指在作品标题最显眼的地方,在正文开始之前的文本。
“发布者”系指向公众分发本文件副本的任何个人或实体。
“标题为XYZ”的部分是指文档的命名子单元,其标题精确地为XYZ,或者在将XYZ翻译成另一种语言的文本后面的括号中包含XYZ。(这里XYZ代表下面提到的特定部分名称,例如“致谢”、“奉献”、“背书”或“历史”。)当您修改文档时,“保留这样一个部分的标题”意味着根据这个定义,它仍然是一个“标题为XYZ”的部分。
文件可以在声明本许可证适用于文件的通知旁边包括保证免责声明。这些保证免责声明被视为包含在本许可证中,但仅涉及放弃保证:这些保证免责声明可能具有的任何其他含义都是无效的,并且对本许可证的含义没有影响。
2. 逐字的复制(VERBATIM COPYING)
您可以在任何媒介上复制和分发文档,无论是商业的还是非商业的,前提是本许可证、版权声明以及说明本许可证适用于本文档的许可证通知在所有副本中都被复制,并且您没有在本许可证的那些条件中添加任何其他条件。您不得使用技术手段阻碍或控制您制作或分发的副本的阅读或进一步复制。但是,您可以接受补偿,以换取副本。如果您发布了足够多的副本,您还必须遵守第3节中的条件。
您也可以在上述相同条件下出借副本,并且您可以公开展示副本。
3. 大量地复制(COPYING IN QUANTITY)
如果您发布文档的印刷副本(或通常具有印刷封面的媒体副本),数量超过100个,并且文档的许可声明要求封面文字,则您必须将副本装入封面中,并清晰易读地携带所有这些封面文字:封面上的前封面文字,封底上的后封面文字。这两个封面也必须清楚清楚地表明你是这些副本的出版商。封面必须呈现完整的标题,标题的所有单词同样突出和可见。你可以在封面上添加其他材料。只要保留文件的标题并满足这些条件,仅限于封面的复制就可以被视为在其他方面的逐字复制。
如果任何一个封面所需的文字都太大而无法清晰地容纳,您应该将列出的第一个(尽可能多地适合)放在实际封面上,并将其余的继续放在相邻的页面上。
如果您发布或分发文档的不透明副本的数量超过100个,则您必须在每个不透明副本中包含一份机器可读的透明副本,或者在每个不透明副本中或在每个不透明副本中声明一个计算机网络位置,以便一般使用网络的公众可以使用公共标准网络协议从该位置下载文档的完整透明副本,且不添加任何材料。如果您使用后一种选择,当您开始大量分发不透明副本时,您必须采取合理的谨慎措施,以确保在您最后一次向公众分发该版本的不透明副本(直接或通过您的代理商或零售商)一年后,该透明副本在指定地点仍可获得。
请求,但不是必须,您在重新分发任何大量副本之前与文件的作者联系,让他们有机会为您提供文件的更新版本。
4. 修改(MODIFICATIONS)
您可以在上述第2节和第3节的条件下复制和分发文件的修改版本,前提是您完全按照本许可证发布修改版本,并且修改版本承担文件的角色,从而将修改版本的分发和修改许可给任何拥有其副本的人。此外,您必须在修改版本中做这些事情:
- 在扉页(和封面,如果有的话)使用与正文不同的标题文档,并从以前的版本(如果有的话,应该在文档的历史部分列出)。如果该版本的原始出版商给予许可,您可以使用与先前版本相同的标题。
- 作为作者,在标题页上列出一个或多个负责修改版本的作者身份的个人或实体,以及至少五位文件的主要作者(如果少于五位,则为所有主要作者),除非他们免除了此要求。
- 在标题页写明修改版本的发布者的名称,作为发布者。
- 保存文件的所有版权声明。
- 在其他版权声明旁边为您的修改添加适当的版权声明。
- 在版权声明之后,立即附上一份许可声明,允许公众在本许可的条款下使用修改后的版本,格式如下面的附录所示。
- 在该许可通知中保留不变章节的完整列表和所需的封面文档许可声明中给出的文本。
- 包括一份未经修改的本许可证副本。
- 保留标题为“历史”的部分,保留其标题,并在其中添加一个项目,至少说明标题页上给出的修改版本的标题,年份,新作者和出版商。如果文档中没有标题为“历史”的部分,则创建一个说明文档标题页上给出的标题、年份、作者和出版商的部分,然后添加一个描述前面句子中所述的修改版本的项。
- 保留文档中给出的网络位置(如果有的话),以供公众访问文档的透明副本,同样地,保留文档中给出的先前版本所基于的网络位置。这些可以放在“历史”一节。您可以省略在文档本身发布至少四年之前发布的作品的网络位置,或者如果它所引用的版本的原始出版商给予许可。
- 对于任何标题为“致谢”或“奉献”的部分,保留该部分的标题,并在该部分中保留每个贡献者致谢和/或奉献的所有内容和语气。
- 保留文件中所有不变章节,文本和标题保持不变。章节编号或同等内容不被视为章节标题的一部分。
- 删除任何标题为“背书”的部分。该部分不得包括在修改版本中。
- 不要将任何现有章节重新命名为“背书”,也不要将标题与任何不变章节冲突。
- 保留任何保证免责声明。
如果修改版本包含新的前置性章节或附录,这些章节或附录符合次要章节的资格,并且不包含从文档复制的材料,您可以选择指定这些章节中的一些或全部为不变章节。要做到这一点,将它们的标题添加到修改版本许可声明中的不变章节列表中。这些标题必须区别于任何其他章节标题。
您可以添加一个标题为“认可”的部分,只要它只包含各方对您的修改版本的认可-例如,同行评审的声明或文本已被某个组织批准为标准的权威定义。
您可以在修改版本的封面文本列表的末尾添加一段最多五个单词的前封面文本,以及一段最多25个单词的后封面文本。任何一个实体(或通过其安排)只能增加一段封面文字和一段封底文字。如果文件已包含由你或由你所代表的同一实体所作安排而先前添加的同一封面的封面文字,则你不得再添加另一封面文字;但是,您可以替换旧版本,但必须得到添加旧版本的前一个出版商的明确许可。
文档的作者和发布者不允许使用他们的名字进行宣传,或声称或暗示对任何修改的认可的版本。
5. 组合文件(COMBINING DOCUMENTS)
您可以将本文档与在本许可证下发布的其他文档结合起来,根据上面第4节中为修改版本定义的条款,只要您在组合中包含所有原始文档的所有不变部分,未经修改,并在其许可声明中将它们全部列为组合作品的不变部分,并且您保留所有它们的保证免责声明。
合并后的作品只需要包含本许可证的一个副本,并且多个相同的不变章节可以用一个副本替换。如果有多个具有相同名称但内容不同的不变章节,则通过在其末尾添加括号中已知的该章节的原作者或出版商的名称,或其他唯一数字,使每个此类章节的标题唯一。对合并作品的许可声明中恒常章节列表中的章节标题进行相同的调整。
在合并时,您必须将各种原始文件中标题为“历史”的任何部分合并,形成一个标题为“历史”的部分;同样地,将任何标题为“致谢”的部分和任何标题为“奉献”的部分结合起来。您必须删除所有标题为“背书”的部分。
6. 文件集合(COLLECTIONS OF DOCUMENTS)
您可以将本文件和在本许可证下发布的其他文件组成一个集合,并将本许可证在各种文件中的单个副本替换为包含在集合中的单个副本,前提是您遵循本许可证的规则,在所有其他方面逐字复制每个文件。
您可以从这样的集合中提取单个文档,并在本许可证下单独分发它,只要您在提取的文档中插入本许可证的副本,并在有关该文档的逐字复制的所有其他方面遵循本许可证。
7. 独立作品的聚合(AGGREGATION WITH INDEPENDENT WORKS)
将文件或其衍生文件与其他单独和独立的文件或作品汇编在存储或分发介质的卷中或在卷上,如果汇编产生的版权不用于限制汇编用户的合法权利超出单个作品允许的范围,则称为“集合”。当文档包含在集合中时,本许可不适用于集合中其他本身不是文档派生作品的作品。
如果第3条的封面文字要求适用于这些文件副本,那么如果文件小于整个集合体的一半,则文件的封面文字可以放置在集合体内支撑文件的封面上,或者如果文件是电子形式的,则可以放置在电子等价物的封面上。否则,它们必须出现在支撑整个聚集体的印刷封面上。
8. 翻译(TRANSLATION)
翻译被认为是一种修改,因此您可以根据第4节的条款发布文档的翻译。用翻译替换不变章节需要获得其版权所有者的特别许可,但是除了这些不变章节的原始版本之外,您可以包括部分或所有不变章节的翻译。您可以在文件中包括本许可证、所有许可证声明和任何保证免责声明的翻译,前提是您还包括本许可证的原始英文版本以及这些声明和免责声明的原始版本。如果本许可证的翻译版本与原版本、通知或免责声明有不一致之处,以原版本为准。
如果文件中的某部分标题为“致谢”、“奉献”或“历史”,则要求(第4节)保留其标题(第1节)通常需要更改实际标题。
9. 结尾(TERMINATION)
除非本许可证明确规定,否则您不得复制、修改、再许可或分发本文件。任何以其他方式复制、修改、再许可或分发它的企图都是无效的,并且将自动终止您在本许可下的权利。
但是,如果您停止所有违反本许可的行为,那么您从特定版权所有者处获得的许可将(a)暂时恢复,除非版权所有者明确并最终终止您的许可,以及(b)永久恢复,如果版权所有者未能在终止后60天内以某种合理的方式通知您违规行为。
此外,如果版权所有者以某种合理的方式通知您违反了本许可证,这是您第一次从该版权所有者那里收到违反本许可证的通知(对于任何作品),并且您在收到通知后30天内纠正了违规行为,则您从特定版权所有者处获得的许可将永久恢复。
终止您在本节项下的权利并不会终止从您处获得本许可的副本或权利的各方的许可。如果您的权利已被终止且未永久恢复,则收到部分或全部相同材料的副本并不赋予您使用该材料的任何权利。
10. 本许可证的未来修订版(FUTURE REVISIONS OF THIS LICENSE)
自由软件基金会可以发布GNU自由软件的新修订版本的文件许可。这些新版本将在精神上与当前版本相似,但可能在细节上有所不同,以解决新的问题或关注点。见https://www.gnu.org/licenses/。
许可证的每个版本都有一个不同的版本号。如果文档指定本许可证的特定编号版本“或任何更新版本”适用于它,您可以选择遵循该指定版本或自由软件基金会发布的任何更新版本(不是草案)的条款和条件。如果文档没有指定本许可证的版本号,您可以选择自由软件基金会曾经发布过的任何版本(不是草稿)。如果文件指定代理可以决定本许可证的哪个未来版本可以被使用,那么该代理接受某个版本的公开声明将永久授权您为文件选择该版本。
11. 重新获得许可证( RELICENSING)
“大规模多作者协作站点”(或“MMC站点”)指任何世界性的发布受版权保护的作品并为任何人编辑这些作品提供显著便利的Web服务器。任何人都可以编辑的公共wiki就是这种服务器的一个例子。本网站包含的“大规模多作者合作”(或“MMC”)是指在MMC网站上发布的任何一组具有版权的作品。
“CC-BY-SA”是指由Creative Commons Corporation(一家主要营业地点位于加利福尼亚州旧金山的非营利公司)发布的知识共享署名-相同方式共享3.0许可协议,以及该组织发布的该许可协议的未来copyleft版本。
“合并”系指作为另一文件的一部分,全部或部分地发布或重新发布一份文件。
一个MMC“有资格获得再授权”,如果它是在本许可证下授权的,并且如果所有作品在本许可证下首次在其他地方发布,随后全部或部分并入MMC,(1)没有封面文本或不变章节,并且(2)因此在2008年11月1日之前并入MMC。
MMC网站的运营商可以重新发布包含在以下网站中的MMC,CC-BY-SA在2009年8月1日之前的任何时间在同一地点,只要MMC有资格重新颁发许可证。
8.3 添加许可证
要在您编写的文档中使用本许可证,请在文档中包含一份许可证副本,并在标题页后面放置以下版权和许可证声明:
Copyright (C) year your name. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled ‘‘GNU Free Documentation License’’.
如果你有固定章节,前封底文字和后封底文字,替换“with…Texts“。一行是这样的:
with the Invariant Sections being list their titles, with the Front-Cover Texts being list, and with the Back-Cover Texts being list.
如果你有没有封面文本的不变章节,或者这三者的其他组合,将这两种选择合并以适应情况。如果您的文档包含重要的程序代码示例,我们建议在您选择的自由软件许可证下并行发布这些示例,例如GNU通用公共许可证,允许它们在自由软件中使用。