目录
Linux编译器-gcc/g++使用
Linux项目自动化构建工具-make/Makefile
Linux编译器-gcc/g++使用
1. 背景知识
1.2 gcc/g++ -v 查看当前服务器的编译器版本
1.3 安装gcc / g++
sudo yum install -y gcc-c++
1.4 预处理 -> 编译 -> 汇编 -> 链接
[wxq@VM-4-9-centos Test]$ touch test.c #创建文件
[wxq@VM-4-9-centos Test]$ vim test.c #用vim打开文件
[wxq@VM-4-9-centos Test]$ ll
total 4
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
[wxq@VM-4-9-centos Test]$ gcc test.c -o test #一步生成可执行文件 -o:指明告诉我们生成的可执行文件名
[wxq@VM-4-9-centos Test]$ ll
total 16
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:51 test
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
[wxq@VM-4-9-centos Test]$ gcc -E test.c -o test.i #-E :从现在开始进行程序的翻译,如果预处理完成,就停下来
[wxq@VM-4-9-centos Test]$ ll
total 36
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:51 test
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
-rw-rw-r-- 1 wxq wxq 16877 Jan 9 20:51 test.i
[wxq@VM-4-9-centos Test]$ gcc -S test.i -o test.s #-S:从现在开始进行程序的翻译,如果编译完成,就停下来
[wxq@VM-4-9-centos Test]$ ll
total 40
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:51 test
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
-rw-rw-r-- 1 wxq wxq 16877 Jan 9 20:51 test.i
-rw-rw-r-- 1 wxq wxq 447 Jan 9 20:52 test.s
[wxq@VM-4-9-centos Test]$ gcc -c test.s -o test.o #-c:从现在开始进行程序的翻译,如果汇编完成,就停下来
[wxq@VM-4-9-centos Test]$ ll
total 44
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:51 test
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
-rw-rw-r-- 1 wxq wxq 16877 Jan 9 20:51 test.i
-rw-rw-r-- 1 wxq wxq 1496 Jan 9 20:52 test.o
-rw-rw-r-- 1 wxq wxq 447 Jan 9 20:52 test.s
[wxq@VM-4-9-centos Test]$ gcc test.o -o test_1 #链接
[wxq@VM-4-9-centos Test]$ ll
total 56
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:51 test
-rwxrwxr-x 1 wxq wxq 8360 Jan 9 20:59 test_1
-rw-rw-r-- 1 wxq wxq 83 Jan 9 20:50 test.c
-rw-rw-r-- 1 wxq wxq 16877 Jan 9 20:51 test.i
-rw-rw-r-- 1 wxq wxq 1496 Jan 9 20:52 test.o
-rw-rw-r-- 1 wxq wxq 447 Jan 9 20:52 test.s
[wxq@VM-4-9-centos Test]$
在这里涉及到一个重要的概念:函数库
- 我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?
- 最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用
函数库一般分为静态库和动态库两种
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。其后缀名一般为“.a”(优点是不依赖库,缺点是消耗资源大)
- 动态库与之相反,在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销。动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件,如下所示。(优点是不消耗资源)
- windows :".dll"(动态库) ".lib"(静态库)
- gcc hello.o –o hello
- gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证
查看所有的头文件
ls /usr/include/
gcc/g++下的体现:
[wxq@VM-4-9-centos Test]$ ls /lib64/libc.*
/lib64/libc.a /lib64/libc.so /lib64/libc.so.6
//静态库: /lib64/libc.a
//动态库: /lib64/libc.so.6
gcc、g++默认形成的可执行程序是动态链接的!!
ldd 文件名 :查看文件与共享库的依赖关系
file 文件名 :辨识文件类型
当然,也可以修改为静态链接:
-static
云服务器默认是没有静态库的,可以自行下载:
sudo yum install -y glibc-static # C静态库
sudo yum install -y libstdc++-static # C++静态库
Linux项目自动化构建工具-make/Makefile
背景
- 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
- make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
示例:
1: Makefile
1 proc:proc.c
2 gcc -o proc proc.c
3
4 .PHONY:clean
5 clean:
6 rm -rf proc
说明:
此时我们会发现,程序会根据依赖关系,自动执行依赖方法,可以把这里的 make / make clean 理解为构建和清理,也就是vs下的:
关于 .PHONY :linux下的关键字,用来修饰伪目标,表示指令总是被执行的。什么意思呢?请看示例:
这里我们习惯把 clean 设置成伪目标。
另外:make指令是自上而下向下进行扫描,只会执行第一个遇到的目标文件,除此之外,我们想要执行新的目标需要在make后面带上目标文件
总结:—般我们把要执行的文件会放在第一个
示例:
这里会有一个疑问,当我们执行make指令的时候,make指令是如何知道当前文件时最新的?
这里的答案是:根据文件的最近修改时间,这里我们需要借助一条指令帮助我们理解 - stat 指令
- 需要注意Access并不是每次访问都会被修改,因为数据是存储在磁盘上,每次访问数据都进行修改会降低访问磁盘的效率,所以现在通过linux内核的修复,Access只会达到一定次数只会才会被修改
- 源文件一定是比可执行程序要早的,可执行程序的时间一定比源文件的时间要晚,make指令会比较两者的修改时间
示例:
写到可能会有人觉得这不是多此一举吗?我直接gcc/g++进行编译不香吗?原因是因为这里只是为了演示,实际项目中可能是多个文件进行编译。
示例:
[wxq@VM-4-9-centos lesson1]$ ll
total 16
-rw-rw-r-- 1 wxq wxq 61 Jan 9 13:23 main.c
-rw-rw-r-- 1 wxq wxq 170 Jan 9 13:36 Makefile
-rw-rw-r-- 1 wxq wxq 64 Jan 9 13:22 test.c
-rw-rw-r-- 1 wxq wxq 55 Jan 9 13:21 test.h
[wxq@VM-4-9-centos lesson1]$ cat test.h
#pragma once
#include <stdio.h>
extern void show();
[wxq@VM-4-9-centos lesson1]$ cat test.c
#include "test.h"
void show()
{
printf("hello linux\n");
}
[wxq@VM-4-9-centos lesson1]$ cat main.c
#include "test.h"
int main()
{
show();
return 0;
}