linux make使用的简单翻译

原文地址:http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html


分开编译:

一个.cpp文件包含一个对应的.h文件,以及一下:

      1. class中所有类方法的实现

      2. 独立的函数

      3. 全局变量(尽量避免使用)

一个对应的.h文件应包含:

      1. class的声明

      2. 函数的原型

      3. extern变量(全局变量)


.h文件的目的在于exportservice给其他的.cpp


编译一个.cpp文件

当编译器看到带有#include.h.cpp文件时会怎么做呢?预处理器会在.cpp的一个副本上插入这个.h文件,完成预处理阶段后就将整个修改后的副本发给编译器。所以.cpp文件只知道该.h中的类的成员变量和方法的接口,而不知道这些方法是怎么实现的。例如MovieTheater.cpp#includeVector.h。只要了解Vector类的大小以及其中类方法的接口即可保证正确的初始化Vector类(足够的内存),和正确的函数使用。有了这些信息就可编译.cpp,生存目标文件(ObjectFile, .o)

最后要运行时,将所有的目标文件link在一起即可。


g++-Wall -c MovieTheater.cpp //-Wall选项是打印所有warning信息

-c选项告诉g++是编译而不是编译完后继续link


常见的误区

当你使用-c选项编译一个.cpp文件时,会顺带把.cpp#include的所有.h文件相关的.cpp文件一起编译”。

这是错误的。只会编译单个.cpp


当写下如下命令时:

g++-Wall foo.cpp bar.cpp baz.cpp

会在编译foo.cpp时查看bar.cppbaz.cpp”

这也是错误的。会分开编译。


Makefiles

makefile的一个好处就是没修改的类可以不重新编译。只编译修改过的。当一个工程需要100多个文件时,重新编译每个文件是很花时间的。

一个makefile中一般包含如下东西:


atarget (usually a file)

    thedependencies (files which the target depends on)

    andcommands to run, based on the target and dependencies.

例子如下:

Movie.o:Movie.cpp Movie.h Vector.h

g++-Wall -c Movie.cpp


基本语法:

<target>:[ <dependency > ]*

    [ <TAB> <command> <endl> ]+
 

一个makefile文件中一般包含很多entries

target和冒号之后是依赖关系。这些依赖关系一般是用来告诉makefile这个target要不要重新编译的。make工具会根据一个非常简单的规则:依赖文件的最后修改时间(lastmodified, mtime)。这些更新是递归性质的,例如依赖的A.h没改变,但是A.h依赖的B.h作出了改变这也是需要重新编译的。

因为A可能包含B类的实例,B的大小变了,A的大小也跟着变了,那么.cpp也需要根据变化作出改变。


Making .o files

最常见的target就是.o文件

例子:

Movie.o: Movie.cpp Movie.h Vector.h

g++-Wall -c Movie.cpp

目标targetMovie.o。依赖的文件是后面的。


Deciding on 依赖

把所有的用 “”#include.h文件都写进来。

能够使用以下方法来定制一种依赖

Vector:Foo.h

在这个例子中,不会生成任何target。只是告诉编译器一种依赖关系的存在。


命令(commands)

需要在命令前加TAB键。


Excuteable as targets

makefile的目的是生成可执行文件。

例子如下:

p1:MovieList.o Movie.o NameList.o Name.o Iterator.o

g++-Wall MovieList.o Movie.o NameList.o Name.o Iterator.o -o p1


即把所有的.o链接在一起,生成可名字为p1的可执行文件,如果没-o选项则默认生成a.out


Howto name the makefile

顺序如下:

键下make后,

先在当前工作目录找makefile,找不到找Makefile

如果键下的是make-f <filename>则找filename那个文件


宏—为了灵活性

尽量使用宏,如:

OBJS= MovieList.o Movie.o NameList.o Name.o Iterator.o

 CC = g++
 DEBUG = -g
 CFLAGS = -Wall -c $(DEBUG)
 LFLAGS = -Wall $(DEBUG)

 p1 : $(OBJS)
     $(CC) $(LFLAGS) $(OBJS) -o p1


宏的格式:

<macro_name>= <macro_string>


常见的宏

CC:编译器名字

DEBUG :调试标志

LFLAGS linking时的标志

CFLAGS :编译时的标志


Dummy targets


make clean

\rm*.o *~ p1

rm前面的\防止你删除文件时的一些抱怨。

上面的意思是删除所有包含.o和 ~的文件,同时删除p1

make tar

打包文件用的

tar:

     tar cfv p1.tar Movie.h Movie.cpp Name.h Name.cpp NameList.h \
             NameList.cpp Iterator.cpp Iterator.h

将生成p1.tar


make all

当需要生成几个可执行文件或者完成多于一个任务时。

例子


all:p1 p2 p3

 p1: Foo.o main1.o
    g++ -Wall Foo.o main1.o -o p1

 p2: Bar.o main2.o
    g++ -Wall Bar.o main2.o -o p2

 p3: Baz.o main3.o
   g++ -Wall Baz.o main3.o -o p3


all没有命令行。


在使用makefile时常见的错误

      1. 忘记在命令前加TAB

      2. 依赖关系弄错了。


一个完整的例子:

OBJS = MovieList.o Movie.o NameList.o Name.o Iterator.o
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)

p1 : $(OBJS)
    $(CC) $(LFLAGS) $(OBJS) -o p1

MovieList.o : MovieList.h MovieList.cpp Movie.h NameList.h Name.h Iterator.h
    $(CC) $(CFLAGS) MovieList.cpp

Movie.o : Movie.h Movie.cpp NameList.h Name.h
    $(CC) $(CFLAGS) Movie.cpp

NameList.o : NameList.h NameList.cpp Name.h 
    $(CC) $(CFLAGS) NameList.cpp

Name.o : Name.h Name.cpp 
    $(CC) $(CFLAGS) Name.cpp

Iterator.o : Iterator.h Iterator.cpp MovieList.h
    $(CC) $(CFLAGS) Iterator.cpp

clean:
    \rm *.o *~ p1

tar:
    tar cfv p1.tar Movie.h Movie.cpp Name.h Name.cpp NameList.h \
            NameList.cpp Iterator.cpp Iterator.h



你可能感兴趣的:(linux make使用的简单翻译)