gcc编译器、gdb调试、Makefile学习

1、gcc编译器

        1、预处理,做#的事

                展开头文件 #include 

                宏替换 #define

                条件编译 #if #else #endif #elif

                删除注释

        2、编译阶段:检测语法错误,把文件转换为汇编

                gcc -S xxx.c -0 xxx.s

        3、汇编阶段:把汇编语言转换为机器语言

                gcc -c xxx.c -o xxx.o

        4、链接:把所有二进制文件链接整合为一个可执行文件

                gcc xxx.c -o app

                -o :给生成的文件取名字。其中有几个优先级包括o2等等。等待补充

                -I(i的大写) :需要引用的头文件路径

                -l(L的小写):

2、gdb调试

        要使用gdb调试在编译时必须加上-g选项

        gdb +r:让程序执行一次

        gdb +l:查看十行代码内容

        gdb +b:在对应行设置一个断点

        gdb +p:变量名,查看变量的内容

        gdb +n:让程序继续运行

        quit:退出gdb调试

3、Makefile

make是一个工程管理器,用来管理多文件项目的

Makefile是make工具的唯一配置文件,文件名只能叫makefile

目标文件:依赖文件

        功能语句

现有一个学生的项目,其中c_code内是c语言文件,h_code是.h文件。使用makefile对其进行编译

1、基本理解

app:main.o student.o
	gcc main.o student.o -o app
main.o:./c_code/main.c
	gcc -c ./c_code/main.c -I ./h_code/ -o main.o
student.o:./c_code/student.c
	gcc -c ./c_code/student.c -I ./h_code -o student.o

该脚本是初级理解,代码会逐行检查依赖,若没有,就会用接下来的代码生成

2、使用shell脚本提升其复用性。使用到通配符。以后若需要添加.依赖文件,直接在obj内后方添加

B=gcc
Target=app
obj=main.o student.o
BFlages=-c -Wall#编译选项,表示显示编译期间发生的所有警告,此处有 -c了!!!!!!!!!
Hin=-I ./h_code #申明h文件的位置,-I是gcc编译的时候带着头文件一起编译
Cin=./c_code/
#格式:目标:依赖
#第一步,基于 .o文件生存目标文件,而.o文件来源于.c文件,此步骤在makefile当前文件夹执行,所以不需要添加路径
#下面的$^表示依赖文件,$@表示目标文件
#app:main.o student.o
#	gcc  main.o student.  o -o app
$(Target):$(obj)
	$B $^ -o $@  
#第二部,给定所有的.o文件的依赖都是(Hin)路径下的.c文件的东西。$^表示上面的所有c文件
%.o: $(Cin)%.c
	$B  $(Hin) $(BFlages) $^ -o $@
#清理文件
clean:
	rm -f *.o $(Target)

今日学习动态库

CC = gcc  # 设置编译器为gcc
TARGET = app  # 设置目标文件名为app
Cin = ./c_code/  # 设置C源文件的路径
Hin = ./h_code/  # 设置头文件的路径
SRC = $(Cin)student.c  # 设置源文件为c_code目录下的student.c
METHOD= -shared -o  # 设置编译选项为-shared和-o,用于生成动态库
FP = -fPIC  # 设置编译选项为-fPIC,用于生成位置无关代码
OBJ = $(SRC:.c=.o)  # 将源文件名的.c后缀替换为.o,得到目标文件名
HEAD =-I $(Hin)  # 设置编译选项-I,用于指定头文件的路径
VERSION = 1.0.0  # 设置版本号为1.0.0
LIBDIR = /usr/lib  # 设置库文件的路径
SO = libdtudent.so  # 设置动态库的文件名
MAIN = ./c_code/main.c  # 设置主函数的源文件

all:$(TARGET)  $(SO)  # 定义目标all,依赖于目标app和libdtudent.so

$(SO):$(OBJ)  # 定义目标libdtudent.so,依赖于目标文件
	$(CC) $(METHOD) $@ $^  # 编译命令,$@表示目标文件名,$^表示所有的依赖文件

%.o: %.c  # 定义模式规则,.o文件依赖于对应的.c文件
	$(CC) $(HEAD) -c $(FP) $< -o $@  # 编译命令,$<表示依赖文件,$@表示目标文件

$(TARGET): $(MAIN) $(SO)  # 定义目标app,依赖于main.c和libdtudent.so
	$(CC) $(HEAD) -o $@ $^  # 编译命令,$@表示目标文件名,$^表示所有的依赖文件

clean:  # 定义目标clean,用于清理编译生成的文件
	rm -f $(OBJ) $(SO).$(VERSION) $(TARGET) $(SO)  # 删除命令

实际运用的时候,记得把注释去掉,可能会因为空格导致一些路径出现问题

有的时候会出现错误

gcc -fPIC -shared -o  libstudent.so c_code/student.o
/usr/bin/ld: c_code/student.o: relocation R_X86_64_PC32 against symbol `year_cmp' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make: *** [makefile:18: libstudent.so] Error 1

具体原因不明,手动执行

gcc -I ./h_code/ -c -fPIC c_code/student.c -o c_code/student.o 
gcc  -shared -o  libstudent.so c_code/student.o
gcc -I ./h_code/ -o app c_code/main.c libstudent.so

也即是makefile文件内执行的语句,发现make又能正常运行了

网上有一个解释,但由于没有再出现这个错误,就没有再尝试了relocation R_X86_64_PC32 against symbol ff_pw_9 can not be used when making a shared object-阿里云开发者社区 (aliyun.com)

经过大佬提醒,编译动态库最好不在makefile内进行,最好在脚本内执行。makefile和脚本有一定区别

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值