应用程序打包技术之四(exe篇)

1. 应用程序打包技术之一(源代码篇)
2. 应用程序打包技术之二(deb篇)
3. 应用程序打包技术之三(rpm 篇)
4. 应用程序打包技术之四(exe篇)

exe 是 Windows 下通用应用程序的后缀,因此也是 Windows 下安装程序的后缀,我就以 exe 篇来命名这篇文章吧。

我们在 Windows 下写程序,尤其是带有图形界面的应用程序,往往不仅需要一个可执行的 exe 文件,还需要一些辅助的 dll 或者资源文件。一般情况下,我们可以采用打包整个目录的方式来发布软件(也是目前很多所谓“绿色软件”的做法),当然我们也可以发布传统的 Windows 安装文件。这样用户不需要额外的解压缩软件,双击执行安装文件就可以安装软件。

HM NIS Edit

将 Win 下应用程序打包成安装文件的方法有很多,这里我们主要介绍一个开源的安装文件制作工具 NSIS(Nullsoft Scriptable Install System)。比如我们耳熟能详的软件 WiNamp 和 eMule 的安装文件,就是使用 NSIS 生成的。它的主页在http://nsis.sourceforge.net,您可以从它的主页下载到最新版本。

NSIS 是一个基于脚本的安装文件制作工具,因此我们必须写好一个脚本提供给它执行。总是要学一些“微语言”真是麻烦的事情,幸好我们还有 HM NIS Edit,一个开源的 NSIS 脚本编辑工具。使用 HM NIS Edit,我们可以一步一步地按照向导生成 NSIS 所需的脚本。因此,我们这篇文章其实主要是介绍 HM NIS Edit 的使用,和 NSIS 的部分脚本格式。使用 NSIS 脚本生成安装文件那一步,实在是太简单不过了,点一下鼠标或者敲一个命令而已。

假设我们要为 foo 程序生成一个安装文件,在打包之前您应该将 foo 的可执行程序、所需 dll 和资源文件等放在一个文件夹 foo 中。比如假设 foo 程序的目录是这样的。

D:>tree /F foo
D:FOO
│  foo.dll
│  foo.exe
│  licence.txt
│
└─image
        foo.ico

下面我们就可以使用 HM NIS Edit 来创建 NSIS 脚本了。启动 HM NIS Edit,在 File 菜单中选择 New script from wizard 脚本生成向导,点击 Next 下一步,进入程序信息页。

Application name 程序名这里我们填入要打包的程序名 "foo";Application version 程序版本我们填入 foo 的版本,比如 "1.0";Application publisher 发布者我们填程序的开发公司名或者自己的名字,比如 "张三";Application website 程序主页我们填程序的主页名,没有主页的就可以不填。然后点击下一步进入安装文件选项页。

Setup icon 安装图标是您希望您的安装文件长什么样子,而不是您应用程序的图标,一般选择默认即可;Setup file 是您希望安装文件叫什么名字,比如 "foo-1.0-setup.exe";Setup lang 安装程序语言是安装过程中的提示所使用的语言,您可以根据您的需要选择,比如简体中文 "SimpChinese";GUI 是安装文件的对话框风格,随便您喜欢哪种;Compress 压缩格式是您希望使用什么格式将应用程序压缩存放在安装文件中。然后点击下一步进入应用程序默认安装目录和协议页。

Application default directory 里面填您的应用程序默认安装到哪里,比如 $PROGRAMFILESfoo 是默认安装到 C:Program Filesfoo 目录下,最好勾选上 Allow user to change the application directory,允许用户更改安装目录,这样您的程序显得更人性化一点儿;License file 是指应用程序所使用的协议文本,如果您在 foo 目录下已经准备了协议文件 license.txt,那么直接填 licence.txt 即可。这个协议就是您通常在 Windows 下安装软件时,第一个页面提示的“是否同意上述协议”的“上述协议”文本框里的内容;下面几个选项是让用户选择如何接受协议。点击下一步,进入应用程序文件选择页。

在应用程序文件选择页中会有三个文本框。这个页面的作用是分组添加应用程序所需要的程序文件,这样用户安装时就可以通过选择“最小安装”、“完全安装”、“自定义”等选择安装不同的组件。左上方的文本框是组件框,右下方的文本框是组件信息说明框,右方最大的文本框是每个组件所包含的可执行、dll 和资源文件。如果我们的程序很简单,不用分什么组件,我们就只用一个 MainSection 就行了。点中左上方文本框中的 MainSection,在右侧将所有程序文件添加进去。由于我们已经将所有文件都放置在了 D:foo 目录下,我们只需要点选第二个图标:Add directory tree,在对话框中将源目录选择为 F:Moviefoo,目标目录选择为 $INSTDIR,这样 foo 下所有的文件和目录都将会被安装到 $INSTDIR(默认是 C:Program Filesfoo)目录下。确定之后返回文件选择页,点击下一步进入应用程序图标页。

应用程序图标页的主要作用是选择将会被安装到“桌面”和“开始”菜单的快捷方式指向的可执行程序。如果您的程序名和项目名一样,或者 foo 目录下只有一个 exe 可执行文件,此处就使用默认设置即可。Create an Internet shortcut in the Start Menu folder 的意思是在“开始”菜单中添加一个到软件主页的快捷方式;Create an Uninstall shortcut in the Start Menu folder 的意思是在“开始”菜单中添加一个到卸载程序快捷方式。点击下一步进入安装后执行设置页。

安装后执行的意思是当安装程序安装完成后,用户选择安装后直接启动应用程序或者查看自述文件时,程序的行为。如果您有自述文件,就在 Readme 中填入自述文件的名字,比如 readme.txt,如果没有,就什么也不填,直接进入下一步程序卸载选项。

如果您选择了使用卸载程序 Use uninstaller,NSIS 将会为您自动生成一个卸载程序,其选项使用默认即可。点击下一步进入结束页。

最后结束时,HM NIS Edit 会询问您是否保存脚本。当然要保存了,保存了以后再需要生成安装文件时就不必使用 HM NIS Edit 重新生成脚本了。Convert file paths to relative paths 将脚本中的文件路径修改成相对于脚本文件的路径,这个选项也最好选上,这样在更改 foo 的目录时,我们只需要 NSIS 脚本与 foo 的相对位置不变就不影响脚本的使用。接下来保存脚本文件,最好将脚本文件保存在 foo 目录下,这样以后需要重新生成安装文件,只需要将 NSIS 拷贝到 foo 目录下就可以编译了。比如取名为 foo.nsi。

这样,整个脚本文件我们已经编写好了。现在我们到 D:foo 目录下,就能发现一个 foo.nsi 文件,右键点击 foo.nsi,在下拉菜单中选择 Compile NSIS script,不出错的话,就能在当前目录下生成一个名为 foo-1.0-setup.exe 安装文件了。您可以双击执行一下它,看看安装过程是否如您所料。

我们也可以使用命令行编译 NSIS 脚本,您可以使用这个命令:

C:Program FilesNSISmakensis.exe foo.nsi

如果您将 C:Program FilesNSIS 添加到了 PATH 环境变量中,就可以直接使用 makensis.exe foo.nsi 来编译了。

小技巧:

1. 当生成 NSIS 脚本之后,我们想修改设置,不需要重新执行一遍脚本生成向导。只需要用文本编辑器打开 foo.nsi,找到相应的域,更改设置即可。

2. NSIS 是一个相当强大的安装文件生成器,但是使用 HM NIS Edit 脚本生成向导生成的脚本并不具有很灵活的定制性。如果您需要更多特性,请阅读 NSIS 用户手册,您能从网上搜索到该手册的中文版本。然后直接去修改 NSIS 脚本。

3. 用 NSIS 产生的卸载程序有可能会产生卸载不干净的现象,主要原因是 NSIS 卸载程序不支持递归删除目录。如果您想要它把所有文件和目录都删除的话,就需要在 Section Uninstall 中将所有程序可能会生成的文件和目录都添加进去,这样生成的卸载程序就能卸载全部文件和目录了。

4. 您可以在这里找到更漂亮的图文教程。

应用程序打包技术之三(rpm 篇)

1. 应用程序打包技术之一(源代码篇)
2. 应用程序打包技术之二(deb篇)
3. 应用程序打包技术之三(rpm 篇)
4. 应用程序打包技术之四(exe篇)

rpm 是 RedHat 系 Linux 使用的软件包格式。流行的 Linux 发行版:Fedora, RHEL, OpenSUSE, Oracle 包括国产的红旗 Linux,都采用 rpm 来管理软件包。

我不是很喜欢 rpm 软件包格式,原因主要有两个,一个是它的依赖关系很难处理,另一个是控制文件比较复杂。但是 rpm 包有着非常广泛的应用,也是一个提高生产力的重要工具。

像前一篇文章提到的一样,checkinstall 也可以用来打 rpm 包,但我不是很熟悉这个软件。这里我仅仅介绍如何使用原始的 rpm(rpmbuild) 工具来打 rpm 软件包。

和前面 deb 包使用 fakeroot 一样,rpmbuild 也是利用沙盒的方式来构建软件包,除了控制文件比较繁琐,过程可能还更自动一些。构建 rpm 包的工作目录默认是 /usr/src/redhat,如果您在 Debian 下安装了 rpm 这个软件包,它可能是 /usr/src/rpm。您可以使用 rpm --eval %_topdir 查看自己的 rpm 工作目录。

$ tree `rpm --eval %_topdir`
/usr/src/redhat
|-- BUILD
|-- RPMS
|   |-- athlon
|   |-- i386
|   |-- i486
|   |-- i586
|   |-- i686
|   `-- noarch
|-- SOURCES
|-- SPECS
`-- SRPMS

我们可以看到,/usr/src/redhat/ 下有几个子目录:SOURCES 用来存放源代码包,SPECS 用来存放 spec 控制文件,BUILD 用来解压源代码包和构建软件,RPMS 里存放的是打好的二进制应用程序 RPM 包,SRPMS 里存放的是打好的源代码 RPM 包。但是,我们应该知道 _topdir 是可以在 spec 文件中修改的,否则我们只能用 root 才能在默认的工作目录 /usr/src/redhat 下创建文件和执行命令。我们可以先把工作目录树拷贝到用户自己的目录中:

$ cp -r /usr/src/redhat ~/rpm

这样,我们就可以在用户目录 ~/rpm 下打 rpm 包了。打 rpm 包之前的准备工作只有两件:1. 准备好源代码包并放置在 SOURCES 目录下;2. 准备好 spec 控制文件并放在 SPECS 目录下。如何打源代码包我们已经在 《源代码篇》中介绍过,下面我们主要来介绍 spec 文件的格式。下面是一个实例 spec 文件。

$ more ~/rpm/SPECS/casnet.spec
%define   _topdir    /home/solrex/rpm
Name:     casnet
Version:  1.3
Release:  1
License:  GPL
Packager: Solrex Yang
Summary:  CASNET Client
Group:    Network
Source:   %{name}-%{version}.tar.gz
URL:      http://share.solrex.org/casnet/
Prefix:   /usr

%description
CASNET is a gui client for ip gateway of GUCAS(Graduate University of Chinese
Academy of Sciences), which is written in Python and PyGtk.

%prep
%setup -q

%build

%install
make -e PREFIX=%{prefix} install

%files
%{prefix}/bin/casnetconf
%{prefix}/bin/casnet
%{prefix}/bin/casnet-gui
%{prefix}/share/casnet/casnetconf.py
%{prefix}/share/casnet/casnet.py
%{prefix}/share/casnet/casnet-gui.py
%{prefix}/share/casnet/pics/*.png
%{prefix}/share/applications/casnet.desktop
%{prefix}/share/icons/casnet.png

我们可以看到,spec 文件与 deb 包的 control 文件有很多相似之处:Name, Version, Release, License, Packager, URL 是软件的名称、版本、小版本、使用的协议、维护者和网址;Summary 和 %description 是软件的信息;Group 是软件所归类别。剩下的就有些不同了:Source 是指软件的源代码包名称,rpm 会到 SOURCES 目录下找这个包;Prefix 是软件的默认安装位置;%prep、%build、%install 下分别是软件的预处理、编译和安装命令;%files 是所有需要被打包进去的文件。

因此,作者需要将 spec 文件中的各个域填写正确。%prep 下的 %setup 宏一般是用来将源代码 tar 包释放到 BUILD 目录下;%build 下可以添加 %configure 宏和 make 命令,如果您的软件需要编译的话;%install 下是您的安装命令;%files 下是您程序运行所需要的全部文件,其路径即为您安装完软件后它应该在的位置。%{name} 可以用来指代 Name: 域的内容,%{version } 指代 Version: 域的内容,以此类推。

需要注意的是,rpmbuild 使用 BUILD/%{name}-%{version} 作为您的源代码包释放后的目录,进入其进行编译。因此当您使用 tar 打源代码包时,tar 包的顶层目录名应该为 %{name}-%{version} 而不是仅仅是 %{name},比如:

$ tar czvf casnet-1.3.tar.gz casnet-1.3
$ mv casnet-1.3.tar.gz ~/rpm/SOURCES

现在我们在 ~/rpm/SOURCES 下有了 casnet-1.3.tar.gz,在 ~/rpm/SPECS 目录下有了 casnet.spec,那么我们就可以使用下面的命令生成 rpm 包了。如果您的安装位置 Prefix 选择的是一个系统目录,比如 /usr, /usr/local 之类,您也许需要使用 root 权限来运行 rpmbuild 命令。

$ rpmbuild -ba ~/rpm/SPECS/casnet.spec

这样我们就能在 ~/rpm/RPMS/i386 目录下获得我们生成的 rpm 软件包了。rpmbuild 命令的执行过程是这样的:首先根据 spec 文件定位源代码包,然后将源代码包释放到 BUILD 目录下,使用 spec 文件中给出的命令编译和安装,然后将 spec 中列的文件提取出来,按照包信息打出来 rpm 包。

我们可以使用 rpm -qpi 命令来查看 rpm 包的信息,rpm -qpl 命令来查看 rpm 包所包含的文件列表:

$ rpm -qpi ~/rpm/RPMS/i386/casnet-1.3-1.i386.rpm
Name        : casnet                       Relocations: /usr
Version     : 1.3                               Vendor: (none)
Release     : 1                             Build Date: Thu 26 Feb 2009 08:03:50 PM CST
Install Date: (not installed)               Build Host: laptop
Group       : Network                       Source RPM: casnet-1.3-1.src.rpm
Size        : 40883                            License: GPL
Signature   : (none)
Packager    : Solrex Yang
URL         : http://share.solrex.org/casnet/
Summary     : CASNET Client
Description :
CASNET is a gui client for ip gateway of GUCAS(Graduate University of Chinese
Academy of Sciences), which is written in Python and PyGtk.

$ rpm -qpl ~/rpm/RPMS/i386/casnet-1.3-1.i386.rpm
/usr/bin/casnet
/usr/bin/casnet-gui
/usr/bin/casnetconf
/usr/share/applications/casnet.desktop
/usr/share/casnet/casnet-gui.py
/usr/share/casnet/casnet.py
/usr/share/casnet/casnetconf.py
/usr/share/casnet/pics/casnet.png
/usr/share/casnet/pics/offline.png
/usr/share/casnet/pics/online.png
/usr/share/icons/casnet.png

如果您想了解更详细的内容,您可以进一步参考 Jake's RPM Build Tutorial 这篇文章。

应用程序打包技术之二(deb篇)

1. 应用程序打包技术之一(源代码篇)
2. 应用程序打包技术之二(deb篇)
3. 应用程序打包技术之三(rpm 篇)
4. 应用程序打包技术之四(exe篇)

deb 是 Debian 系 Linux 使用的软件包格式,也是我最欣赏的软件包格式。我所知道的打 deb 软件包的方法有两种,一种是使用 checkinstall,另一种是使用 dpkg。

checkinstall 不仅仅可以用来打 deb 包,还可以打 rpm 和 tgz 包,而且使用方法相对简单。但是 checkinstall 的运行不是那么稳定,我搞不懂它在什么情况下才能正常运行,而且它的定制性不是很强,使用时老是要交互地输入些信息,所以我还是放弃了使用它来打包软件。感兴趣的朋友可以在网上搜索一下这个程序的使用方法。

dpkg 是 Debian 的“原生”包管理软件,但是很多人不太愿意使用 dpkg 来打包 deb。究其原因可能是需要写麻烦的配置文件,但是写配置文件的一个好处就是在下次打包时候可以直接用上次的配置文件,只修改一个版本号就可以了,而不用每次都需要填包信息。在介绍如何打 deb 包之前,我们现看一下如何解 deb 包。

$ sudo apt-get install tree
$ dpkg -X /var/cache/apt/archives/tree_1.5.1.1-1_i386.deb fakeroot
$ cd fakeroot
$ dpkg -e /var/cache/apt/archives/tree_1.5.1.1-1_i386.deb
$ tree
.
|-- DEBIAN
|   |-- control
|   `-- md5sums
`-- usr
    |-- bin
    |   `-- tree
    `-- share
        |-- doc
        |   `-- tree
        |       |-- README
        |       |-- changelog.Debian.gz
        |       |-- changelog.gz
        |       `-- copyright
        `-- man
            `-- man1
                `-- tree.1.gz

dpkg -X 是将 deb 包的内容文件释放出来,dpkg -e 是将 deb 包的控制信息释放出来。前面执行那个 sudo apt-get install tree 是为了将 tree_1.5.1.1-1_i386.deb 下载到本地 apt cache,如果您已经安装过 tree 这个软件,可以为 apt-get 加上 -d 参数,使其只下载而不安装。

从上面 tree 命令的执行结果我们发现,deb 包解开后分两部分:一部分是控制信息,在 DEBIAN 目录下;一部分是安装内容,在 usr 目录下。现在您大概明白为什么我们使用 fakeroot 作为目录名了,因为这个目录就是一个"假根目录",您在这个目录下所有的修改,最后都会被映射到目标机的根目录 / 下。比如 fakeroot/usr/bin/tree 这个文件,就会被安装到 /usr/bin 下,以此类推。

只要您能理解 fakeroot 这个目录映射,您就知道如何安放自己的文件了。为了让生成的包将文件 foo 安装到目录 /usr/xx/yy 目录下,您只用在 fakeroot 目录下建立 usr/xx/yy 目录,并将 foo 拷贝进去就行了。

好,下面进入关键的配置文件部分,关于 control 和 md5sums。

$ more DEBIAN/control
Package: tree
Version: 1.5.1.1-1
Architecture: i386
Maintainer: Ubuntu MOTU Developers
Original-Maintainer: Florian Ernst
Installed-Size: 92
Depends: libc6 (>= 2.6-1)
Section: utils
Priority: optional
Description: displays directory tree, in color
Displays an indented directory tree, using the same color assignments as
ls, via the LS_COLORS environment variable.
.
Homepage: http://mama.indstate.edu/users/ice/tree/

我们可以看到,control 文件中包含的主要是软件的版本和维护者信息,我相信大家都能基本看懂上面这些信息什么意思:Package 包名(tree)、Version 版本(1.5.1.1-1)、Architecture 目标机架构(i386 386及以后)、Maintainer 维护者(Ubuntu MOTU Developers)、Original-Maintainer 原维护者(Florian Ernst)、Installed-Size 安装后大小(92K)、Depends 依赖软件包(libc6 不低于 2.6-1 版本)、Section 包分类(工具)、Priority 优先级(可选)、Description 包描述、Homepage 软件主页。

由于咱们分析这个包是 Ubuntu 发布的包,所以包信息给的比较全,其实并不是上面所有的信息都有必要提供(小声说一句,就算全提供也不是很难吧?除了咱不用的,Original-Maintainer 这种就算了)。关于哪些信息比较重要,以及每个域的具体含义和可选项,可以参考 Debian 的文档 Debian Policy Manual Chapter 5 - Control files and their fields

您也可以依样画葫芦,写一个类似的 control 文件放到 DEBIAN 目录下,提供一些自己软件包的信息,基本有这个配置文件就可以打包了。

$ more DEBIAN/md5sums
d60a3b4736f761dd1108cb89e58b9d4e usr/bin/tree
981ea0343c2a3eb37d5fc8b5ac5562df usr/share/man/man1/tree.1.gz
483a56158a07a730ec60fc36b3f81282 usr/share/doc/tree/README
ea56d78ae0d54693ae8f3c0908deeeff usr/share/doc/tree/copyright
4456e04c3c268eabcd10ee9b949a9b9a usr/share/doc/tree/changelog.gz
ec104db6914cfce2865a0d8c421512bb usr/share/doc/tree/changelog.Debian.gz

md5sums,这文件名一看,就知道是保存着软件包中各文件的 md5 校验值,用来校验软件包是否被损坏了。其实这个文件纯属“腊月三十逮兔子,有它没它都过年”,您可以完全不提供它。

这样呢,我们就准备好了 deb 包的内容文件和控制信息:控制文件放在了 fakeroot/DEBIAN 目录下,内容文件放在 fakeroot/usr 下,目录树就像开头 tree 命令的结果。下面只需要一个命令就能打出来 deb 安装包了:

$ cd ..
$ dpkg -b fakeroot/ foo.deb

这时候当前目录下就出现了 foo.deb。您可以使用 dpkg -I foo.deb 查看 foo.deb 的控制信息,dpkg -c foo.deb 查看 foo.deb 包含了什么文件,sudo dpkg -i 安装 foo.deb。

小技巧:

1. 如果您懒得自己新建一个控制文件和目录树,您完全可以像本文开头那样,找一个简单的软件包,将它的内容和控制信息释放出来,对它进行修改,然后打出来自己的包。

2. 生成 md5sums 文件不是什么难事,您只需要在 fakeroot 目录使用下面这个命令:

$ md5sum `find usr -type f` > DEBIAN/md5sums
或者
$ find usr/ -type f -exec md5sum {} + > DEBIAN/md5sums

3. 将您的可执行文件拷贝到 fakeroot/usr 下并不一定要手动一个个拷。如果您使用 GNU 自动工具集,./configure 时加个参数 --prefix=fakeroot/usr/ 即可;如果您自己写的 Makefile,可以在 Makefile 中使用一个变量 PREFIX=/usr,当您不加参数时,make install 的安装目标就是 /usr 下,您可以使用 Makefile -e PREFIX=fakeroot/usr/ install 来覆盖 Makefile 中的变量设置。

应用程序打包技术之一(源代码篇)

1. 应用程序打包技术之一(源代码篇)
2. 应用程序打包技术之二(deb篇)
3. 应用程序打包技术之三(rpm 篇)
4. 应用程序打包技术之四(exe篇)

相信很多朋友都曾经为方便做某件事写过自己的小程序(像我写过的 casnetsendsms),但很多怕都是藏在深山没人识,最后不了了之,自己也把它们丢在角落里忘记了。

把这些小工具上传到技术论坛或者 CSDN 下载频道之类的网站,还是能收到一些关注的,而且还能攒积分和声望。但是为什么不把它们发布出去呢?估计有几个原因:源代码太乱,编译又挺复杂,不好意思给别人看;二进制程序包不会打,不知道该怎么发布。

因此我打算在本系列文章中分享一下我的程序打包经验,目前来讲计划有四篇:源代码篇、deb 篇、rpm 篇和 exe 篇。这些技术在网上您都能找到,因为我也是从网上学习的,算是一个笔记和汇总吧。如果您有好的批评或建议,不妨在评论中指出,帮助我完善这篇文章。

源代码篇

发行源代码包是件最简单的事情,因此也在最先介绍。有同学会说,打个压缩包不就完了嘛。的确如此,但是在压缩之前您也要有几个注意事项:

1. 删除版本管理目录,比如 .svn,.cvs 之类的目录。像 Subversion 版本管理软件,会在每个目录下都建立名为 .svn 的目录,里面一般保存着目录下文件的最新版本,可以用来 revert 修改。不删除 .svn 目录,会使源代码包臃肿,而且最重要的是可能会有安全隐患。.svn 目录下还包含您的用户名和 SVN 服务器信息,可能您并不想让别人知道。但是如果您网速够快的话,可以重新 svn export 一份,而不是仅仅从您的 svn 树上拷贝一份出来,那就没有 .svn 目录了。

2. 规整一下编译过程,如果编译过程不规范,您应该添加一个 README。如果您的代码不是脚本,很可能是需要用户编译的。如果编译过程规范,*nix(Linux/Unix, CygWin, Mingw 等) 下就是 ./configure, make, make install,用户很容易理解。但如果编译过程不规范,您就最好添加一下 README 或者 INSTALL 文件,指导用户该如何编译。使用 MS VisualStudio 的用户要注意工程文件的整洁性,最好导出一个 Makefile(是的,VS 也可以用 Makefile),这样用户就不必打开项目,在 CMD 命令行用 nmake Makefile 就可以编译了。

3. 删除二进制中间文件。在 *nix 开发者中,这一般不难做到,Makefile 中一般都会写一个 clean 目标;但是 MS VS 用户一般不会注意那些编译时生成的 .obj 文件。源代码包就应该是源代码,最多包含可执行程序和文档,而不应该包含其它任何二进制的文件。否则您的源代码包就会很大,而且对用户也是困扰,到底哪些文件有用呢?

4. 修改编译目标从 debug 版本到 release 版本。*nix 下,这一般意味着 CFLAGS 要改成 -O2 而不是 -g;VS 一般意味着将目标从 debug 转为 release。这样用户生成的可执行程序才能足够小和足够快,他们如果有能力自己调试,会知道如何将选项改回去的。

5. 添加知识产权信息,就是授权协议。小程序大家一般都不在乎,但如果是您在这个项目上花了足够的心血,还是最好选择一个自己喜欢的授权协议。可以将协议声明放在每个源文件的最前注释中,也可以在项目的根目录下放一个 license 文件。

6. 不要用 rar 包。在 Windows 下推荐使用 zip 格式压缩;*nix 下推荐使用 .tar.gz 或者 .tar.bz2 格式。因为这些格式在这些系统上不需要安装额外的软件解压。WinRAR 是一个商业软件,而且 RAR 格式也是受版权保护的。

打包命令:

在 Windows 下,如果您使用开源软件 7-zip 来压缩 zip 包,可以使用这个命令(首先将 7-zip 可执行文件目录添加到 PATH 环境变量中):

7z a foo.zip foo

*nix 下,就是下面几个命令了:

tar czvf foo.tar.gz foo
tar cjvf foo.tar.bz2 foo
zip -r foo.zip foo