一、引言:常见的安装步骤

经常在安装一些软件时会进行一系列编译步骤,突然冒出一个make来,不知道什么用。

$ ./configure
# 在安装 nginx 配置安装地址时,还会加参数
# ./configure --prefix=/usr/locale/nginx
$ make
$ make install

二、编译

之前的命令其实就是在做编译工作,只不过命令不同,现在举一个简单的例子:

文件 test.c

#include <stdio.h>

int main(void)
{
  fputs("Hello, world!\n", stdout);
  return 0;
}

编译 -> 运行

$ gcc test.c
$ ./a.out
Hello, world!

三、编译详解

  1. 配置(约定俗成:configure)
预编译工作:

- 编译器在开始工作之前,需要知道当前的系统环境,比如标准库在哪里、软件的安装位置在哪里、需要安装哪些组件等等。

- 因为不同计算机的系统环境不一样,通过指定编译参数,编译器就可以灵活适应环境,编译出各种环境都能运行的机器码。
  确定编译参数的步骤,就叫做 "配置"(configure)。

- 这些配置信息保存在一个配置文件 configure 的脚本文件中。
  通常它是由 autoconf 工具 生成的。编译器通过运行这个脚本,获知编译参数。

- configure脚本已经尽量考虑到不同系统的差异,并且对各种编译参数给出了默认值。
  如果用户的系统环境比较特别,或者有一些特定的需求,就需要手动向configure脚本提供编译参数。
  例如:$ ./configure --prefix=/www --with-mysql
  (指定安装后的文件保存在www目录,并且编译时加入mysql模块的支持) 就是php源码的一种编译配置
  1. 编译(make)
1. 确定标准库和头文件的位置

2. 确定依赖关系
- 需要确保,只有在被依赖文件编译完成后,才开始编译子文件,且当被依赖文件发生变化时,文件需要被重新编译。
- 编译顺序保存在一个叫做makefile的文件中,里面列出哪个文件先编译,哪个文件后编译。
  而makefile文件由configure脚本运行生成,这就是为什么编译时configure必须首先运行的原因。
- 在确定依赖关系的同时也确定了编译时会用到哪些头文件。

3. 头文件的预编译(precompilation)
- 头文件的预编译(precompilation)确保头文件只需编译一次,不必每次用到的时候,都重新编译。

4. 预处理(Preprocessing)
- 替换掉源码中bash的头文件和宏
- 移除注释

5. 编译(Compilation)
- 源码转为汇编码(assembly),然后再把汇编码转为机器码。
- 转为汇编码后的文件称为对象文件(object file)。

6. 连接(Linking)
- 把外部函数的代码(通常是后缀名为.lib和.a的文件),添加到可执行文件中。
  1. 安装(make install)
将可执行文件保存到用户事先指定的安装目录(拷贝过去就行了),需要创建目录、保存文件等权限。

四、MarkFile

构建规则都写在Makefile文件里面,要执行 Make命令,就必须学会如何编写 Makefile文件。

规则:

<target>: <prerequisites> 
	<commands>

如:

clean:
      rm *.o

如:

all: build-js build-css

build-js: 
  browserify -t brfs src/app.js > site/app.js

build-css:
  stylus src/style.styl > site/style.css

.PHONY build-js build-css

五、Reference:

compiler

make

build website with make

六. 源码安装 CMake

# 逐行执行
sudo apt install build-essential
sudo wget https://cmake.org/files/v3.28/cmake-3.28.0.tar.gz
tar -zxvf cmake-3.28.0.tar.gz
cd cmake-3.28.0
./configure
sudo make
sudo make install
# 安装完成, 检查版本
cmake --version

七. Make 命令升级 Nginx

  • nginx 使用服务信号升级
# 准备工作
# ./configure && make && make install # 旧版安装 nginx 1.16

# 开始升级, 新版打包
./configure && make # 新版 nginx 1.20
# 备份原有的二进制 nginx 
mv nginx oldnginx
# 更新 nginx 二进制文件
cp ~/nginx-1.20.1/objs/nginx /usr/local/nginx/sbin/
# 复制得到新的进程(根据新的二进制文件运行的进程)
kill -USR2 'more /usr/local/nginx/logs/nginx.pid'
# 退出旧版本
kill -QUIT 'more /usr/local/nginx/logs/nginx.pid.oldbin'

原理: kill -USR2 PID # 这样会复制一份,并得到nginx.pid.oldbin文件,再继续运行kill -QUIT OLDPID 这样平滑更新就完成了。


kill 命令信号:TERM/INT、 QUIT、 HUP、 USR1、 USR2、 WINCH

  • nginx 使用make命令升级
# 准备工作
./configure && make && make install # 旧版
./configure && make # 新版
# 备份原有的二进制 nginx 
mv nginx oldnginx
# 更新 nginx 二进制文件
cp ~/nginx-1.17.1/objs/nginx /usr/local/nginx/sbin/
# 在新版本的根目录下执行
make upgrade
  • nginx 更新模块
# 查看之前安装的模块有哪些(需要添加到后面)
nginx -V
# 清理
make clean
# 模块更新
./configure --without.... --with...
# 编译
make
# 更新
mv objs/nginx /opt/nginx/sbin/ && make upgrade
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐