图片 9

Makefile简单入门教程,变量重定义

并发变量重定义的情况?

一、简介

后天在Linux下编制程序开采多少个奇异的光景,就是在链接二个静态库的时候总是报错,形似上边那样的大错特错:(.text+0x13卡塔尔:
undefined reference to `func’

源文件与include的公文定义了同叁个变量

main.c

1 #include <stdio.h>
2 #include "a.c"
3 
4 int a = 100;
5 
6 int main() {
7 
8     return 0;
9 }

a.c

 1 int a = 200; 

编写翻译命令:

gcc main.c -o main

编写翻译报错:

 图片 1

make命令推行时,需求一个 Makefile
文件,以报告make命令要求如何的去编写翻译和链接程序(简单将:管理工科程的文书,决定先编写翻译哪些文件,编写翻译顺序)。

关于undefined
reference那样的标题,大家实在平时会越过,在这,作者以详尽地示范给出置之不理错误的种种缘由以致减轻办法,希望对初学者有所扶助。
1. 链接时缺点和失误了连带目的文件(.o)
**
**测试代码如下:

链接的多个文件都定义了同一个变量

main.c

1 #include <stdio.h>
2 
3 int a = 100;
4 
5 int main() {
6 
7     return 0;
8 }

a.c

int a = 200;

编写翻译命令:

gcc -c main.c -o main.o

gcc -c a.c -o a.o

gcc main.o a.o -o main

末段一步链接会报错:

 图片 2

二、编写法规:

图片 3

指标1:目的依赖  然后回车+tab键
 命令;

对象2:指标注重  然后回车+tab键
 命令;

然后编写翻译。

对象n:指标重视  然后回车+tab键
 命令;

gcc -c test.c

gcc –c main.c 

瞩目:命令必需是tab键开首的。

获取七个 .o 文件,二个是 main.o,一个是 test.o ,然后我们链接 .o
获得可施行程序:
gcc -o main main.o

三、Makefile演进
1、一个项目有main.c/a.c/a.h/b.c/b.h七个文本;main.c包蕴a.h和b.h并动用有关函数;然后建构八个新的Makefile文件,内容如下:
main:a.o b.o
 gcc -o main a.o b.o 
a.o:a.c
 gcc -c a.c -o a.o 
b.o:b.c
 gcc -c b.c -o b.o

此刻,你会发觉,报错了:
main.o: In function
main': main.c:(.text+0x7): undefined reference totest’
collect2: ld returned 1 exit status

2、Makefile升级1
动用makefile变量:想用就用,未有项目,无需定义(引用变量使用$(obj卡塔尔(قطر‎来含有越来越多.o文件)
方法:obj:=a.o b.o
那正是说地点的Makefile程序晋级如下:
obj:=a.o b.o
main:$(obj)
 gcc -o main a.o b.o 
a.o:a.c
 gcc -c a.c -o a.o 
b.o:b.c
 gcc -c b.c -o b.o

那即是最特异的undefined
reference错误,因为在链接时发掘找不到某些函数的贯彻公文,本例中test.o文件中富含了test(卡塔尔(قطر‎函数的完毕,所以假设按下边这种办法链接就没事了。
gcc -o main main.o test.o

3、Makefile升级2
透过以上三个makefile的编写翻译,项目施行是水到渠成的,可是尽管main.c要求援用更加的多文件中的函数时,是或不是要填写那么多的编写翻译命令吗?显著这些艺术不可取。
校勘:makefile特殊变量和活动推导功能
知识点表明:
$@  代表目的名,
$^  代表注重文件
%  代表私行字符
%.o  代表放肆.o文件
%.c  代表任意.c文件

【扩充】:其实上面为了让我们尤为明亮底层原因,笔者把编写翻译链接分开了,上面那样编译也会报undefined
reference错,其实底层原因与地点是意气风发致的。
gcc -o main main.c //缺乏test(卡塔尔的完毕文件

如上Makefile晋级如下:
obj:=a.o b.o
main:$(obj)
 gcc -o main $(obj) 
%.o:%c      #讲解:格局通配,自动将.c文件编写翻译成.o文件
 gcc -o $@ -c $^    #注释:通配符
clean:
 rm -rf *.o main

内需改成如下格局能力成功,将test(卡塔尔函数的兑现文件一起编写翻译。
gcc -o main main.c test.c //ok,没难题了

4、Makefile升级3
exe=main      #批注:最终的编写翻译结果名字
obj:=main.o a.o b.o c.o   #注解:重视文件
all:$(obj)
gcc -o $(exe) $(obj)
%.o:%.c
gcc -c $^ -o $@
clean:
rm -rf $(obj) $(exe)

2. 链接时缺乏相关的库文件(.a/.so)
在这里,只举个静态库的事例,如果源码如下。

如上程序看似未有何难点的,但是clean有一点点劣点,倘使也是有四个文件叫clean那如何是好?假使make
clean就不能够实行那条命令。

图片 4

5、Makefile升级4
使用伪指标.PHONY来缓慢解决clean瑕玷难题,晋级Makefile如下:
exe:=main
obj:=main.o a.o b.o c.o
all:$(obj)
 gcc -o $(exe) $(obj)
%.o:%.c
 gcc -c $^ -o $@
.PHONY:clean     #评释:注脚clean是伪目的
clean:
 rm -rf $(obj) $(exe)

注释#.PHONY:clean申明伪目的,防止当前目录存在名称为clean文件的时候吩咐不可能进行的情况

先把test.c编写翻译成静态库(.a卡塔尔国文件
gcc -c test.c
ar -rc test.a test.o

6、Makefile升级5
不时利用的编写翻译器或许是g++、gcc以至是arm-linux-gcc。为了有援助统生龙活虎管理,最棒开首定义三个变量来表示编辑器,然后在gcc命令上形成$(CC卡塔尔(英语:State of Qatar):
Makefile升级如下:
CC:=gcc    #批注:定义三个变量,表示近日编辑器为gcc
exe:=main
obj:=main.o a.o b.o c.o
all:$(obj)
 $(CC) -o $(exe) $(obj) 
%.o:%.c
 $(CC) -c $^ -o $@
.PHONY:clean
clean:
 rm -rf $(obj) $(exe)

于今截至,大家收获了test.a文件。大家开端编写翻译main.c
gcc -c main.c

基本上以后的Makefie能够编写超级多习感觉常的主次了。秩序要对Makefile的文件名合适稍加改革就能够。要是在可比大型的次第里面写Makefile会相对知识点多或多或少,比方加多静态库、动态库、线程等等;后续再做进步。

那时,则生成了main.o文件,然后大家再通过如下命令实行链接希望收获可执路程序。
gcc -o main main.o

推荐一本书:GNU make普通话手册(翻译收拾:徐海兵)

您会发觉,编写翻译器报错了:
/tmp/ccCPA13l.o: In function
main': main.c:(.text+0x7): undefined reference totest’
collect2: ld returned 1 exit status

本文长久更新链接地址:http://www.linuxidc.com/Linux/2017-06/145306.htm

其根本原因也是找不到test(卡塔尔(英语:State of Qatar)函数的贯彻公文,由于该test(卡塔尔(英语:State of Qatar)函数的实以后test.a那些静态库中的,故在链接的时候供给在其后插手test.a那些库,链接命令改革为如下情势就可以。
gcc -o main main.o ./test.a //注:./ 是提交了test.a的不二秘诀

图片 5

【扩充】:相像,为了把难点说了然,上边我们把代码的编写翻译链接分开了,假诺指望一回性生成可执路程序,则足以对main.c和test.a实行如下命令。
gcc -o main main.c ./test.a //相符,借使不加test.a也会报错

3. 链接的库文件中又接收了另叁个库文件
这种主题素材相比较隐瞒,也是自家近年凌驾的与网络海高校家争辩的区别的难点,比如表达如下,首先,依旧看看测量检验代码。

图片 6

从上航海用体育场合能够看来,main.c调用了test.c的函数,test.c中又调用了fun.c的函数。
首先,大家先对fun.c,test.c,main.c进行编写翻译,生成 .o文件。
gcc -c func.c
gcc -c test.c
gcc -c main.c

接下来,将test.c和func.c各自打包成为静态库文件。
ar –rc func.a func.o
ar –rc test.a test.o

那会儿,我们希图将main.o链接为可执路程序,由于大家的main.c中蕴藏了对test(卡塔尔(英语:State of Qatar)的调用,由此,应该在链接时将test.a作为咱们的库文件,链接命令如下。
gcc -o main main.o test.a

那会儿,编写翻译器依旧会报错,如下:
test.a(test.o): In function
test': test.c:(.text+0x13): undefined reference tofunc’
collect2: ld returned 1 exit status

正是说,链接的时候,开掘我们的test.a调用了func(卡塔尔(英语:State of Qatar)函数,找不到相应的得以完毕。由此我们发现,原本笔者们还索要将test.a所引用到的库文件也加进去技术打响链接,由此命令如下。
gcc -o main main.o test.a func.a

ok,那样就能够成功博得终极的顺序了。相似,假设大家的库也许程序中引用了第三方库(如pthread.a)则未有差距于在链接的时候供给提交第三方库的门径和库文件,不然就能博得undefined
reference的荒谬。
4 八个库文件链接顺序难点
这种主题材料也突出的躲避,不紧凑商量您恐怕会觉获得极其地莫明其妙。我们照样回到第3小节所研究的主题素材中,在最终,假诺大家把链接的库的逐个换一下,看看会生出如何结果?
gcc -o main main.o func.a test.a

咱俩会博得如下报错.
test.a(test.o): In function
test': test.c:(.text+0x13): undefined reference tofunc’
collect2: ld returned 1 exit status

就此,我们必要专心,在链接命令中给出所重视的库时,供给注意库之间的依据顺序,注重别的库的库一定要放手被重视库的前面,那样技能真的制止undefined
reference的失实,完毕编写翻译链接。
5.
在c++代码中链接C语言的库

黄金时代经您的库文件由c代码生成的,则在c++代码中链接库中的函数时,也会遇上undefined
reference的主题素材。下边举个例子表明。
首先,编写c语言版库文件:

图片 7

编写翻译,打包为静态库:test.a
gcc -c test.c
ar -rc test.a test.o

至此,大家收获了test.a文件。上面大家起头编写制定c++文件main.cpp

图片 8

然后编写翻译main.cpp生成可推行程序:
g++ -o main main.cpp test.a

会开采报错:
/tmp/ccJjiCoS.o: In function
main': main.cpp:(.text+0x7): undefined reference totest()’
collect2: ld returned 1 exit status

原因就是main.cpp为c++代码,调用了c语言库的函数,由此链接的时候找不到,解决措施:即在main.cpp中,把与c语言库test.a相关的头文件包蕴增多叁个extern
“C”的宣示就能够。比方,校勘后的main.cpp如下:

图片 9

g++ -o main main.cpp test.a

再编写翻译会发掘,难题已经打响解决。

发表评论

电子邮件地址不会被公开。 必填项已用*标注