- 浏览: 335294 次
- 性别:
- 来自: 北京
-
最新评论
-
lshhjxlj:
不错,赞一个
[翻译]Swing组件集合的事件处理(一) -
mxjisp:
...
Linux下的汇编开发 -
arust:
CSDN 的开发团队技术稀烂的
Linux杂记
Makefile中的注释
makefile文件中的注释以#开始,并且直到本行结束。正如在C源文件中一样,makefile文件中的注释有助于作者也其他人更好的理解文件编写时所期望的作用。
Makefile中的宏
即使有make与makefile是管理多个源码文件工程的强大工具。然而,对于由大量的文件所组成的工程来说,他们仍显得庞大和不灵活。所以Makefile允许我们使用宏,从而我们可以将其写为更为通用的形式。
我们在makefile文件中以MACRONAME=value的形式定义一个宏,然后以$(MACRONAME)或是${MACRONAME}的形式来访问MACRONAME的值。一些版本的make也可以接受$MACRONAME的形式。我们也可以通过将=之后的部分留空来设置一个空的宏。
在makefile文件中,宏通常用于编译的选项。通常,当正在开发一个程序时,我们通常并不会使用优化选项来进行编译,但是却需要包含调试信息。而对于发布一个程序通常是相反的情况:发布一个运行速度尽量快而不带任何调试信息的二进制程序。
Makefile1的另一个问题是他假定编译器为gcc。在其他的Unix系统上,我们也许会使用cc或是c89。如果我们希望将我们的makefile运行在其他版本的Unix系统上,或是如果我们在我们的系统上使用一个不同的编译器,我们就需要修改makefile的多行来使其工作。宏是用于收集系统相关部分的好方法,从而可以很容易的进行修改。
宏通常是在makefile文件本身内部定义的,但是也可以通过带有宏定义的make命令来指定,例如make CC=c89。类似这样的命令行定义可以覆盖makefile文件中的定义。当在makefile文件外部使用时,宏定义必须作为一个单独的参数进行传递,所以要避免空格或是使用引号的形式:make "CC = c89"。
试验--带有宏的Makefile
下面是我们的makefile的一个修正版本,Makefile2,其中使用一些宏:
all: myapp
# Which compiler
CC = gcc
# Where are include files kept
INCLUDE = .
# Options for development
CFLAGS = -g -Wall -ansi
# Options for release
# CFLAGS = -O -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
如果我们删除我们原有的安装,而使用这个新的makefile来创建一个新的安装,我们会得到下面的信息:
$ rm *.o myapp
$ make -f Makefile2
gcc -I. -g -Wall -ansi -c main.c
gcc -I. -g -Wall -ansi -c 2.c
gcc -I. -g -Wall -ansi -c 3.c
gcc -o myapp main.o 2.o 3.o
$
工作原理
make程序使用合适的定义来替换$(CC),$(CFLAGS)以及$(INCLUDE),与带有#define形式的C编译器类似。现在如是我们需要修改编译命令,我们只需要修改makefile文件中的一行。
事实上,make有多个内部宏,从而我们可以更为简洁的来使用。在下表中,我们列出其中最常用的一些;我们会在后的例子中看到他们的使用。这些宏中的每一个仅会在他们刚要被使用时进行扩展,所以宏的语义会随着makefile文件的处理而变化。事实上,如果这些不以这样的方进行工作,他们就不会太大的作用。
$? 距离当前目标最近一次修改的需求列表
$@ 当前目标的名字
$< 当前需求的名字
$* 不带前缀的当前需求的名字
还有另外两个有用的特殊字符,也许我们会在makefile文件中的命令前遇到:
-选择make忽略所有错误。例如,如果我们希望创建一个目录,但是希望忽略错误,也许是因为这个目录已经存在了,我们只需要在mkdir命令之前带有一个负号。我们将会在后面的章节中看到-的使用。
@告诉make在执行命令之前不要将命令输出到标准输出。如果我们希望使用echo来显示一些指令时,这个字符就特别有用。
多个目标
通常需要构建多个目标文件,而不是一个目标文件,或者是在一个地方收集多个命令组。我们可以扩展我们的makefile文件来完成这些任务。下面我们添加一个"clean"选项来移除不需要的目标文件,以及一个"install"选项来将完成的程序移动到另一个不同的目录中。
试验--多个目标
下面是下一个版本的makefile,Makefile3。
all: myapp
# Which compiler
CC = gcc
# Where to install
INSTDIR = /usr/local/bin
# Where are include files kept
INCLUDE = .
# Options for development
CFLAGS = -g -Wall -ansi
# Options for release
# CFLAGS = -O -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.c a.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c a.h b.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c b.h c.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c 3.c
clean:
-rm main.o 2.o 3.o
install: myapp
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR);\
chmod a+x $(INSTDIR)/myapp;\
chmod og-w $(INSTDIR)/myapp;\
echo “Installed in $(INSTDIR)”;\
else \
echo “Sorry, $(INSTDIR) does not exist”;\
fi
在这个makefile中需要注意多个地方。首先,特殊目标all仍然只是指定myapp作为目标。所以,当我们执行make命令而没有指定一个目标时,默认的行为就是构建目标myapp。
接下来需要特别注意的另外两个目标,clean与install。clean目标使用rm命令来移除目标文件。这个命令以-开头,这会使得make命令忽略命令的结果,所以make clean总会成功,即使并没有目标文件而rm命令返回一个错误。目标"clean"并没有为clean指定任何所依赖的条件;clean之后的行是空的。所以这个目标总是被认为是最新的,并且如果clean被指定为一个目标,那么其规则总是被执行。
install目标依赖于myapp,所以make会知道在执行其他命令运行install之前必须先创建myapp。install的规则由一些shell脚本命令所组成。因为make会为执行规则而调用shell,并且第一条规则使用一个新的shell,所以我们必须添加反斜线,这样所有的脚本命令就全在一个逻辑行,并且会全部传递给一个单独的shell调用。这个命令以@开头,这会通知make命令在执行规则之前不要在标准输出上打印出命令。
install目标顺序执行命令将程序安装在其最终位置上。他在执行下一条命令之前并不会检测前一条命令是否执行成功。如果只有前一条命令成功执行之后才可以执行后续的命令,那么我们必须使用&&符号将其联合,如下所示:
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR) &&\
chmod a+x $(INSTDIR)/myapp && \
chmod og-w $(INSTDIR/myapp && \
echo “Installed in $(INSTDIR)” ;\
else \
echo “Sorry, $(INSTDIR) does not exist” ; false ; \
fi
也许我们会回想起第2章的内容,这就是一个shell "and"命令,而且其效果是只有前一条命令执行成功之后才会执行后续的命令。在这里我们并不会关心是否保证前一条命令执行成功,所以我们只是使用这种较为简单的形式。
也许我们作为一个普通用户并不具有在/usr/local/bin目录下安装程序的权限。我们可以修改makefile文件从而使用另一个不同的安装目录,或是改变这个目录的权限,或者是在执行make install之前切换到root用户。
$ rm *.o myapp
$ make -f Makefile3
gcc -I. -g -Wall -ansi -c main.c
gcc -I. -g -Wall -ansi -c 2.c
gcc -I. -g -Wall -ansi -c 3.c
gcc -o myapp main.o 2.o 3.o
$ make -f Makefile3
make: Nothing to be done for ‘all’.
$ rm myapp
$ make -f Makefile3 install
gcc -o myapp main.o 2.o 3.o
Installed in /usr/local/bin
$ make -f Makefile3 clean
rm main.o 2.o 3.o
$
工作原理
首先,我们删除myapp与所有的目标文件。make命令会使用目标all,从而构建myapp。接下来我们再次运行make玲,因为myapp已经是最新的了,所以make不会做任何事情。然后我们删除myapp并且运行make install。这会重新构建这个二进制文件,并且将其拷贝到安装目录。最后我们运行make clean,这会删除目标文件。
发表评论
-
Linux杂记
2009-09-04 23:28 1095最近一段时间似乎国内 ... -
关于Beginning Linux Programming 3ed
2009-08-25 19:00 1169关于<Beginning Linux Progr ... -
进程间通信应用-CD程序
2009-08-25 18:06 1020CD数据库程序 现在我们可以使用我们在这一章所了解的IP ... -
进程间通信之消息队列
2009-08-24 23:33 1413消息队列 现在我们来讨论第三种也是最后一种System ... -
进程间通信之共享内存
2009-08-23 11:51 2059共享内存 共享内存是第二种IPC工具。他允许两个无关的进 ... -
Linux进程间通信之信号量
2009-08-22 08:43 1952第14章 信号量,共享内存与消息队列 在这一章,我们将会 ... -
fglrx 9.8与kernel 2.6.30
2009-08-20 12:11 905Linux Kernel 2.6.30的发布已是很早之前的事情 ... -
进程间通信(九)
2009-08-15 10:49 1035管道 下面是管道实现文件,pipe_imp.c,其中有客 ... -
进程间通信(八)
2009-08-11 23:25 887搜索数据库 在CD关键字上的搜索比较复杂。函数的用户希望 ... -
进程间通信(七)
2009-08-09 10:11 953CD数据库程序 现在我们已经了解了我们可以如何使用有名管 ... -
进程间通信(六)
2009-08-08 10:08 1220读取与写入FIFO 使用O_NONBLOCK模式会影响作 ... -
进程间通信(五)
2009-08-04 12:20 1485有名管道:FIFO 到目前为止,我们只是可以在两个相关的 ... -
进程间通信(四)
2009-08-03 12:37 1011父子进程 我们的pipe调用探索的下一步就是使得子进程是 ... -
进程间通信(三)
2009-08-02 09:04 1100管道调用 我们已经了解了高层的popen函数,现在我们继 ... -
进程间通信(二)
2009-08-01 13:00 1373传递更多的数据 到目 ... -
进程间通信(一)
2009-07-31 15:41 1516第13章 进程间通信:管道 在第11章,我们了解了使用信 ... -
POSIX线程-(六)
2009-07-23 18:24 1931线程属性-调度 下面我们来看一下我们也许希望改变的第二个 ... -
POSIX线程-(四)
2009-07-19 15:06 1315使用互斥同步 在多线程程序中同步访问的另一个方法就是使用 ... -
POSIX线程-(五)
2009-07-21 18:02 1445线程属性 当我们第一次了解线程时,我们并没有讨论线程属性 ... -
POSIX线程(三)
2009-07-08 18:21 1306并发执行 下面我们将要编写一个检测两个线程是否并发执行的 ...
相关推荐
然而,对于有更高级需求的用户,如定制化功能、自动化设计流程或者集成企业内部系统,SolidWorks的二次开发工具就显得尤为重要。 在SolidWorks的二次开发中,主要涉及到以下几个方面: 1. **API接口**:SolidWorks...
U8二次开发工具包···一些控件调用说明·U8二次开发工具包···一些控件调用说明·
《用友二次开发工具在分销与零售系统的应用详解》 用友二次开发工具,作为一款专为用友软件量身定制的开发辅助平台,极大地简化了企业信息化建设过程中的复杂编程工作,使得非专业程序员也能高效地进行系统扩展与...
基于用友U8产品的二次开发工具,即U8快速开发工具,旨在解决上述问题。该工具原本是北京齐力创辉科技公司内部针对U8开发团队的一种内部开发工具,其初衷是降低成本并提高效率,从而在用友的互联网思维指导下,将好...
MES软件:AVEVA二次开发_AVEVA二次开发工具与技术.docx MES软件:AVEVA二次开发_AVEVA二次开发案例分析与实践.docx MES软件:AVEVA二次开发_AVEVA安全性与权限管理.docx MES软件:AVEVA二次开发_AVEVA工作流与业务...
SCADA软件:Rockwell Software二次开发_RockwellSoftware二次开发工具介绍.docx SCADA软件:Rockwell Software二次开发_RockwellSoftware二次开发环境搭建.docx SCADA软件:Rockwell Software二次开发_...
MES软件:Rockwell Automation FactoryTalk二次开发_FactoryTalk二次开发工具与环境.docx MES软件:Rockwell Automation FactoryTalk二次开发_FactoryTalk安全性和权限管理.docx MES软件:Rockwell Automation ...
包装质量检测软件:Cognex二次开发_Cognex编程语言与工具.docx 包装质量检测软件:Cognex二次开发_Cognex视觉系统基础.docx 包装质量检测软件:Cognex二次开发_Cognex软件架构与开发环境.docx 包装质量检测软件:...
JIRA 插件开发工具集成指南 JIRA 是一个流行的项目管理和 issue 跟踪工具,广泛应用于软件开发、项目管理等领域。为了提高开发效率和团队协作,集成 JIRA 插件于开发工具中显得尤为重要。本文将详细介绍 JIRA 插件...
二、脚本驱动开发工具的特性 1. 自动化脚本生成:MCGS脚本驱动开发工具提供自动脚本生成功能,用户只需配置相关的硬件接口和参数,工具即可自动生成对应的脚本代码,极大地减少了开发时间。 2. 灵活性高:通过脚本...
二、软件开发工具的产生与演变 1、软件开发工具的产生与演变 第一代语言——机器语言 第二代语言——汇编语言 第三代语言——高级程序设计语言(过程化语言) 第四代语言——非过程化语言 2、第三代语言与第...
森焱工具是一款集成在NX11.0版上的相关二次开发工具,方便设计者提高设计效率。工具大部分采用NXOpen C 代码完成,画面的直观感受就是摒弃了“非主流”与“老怪物”的操作界面。需要的朋友可下载试试! 注: 1、本...
《Epulis开发工具类详解》 在软件开发领域,工具类是程序员的得力助手,它们提供了一系列常用功能,使得代码编写更为高效便捷。Epulis开发工具类就是这样一个旨在优化开发流程、提升代码复用性的重要工具集。本文将...
ERP软件:Microsoft Dynamics二次开发_二次开发工具介绍.docx ERP软件:Microsoft Dynamics二次开发_多语言与多币种支持.docx ERP软件:Microsoft Dynamics二次开发_安全权限与角色管理.docx ERP软件:Microsoft ...
PML二次开发工具则是基于PDMS(Plant Design Management System)系统,为用户提供了对PML进行扩展和定制的强大平台。PDMS是由AVEVA公司开发的一款三维工厂设计软件,它允许用户创建、管理和协作大型复杂工程的设计...
### CAD二次开发工具概述 #### AutoCAD二次开发工具发展历程与特性 AutoCAD,作为全球领先的计算机辅助设计(CAD)软件,不仅以其强大的通用性和开放的架构在各行各业中得到广泛应用,而且通过不断迭代的二次开发...
AutoCAD的二次开发是利用其提供的开发工具和接口来扩展或定制CAD软件功能的过程,而ObjectARX是AutoCAD的主要开发平台。ObjectARX是一种基于C++的编程库,允许开发者深入到AutoCAD的内核,创建能够与AutoCAD内部对象...
用C#语言,CAD二次开发的托管工具,无需每次打开CAD加载文件,支持多个版本CAD
【自考软件开发工具习题】的题目涵盖了软件开发的不同环节,从选择题到填空题,测试了考生对软件开发基础知识的掌握。以下是根据题目内容解析的关键知识点: 1. **软件开发的重点**:题干指出,为了推广应用计算机...
组态王图库开发工具是一种专门用于创建和定制工控软件界面的专业软件,它为用户提供了自定义图形界面的能力,使工业自动化应用的可视化设计更加灵活、个性化。在这个“kv图库开发包”中,我们可以预见到包含了一系列...