!! 阅读前提示:
1)本文是自己的学习过程和经验的总结,和大多数人一样,不懂就搜度娘、csdn、博客园等等,内容难免有不足之处和理解不到位的情况,请见谅。所有知识来源于网络,摘录内容会指明出处。
2)本文默认读者对基本名词已经清楚,如编译,c++,linux等。
3)本文更新于2022/11/5,未完待续,持续更新。
g++ 是C++语言的编译器;makefile 自动化编译工具;automake,自动生成makefile的工具。
makefile是自动化编译项目工程的工具,必须先明白编译过程
总共四个阶段:预处理、编译、汇编、链接
【文章推荐:】
【C++程序编译过程_WhiteTian的博客-CSDN博客_c++编译https://blog.csdn.net/u011718663/article/details/118163962】(这位大佬写的非常详细)
在linux下编译C/C++程序,用到的编译器:
【编译器的介绍:】
【gcc与g++的区别_ericwzy2012的博客-CSDN博客_g++和gcc的区别https://blog.csdn.net/wuzheyan2008/article/details/119715526】
【自己搜吧,我也没看见好的介绍,反正也不是历史学家,能用就行】
编译是 源文件->目标文件 的过程,目标文件有以下几种:
文件类型 | 说明 |
---|---|
*.i | 预编译后的文件,见4编译选项的1) |
*.s | 编译后的文件,内容为汇编代码,见4编译选项的2) |
*.o | 目标文件,内容为二进制,见4编译选项的3) |
*.d | 依赖文件,内容为源文件的依赖关系。 |
*.elf | 可执行二进制文件,一般得到的可执行文件没有写后缀名 |
*.a | 静态库文件,windows下后缀名为*.lib |
*.so | 动态库文件,windows下后缀名*.dll |
命令: g++ [编译选项]
例如:
g++ main.cpp –o main
编译选项决定了编译什么,怎么编译,编到出什么结果。下面开始介绍
!!注意:编译选项区分大小写,例如1)的 –E选项
g++ -E mian.cpp //仅预处理,生成main.i文件
g++ -e main.cpp //因为g++编译器没有-e选项,因此此条语句
//等价于g++ main.cpp ,直接生成a.out文件(a.out是g++的默认的可执行文件名称)
!!以下所有出现文件名的地方都可以相对路径或绝对路径。
【编译目标相关选项】
0)什么也不写,直接g++要编译的文件,得到a.out的可执行二进制文件。
g++ main.cpp //g++采用默认参数,直接生成a.out文件
g++ -E mian.cpp 仅预处理,生成main.i文件
g++ -S mian.cpp 将源文件进行到编译,得到main.s文件
g++ -c mian.cpp 将源文件进行到汇编,得到main.o文件
g++ -o main mian.cpp 编译mian.cpp,得到可执行文件main
g++ -M main.cpp
//执行上面这条语句,将得到
main.o: main.cpp /usr/include/stdc-predef.h /usr/include/c++/11/iostream \
/usr/include/x86_64-linux-gnu/c++/11/bits/c++config.h \
/usr/include/x86_64-linux-gnu/c++/11/bits/os_defines.h \
/usr/include/features.h /usr/include/features-time64.h \
/usr/include/x86_64-linux-gnu/bits/wordsize.h \
/usr/include/x86_64-linux-gnu/bits/timesize.h \
/usr/include/x86_64-linux-gnu/sys/cdefs.h \
/usr/include/x86_64-linux-gnu/bits/long-double.h \
/usr/include/x86_64-linux-gnu/gnu/stubs.h \
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
/usr/include/x86_64-linux-gnu/c++/11/bits/cpu_defines.h \
/usr/include/c++/11/pstl/pstl_config.h /usr/include/c++/11/ostream \
/usr/include/c++/11/ios /usr/include/c++/11/iosfwd \
/usr/include/c++/11/bits/stringfwd.h \
/usr/include/c++/11/bits/memoryfwd.h /usr/include/c++/11/bits/postypes.h \
/usr/include/c++/11/cwchar /usr/include/wchar.h \
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
/usr/include/x86_64-linux-gnu/bits/floatn.h \
/usr/include/x86_64-linux-gnu/bits/floatn-common.h \
/usr/lib/gcc/x86_64-linux-gnu/11/include/stddef.h \
/usr/lib/gcc/x86_64-linux-gnu/11/include/stdarg.h \
/usr/include/x86_64-linux-gnu/bits/wchar.h \
/usr/include/x86_64-linux-gnu/bits/types/wint_t.h \
/usr/include/x86_64-linux-gnu/bits/types/mbstate_t.h \
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/FILE.h \
/usr/include/x86_64-linux-gnu/bits/types/locale_t.h \
这个结果非常长,上面只列举了一部分。这就是所谓的依赖关系,依赖关系一般写为
xxx.o : xxx.cpp xxx.h xxx1.h xxx2.h …
意思是生成xxx.o文件需要后面这些文件(依赖关系是makefile工具不可或缺的一部分)。
-MM:作用同上,但是-M选项列举的太全面了,如果只希望列举出自己写的文件,
g++ -MM main.cpp
//就会得到
main.o: main.cpp
!与-M选项相关的,还有-MF,-MD,-MG,-MMD,-MT等等选项,讲解看这篇文章吧 【Linux Makefile 生成 *.d依赖文件及 gcc -M -MF -MP等相关选项说明_EtcFly的博客-CSDN博客https://blog.csdn.net/u014170207/article/details/88208520】
【编译参数相关选项】
6) -L:用于指定库路径
-l:用于指定库文件,例如:
g++ main.cpp –lXX –L./lib/
//意思为,编译main.cpp需要用到库XX,库XX在main这个目录下的lib文件夹里,文件的名字是libXX.a或者libXX.so
补充:如果依赖的库是系统库,则不需要-L选项
TODO:库文件的搜索顺序
g++ main.cpp –I../include 编译main需要用到../include文件夹下的文件
【文章推荐:】(这位作者总结的很全) 【【GCC】gcc警告选项汇总–编辑中|gcc编译选项_bandaoyu的博客-CSDN博客https://blog.csdn.net/bandaoyu/article/details/115419255】
-g:允许gcc产生带调试信息的可执行文件test
-O数字:此选项为优化代码,建议选择-O2
-O | 效果同-O1 |
-O0 | 不做优化 |
-O1 | 默认优化 |
-O2 | 在-O1基础上,进行一些额外调整,如指令调整 |
-O3 | 包含循环展开和其他优化工作 |
g++ -std=c++11 main.cpp 以c++11标准编译main
g++ -DLINUX –DDEBUG main.cpp 编译main时,加入LINUX或者DEBUG两个宏
问题:
什么是静态库,什么是动态库?
【】
Linux下静态库有统一名称格式:lib***.a,***就是库的真正名字
编译过程:
1)将所有源文件编译成目标文件(*.o)
g++ -c 源文件
2)打包所有目标文件。
ar crv libXXX.a *.o
【文章推荐:】
【linux编译生成动态库、静态库,以及使用_锅锅是锅锅的博客-CSDN博客_linux
编译动态库https://blog.csdn.net/u010835747/article/details/119151003】
【Linux —— 动态库和静态库_霄沫凡的博客-CSDN博客_linux
动态库https://blog.csdn.net/sjsjnsjnn/article/details/125836184】
Linux下动态库有统一名称格式:lib***.so,***就是库的真正名字
(2023.3.9更新,动态库的名字有命名规则(http://t.csdn.cn/WLj6Y)),我编译时ld死活找不到动态库,明明-L已经指定了路径,最后发现,文件夹内只有libXXX.so.0.0.0,而编译器只认libXXX.so)
编译过程:
gcc -fPIC -shared xxx.o -o libxxx.so
gcc -fPIC -shared xxx1.o xxx2.o xxx3.o -o libxxx.so
13)编译选项 -fPIC:生成位置无关代码
C/C++编译总结 (Linux下g++、makefile、automake)Makefile笔记
makefile的学习笔记搞完了,另开了一篇文章,主要是因为本文是用makedown写的,makefile笔记用了普通文档格式,懒得再去改一遍了。
automake最近用不到,有需要的看这篇吧,这位博主讲的很详细
linux下automake用法
1、跟我一起写makefile 陈皓