c语言编译器dev使用找不到指定,GCC Makefile说明

1、GCC 简介

首先了解一下GCC,GCC 的意思也只是 GNU C Compiler 而已。经过了这么多年的发展,GCC 已经不仅仅能支持 C 语言;它现在还支持 Ada 语言、C++ 语言、Java 语言、Objective C 语言、Pascal 语言、COBOL语言,以及支持函数式编程和逻辑编程的 Mercury 语言,等等。而 GCC 也不再单只是 GNU C 语言编译器的意思了,而是变成了 GNU Compiler Collection 也即是 GNU 编译器家族的意思了。

/* filename: main.c */

#include "mytool1.h"

#include "mytool2.h"

int main(int argc,char **argv)

{

myprint1("hello");

myprint2("world");

}

对于上述的例子,编译的命令为gcc main.c -o test1 ,这样可生产可执行文件。实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

对于多个文件的编译,假设有一个由test1.c和 test2.c两个源文件组成的程序,为了对它们进行编译,并最终生成可执行程序test,可以使用下面的命令:

gcc -c test1.c

gcc -c test2.c

gcc -o test test1.o test2.o

2、库文件连接

开发软件时,完全不使用第三方函数库的情况是比较少见的,通常来讲都需要借助许多函数库的支持才能够完成相应的功能。从程序员的角度看,函数库实际上就是一些头文件(.h)和库文件(so、或lib、dll)的集合。。虽然Linux下的大多数函数都默认将头文件放到/usr/include/目录下,而库文件则放到/usr/lib/目录下;Windows所使用的库文件主要放在Visual Stido的目录下的include和lib,以及系统文件夹下。但也有的时候,我们要用的库不再这些目录下,所以GCC在编译时必须用自己的办法来查找所需要的头文件和库文件。

例如我们的程序test.c是在linux上使用c连接mysql,这个时候我们需要去mysql官网下载MySQL Connectors的C库,下载下来解压之后,有一个include文件夹,里面包含mysql connectors的头文件,还有一个lib文件夹,里面包含二进制so文件libmysqlclient.so,

其中inclulde文件夹的路径是/usr/dev/mysql/include,lib文件夹是/usr/dev/mysql/lib,首先我们要进行编译test.c为目标文件,这个时候需要执行

gcc –c –I /usr/dev/mysql/include test.c –o test.o

最后我们把所有目标文件链接成可执行文件:

gcc –L /usr/dev/mysql/lib –lmysqlclient test.o –o test

Linux下的库文件分为两大类分别是动态链接库(通常以.so结尾)和静态链接库(通常以.a结尾),二者的区别仅在于程序执行时所需的代码是在运行时动态加载的,还是在编译时静态加载的。

静态库链接时搜索路径顺序:

1. ld会去找GCC命令中的参数-L

2. 再找gcc的环境变量LIBRARY_PATH

3. 再找内定目录 /lib /usr/lib /usr/local/lib 这是当初compile gcc时写在程序内的

动态链接时、执行时搜索路径顺序:

1. 编译目标代码时指定的动态库搜索路径

2. 环境变量LD_LIBRARY_PATH指定的动态库搜索路径

3. 配置文件/etc/ld.so.conf中指定的动态库搜索路径

4. 默认的动态库搜索路径/lib

5. 默认的动态库搜索路径/usr/lib

有关环境变量:

LIBRARY_PATH环境变量:指定程序静态链接库文件搜索路径

LD_LIBRARY_PATH环境变量:指定程序动态链接库文件搜索路径

3、 Makefile说明

1 、Makefile 一个例子

假设我们有下面这样的一个程序,源代码如下:

/* filename: main.c */

#include "mytool1.h"

#include "mytool2.h"

int main(int argc,char **argv)

{

myprint1("hello");

myprint2("world");

}

/* filename: mytool1.c */

#include "mytool1.h"

void myprint1(char *print_str)

{

printf("This is mytool1 print %s/n",print_str);

}

/* filename: mytool2.h */

#ifndef _MYTOOL_2_H

#define _MYTOOL_2_H

void myprint2(char *print_str);

#endif

/* filename: mytool2.c */

#include "mytool2.h"

void myprint2(char *print_str)

{

printf("This is mytool2 print %s/n",print_str);

}

我们可以这样来编译:

gcc -c main.c

gcc -c mytool1.c

gcc -c mytool2.c

gcc -o main main.o mytool1.o mytool2.o

这样也可以产生main程序,且不是很麻烦。但如果有一天我们修改了其中的一个文件(比如说mytool1.c),那么难道我们还要重新输入上面的命令吗?也许你会说,这个很容易解决啊,我写一个SHELL脚本,让她帮我去完成不就可以了。是的,对于这个程序来说,是可以的,但如果我们的程序有几百个源程序的时候,怎么办?难道也要编译器重新一个一个的编译?

为此,聪明的程序员们想出了一个很好的工具来做这件事情,这就是make。我们只要执行一下make命令,就可以把上面的问题解决掉。在我们执行make命令前,要先编写Makefile文件。

对于上面的例子,一个可能的Makefile的文件如下。

main: main.o mytool1.o mytool2.o

gcc -o main main.o mytool1.o mytool2.o

main.o: main.c

gcc -c main.c

mytool1.o: mytool1.c

gcc -c mytool1.c

mytool2.o: mytool2.c

gcc -c mytool2.c

4 、Makefile的编写注意:

(1)Makefile文件中,注释以"#"开始。

(2)编译时需要引用环境变量时用$符号加上{}来使用,如:${JAVA_HOME}  ;需要应用本文中的别名,则可使用 $()  。

(3)隐含规则,看下面一个例子

foo : foo.o bar.o cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)

我们可以注意到,这个Makefile中并没有写下如何生成foo.o和bar.o这两目标的规则和命令。因为make的“隐含规则”功能会自动为我们自动去推导这两个目标的依赖目标和生成命令。make 会在自己的“隐含规则”库中寻找可以用的规则,如果找到,那么就会使用。如果找不到,那么就会报错。在上面的那个例子中,make调用的隐含规则是,把 [.o]的目标的依赖文件置成[.c],并使用C的编译命令“cc –c $(CFLAGS) [.c]”来生成[.o]的目标。也就是说,我们完全没有 必要写下面的两条规则:

foo.o : foo.ccc –c foo.c $(CFLAGS) bar.o : bar.c cc –c bar.c $(CFLAGS)

当然,如果c++文件或者c文件在子目录中,隐含规则是找不到的,那就需要写完整并且加上指定的子目录路径,这样才能生成.o文件了

自己写的一个列子

CC=g++

OBJS=DBUtil.o MQBDSolution.o Lock.o

LIB=-L/opt/db/oracle/product/11.2.0/dbhome_1/lib -L/opt/db/oracle/product/11.2.0/dbhome_1/rdbms/lib/ # -L代表链接的库文件

INCLUDE=-I/opt/db/oracle/product/11.2.0/dbhome_1/precomp/public -I/opt/db/oracle/product/11.2.0/dbhome_1/rdbms/public

# -I 代表链接的第三方头文件

MQBDSolution: $(OBJS)

$(CC) -o MQBDSolution $(OBJS) $(LIB) -pthread -locci -lclntsh

DBUtil.o: dao/DBUtil.cpp

$(CC) -c dao/DBUtil.cpp $(INCLUDE)

Lock.o: util/Lock.cpp

$(CC) -c util/Lock.cpp $(INCLUDE)

MQBDSolution.o:MQBDSolution.cpp

$(CC) -c MQBDSolution.cpp $(INCLUDE) -Wall -O -g

clean:

rm -rf *.o & rm MQBDSolution

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值