外贸网站图片素材,谷歌seo和百度seo区别,网站设计的主题,黄岩网站开发Makefile
这里使用的Makefile操控编译器
gcc
常见的组成部分
c#xff1a; gcc 的一个版本#xff0c;默认语言设置为 C#xff0c;而且在链接的时候自动包含标准 C 库。这和 g 一样configure#xff1a; GCC 源代码树根目录中的一个脚本。用于设置配置值和创建 GCC 编…Makefile
这里使用的Makefile操控编译器
gcc
常见的组成部分
c gcc 的一个版本默认语言设置为 C而且在链接的时候自动包含标准 C 库。这和 g 一样configure GCC 源代码树根目录中的一个脚本。用于设置配置值和创建 GCC 编译程序必需的 make 程序文件g gcc 的一个版本默认语言设置为 C而且在链接的时候自动包含标准 C库。这和 c 一样gcc 该驱动程序等同于执行编译程序和连接程序以产生需要的输出libgcc 该库包含的例程被作为编译程序的一部分是因为它们可被链接到实际的可执行程序中。它们是特殊的例程链接到可执行程序来执行基本的任务例如浮点运算。这些库中的例程通常都是平台相关的libstdc 运行时库包括定义为标准语言一部分的所有的 C类和函数
包含的常见的软件
ar 这是一个程序可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。该程序是 binutils 包的一部分as GNU 汇编器。实际上它是一族汇编器因为它可以被编译或能够在各种不同平台上工作。该程序是 binutjls 包的一部分 autoconf产生的 shell 脚本自动配置源代码包去编译某个特定版本的 UNIXgdb GNU 调试器可用于检查程序运行时的值和行为 GNATSGNU 的调试跟踪系统GNU Bug Tracking System。一个跟踪 GCC和其他 GNU 软件问题的在线系统gprof 该程序会监督编译程序的执行过程并报告程序中各个函数的运行时间可以根据所提供的配置文件来优化程序。该程序是 binutils 包的一部分ld GNU 连接程序。该程序将目标文件的集合组合成可执行程序。该程序是 binutils 包的一部分libtool 一个基本库支持 make 程序的描述文件使用的简化共享库用法的脚本make 一个工具程序它会读 makefile 脚本来确定程序中的哪个部分需要编译和连接然后发布必要的命令。它读出的脚本叫做 makefile 或 Makefile定义了文件关系和依赖关系
默认的搜索路径
查看命令
echo | gcc -v -x c -E -/usr/lib/gcc/x86_64-linux-gnu/7/include/usr/local/include/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed/usr/include/x86_64-linux-gnu/usr/include
简单的编译原理 预处理阶段, 把.c结尾的文件的#开头的命令进行预处理, 直接把对应的文本内容放到对应的位置
编译器, 把预处理之后的文件修改为汇编文件
汇编器, 汇编文件转换为二进制文件
连接器, 把所有的.o文件连接在一起形成一个可执行文件
各种文件的后缀
.a 静态库文件
.c C语言文件
.h 头文件
.i 预处理之后的文件
.o 目标文件
.s 汇编文件
.so 共享的库
实际使用gcc进行编译
预处理
gcc -E mian.c这一个会进行预处理但是没有生成一个文件 gcc -E main.c -o main.i使用-o指明输出文件的名字 生成汇编文件
gcc -S main.c
gcc -S main.c -o main.s生成目标文件
gcc -c main.c
gcc -c main.c -o main.o之间编译成可执行文件
gcc main.c静态库编译以及链接
把c文件编译成o文件编译静态库
ar -r [lib库名.a] [.o] [.o]连接成可执行文件
gcc [.c] [.a] -o [输出的文件名]
gcc [.c] -o [输出的文件名] -l [库的名字] -L [库所在的位置]注: windows下面为.lib文件, 但是测试的时候.a文件才可以使用 编译动态库
gcc -c -fpic [.c/.cpp] ...编译成-o文件, 这样编译出来的文件使用都是相对地址 gcc -shared [.o] [.o] ... -o [lib.so]创建动态库 gcc [.c/.cpp] -o [自定义可执行文件] -l[库名] -L[库路径] -wl,-rpath[库路径]链接动态库到可执行文件 注: windows下面为dll文件 静态库和动态库的区别
静态库在编译时会被完整地复制到可执行文件中因此它们会增加可执行文件的大小。在链接时刻编译器会将静态库的代码与可执行文件的代码合并生成一个完整的可执行文件。由于静态库已经被完整地复制到可执行文件中因此程序在运行时不需要再加载静态库这样可以提高程序的运行速度。但是如果多个可执行文件都使用同一个静态库那么静态库的代码会被复制多次浪费空间。
动态库则是在程序运行时才被加载到内存中因此它们不会增加可执行文件的大小。在链接时刻编译器只会将动态库的引用信息添加到可执行文件中而不会将动态库的代码复制到可执行文件中。程序在运行时会动态地加载动态库并将其映射到内存中。由于多个可执行文件可以共享同一个动态库因此动态库可以节省内存空间。但是由于动态库需要在程序运行时才能加载因此程序的启动速度可能会受到影响。
总的来说静态库适用于需要高效运行的小型程序而动态库适用于需要共享代码和节省内存空间的大型程序。
C编译文件的过程
.a 静态库文件.c .c .cc .cp .cpp .cxx 源代码的文件.h 头文件.ii 预处理文件.o 目标文件.s 汇编文件
g -E main.c
g -E main.c -o maim.i预处理文件 g -S main.c -o mian.s生成汇编文件 g -c main.c -o main.o生成预处理文件 g main.c -o main.exe生成可执行文件 ar -cr [lib库的名字.a] [.o] [.o]g [.c] [.a] -o [输出的文件名]
g [.c] -o [输出的文件名] -l[库的名字] -L[库所在的位置]静态库文件 g -c -fpic [.c/.cpp] ...编译成-o文件 g -shared [.o] [.o] ... -o [lib库的名字.lib]创建动态库 g [.c/.cpp] -o [自定义可执行文件] -l[库名] -L[库路径] -wl,-rpath[库路径]链接动态库到可执行文件 Makefile语法
基本的格式
targets : prerequisties
[tab键]commandtarget目标文件可以是 OjectFile也可以是执行文件还可以是一个标签Label对于标签这种特性在后续的“伪目标”章节中会有叙述。prerequisite要生成那个 target 所需要的文件或是目标。command是 make 需要执行的命令 这样的话会输出使用的命令, 可以在前面添加使得输出隐藏 debug :echo helloPS E:\桌面\c_test make
hello
PS E:\桌面\c_test Makefile规则
会在文件夹里面找到Makefile文件或者makefile文件会找到文件中的第一个目标文件(target), 把这个文件作为目标文件target文件不存在或者依赖的.o文件修改时间比这个文件新的话会执行定义的commang命令生成这个文件如果.o文件也存在, 会找到.o文件的依赖, 依据规则生成.o文件
伪目标
为了避免 target 和 Makefile 同级目录下 文件/文件夹 重名的这种情况我们可以使用一个特殊的标记 .PHONY 来显式地指明一个目标是 “伪目标”向 make 说明不管是否有这个文件/文件夹这个目标就是 “伪目标”
.PHONY : clean如果有一个名字叫clean的文件在这个文件夹下面, 就不会执行这一个命令 这个时候就会输出 debug : worldecho helloworld :echo worldclean :rm *.oPS E:\桌面\c_test make clean
make: clean is up to date.
PS E:\桌面\c_test只要有这个声明不管是否有 “clean” 文件/文件夹要运行 “clean” 这个目标只有make clean 这个命令 注意 对于有 prerequisties 的 target
debug : worldecho helloworld :echo worldclean :rm *.o.PHONY : clean这个时候就会执行这一个命令了 变量
变量的定义
cpp : src/main.cpp
obj : objs/main.o变量的引用
可以使用()或者{}
cpp : src/main.cpp
obj : objs/main.o$(obj) : ${cpp}g -c $(cpp) -o $(obj)compile : $(obj)compiler : cppdebug : echo $(compiler)PS E:\桌面\c_test make
cpp变量会被转化为在上面输入的变量 预定义的变量
$: 目标(target)的完整名称$: 第一个依赖文件prerequisties的名称$^: 所有的依赖文件prerequisties以空格分开不包含重复的依赖文件
cpp : src/main.cpp
obj : objs/main.o$(obj) : ${cpp}g -c $ -o $echo $^compile : $(obj)
.PHONY : compile常用的符号 简单的赋值在后面的语句里面重新定义该变量, 会使用新的值
HOST_ARCH arrch64
TARGET_ARCH $(HOST_ARCH)HOST_ARCH amd64
debug :echo $(TARGET_ARCH)PS E:\桌面\c_test make debug
amd64
PS E:\桌面\c_test 会随时更新使用的变量 :
赋值了之后就不会进行更改
HOST_ARCH : arrch64
TARGET_ARCH : $(HOST_ARCH)HOST_ARCH : amd64
debug :echo $(TARGET_ARCH)echo $(HOST_ARCH)PS E:\桌面\c_test make debug
arrch64
amd64
PS E:\桌面\c_test ?
默认赋值运算符如果变量已经定义就不进行任何操作如果没有定义就求值并进行分配
HOST_ARCH : arrch64
TARGET_ARCH : $(HOST_ARCH)HOST_ARCH ? amd64
debug :echo $(TARGET_ARCH)echo $(HOST_ARCH)PS E:\桌面\c_test make debug
arrch64
arrch64累加符号
HOST_ARCH : arrch64
TARGET_ARCH : $(HOST_ARCH)HOST_ARCH amd64
debug :echo $(TARGET_ARCH)echo $(HOST_ARCH)PS E:\桌面\c_test make debug
arrch64
arrch64 amd64
PS E:\桌面\c_test \
续行符
HOST_ARCH : arrch64 \arm63 x86
TARGET_ARCH : $(HOST_ARCH)HOST_ARCH amd64
debug :echo $(TARGET_ARCH)echo $(HOST_ARCH)PS E:\桌面\c_test make debug
arrch64 arm63 x86
arrch64 arm63 x86 amd64
PS E:\桌面\c_test 常用的函数
函数的调用
$(fn , argument) or ${fn, argument}
fn: 函数名argument: 函数的参数
shell
$(shell commend argument)名称: shell 功能: 调用shell 使用commend 返回: shell执行commend的结果 pwd : $(shell pwd)debug :echo $(pwd)PS E:\桌面\c_test make debug
/e/妗岄潰/c_test
PS E:\桌面\c_test subst
$(subst from,to,text)名称: 字符串替换函数功能: 把字符串 中的 替换为 返回的是替换之后的字符串
cpp_src : $(shell ls *.c)
cpp_objs : $(subst .c,.exe, $(cpp_src))debug : echo $(cpp_src)echo $(cpp_objs) PS E:\桌面\c_test make
add.c main.c
add.exe main.exe
PS E:\桌面\c_test patsubst
$(patsubst pattern,replacement,text)通配符替换字符串 通配符%把要替换的文字分割开来, 可以一次性替换多个不同的字符串 cpp_src : $(shell pwd)
cpp_objs : $(patsubst /e%/c_test,/c%/jiao, $(cpp_src))debug : echo $(cpp_src)echo $(cpp_objs) .PHONY : debugPS E:\桌面\c_test make debug
/e/妗岄潰/c_test
/c/妗岄潰/jiao
PS E:\桌面\c_test foreach
$(foreach var,list,text)名称循环函数——foreach。功能把字串中的元素逐一取出来执行 包含的表达式 返回 所返回的每个字符串所组成的整个字符串以空格分隔
library_paths : /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \/usr/local/cuda-10.1/lib64library_paths : $(foreach item,$(library_paths),-L$(item))debug : echo $(library_paths)PS E:\桌面\c_test make debug
-L/datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib -L/usr/local/cuda-10.1/lib64
PS E:\桌面\c_test 可以使用下面的方式进行代替
I_flag : $(include_paths:%-I%)library_paths : /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \/usr/local/cuda-10.1/lib64# library_paths : $(foreach item,$(library_paths),-L$(item))
library_paths : $(library_paths:%-L%)
debug : echo $(library_paths)PS E:\桌面\c_test make debug
-L/datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib -L/usr/local/cuda-10.1/lib64
PS E:\桌面\c_test dir
$(dir names...)名称取目录函数——dir。 功能从文件名序列中取出目录部分。目录部分是指最后一个反斜杠“/”之前 的部分。如果没有反斜杠那么返回“./”。 返回返回文件名序列的目录部分。 .PHONY : debug
cpp_srcs : $(shell ls *.c)
# 在文件名前面加上路径
cpp_objs : $(foreach item,$(cpp_srcs),./output/$(item))
# 获取输出的文件的文件名
cpp_objs : $(subst .c,.o,$(cpp_objs))
debug :echo $(cpp_srcs) echo $(cpp_objs)
# 生成所有的.o文件
./output/%.o : %.cmkdir -p $(dir $)gcc -c $^ -o $compile : $(cpp_objs)PS E:\桌面\c_test make compile
gcc -c add.c -o output/add.o
gcc -c main.c -o output/main.o
PS E:\桌面\c_test 使用makedir -p可以在没有文件夹的时候创建文件夹 In a Makefile, the % symbol is used as a wildcard character to match any string. It is often used in conjunction with pattern rules to specify a set of targets and dependencies that follow a certain pattern. notdir
$(notdir names...)如果输入的文件里面有文件夹的路径名, 就会去掉 libs : $(notdir $(shell find /usr/lib -name lib*))会寻找这里面的所有的库文件, 之后会把所有的文件的文件路径去除 filter
$(filter names...)根据自己的需求过滤掉一些文件 libs : $(notdir $(shell find /usr/lib -name lib*))
a_libs : $(filter %.a,$(libs))
so_libs : $(filter %.so,$(libs))在这里面可以会找到两种不同格式的库文件 basename
会把文件的后缀去掉
$(basename names...)libs : $(notdir $(shell find /usr/lib -name lib*))
a_libs : $(subst lib,,$(basename $(filter %.a,$(libs))))
so_libs : $(subst lib,,$(basename $(filter %.so,$(libs))))会去除.o和.so的文件后缀名,在之后就是去掉文件的前缀 filter-out
剔除不想要的字符串
objs : objs/add.o objs/minus.o objs/main.o
cpp_objs : $(filter-out objs/main.o, $(objs))wildcard
The wildcard function expands to a space-separated list of filenames that match the given patterns
cpp_srcs : $(wildcard src/*.cc src/*.cpp src/*.c)实战教程
.PHONY : debug compile
c_srcs : $(shell ls *.c)
# 添加输出的文件的文件夹名字
c_objs : $(foreach item,$(c_srcs),./output/$(item))
# 获取要输出的各种文件的名字
c_objs : $(subst .c,.o,$(c_objs))
c_i : $(subst .o,.i,$(c_objs))
c_s : $(subst .o,.s,$(c_objs))run : output/result.exe.\$debug :echo $(c_objs) echo $(c_i)output/%.o : %.cmkdir -p $(dir $)gcc -c $^ -o $output/%.i : %.cmkdir -p $(dir $)gcc -E $^ -o $output/%.s : %.cmkdir -p $(dir $)gcc -S $^ -o $output/result.exe : $(c_objs)mkdir -p $(dir $)gcc $^ -o $ clean :rm -rf outputcompile : $(c_objs) $(c_i) $(c_s) output/result.exe
编译的选项 编译选项 -m64: 指定编译为 64 位应用程序-std: 指定编译标准例如-stdc11、-stdc14-g: 包含调试信息-w: 不显示警告-O: 优化等级通常使用-O3-I: 加在头文件路径前fPIC: (Position-Independent Code), 产生的没有绝对地址全部使用相对地址代码可以被加载到内存的任意位置且可以正确的执行。这正是共享库所要求的共享库被加载时在内存的位置不是固定的 链接选项 -l: 加在库名前面-L: 加在库路径前面-Wl,选项: 将逗号分隔的 选项 传递给链接器-rpath: “运行” 的时候去找的目录。运行的时候要找 .so 文件会从这个选项里指定的地方去找
通常使用的变量名
CC: Program for compiling C programs; default ccCXX: Program for compiling C programs; default gCFLAGS: Extra flags to give to the C compilerCXXFLAGS: Extra flags to give to the C compilerCPPFLAGS: Extra flags to give to the C preprocessorLDFLAGS: Extra flags to give to compilers when they are supposed to invoke the linker
编译带头文件的程序
c_srcs : $(shell ls ./src//*.c)
c_objs : $(patsubst ./src%.c,./output%.o, $(c_srcs))in_path : ./inc
I_flags : $(foreach item,$(in_path),-I$(item))compile_options : -g -O1 -w $(I_flags)output/%.o : src/%.cmkdir -p $(dir $)gcc -c $^ -o $ $(compile_options)output/result : $(c_objs)mkdir -p $(dir $)gcc $^ -o $ $(compile_options)run : output/result./output/resultclean : rm -rf ./outputgdb : output/resultgdbdebug :echo $(I_flags).PHOHY : debug run gdb clean