网站快速排名方法,php cms网站,营销网站模板htlm,分辨率大于1920的网站怎么做目录含有交叉编译、pthread_create()处理初次使用1、编写Makefile文件2、make3、make cleanMakefile基本语法1、Makefile规则格式2、变量3、变量赋值符#xff08;、:、?、#xff09;4、模式规则#xff08;通配符#xff09;5、自动化变量6、伪目标7、条件判断8、函数使…
目录含有交叉编译、pthread_create()处理初次使用1、编写Makefile文件2、make3、make cleanMakefile基本语法1、Makefile规则格式2、变量3、变量赋值符、:、?、4、模式规则通配符5、自动化变量6、伪目标7、条件判断8、函数使用1、函数 subst2、函数 patsubst3、函数 dir4、函数 notdir5、函数 foreach6、函数 wildcard含有交叉编译、pthread_create()处理 摘自使用makefile编译含有pthread_create()函数时报错对‘pthread_create’未定义的引用 交叉编译的话直接将Makefile里面的gcc替换成arm-linux-gnueabihf-gcc即可。
在linux应用程序中使用了多线程编程但是makefile编译却报如下错误
/tmp/cc5i6uH7.o在函数‘main’中
tcpSever.c:(.text0x62)对‘modRegInit’未定义的引用
tcpSever.c:(.text0x76)对‘ryS’未定义的引用
tcpSever.c:(.text0xc0)对‘ryS’未定义的引用
tcpSever.c:(.text0x10a)对‘ryS’未定义的引用
tcpSever.c:(.text0x14e)对‘ryS’未定义的引用
collect2: error: ld returned 1 exit status网上查找解决方案发现修改makefile即可。如下
test: rySys.o tcpSever.ogcc -o test rySys.o tcpSever.o -lpthread
rySys.o: rySys.c rySys.hgcc -c rySys.c -lpthread
tcpSever.o: tcpSever.c rySys.c rySys.hgcc -c tcpSever.c -lpthread
clean:rm *.orm test初次使用
当文件有几十、上百甚至上万个的时候用终端输入 gcc 命令的方法显然是不现实的为此提出了一个解决大工程编译的工具make描述哪些文件需要编译、哪些需要 重新编译 的文件就叫做 Makefile。使用的时候只需要一个 make 命令即可完成整个工程的自动编译极大的提高了软件开发的效率。
使用make工具可以自动完成编译工作这些工作包括
如果修改了某几个源文件则只重新编译这几个源文件如果某个头文件被修改了则重新编译所有包含该头文件的源文件。 1、编写Makefile文件
在工程目录下创建Makefile文件
Makefile 里面是由一系列的规则组成的这些规则格式如下
目标…... : 依赖文件集合……命令1命令2……Makefile 和 .c 文件是处于同一个目录的在Makefile文件中输入如下代码
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o
main.o: main.cgcc -c main.c
fun1.o: fun1.cgcc -c fun1.c
fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm main上述代码中所有行首需要空出来的地方一定要使用 “TAB” 键不要使用空格键这是 Makefile 的语法要求
2、make
Makefile 编写好以后我们就可以使用make命令来编译我们的工程了直接在命令行中输入make即可make 命令会在当前目录下查找是否存在 “Makefile” 这个文件如果存在的话就会按照 Makefile 里面定义的编译方式进行编译
make此时我们修改一下 fun1.c 的文件源码再make 可以看出因为我们修改了fun1.c这个文件所以fun1.c和最后的可执行文件main重新编译了其它没有修改过的文件就没有编译而且我们只需要输入make命令即可非常方便。
3、make clean
make cleanMakefile基本语法
1、Makefile规则格式
目标...: 依赖文件集合...命令1命令2......命令列表中的每条命令必须以 TAB 键开始不能使用空格 比如
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o这条规则的目标是mainmain.o、fun1.o、fun2.o是生成main的依赖文件如果要更新目标main就必须先更新它的所有依赖文件如果依赖文件中的任何一个有更新更改时间那么目标也必须更新“更新”就是执行一遍规则中的命令列表。make命令会为Makefile中的每个以 TAB 开始的命令创建一个 Shell 进程去执行。
示例
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o
main.o: main.cgcc -c main.c
fun1.o: fun1.cgcc -c fun1.c
fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm mainmake命令在执行这个Makefile的时候其执行步骤如下
首先更新第一条规则中的main第一条规则的目标成为默认目标只要默认目标更新了那么就认为Makefile的工作完成。在第一次编译的时候由于main还不存在因此第一条规则会执行第一条规则依赖于文件main.o、fun1.o和fun2.o这个三个.o文件这三个.o文件目前还都没有因此必须先更新这三个文件。make 会查找以这三个.o文件为目标的规则并执行。
以main.o为例发现更新main.o的是第二条规则因此会执行第二条规则第二条规则里面的命令为“gcc –c main.c”这行命令就是不链接编译main.c生成main.o。
最后一个规则目标是clean它没有依赖文件因此会默认为依赖文件都是最新的所以其对应的命令不会执行当我们想要执行clean的话可以直接使用命令make clean执行以后就会删除当前目录下所有的.o文件以及main因此clean的功能就是完成工程的清理工作。
总结make执行过程
① make命令会在当前目录下查找以 Makefile(或makefile) 命名的文件。
② 当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
③ 当发现目标文件不存在或者目标所依赖的文件比目标文件新也就是最后修改时间比目标文件晚的话就会执行后面的命令来更新目标。 注意 除了 Makefile 的“终极目标”所在的规则以外其它规则的顺序在 Makefile中是没有意义的“终极目标”就是指在使用 make 命令的时候没有指定具体的目标时make 默认的那个目标它是 Makefile 文件中第一条规则的目标如果 Makefile 中的第一个规则有多个目标那么这些目标中的第一个目标就是 make 的“终极目标”。 2、变量
跟 C 语言一样 Makefile 也是支持变量的如前面的例子
main: main.o fun1.o fun2.ogcc -o main main.o fun1.o fun2.o上述 Makefile 语句中main.o、fun1.o、fun2.o 这三个依赖文件我们输入了两遍我们这个 Makefile 比较小如果 Makefile 复杂的时候这种重复输入的工作就会非常费时间Makefile 加入了变量支持类似 C 语言中的宏。使用变量将上面的代码修改
# Makefile 变量的使用
objects main.o fun1.o fun2.o
main: $(objects)gcc -o main $(objects)Makefile 的注释用#。 我们定义了一个变量objects并且给这个变量进行了赋值其值为字符串main.o fun1.o fun2.oMakefile 中变量的引用方法是 $(变量名)如本例中 $(objects)。
我们在定义变量objects 的时候使用“”对其进行了赋值Makefile 变量的赋值符还有其它两个“:”和“?”我们来看一下这三种赋值符的区别
3、变量赋值符、:、?、
使用“”在给变量的赋值的时候不一定要用已经定义好的值也可以使用后面定义的值比如如下代码
① 赋值符
name lcx
curname $(name)
name licxprint:echo curname: $(curname)第一行定义了一个变量name值为lcx第二行定义了变量curname值也为lcx第三行变量name的值改为licx第五、六行是输出变量curname的值。在 Makefile 要输出一串字符的话使用echo。第六行中的echo前面加了个 符号因为 Make 在执行的过程中会自动输出命令执行过程在命令前加上就不会输出命令执行过程执行结果 可以看出curname的值不是lcx而是变量name最后一次赋值的结果。
② 赋值符:
name lcx
curname : $(name)
name licxprint:echo curname: $(curname)执行结果 显然此时curname值为lcx因为赋值符:只能使用前面定义的值。
③ 赋值符?
curname ? licx上述代码的意思是如果变量curname前面没有被赋值那么此变量就是licx如果前面已经赋过值了那么就使用前面赋的值。
④ 变量追加符
Makefile 中的变量是字符串有时候我们需要给前面已经定义好的变量添加一些字符串此时就要使用变量追加符号如
objects main.o fun1.o
objects fun2.oprint:echo objects: $(objects)可以看出objects最后的值为main.o fun1.o fun2.o。
4、模式规则通配符
如下示例代码
objects main.o fun1.o fun2.o
main: $(objects)gcc -o main $(objects)main.o: main.cgcc -c main.c
fun1.o: fun1.cgcc -c fun1.c
fun2.o: fun2.cgcc -c fun2.cclean:rm *.orm main显然如果工程中.c文件很多这样做就很不方便我们可以使用 Makefile 中的模式规则使用一条规则来将所有的.c文件编译为对应的.o文件。
模式规则中至少在规则的目标定义中要包含%否则就是一般规则目标中的%表示对文件名的匹配%表示长度任意的非空字符串比如%.c就是所有的以.c结尾的文件类似于通配符。
示例可以改成如下形式
objects main.o fun1.o fun2.o
main: $(objects)gcc -o main $(objects)%.o: %.c#命令clean:rm *.orm main第六行的命令我们需要借助下面的自动化变量 ↓↓↓
5、自动化变量
上面讲的模式规则中目标和依赖都是一系列的文件每一次对模式规则进行解析的时候都会是不同的目标和依赖文件而命令只有一行那么如何通过一行命令来从不同的依赖文件中生成对应的目标自动化变量就是完成这个功能的
自动化变量就是这种变量会把模中所定义的一系列的文件自动的挨个取出直至所有的符合模式的文件都取完自动化变量只应该出现在规则的命令中常用的自动化变量如下 常用的三种 $、 $ 和 $^
那么上述代码我们可以完善
objects main.o fun1.o fun2.o
main: $(objects)gcc -o main $(objects)%.o: %.cgcc -c $clean:rm *.orm main6、伪目标
伪目标的主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突有时候我们需要编写一个规则用来执行一些命令但是这个规则不是用来创建文件的比如文章示例有如下代码用来完成清理工程的功能
clean:rm *.orm main上述规则中并没有创建clean文件的命令因此工作目录下永远都不会存在文件clean当我们输入make clean以后后面的rm *.o和rm main总是会执行。如果我们在工作目录下创建一个名为clean重名的文件当执行make clean的时候规则因为没有依赖文件所以目标被认为是最新的 刚创建了一个clean文件是最新的因此后面的rm命令也就不会执行如图所示 为了避免这个问题我们可以将clean声明为伪目标声明方式如下
.PHONY:clean那么我们可以将示例代码修改为
.PHONY : cleanclean:rm *.orm main7、条件判断
在 C 语言中我们通过条件判断语句来根据不同的情况来执行不同的分支Makefile 也支持条件判断语法有两种如下
条件关键字
条件为真时执行的语句
endif以及
条件关键字
条件为真时执行的语句
else
条件为假时执行的语句
endif其中条件关键字有 4 个ifeq、ifneq、ifdef 和 ifndef这四个关键字其实分为两对、ifeq 与ifneq、ifdef 与 ifndef先来看一下 ifeq 和 ifneqifeq 用来判断是否相等ifneq 就是判断是否不相等ifeq 用法如下
ifeq (参数 1, 参数 2)
ifeq ‘参数 1 ’,‘ 参数 2’
ifeq “参数 1”, “参数 2”
ifeq “参数 1”, ‘参数 2’
ifeq ‘参数 1’, “参数 2”上述用法中都是用来比较“参数 1”和“参数 2”是否相同如果相同则为真“参数 1”和“参数 2”可以为函数返回值。ifneq 的用法类似只不过 ifneq 是用来了比较“参数 1”和“参数 2”是否不相等如果不相等的话就为真。
ifdef 和 ifndef 的用法如下
ifdef 变量名如果“变量名”的值非空那么表示表达式为真否则表达式为假。“变量名”同样可以是一个函数的返回值。ifndef 用法类似但是含义用户 ifdef 相反。
8、函数使用
Makefile 支持函数类似 C 语言一样Makefile 中的函数是已经定义好的我们直接使用不支持我们自定义函数。make 所支持的函数不多函数的用法如下
$(函数名 参数集合)或者
${函数名 参数集合}可以看出调用函数和调用普通变量一样使用符号 “$ ” 来标识。参数集合是函数的多个参数参数之间以逗号“,”隔开函数名和参数之间以“空格”分隔开函数的调用以“$”开头。 接下来我们介绍几个常用的函数来保证后面的学习。其它的函数大家可以参考《跟我一起写 Makefile》这份文档。 1、函数 subst
函数 subst 用来完成字符串替换调用形式如下
$(subst from,to,text)此函数的功能是将字符串 text中的内容替换为 to函数返回被替换以后的字符串比如如下示例
$(subst zzk,ZZK,my name is zzk把字符串“my name is zzk”中的“zzk”替换为“ZZK”替换完成以后的字符串为“my name is ZZK”。
2、函数 patsubst
函数 patsubst 用来完成模式字符串替换使用方法如下
$(patsubst pattern,replacement,text)此函数查找字符串 text中的单词是否符合模式 pattern如果匹配就用 replacement来替换掉 pattern可以使用通配符“%”表示任意长度的字符串函数返回值就是替换后的字符串。如果 replacement中也包涵“%”那么 replacement中的“%”将是 pattern中的那个“%”所代表的字符串比如
$(patsubst %.c,%.o,a.c b.c c.c)将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串替换为“%.o”替换完成以后的字符串为“a.o b.o c.o”。
3、函数 dir
函数 dir 用来获取目录使用方法如下
$(dir names…)此函数用来从文件名序列 names中提取出目录部分返回值是文件名序列 names的目录部分比如
$(dir /src/a.c)提取文件“/src/a.c”的目录部分也就是“/src”。
4、函数 notdir
函数 notdir 看名字就是知道去除文件中的目录部分也就是提取文件名用法如下
$(notdir names…)此函数用与从文件名序列 names中提取出文件名非目录部分比如
$(notdir /src/a.c)提取文件“/src/a.c”中的非目录部分也就是文件名“a.c”。
5、函数 foreach
foreach 函数用来完成循环用法如下
$(foreach var, list,text)此函数的意思就是把参数中的单词逐一取出来放到参数 var 中 然后再执行 text 所包含的表达式。每次 text 都会返回一个字符串循环的过程中 text 中所包含的每个字符串会以空格隔开最后当整个循环结束时 text 所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。
6、函数 wildcard
通配符“%”只能用在规则中只有在规则中它才会展开如果在变量定义和函数使用时通配符不会自动展开这个时候就要用到函数 wildcard使用方法如下
$(wildcard PATTERN…)比如
$(wildcard *.c)上面的代码是用来获取当前目录下所有的.c 文件类似“%”。