当前位置:首页 » 编程软件 » makefile编译规定

makefile编译规定

发布时间: 2022-10-06 21:12:13

① Ubuntu下面Makefile的使用方法

运行可执行文件hello

./hello

移除文件 rm hello

编译文件得到可执行文件的同时,保留产生的中间文件

g++ -save-temps hello_world.cpp -o hello

单个文件编译过程:
实际的编译过程:预处理,对应临时文件hello_world.ii

g++ -E hello_world.cpp -o preprocessed.ii

cat preprocessed.ii

预处理的工作主要包含去掉注释,然后将我们include的库tack上,以上过程使我们自己主动调用预处理器的过程

cat hello_world.ii

则展示了我们在第5)中编译时保留的中间文件,两者是一样的

实际的编译过程:这是真正的编译过程compilation step,对应临时文件hello_world.s(assembly code)

我们自己把.ii文件进行assembly code得到.s的方法。

g++ -S preprocessed.ii -o complied.s

.s文件是高级语言和机器语言之间的中间环节

实际的编译过程:Assembly,将.s对应的assembly code转换成.o对应的机器语言的过程,也叫machine-readable code或者object code

让编译器将.s文件assembly起来

g++ -c complied.s -o assembled.o

实际的编译过程:最后一步Linking,产生最终的可执行文件。

"Undefined reference" errors are pretty much always linking errors, and you will probably have them. Remember this.

我们通过连接一堆.o文件,得到.exe文件的过程,命令:

g++ assembled.o -o hello_manual

多个文件编译过程:
举例,如果我们有定义一个class,然后我们的文件中包含dog.hpp,dog.cpp和main.cpp三个文件,然后我们只使用以下两个命令:

g++ -c main.cpp -o main.o

g++ main.o dog_program

的话就会出错,告诉我们undefined reference of dog::bark()

因为对于不同的.cpp文件,都要生成一个object file,也就是.o文件。所以如果我们用以下命令:

g++ -c main.cpp -o main.o

g++ -c dog.cpp

g++ dog.o main.o -o dog_program

的话,就不会出错。

我们如果修改main.cpp中的内容的话,我们只需要重新用最后一个连接命令。但是,如果我们修改了dog class本身的内容的话,例如添加一个函数,我们就需要重新产生object file of dog.cpp,然后重新连接。

关于Make的介绍
用自己常用的记事本创建一个Makefile,并注意大小写。在program对应的目录下面。

gedit Makefile

Makefile里面语句的书写规则是

Target: tgt_dependency1 tgt_dependency2 ……
Command

所以dog.o和main.o对应的语句分别是:

dog.o: dog.hpp dog.cpp
g++ -c dog.cpp

main.o: main.cpp
g++ -c main.cpp

在Makefile中Tab是很重要的,所以不要忘记在command对应的第二行加Tab

Makefile的编译顺序

如果Makefile中有如下语句

animal_assembly : moose goose cat
command

moose : antlers hooves fur
command

goose : beak wings webbed_feet interest_in_bread
command

cat : whiskers evil_personality
command

我们可以看到animal_assembly的dependency是 moose goose cat。如果文件夹中存在moose goose cat的话,make命令只需要执行第一句就可以了。如果文件夹中缺少moose goose cat中的一个或者几个,make命令执行的时候,需要先找到moose goose cat的生成方法,然后执行对应的命令,最后执行animal_assembly生成的命令。

moose : antlers hooves fur
command

animal_assembly : moose goose cat
command

goose : beak wings webbed_feet interest_in_bread
command

cat : whiskers evil_personality
command

如果Makefille是以上形式的话,我们只运行make的话,Makefile会只执行第一句,因为第一句的dependency都存在了,所以只把moose生成的命令执行完就好了。如果我们要生成animal_assembly,就要运行命令make animal_assembly。所以,我们需要把最重要的命令,我们最重要生成的object file对应的命令放在第一行。

所以我们的dog_program的完整的Makefile文件应该是:

dog_program: dog.o main.o
g++ dog.o main.o -o dog_program

dog.o: dog.hpp dog.cpp
g++ -c dog.cpp

main.o: main.cpp
g++ -c main.cpp

在Makefile的最后写clean语句。

clean:
rm dog_program *.o

然后我们在命令窗口运行make clean的话,就会删除文件夹中生成的可执行文件,和所有过程中产生的副产品。

对于Makefile中的dependency list,我们需要将每个object file的dependency list都写好。因为make不负责检查文件中的具体的语句,只负责执行Makefile中的语句。

dog_program:
g++ dog.o main.o -o dog_program

dog.o: dog.hpp dog.cpp
g++ -c dog.cpp

main.o: main.cpp
g++ -c main.cpp

如果像上面所示去掉dog_program的dependency list的话,运行make就会出错,因为main是依赖于dog.cpp的。

如果文件中本身就存在dog.o和main.o的话,运行make不会出错,因为make就是先check dog.o main.o是否存在,存在的话就直接运行。

所以,我们如果修改了main.cpp或者dog.cpp的话,我们需要重新生成dog.o和main.o。因为make是不管这个问题的。

make这个命令的功能就是执行Makefile中我们要求执行的语句,对结果没有任何的预期,也不会检查命令有没有问题。所以,我们必须遵守Makefile书写中的一些规则。

all : fill_file_with_nonsense
echo "I have mostly created a lot of junk today!"

fill_file_with_nonsense : create_file
echo "Hello, there is nothing important here" > silly_file

create_file :
touch silly_file touch是Unix中的典型命令,用于生成空的文件

move_file :
mv silly_file silly_file_new_name

delete_file :
rm _file

open_file :
gedit another_silly_file

clean :
touch junk1 junk2 junk3 junk4 junk5

really_clean :
rm junk*

如果想体验的更加清楚,就可以运行这个文件中的内容,然后就知道make完全不会管结果是什么,只是没有脑子的执行命令。

解释上面的内容:

Makefile的书写规则。all: 放在第一句,把所以我们要生成executable依赖的Targets列出来,这样我们需要的所有的文件都可以生成。我们看到all对应的dependency是file_file_with_nonsense,就去找file_file_with_nonsense的生成语句,发现它的dependency是create_file,然后去找create_file的生成语句,就到touch silly_file,touch是Unix中的典型命令,用于生成空的文件。create_file的语句执行完之后,回到file_file_with_nonsense,执行echo "Hello, there is nothing important here" > silly_file,就把"Hello, there is nothing important here" 写入silly_file中,file_file_with_nonsense的语句也执行完之后,我们就返回到all,然后在命令行输出"I have mostly created a lot of junk today!"。

因为其他的target,不在all的dependency list中,也不在all的dependency的dependency当中,所以只能通过make target的形式来调用对应的命令。

Marvelous macros(宏)
一个宏的示例,宏就是Makefile中的variables,用来定义我们需要的操作,一些变量之类的

CXX = clang++

FLAGS = -O

hello : hello_world.cpp
$(CXX) $(FLAGS) $? -o $@

clean :
rm hello

CXX,这是一个预定义的宏,default value是g++。这里把CXX定义成clang++了。

FLAGS,这里定义的是-O。FLAGS也不一定非得定义成-o,也可以是some moose have large antlers,但是这样定义的话,就会导致调用的时候出错。

对于上面的文件,我们在命令行输入make的时候,实际运行的是clang++ -O hello_world.cpp -o hello。

如果我们把CXX=clang++这一行删掉的话,在命令行输入make,实际运行的就是g++ -O hello_world.cpp -o hello。

定义好macro宏,我们使用的时候,就要用$(MACRO)这样的形式,这是makefile语言的一种语法。我们注意到MACRO全部用的大写,虽然不是明确规定的,但是通常情况下用大写。

$?和$@是makefile language里面特别的预定义的宏。$?是指的"names of the dependencies(newer than the target)",$@是指的"name of the target"。

Complier and liner flags in CS 225

CXX = clang++ LD = clang++

CXXFLAGS = -std=c++1y -stdlib=libc++ -c -g -O0 -Wall -Wextra -Werror -pedantic

LDFLAGS = -std=c++1y -stdlib=libc++ -lpng -lc++abi

② 如何自己编写Makefile

相信很多朋友都有过这样的经历,看着开源项目中好几页的makefile文件,不知所云。在日常学习和工作中,也有意无意的去回避makefile,能改就不写,能用ide就用ide。其实makefile并没有想象的那么难写,只要你明白了其中的原理,自己实践几次。你也可以自己写makefile,让别人对你头来羡慕的目光。

下面本人介绍一下自己的学习成果,初学阶段,欢迎大家多多指正。

简单的说,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至可以在makefile中执行shell脚本。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

关于程序的编译和链接

一般来说,无论是C还是C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o
文件,即 Object File,这个动作叫做编译(compile),一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。然后再把大量的Object
File合成执行文件,这个动作叫作链接(link)。

编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。

链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object
File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library
File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。

下面我们开始看看如何自己写出makefile。

Makefile的规则

目标 :
需要的条件 (注意冒号两边有空格)

命令(注意前面用tab键开头)

解释一下:

1
目标可以是一个或多个,可以是Object File,也可以是执行文件,甚至可以是一个标签。

2
需要的条件就是生成目标所需要的文件或目标

3
命令就是生成目标所需要执行的脚本

总结一下,就是说一条makefile规则规定了编译的依赖关系,也就是目标文件依赖于条件,生成规则用命令来描述。在编译时,如果需要的条件的文件比目标更新的话,就会执行生成命令来更新目标。

下面举个简单的例子说明。如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。

edit : main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o
cc -o edit
main.o kbd.o command.o display.o /
insert.o search.o
files.o utils.o

main.o : main.c
defs.h
cc -c main.c
kbd.o : kbd.c defs.h
command.h
cc -c kbd.c
command.o : command.c defs.h
command.h
cc -c command.c
display.o : display.c defs.h
buffer.h
cc -c display.c
insert.o : insert.c defs.h
buffer.h
cc -c insert.c
search.o : search.c defs.h
buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h
command.h
cc -c files.c
utils.o : utils.c
defs.h
cc -c utils.c
clean :
rm edit main.o
kbd.o command.o display.o /
insert.o search.o files.o
utils.o

将上面的内容写入到Makefile文件中,然后执行make就可以进行编译,执行make
clean就可以删除所有目标文件。解释一下,也就是说生成最终的目标文件edit,依赖于一系列的.o目标文件,而这些.o文件又是需要用源文件来编译生成的。

需要注意的是,clean后面没有条件,而clean本身也不是文件,它只不过是一个动作名字,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。

make是如何工作的

在默认的方式下,也就是我们只输入make命令。那么,

1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。

2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。

3、如果edit文件不存在,或是edit所依赖的后面的 .o
文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。

4、如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)

5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o
文件生命make的终极任务,也就是执行文件edit了。

makefile中使用变量

前面的知识已经足以让你自己完成一个简单的makefile了,不过makefile的精妙之处远不止如此,下面来看看如何在makefile中使用变量吧。

在上面的例子中,先让我们看看edit的规则:

edit : main.o kbd.o command.o
display.o /
insert.o search.o files.o
utils.o
cc -o edit main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o

我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该是三个地方,还有一个地方在clean中)。当然,我们的makefile并不复杂,所以在两个地方加也不累,但如果
makefile变得复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败。所以,为了makefile的易维护,在makefile中我们可以使用变量。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。

于是,我们使用变量objects

objects = main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o

这样一来,原来的makefile变成如下的样子:

objects = main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o

edit : $(objects)

cc -o edit $(objects)
main.o : main.c defs.h
cc -c
main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c

command.o : command.c defs.h command.h
cc -c command.c

display.o : display.c defs.h buffer.h
cc -c display.c

insert.o : insert.c defs.h buffer.h
cc -c insert.c

search.o : search.c defs.h buffer.h
cc -c search.c
files.o
: files.c defs.h buffer.h command.h
cc -c files.c
utils.o
: utils.c defs.h
cc -c utils.c
clean :
rm
edit $(objects)

这样看起来方便多了吧,也更加省事了。如果有新的.o文件怎么办?当然是在objects里面添加了,这样只需要一处改变,很方便吧。

让make自动推导

GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。

只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且
cc -c whatever.c
也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。

objects = main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o

edit : $(objects)

cc -o edit $(objects)

main.o : defs.h
kbd.o :
defs.h command.h
command.o : defs.h command.h
display.o : defs.h
buffer.h
insert.o : defs.h buffer.h
search.o : defs.h
buffer.h
files.o : defs.h buffer.h command.h
utils.o :
defs.h

clean :
rm edit
$(objects)

当然,如果你觉得那么多[.o]和[.h]的依赖有点不爽的话,好吧,没有问题,这个对于make来说很容易,谁叫它提供了自动推导命令和文件的功能呢?来看看最新风格的makefile吧。

objects = main.o kbd.o command.o display.o
/
insert.o search.o files.o utils.o

edit : $(objects)

cc -o edit $(objects)

$(objects) : defs.h
kbd.o
command.o files.o : command.h
display.o insert.o search.o files.o :
buffer.h
clean :
rm edit $(objects)

③ makeFile文件作用是什么

其作用如下:
makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
记得要赞一个哦

④ Makefile.am 规则和实例详解

编写linux C 程序的时候,自己来写Makefile着实的让人很头疼,如果是简单的项目自己写写也就罢了,但是如果遇到大项目自己写Makefile,那是要弄死人的,所以最近在研究Autotools工具自动生成Makefile,在用到autotools工具生成Makefile的时候,还是有一部分需要自己来完成的,那就是Makefile.am文件。

项目中写在源文件里的Makefile.am是一种比我们了解的Makefile更高层次的编译规则,它可以和编写的configure.in(了解更多configure.in的规则请阅读《 configure.ac (configure.in)详解 》)文件一起通过调用automake命令,来生成Makefile.in文件,然后再调用./configure,将Makefile.in文件自动的生成Makefile文件。所以Makefile.am文件是要自动生成Makefile必不可少的元素,下面鹏博客就来和大家着重的学习下Makefile.am的写法和规则。

先来说下Makefile.am中常见的文件编译类型,详细的编译类型和全局变量鹏博客会在下面在图表中列出:

PROGRAMS           表示可执行文件

SOURCES              表示源文件

HEADERS              头文件。

LIBRARIES             表示库文件

LTLIBRARIES         这也是表示库文件,前面的LT表示libtool。

DATA                       数据文件,不能执行。

SCRIPTS                脚本文件,这个可以被用于执行。如:example_SCRIPTS,如果用这样的话,需要我们自己定义安装目录下的example目录,很容易的,往下看。

一、基本写法

下面就直接引入一个例子进行详细讲解,如下:

AUTOMAKE_OPTIONS = foreign

bin_PROGRAMS = client

client_SOURCES = key.c connect.c client.c main.c session.c hash.c

client_CPPFLAGS = -DCONFIG_DIR=\“$(sysconfdir)\” -DLIBRARY_DIR=\”$(pkglibdir)\”

client_LDFLAGS = -export-dynamic -lmemcached

noinst_HEADERS = client.h

INCLUDES = -I/usr/local/libmemcached/include/

client_LDADD = $(top_builddir)/sx/libsession.la \

$(top_builddir)/util/libutil.la

上面就是一个Makefile.am示例文件,这个文件是用于生成client可执行应用程序,引用了两个静态库和MC等动态库的连接。

先来看个图表一(列出了可执行文件、静态库、头文件和数据文件,四种书写Makefile.am文件个一般格式。):

对于可执行文件和静态库类型,如果只想编译,不想安装到系统中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。以此类推。

根据这个图表一来分析下具体内容:

AUTOMAKE_OPTIONS :这个是用来设定automake的选项。automake主要是帮助开发GNU软件的人员维护软件套件,一般在执行automake时会检查目录下是否存在标准GNU套件中应具备的文件档案,例如NEWS、AUTHOR、ChangeLog等,设成foreign时,automake会改用一般软件套件标准来检查,而gnu是缺省设置,该级别下将尽可能地检查包是否服从GNU标准,gnits是严格标准,不推荐。

bin_PROGRAMS :表示要生成的可执行应用程序文件,这里的bin表示可执行文件在安装时需要被安装到系统中,如果只是想编译。不想被安装到系统中,可以用noinst_PROGRAMS来代替。

那么整个第一行 bin_PROGRAMS=client 详细表示什么意思那,解释如下:

PROGRAMS知道这是一个可执行文件。

client表示编译的目标文件。

bin表示目录文件被安装到系统的目录。

如程序和图片所示,包括头文件,静态库的定义等等都是这种形式,如lib_LIBRARIES=util,表示将util库安装到lib目录下。

继续解释文件内容:

client_SOURCES :表示生成可执行应用程序所用的所有源文件源文件,多个就空格隔开,我们注意到client_是由前面的bin_PROGRAMS指定的,如果前面是生成example, 那么这里也就变成example_SOURCES,其它的规则类似标识也是一样。

client_CPPFLAGS :这个和我们写Makefile的时候意思是一样的,都表示C语言的预处理器参数,这里指定了DCONFIG_DIR,以后在程序中,就可以直接使用CONFIG_DIR,不要把这个和另一个CFLAGS混淆,后者表示编译器参数。

client_LDFLAGS :表示在连接时所需要的库文件选项标识。这个也就是对应一些如-l,-shared等选项。

noinst_HEADERS :表示该头文件只是参加可执行文件的编译,而不用安装到安装目录下。如果需要安装到系统中,可以用include_HEADERS来代替。

INCLUDES :表示连接时所需要的头文件。

client_LDADD :表示连接时所需要的库文件,这里表示需要两个库文件的支持,下面会看到这个库文件又是怎么用Makefile.am文件后成的。

如图表二:

全局变量 ,可能有人注意到文件中的$(top_builddir)等全局变量,其实这个是Makefile.am系统定义的一个基本路径变量,表示生成目标文件的最上层目录,如果这个Makefile.am文件变成其它的Makefile.am文件,那么这个就表示其它的目录,而不是这个当前目录。我们还可以使用$(top_srcdir),这个表示工程的最顶层目录,其实也是第一个Makefile.am的入口目录,因为Makefile.am文件可以被递归性的调用。

如图表三:(在Makefile.am中尽量使用相对路径,系统预定义了两个基本路径)

$(sysconfdir) :在系统安装工具的时候,我们经常能遇到配置安装路径的命令,如:./configure –prefix=/install/apache  其实在调用这个之后,就定义了一个变量$(prefix), 表示安装的路径,如果没有指定安装的路径,会被安装到默认的路径,一般都是/usr/local。在定义$(prefix),还有一些预定义好的目录,其实这一些定义都可以在顶层的Makefile文件中可以看到,如下面一些值:

bindir = $(prefix)/bin。

libdir = $(prefix)/lib。

datadir=$(prefix)/share。

sysconfdir=$(prefix)/etc。

includedir=$(prefix)/include。

这些量还可以用于定义其它目录,例如我想 将client.h安装到include/client目录下 ,这样写Makefile.am文件:

clientincludedir=$(includedir)/client

clientinclude_HEADERS=$(top_srcdir)/client/client.h

这就达到了我的目的,相当于定义了一个安装类型,这种安装类型是将文件安装到include/client目录下。

我们自己也可以 定义新的安装目录下的路径 ,如我在应用中简单定义的:

devicedir = ${prefix}/device

device_DATA = package

这样的话,package文件会作为数据文件安装到device目录之下,这样一个可执行文件就定义好了。注意,这也相当于定义了一种安装类型:devicedir,所以你想怎么安装就怎么安装,后面的XXXXXdir,dir是固定不变的。

二、配置静态库

下面我们来说下编译静态库和编译动态库,我们说下静态库,下面这个例子比较简单。直接指定 XXXX_LTLIBRARIES或者XXXX_LIBRARIES就可以了。同样如果不需要安装到系统,将XXXX换成noinst就可以。

一般推荐使用libtool库编译目标,因为automake包含libtool,这对于跨平台可移植的库来说,是一个很好的事情。

看例子如下:

noinst_LTLIBRARIES = libutil.la

oinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h

ibutil_la_SOURCES = access.c config.c datetime.c hex.c inaddr.c log.c device.c pool.c rate.c sha1.c stanza.c str.c xhash.c

ibutil_la_LIBADD = @LDFLAGS@

第一行的noinst_LTLIBRARIES,这里要注意的是LTLIBRARIES,另外还有LIBRARIES,两个都表示库文件。前者表示libtool库,用法上基本是一样的。如果需要安装到系统中的话,用lib_LTLIBRARIES。

.la 为libtool自动生成的一些共享库,vi编辑查看,主要记录了一些配置信息。可以用如下命令查看*.la文件的格式   $file *.la

.a 为静态库,是好多个.o合在一起,用于静态连接

如果想编译 .a 文件,那么上面的配置就改成如下结果:

noinst_LTLIBRARIES = libutil.a

oinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h

ibutil_a_SOURCES = access.c config.c datetime.c hex.c inaddr.c log.c device.c pool.c rate.c sha1.c stanza.c str.c xhash.c

ibutil_a_LIBADD = @LDFLAGS@

注意:静态库编译连接时需要其它的库的话,采用XXXX_LIBADD选项,而不是前面的XXXX_LDADD。编译静态库是比较简单的,因为直接可以指定其类型。

三、配置动态库

如果想要编译XXX.so动态库文件,需要用到_PROGRAMS类型,有一个关于安装路径的问题,如果希望将动态库安装到lib目录下,按照前面所说的,只需要写成lib_PROGRAMS就可以了,lib表示安装的路径,但是automake不允许这样直接定义,所以可以采用下面的办法,同样是将动态库安装到lib目录下:

projectlibdir=$(libdir)//新建一个目录,就是该目录就是lib目录

projectlib_PROGRAMS=project.so

project_so_SOURCES=xxx.C

project_so_LDFLAGS=-shared -fpic//GCC编译动态库的选项

这个动态库的编译写法是鹏博客网上总结的,希望有要的人自己来验证下。

四、SUBDIRS功能用法

SUBDIRS 这是一个很重要的词,我们前面生成了一个目标文件,但是一个大型的工程项目是由许多个可执行文件和库文件组成,也就是包含多个目录,每个目录下都有用于生成该目录下的目标文件的Makefile.am文件,但顶层目录是如何调用,才能使下面各个目录分别生成自己的目标文件呢?就是SUBDIRS关键词的用法了。

看一下我的工程项目,这是顶层的Makefile.am文件

EXTRA_DIST = Doxyfile.in README.win32 README.protocol contrib UPGRADE

devicedir = ${prefix}/device

device_DATA = package

SUBDIRS = etc man

ifUSE_LIBSUBST

SUBDIRS += subst

endif

SUBDIRS += tools io sessions util client dispatch server hash storage sms

SUBDIRS表示在处理目录之前,要递归处理哪些子目录,要注意处理的顺序。比如配置中的client对sessions和utils这两上目标文件有依赖关系,就在client之前需要处理这两个目标文件。

EXTRA_DIST :将哪些文件一起打包。

五、打包处理

Automake会自动的打包 ,自动打包的内容如下:

所有程序的源文件。

所有子目录里的的Makefile.am文件。

Makefile.am中包含的文件。

./configure所要读取的文件。

EXTRA_DIST所指定的文件。

dist和nodist指定的文件,也可将其中一个源文件指定为不打包:

例如: nodist_client_SOURCES = client.c

六、最后

这里是鹏博客总结的一些比较实用的Makefile.am的写法和规则,看完了这篇文章已经可以很详细的理解这个文件的内容,写起来也应该不会陌生,但automake还有许多其他的规则需要掌握,鹏博客将会继续全面的总结关于autotools 的一些规则和写法,希望对大家有用处。也欢迎大家指出问题,帮我完善这个博客,希望大家支持!

automake的Makefile.am Makefile.am写法

⑤ linux如何编写并使用makefile

1、先写Makefile编译出***.ko文件
模板如下,保存到命名为Makefile文件里,放到你代码的同级目录下
TARGET=my_proc.ko
LINUXDIR=/lib/moles/$(shell uname -r)/build
PWD=$(shell pwd)
obj-m :=
obj-m += my_proc.o

all: $(TARGET)
$(TARGET): $(OBJS)
make -C $(LINUXDIR) SUBDIRS=$(PWD) moles
clean:
rm -f moles.order Mole.symvers $(TARGET) *.mod.c *.o
rm -rf .tmp_versions .mod* Mole.markers
2、make
3、root权限下用命令插入模块
insmod my_proc.ko
4、可以用你写的应用程序打开、操作模块了
5、查看模块命令
lsmod
cat /proc/moles
modinfo my_proc.ko
6、root下卸载模块
rmmod

⑥ 在VC里如何用Makefile文件编译

运行cmd.exe (or command.com in win9x)->进到vc/bin目录->运行vc-vars32.bat->进到makefile 所在的目录->nmake /f makefile
从sourceforge上下载下来的libjpeg源代码中有一个makefile.vc的文件,可以通过nmake /f makefile.vc [nodebug=1]来编译libjpeg,但是只能编译静态库,如果需要编译dll以便在emacs等程序中使用的话,需要修改makefile.vc和jmorecfg.h文件。在makefile.vc文件中添加编译dll规则:
以下内容为程序代码:
libjpeg.lib: $(LIBOBJECTS) $(RM) libjpeg.lib lib -out:libjpeg.lib $(LIBOBJECTS) #
添加以下这行 libjpeg.dll: $(LIBOBJECTS) $(RM) libjpeg.dll link -dll -out:libjpeg.dll $(LIBOBJECTS) 在jmorecfg.h中添加#define _WIN32_#define JPEG_DLL 然后nmake /f makefile.vc nodebug=1就可以编译了。
将makefile复制为一个.mak文件,然后用VC打开即可!
.mak 就是一个makefile
可以指定怎样编译(命令行,必须先设置VC命令行环境)
vcvars32.bat可设置环境,在vc98/bin下 nmake /f XXXX.mak
如果有一个makefile就只要nmake就可以了。

⑦ Makefile详解

make 命令执行时,需要根据一些规则来决定按照怎么样的方式去 编译和链接程序 ,这些规则就由 makefile 文件所指定。如果我们 makefile 文件写的足够好,make 命令会自动地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。

首先,本文将给出一个makefile文件的示例,以便大家能有一个直观感受,这个例子来源于 GNU的make使用手册 。在这个例子中,我们的工程有8个c文件,和3个头文件,我们要写一个makefile来告诉make命令如何编译和链接这几个文件。例子如下:

这个例子里 make 的编码规则如下:

a. 如果这个工程没有编译过,那么我们的所有c文件都要编译并被链接。
b. 如果这个工程的某几个c文件被修改,那么我们只编译被修改的c文件,并链接目标程序。
c. 如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的c文件,并链接目标程序。

在详细拆解上一节的 Makefile 之前,先来看下 Makefile 的基本范式。

target可以是一个 1) object file(可执行文件) ,2) 可执行文件 ,还可以是个3) label(标签) ,关于标签这个特性,在后面的 伪目标 章节还会有叙述。

prerequisites 就是,要生成那个target所需要的文件或是目标。 command 也就是 make 需要执行的命令,可以是任意的
shell 命令。

这是一个文件的依赖关系,也就是说,target 这一个或多个的目标文件依赖于 prerequisites 中的文件,其生成规则定义在 command 中。同时, prerequisites 中如果有一个以上的文件比target文件要新的话, command 所定义的命令就会被执行。这就是 Makefile 的规则,也是 Makefile 中 最核心 的内容。

有了这些规则后,再来分析上面的例子。在这个 makefile 中,目标文件(target)包含:

依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h 文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。

在定义好依赖关系后,后续的那一行定义了如何生成目标文件的系统命令, 一定要以一个tab键作为开头 。 make 会比较
targets 文件和 prerequisites 文件的修改日期,如果 prerequisites 文件的日期要比targets文件的日期要新,或者 target 不存在的话,那么,make就会执行后续定义的命令。

我们可以把这个内容保存在名字为 makefile 或 Makefile 的文件中,然后在该目录下直接输入命令 make 就可以生成可执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下 make clean 就可以了。 注:反斜线()是换行符的意思,这样比较便于阅读。

这里要说明一点的是, clean 不是一个文件,它只不过是一个动作名字,有点像C语言中的 lable 一样,其冒号后什么也没有,那么,make就不会去找它的依赖性,也就不会自动执行其后所定义的命令。要执行其后的命令(不仅用于 clean,其他 lable 同样适用),就要在 make 命令后显式指出这个 lable 的名字。这样的方法非常有用, 我们可以在一个 makefile 中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份 ,等等。

在默认的方式下,也就是我们只输入make命令。那么,

这就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,这些都不在 make 职责范围内。

通过上述分析,我们知道,像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令 make clean ,以此来清除所有的目标文件,以便重编译。

在上面的例子中可以看到,后缀为 .o 的一大串文件名写了两次,这样比较费时费力,而且如果文件有所增减,要修改的地方也非常多,对以后的维护造成困难。在这种情形下,我们可以在Makefile里使用变量代替这一大串依赖文件,这里变量的使用方式基本类似于shell脚本里变量的使用方法。

我们可以在makefile一开始就这样定义:

那么接下来我们就可以很方便地在我们的Makefile中以 $(objects) 的方式来使用这个变量了,于是如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。

GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个 .o 文件后都写上类似的命令。因为,我们的make会自动识别,并自己推导命令。

只要make看到一个 .o 文件,它就会自动的把 .c 文件加在依赖关系中,如果make找到一个 FILENAME.o ,那么 FILENAME.c ,就会是 FILENAME.o 的依赖文件。并且 cc -c FILENAME.c 也会被推导出来,于是,我们的makefile 再也不用写得这么复杂。我们的新makefile就可以这么写了。

这种方法,也就是make的**。上面文件内容中,“.PHONY”表示,clean是个伪目标文件。

⑧ makefile文件的作用是什么

其作用如下:
makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
记得要赞一个哦

热点内容
内置存储卡可以拆吗 发布:2025-05-18 04:16:35 浏览:336
编译原理课时设置 发布:2025-05-18 04:13:28 浏览:378
linux中进入ip地址服务器 发布:2025-05-18 04:11:21 浏览:612
java用什么软件写 发布:2025-05-18 03:56:19 浏览:32
linux配置vim编译c 发布:2025-05-18 03:55:07 浏览:107
砸百鬼脚本 发布:2025-05-18 03:53:34 浏览:944
安卓手机如何拍视频和苹果一样 发布:2025-05-18 03:40:47 浏览:741
为什么安卓手机连不上苹果7热点 发布:2025-05-18 03:40:13 浏览:803
网卡访问 发布:2025-05-18 03:35:04 浏览:511
接收和发送服务器地址 发布:2025-05-18 03:33:48 浏览:372