文章目录

一、下载并安装CheckInstall

1sudo rpm -ivh checkinstall-1.6.2-1.cnt6.x86_64.rpm
2sudo ln -s /usr/lib64/checkinstall/installwatch.so /usr/lib64/installwatch.so
3sudo ln -s /usr/lib64/checkinstall/checkinstallrc /etc/checkinstallrc
1tar xvf checkinstall-1.6.2.tar.gz

编译会报错:

 1installwatch.c:2942:5: 错误:与‘readlink’类型冲突
 2 int readlink(const char *path,char *buf,size_t bufsiz) {
 3     ^
 4In file included from installwatch.c:41:0:
 5/usr/include/unistd.h:828:16: 附注:‘readlink’的上一个声明在此
 6 extern ssize_t readlink (__const char *__restrict __path,
 7                ^
 8installwatch.c:3080:5: 错误:与‘scandir’类型冲突
 9 int scandir( const char *dir,struct dirent ***namelist,
10     ^
11In file included from installwatch.c:49:0:
12/usr/include/dirent.h:252:12: 附注:‘scandir’的上一个声明在此
13 extern int scandir (__const char *__restrict __dir,
14            ^
15installwatch.c:3692:5: 错误:与‘scandir64’类型冲突
16 int scandir64( const char *dir,struct dirent64 ***namelist,
17     ^
18In file included from installwatch.c:49:0:
19/usr/include/dirent.h:275:12: 附注:‘scandir64’的上一个声明在此
20 extern int scandir64 (__const char *__restrict __dir,

修改源文件installwatch.c: 101行:

1static int (*true_scandir)(	const char *,struct dirent ***,
2				int (*)(const struct dirent *),
3				int (*)(const void *,const void *));

改为:

1static int (*true_scandir)(	const char *,struct dirent ***,
2				int (*)(const struct dirent *),
3				int (*)(const struct dirent **,const struct dirent **));

121行:

1static int (*true_scandir64)(	const char *,struct dirent64 ***,
2				int (*)(const struct dirent64 *),
3				int (*)(const void *,const void *));

改为:

1static int (*true_scandir64)(	const char *,struct dirent64 ***,
2				int (*)(const struct dirent64 *),
3				int (*)(const struct dirent64 **,const struct dirent64 **));

2529行:

1FILE *fopen(const char *pathname, const char *mode) {
2	FILE *result;

改为:

1FILE *fopen(const char *pathname, const char *mode) {
2	FILE *result=0;

2941行:

1#if (GLIBC_MINOR <= 4)
2int readlink(const char *path,char *buf,size_t bufsiz) {
3	int result;
4#else
5ssize_t readlink(const char *path,char *buf,size_t bufsiz) {
6	ssize_t result;
7#endif

改为:

1#if 0
2int readlink(const char *path,char *buf,size_t bufsiz) {
3	int result;
4#else
5ssize_t readlink(const char *path,char *buf,size_t bufsiz) {
6	ssize_t result;
7#endif

3080行:

1int scandir(	const char *dir,struct dirent ***namelist,
2		int (*select)(const struct dirent *),
3		int (*compar)(const void *,const void *)	) {

改为:

1int scandir(	const char *dir,struct dirent ***namelist,
2		int (*select)(const struct dirent *),
3		int (*compar)(const struct dirent **,const struct dirent **)	) {

3692行:

1int scandir64(	const char *dir,struct dirent64 ***namelist,
2		int (*select)(const struct dirent64 *),
3		int (*compar)(const void *,const void *)	) {

改为:

1int scandir64(	const char *dir,struct dirent64 ***namelist,
2		int (*select)(const struct dirent64 *),
3		int (*compar)(const struct dirent64 **,const struct dirent64 **)	) {

来一个直观的修改对比:

修改完成后再重新编译。

二、使用CheckInstall

这里使用的CheckInstall的RPM安装包进行安装的。 在使用checkinstall之前需要做一点小修改,以免在执行的过程中报错:

1error: File not found: /root/rpmbuild/BUILDROOT/

编辑/usr/bin/checkinstall

1sudo vim /usr/bin/checkinstall

搜索关键词-bb,笔者的是在2451行,将:

1$RPMBUILD -bb ${RPM_TARGET_FLAG}${ARCHITECTURE} "$SPEC_PATH" &> ${TMP_DIR}/rpmbuild.log

改为:

1$RPMBUILD -bb ${RPM_TARGET_FLAG}${ARCHITECTURE} --buildroot=$BUILD_DIR "$SPEC_PATH" &> ${TMP_DIR}/rpmbuild.log

下面以制作GCC 9.2的安装包为例,在make完成后,使用checkinstall:

1sudo checkinstall

中途可能会出现:

 1======================== Installation successful ==========================
 2
 3Copying files to the temporary directory...OK
 4
 5Stripping ELF binaries...OK
 6
 7Compressing man pages...OK
 8
 9Building file list...OK
10
11/root/rpmbuild has no SOURCES directory. Please write the path to
12the RPM source directory tree: 

可以安装rpmdevtools:

1sudo yum install rpm-build -y
2sudo yum install rpmdevtools -y
3sudo rpmdev-setuptree

可以看到/root/rpmbuild目录了

再重新执行前面的checkinstall命令,可以看到成功生成RPM安装包,路径在/root/rpmbuild/RPMS/x86_64目录中,并且已经执行了一次RPM安装包的安装,通过

1rpm -qa | grep gcc

可以看到,如图所示。

从上图中可以看到

1Install RPM package... OK

以及

1Writing backup package... OK

即会自动安装RPM包以及备份,同时生成的安装包默认是在/root/rpmbuild/RPMS/目录,我们可以在执行sudo checkinstall的时候添加参数改变这些行为,改为:

1sudo checkinstall --install=no --backup=no --pakdir=.

这样就会在将生成的RPM包放在当前目录,并且不会在制作RPM完成后自动安装和备份。 每次都这样写岂不是很麻烦,修改/usr/lib64/checkinstall/checkinstallrc中的内容即可:

1PAK_DIR="."
2BACKUP=0
3INSTALL=0 

本文所用系统为Centos 6.10