gcc & makefile

gcc


使用gcc,程序员可以对编译过程有更多的控制,编译过程可分为3个阶段

  • 预处理
  • 汇编
  • 链接
程序员可以在编译的任何阶段结束后停止整个编译过程以检查编译器在该阶段输出的信息。




预处理将源代码和头文件结合在一起,也就是将头文件中的内容拷贝一份到原文中中;编译就是讲预编译的文件编译成二进制文件;将库中的文件链接进来,实现链接生成可执行文件。

ldd hello(可执行文件)可以查看该可执行文件连接到哪些库

nm hello 可以查看可执行文件被编译成那些名字

hello.c源文件

  1 #include<stdio.h>                                                                                
  2 #include<stdlib.h>
  4 int main(int argc, char *argv[])
  5 {
  6         if(argc < 3)
  7                 printf("请输入两个参数\n");
  8         else
  9         {
 10                 int a = atoi(argv[1]);
 11                 int b = atoi(argv[2]);
 12                 printf("%d + %d = %d\n", a, b, a+b);
 13         }
 14 
 15         return 0;
 16 }  

预编译:

gcc -o hello1.c -E hello.c

预编译说白了就是将头文件拷贝到源文件中

编译:

gcc -o hello.o -c hello1.c
告诉gcc对源程序hello.c进行编译,但不链接,编译输出hello.o文件中.


链接:

gcc -o hello hello.o
告诉gcc对源程序hello.c进行链接,生成可执行hello


gcc常用选项

为了提高代码的质量,在编译的时候最好加上-Wall

编译多个文件:

源文件add.h
int add(int a, int b);   

源文件add.c
 1 int add(int a, int b)                                                                            
  2 {
  3         return a+b;
  4 }

源文件hello.c
  1 #include<stdio.h>                                                                                
  2 #include<stdlib.h>
  3 #include"add.h"
  4 int main(int argc, char *argv[])
  5 {
  6         if(argc < 3)
  7                 printf("请输入两个参数\n");
  8         else
  9         {
 10                 int a = atoi(argv[1]);
 11                 int b = atoi(argv[2]);
 12                 printf("%d + %d = %d\n", a, b, add(a, b));
 13         }
 14 
 15         return 0;
 16 }

单独编译时因为不会链接库,所以不会出现错误

apple@ubuntu:~/LearnLinux$ ls
add.c  add.h  hello.c
apple@ubuntu:~/LearnLinux$ gcc -o add.o -c add.c
apple@ubuntu:~/LearnLinux$ gcc -o hello.o -c hello.c
apple@ubuntu:~/LearnLinux$ ls
add.c  add.h  add.o  hello.c  hello.o

但是链接时如果不链接相关的库的话就会出现错误
apple@ubuntu:~/LearnLinux$ gcc -o hello hello.o
hello.o:在函数‘main’中:
hello.c:(.text+0x63):对‘add’未定义的引用
collect2: error: ld returned 1 exit status

这时候需要将add.o库链接进来
apple@ubuntu:~/LearnLinux$ gcc -o hello hello.c add.o
apple@ubuntu:~/LearnLinux$ ls
add.c  add.h  add.o  hello  hello.c  hello.o  makefile



make




源文件hello.c
 1 #include<stdio.h>                                                                                
  2 #include<stdlib.h>
  3 int main(int argc, char *argv[])
  4 {
  5         if(argc < 3)
  6                 printf("请输入两个参数\n");
  7         else
  8         {
  9                 int a = atoi(argv[1]);
 10                 int b = atoi(argv[2]);
 11                 printf("%d + %d = %d\n", a, b, a+b);
 12         }
 13 
 14         return 0;
 15 }

创建makefile
  1 start:                                                                                           
  2         gcc -o hello hello.c                             

执行make语句
  tabstop=8apple@ubuntu:~/LearnLinux$ make
gcc -o hello hello.c
apple@ubuntu:~/LearnLinux$ ls
hello  hello.c  makefile

由此可见,make语句能帮助我们编译连接文件。

make文件
1 start:hello.o                                                                                    
  2         gcc -o hello hello.o
  3         @echo '------Succeed!------------'
  4 
  5 hello.o:
  6         gcc -o hello.o -c hello.c
  7 
  8 all:
  9         @echo '显示调用语句'
 10 
 11 clean:
 12         rm hello.o
 13         rm hello

调用make语句
  tabstop=8apple@ubuntu:~/LearnLinux$ ls
hello.c  makefile
apple@ubuntu:~/LearnLinux$ make
gcc -o hello.o -c hello.c
gcc -o hello hello.o
------Succeed!------------
apple@ubuntu:~/LearnLinux$ make all
显示调用语句
apple@ubuntu:~/LearnLinux$ make clean
rm hello.o
rm hello
apple@ubuntu:~/LearnLinux$ ls
hello.c  makefile

第一次执行make命令时,执行两句话,再次make时只执行其中的一句,因为start后边是依赖项,如果没有该依赖项则先调用依赖项,如果有的话直接执行该依赖项后边的语句。


@echo “-------------OK------------”输出字符串,@表示只输出结果不输出命令本身




此时的makefile文件
  1 CC=gcc                                                                                           
  2 SRCS=hello.c
  3 OBJS=$(SRCS:.c=.o)
  4 EXEC=hello
  5 
  6 start:$(OBJS)
  7         $(CC) -o $(EXEC) $(OBJS)
  8         @echo '------Succeed!------------'
  9 
 10 $(OBJS):
 11         $(CC) -o $(OBJS) -c $(SRCS)
 12 
 13 all:
 14         @echo '显示调用语句'
 15 
 16 clean:
 17         rm $(OBJS)
 18         rm $(EXEC)

hello.c  makefile
apple@ubuntu:~/LearnLinux$ make
gcc -o hello.o -c hello.c
gcc -o hello hello.o
------Succeed!------------
apple@ubuntu:~/LearnLinux$ ls
hello  hello.c  hello.o  makefile



  1 .suffixes:.c .o                                                                                  
  2 
  3 CC=gcc
  4 SRCS=hello.c
  5 OBJS=$(SRCS:.c=.o)
  6 EXEC=hello
  7 
  8 start:$(OBJS)
  9         $(CC) -o $(EXEC) $(OBJS)
 10         @echo '------Succeed!------------'
 11 
 12 .c.o:
 13         $(CC) -o $@ -c $<
 14 
 15 all:
 16         @echo '显示调用语句'
 17 
 18 clean:
 19         rm $(OBJS)
 20         rm $(EXEC)
~                       

再次编译时只编译更变的源文件,源文件没有更改的不再编译,根据源文件的修改时间,如果源文件的修改时间在.o文件之后则会发生编译,之前就不会重新编译。


编译调试C++程序
源文件hello.cpp
1 #include<iostream>                                                                               
  2 #include<stdlib.h>
  3 
  4 using std::cout;
  5 using std::endl;
  6 
  7 int main(int argc, char *argv[])
  8 {
  9         if(argc < 3)
 10                 cout<<"请输入两个参数"<<endl;
 11         else
 12         {
 13                 int a = atoi(argv[1]);
 14                 int b = atoi(argv[2]);
 15                 cout<<a<<"+"<<b<< " = "<<a+b<<endl;
 16         }
 17 
 18         return 0;
 19 }

makefile文件
  1 .suffixes:.cpp .o                                                                                
  2 
  3 CC=g++
  4 SRCS=hello.cpp
  5 OBJS=$(SRCS:.cpp=.o)
  6 EXEC=hello
  7 
  8 start:$(OBJS)
  9         $(CC) -o $(EXEC) $(OBJS)
 10 
 11 .cpp.0:
 12         $(CC) -o $@ $<
 13 
 14 clean:
 15         rm $(OBJS)
 16         rm $(EXEC)
~                         

执行命令:
apple@ubuntu:~/LearnLinux$ ls
hello.cpp  makefile
apple@ubuntu:~/LearnLinux$ make
g++    -c -o hello.o hello.cpp
g++ -o hello hello.o
apple@ubuntu:~/LearnLinux$ ls
hello  hello.cpp  hello.o  makefile
apple@ubuntu:~/LearnLinux$ ./hello 4 6
4+6 = 10



同时编译多个源文件只需在SRCS = hello.cpp\ add.cpp即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值