makefile 和我一样的新手来!

软件和网站开发以及相关技术探讨
回复
tiankunmin
帖子: 38
注册时间: 2007-09-07 3:08

makefile 和我一样的新手来!

#1

帖子 tiankunmin » 2007-09-09 1:45

先补充一句,我接触linux不到一星期.输入法以前用windows下的智能ABC
现在用fcitx所以会有很多的同音字出现,原谅我吧,毕竟从开始接触电脑就
用智能ABC输入法,到现在都好几年了,习惯总是难改的,当你看到一些同音字的时候
请不要笑话我.

这文章仅仅是给像我一样刚刚从widnows下转到linux的新人
不过毕竟我们都有些编程知识的,就像我们会开车,但是在不同的国家开车得遵守不同的规矩.
比如有的国家得靠左行驶,有的国家得靠右行驶.
同样我们会在windows下用M$的VS或Borland的delphi,BCB等等
他们往往有这简单,容易上手的界面,操作起来也很方便.同时他们也隐藏了许多细节
甚至你永远都不会知道.你 仅仅通过菜单上的Build就成功的生成可执行文件(当然你的源文件必须是正确的)
的背后隐藏了些什么.等一天你来到了linux或许是因为工作需要或纯粹处于你的兴趣
你才发现,原来没一件事情都是那么复杂,我甚至什么都不会了!仿佛我在windows下进行的一切在这里都没得
发挥!虽然我知道怎么书写完整的源程序.但是我不知道怎么将他们编译成克执行文件 .
好了,我们开始书写我们的第一给linux程序

首先编译器是必须的东西(原谅我说了句废话)
在Ubuntu下

代码: 全选

sudo apt-get install gcc g++
简单的闭这眼睛敲几行代码

代码: 全选

#include <iostream>
int main(int argcount, char **args)
{
   printf("hello linux!");
   return 0;
}
不过上面这些是我睁着眼睛敲的,你应该可以.
源程序写好了当然是编译了.
使用g++编译
#g++ flags 目标文件 源程序集
flags为 -o表示编译并链接
g++ -o ~/hello ~/hello.cpp
则在~/目录下生成了hello这个文件
~/hello
好了,如你所愿 你看到了hello linux!
哎呀,高兴了,我终于能写linux程序了!

如果文件多了怎么办?在 vs或delphi中我们不管有多少个cpp,c,h或pas文件
ide总是会无误的帮我们完成一切!我们要作的仅仅是按一下编译的快捷键.
聪明的你一定会像到
g++ -o targetfile sourcefile1 sourcefile2 sourcefile3 ...
着的确是个不错的办法,但是每次都把所有的源程序进行编译不光浪费事件,关键是
编译时都得敲一大串的源程序名,一两次还可以,事件长了就无法忍受了.
一给完整的项目往往包含多个源程序,如果你一段时间没有涉及过这些源程序,
后来因为某种原意,再回来重新编译时,那时候你才知道什么是麻烦!

你一定听说过或看到过makefile这个东西.通过编辑makefile即可用命令make 编译成可执行文件.
就是他,我们只要为一个项目
首先安装make
在Ubuntu下

代码: 全选

sudo apt-get install automake
在网上搜索makefile能搜到一大堆,篇幅往往都太长.光是看完就已经去了不少时间了
况且我们需要只是一个精简的,看完就能马上用的makefile范例.
make是个功能很强大的东西,我们不必掌握他所有的功能的用法.
我们只需要我们现在需要的功能,等我们还需要其他的功能的时候我们再区学习其他的.
当然了如果你有时间的话最好还是加深一下对make的参数的理解.好处不敢说有没有,
但是至少没有坏处.哈哈.

开始makefile:
首先贴出一个范例包含了我已经理解的注释如果有不对的请支出,我会非常感谢你.

代码: 全选

#--------------------------makefile description-----------------------------#
#use for g++ compiler to complate/link
#edited:	miros
#edit time:	Sep 8, 2007
#------------------------compiler and compiler fags-------------------------#
COMPILER=g++

COMPLATEFLAGS=

#--------------------------project settings---------------------------------#

PROJECTNAME=srv

INCLUDES=srv.cpp srvscks.cpp

LIBS=

OBJECTS=srv.o srvscks.o

#------------------------------make actions---------------------------------#
#use build to be default command
build:		complate	link

complate:
		@echo   "begin complate source files:\r\n${INCLUDES}"
		@$(COMPILER) $(COMPLATEFLAGS) $(INCLUDES) -c $^
		@echo	"complate succeeded"

recomplate:	cleanobjs	complate

link:
		@echo	"begin link object files:\r\n${OBJECTS}"
		@$(COMPILER) $(LIBS) $(OBJECTS) -o $(PROJECTNAME)
		@echo	"link succeeded\r\nsetup target file properties"
		@chmod	+x $(PROJECTNAME)
		@echo	"Done!"

cleanobjs:
		@-rm $(OBJECTS)

cleanapps:
		@-rm $(PROJECTNAME)

cleanall:	cleanobjs	cleanapps

rebuild:	cleanall	build

build-clear:	build		cleanobjs

all:		rebuild	cleanobjs

run:
		@./$(PROJECTNAME)

#----------------------------exports labdles--------------------------------#
.PHONY:	all build rebuild complate recomplate link cleanobjs cleanapps cleanall build-clear






下面是我的理解,详细的注释:

代码: 全选

#--------------------------makefile description-----------------------------#
#use for g++ compiler to complate/link
#edited:	miros
#edit time:	Sep 8, 2007
#------------------------compiler and compiler fags-------------------------#
#以 # 开头的行是注释.
#以下这句理解为宏 COMPLILER 值为 g++
#为社么要这么作? 好处是你把g++改成gcc就等于使用gcc来编译
COMPILER=g++
#编译选项
#-o2表示代码优化程度为中等 -g表示可调试,相当于windows中的debug版本,-d和后面的参数表示定义了一个宏 如 -d __DEBUG__
#从http://zhdklxn.bokee.com/3435659.html看到的
COMPLATEFLAGS=

#--------------------------project settings---------------------------------#
#项目名称同时表示编译的可执行文件的名称
PROJECTNAME=srv
#源程序集
INCLUDES=src1.cpp src2.cpp
#使用到的其他库集
LIBS=
#编译生成的.o文件 于上面的源程序对应
OBJECTS=src1.o src2.o

#------------------------------make actions---------------------------------#
#use build to be default command
#在此使用build作为默认的make 的命令 即makefile文件中的第一个标签是make在没有指定标签时默认执行的
#标签: 行为(可以是shell命令或本makefile中的其他标签) 这里的complate和link都分别是一个标签
#是不是想起了c中的goto我的理解就是make首先判断compalte 如果他是一个标签则执行他,如果他不是则作为
#shell命令执行

build:		complate	link

complate:
#下面这行很简单,就是输出一行文字何windows下的bat文件一样前面加@就不显示命令了
#${宏名}表示打印宏的值
		@echo   "begin complate source files:\r\n${INCLUDES}"
#下面这句就是编译我们的源程序文件
#注意看$(COMPILER) COMPILER是我们定义的一个宏他的值是g++
#$(宏名)表示使用宏的值 
#同理$(COMPLATEFLAGS)是使用COMPLATEFLAGS的值
#$(INCLUDES)是使用INCLUDES的值
#-c表示编译(complate) $^目前我还不知道是什么意思,如果你知道别望了回帖告诉我.
#整句会被翻译成g++ src1.cpp src2.cpp -c $^(目前不知道会成为社么)
#make会自己判断哪些文件需要重新编译从而节省编译时间
#就像我们在vc中只改过一个.cpp文件编译会很快而改一个头文件通常会多需要些时间
		@$(COMPILER) $(COMPLATEFLAGS) $(INCLUDES) -c $^
#如果没有错误的话会打印下面这句
		@echo	"complate succeeded"

recomplate:	cleanobjs	complate

link:
		@echo	"begin link object files:\r\n${OBJECTS}"
#这句和编译的那句一样只是参数变了
#$(LIBS)就是我们使用的其他的库
#$(OBJECTS)就是编译后需要链接的文件通过OBJECTS的值我们知道是src1.o src2.o
#-o 表示指定了需要链接的文件并进行链接
#最后的$(PROJECTNAME)就是最终生链接成的文件名
		@$(COMPILER) $(LIBS) $(OBJECTS) -o $(PROJECTNAME)
		@echo	"link succeeded\r\nsetup target file properties"
		@chmod	+x $(PROJECTNAME)
		@echo	"Done!"

cleanobjs:
#rm这个命令是删除文件 rm 文件1 文件2 ...
#注意杂命令前加-是用来表示即便一个命令或标签没有执行成功也需要执行这个命令或标签即或略执行中的错误
#这里-rm $(OBJECTS)搜删除成功编译生成的.o文件
#我还想让他即便是没有找到文件也不作任何提示,但是我现在还不知道怎么做
		@-rm $(OBJECTS)

cleanapps:
#何cleanobjs一样不过这个是删除链接生成的最终文件
		@-rm $(PROJECTNAME)

cleanall:	cleanobjs	cleanapps

rebuild:	cleanall	build

build-clear:	build		cleanobjs

all:		rebuild	cleanobjs

run:
#这个标签执行可执行文件
		@./$(PROJECTNAME)

#----------------------------exports labdles--------------------------------#
#.PHONY后的标签被标记为伪目标
#关于伪目标请参考
#http://www.chinaunix.net/jh/23/408225.html
#这里的makefile资料很详细,但是我没有看,等有时间再看
.PHONY:	all build rebuild complate recomplate link cleanobjs cleanapps cleanall build-clear
你可以把他命名成makefile或Makefile
make会先查找makefile再查找Makefile...

使用方法自己配置PROJECTNAME INCLUDES OBJECTS等你需要改变的宏
make all 重新编译所有的源文件并链接最后删除编译生成的.o文件
make build 编译并链接(make会判断那些文件需要重新编译)
make rebuild 重新编译并链接
make comolate 编译
make link 链接
make cleanobjs 清除编译生成的.o文件
make cleanapps 清除链接生成的目标文件
make cleanall 清除编译生成的.o文件并清除链接生成的目标文件
make build-clear 编译并链接后删除所有的.o文件


虽然我们可以自己写一些工具来维护编译的工作包括显示正在编译的文件名等
但是可能我们没有足够的时间或兴趣.所以我选择了makefile是因为我懒!呵呵.
头像
stlxv
论坛版主
帖子: 8275
注册时间: 2006-05-03 0:39
来自: المريخ

#2

帖子 stlxv » 2007-09-09 12:07

粗略地看了一下,发现有很多地方不对哦~

:-P
PHP是最好的语言!不服来战!
tiankunmin
帖子: 38
注册时间: 2007-09-07 3:08

#3

帖子 tiankunmin » 2007-09-09 23:19

请指正,谢谢
头像
anod221
帖子: 76
注册时间: 2007-04-10 18:36
来自: 西安

#4

帖子 anod221 » 2007-09-10 13:31

那程序用了<iostream>又没有用到iostream的任何东西啊?考虑<stdio.h>
不用装automake了,默认装了make的,automake有自己的脚本,不过我没有学
你的理解我觉得很好嘛,不过这个文件怎么那么多@的??虽然有也东东也没有关系
不习惯你用的变量名,其它的就没有什么了

学习makefile看这个
http://www.cse.psu.edu/~lxue/doc/gnumaketranslated.html
xiechy
帖子: 1074
注册时间: 2006-01-18 15:01

#5

帖子 xiechy » 2007-09-10 14:01

tiankunmin 写了:请指正,谢谢
比较多~还是好好看看make的文档,不要自己理解的比较好.
回复