0%

GCC参数和Makefile文件编写

GCC参数:

运行示例:

1
2
3
4
5
6
7
8
9
//code/link/main.c
int sum(int *a, int n);

int array[2] = {1, 2};

int main(){
int val = sum(array, 2);
return val;
}
1
2
3
4
5
6
7
8
9
//code/link/sum.c
int sum(int *a, int n){
int i ,s = 0;

for(i = 0; i < n; i++){
s += a[i];
}
return s;
}

大多数编译系统提供编译驱动程序(complier driver),它代表用户在需要时调用语言与处理器、编译器、汇编器和链接器。比如,要用GNU编译系统构造示例程序,我们就要通过在shell中输入下列命令来调用GCC驱动程序:

gcc -Og -o prog main.c sum.c

flowchart LR
    id1("main.c") --> id2("翻译器(cpp, cc1, as)")
    id3("sum.c") --> id4("翻译器(cpp, cc1, as)")
    id2 -->|main.o 可重定位目标文件| id5("链接器(ld)")
  id4 -->|sum.o| id5
  id5 -->id6("prog (完全链接的可执行目标文件)")
  1. 运行C预处理器(cpp) 将C源程序main.c翻译成一个ASCII码的中间文件main.i

    cpp [other argument] main.c /tmp/main.i

  2. 运行C编译器(cc1) 将main.i翻译成一个ASCII汇编语言文件main.s

    cc1 /tmp/main.i -Og [other argument] -o /tmp/main.s

  3. 运行汇编器(as) 将main.s翻译成main.o

    as [other arguments] -o /tmp/main.o /tmp/main.s

    同样生成sum.o

  4. 运行链接器程序ld 将main.o和sum.o以及一些必要的系统目标文件组合起来,创建一个可执行目标文件

    ld -o prog [system object files and args] /tmp/main.o /tmp/ sum.o

必要的:

(0.0 无选项编译并链接🔗

gcc hello.c

将hello.c预处理,编译,汇编并链接成可执行文件 这里未指定输出文件名,故输出a.out

0.1 无选项链接

gcc hello.o -o hello

将hello.o链接成最终可执行文件。)

  1. -i 预处理 生成ASCII码中间文件.i

  2. -S 预处理和编译 生成汇编文件.a

    1
    gcc -S hello.c
  3. -c 预处理 编译 汇编 生成可重定位目标文件.o

    1
    gcc -c hello.c
    1
    2
    //将汇编输出文件hello.s编译输出test.o文件
    gcc -c hello.s
  4. -o 指定生成文件名(默认生成.out)

    1
    2
    3
    gcc -o hello hello.c
    //or gcc hello.c -o hello
    gcc -o hello.asm -S hello.c
  5. -include -I 用来包含头文件,但一般包含头文件都在源码里用#include “”实现,-include参数很少用。
    -I参数是用来指定头文件目录,/usr/include目录一般是不用指定的,gcc知道去那里找,但是如果头文件不在/usr/include里我们就要用-I参数指定了,比如头文件放在/myinclude目录里,那编译命令行就要加上-I/myinclude参数了。-I参数可以用相对路径,比如头文件在当前目录,可以用-I.来指定。

    如图:

P1改为gcc -I ../TestH/ hello.c即可(注意是当前目录相对位置)

P2

补充:相对目录的引用

相对路径 ./当前目录 ../父级目录 只与文件的相对路径有关

(绝对路径:若我要查找idea文件夹中的idea.vmoptions文件的绝对路径,在终端输入命令sudo find / -name idea.vmoptions

  1. -g 只是编译器 在编译的时候产生调试信息(不太懂。

详见:阮一峰的网络日志

静态链接库

1
2
3
4
5
6
7
8
9
//addvec.c
int addcnt = 0;

void addvec(int *x, int *y, int*z, int n){
int i;
addcnt++;
for(i = 0; i < n; i++)
z[i] = x[i] + y[i];
}
1
2
3
4
5
6
7
8
9
//multcnt.c
int multcnt = 0;
void multvec(int *x, int *y, int *z, int n){
int i;

multcnt++;
for(i = 0; i < n; i++)
z[i] = x[i] * y[i];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
//main2.c
#include <stdio.h>
#include "vector.h"

int x[2] = {1, 2};
int y[2] = {3, 4};
int z[2];

int main(){
addvec(x, y, z, 2);
printf("z = [%d %d]", z[0], z[1]);
return 0;
}
1
2
3
//vector.h
void addvec(int *x, int *y, int*z, int n);
void multvec(int *x, int *y, int *z, int n);

目录如下:

.
├── addvec.c
├── addvec.o
├── libvector.a
├── main2.c
├── main2.o
├── multvec.c
├── multvec.o
├── prog2c
└── vector.h

编译并汇编后链接:

gcc -static -o prog2c main2.o ./libvector.a(Linux)

gcc -o prog2c main2.o ./libvector.a(macOS)

NaiOjBCMAmTzceh