这篇文章给大家聊聊关于makefile函数,以及makefile是shell脚本吗对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
简述makefile编写规格举例说明
1.一个简单的makefile例子
假设一个程序有两个文件file1.c,file2.c,每个文件都包含head.h,生成file可执行文件
file:file1.ofile2.o附属行(文件的依存关系)
gcc-ofile1.ofile2.o命令行
file1.o:file1.chead.h
gcc-cfile1.c
file2.o:file2.chead.h
gcc-cfile2.c
从file最终的目标文件开始倒推,依次列出文件的依存关系,make在执行时:
(1)判断file可执行文件是否存在,若不存在,则执行命令行,向下寻找依存关系
(2)若file存在,则检查依靠文件,是否存在更新,若存在更新则执行命令行,若没有更新则给出提示:
make:'file'isuptodate.
2.makefile中的宏定义及内部变量
宏定义:
OBJS=file1.ofile2.o
CC=gcc
CFLAGS=-wall-O-g
引用:
file:$(OBJS)
$(CC)$(OBJS)-ofile
file1.o:file1.chead.h
$(CC)$(FLAGS)-cfile1.c
file2.o:file2.chead.h
$(CC)$(FLAGS)-cfile2.c
内部变量:
$@:当前规则的目的文件名
$<:依靠列表中的第一个依靠文件
$^:整个依靠列表
file:$(OBJS)
$(CC)$^-o$@
file1.o:file1.chead.h
$(CC)$(FLAGS)-c$<-o$@
file2.o:file2.chead.h
$(CC)$(FLAGS)-c$<-o$@
"$(CC)$(FLAGS)-c$<-o$@"是隐含规则,可以不写,默认使用此规则
3.假象
假设一个项目要生成两个可执行文件file1和file2,这两个文件是相与独立的,则在makefile开始处:
all:file1file2
make总是假设all要生成,去检查它的依赖文件
4.清除由make产生的文件
clean:
rm*.o
rmfile
执行:
makeclean
则会清除由make生成的*.o和file文件
如果有clean文件存在,则清除不会执行(因clean没有可依赖的文件,永远是最新的)
使用PHONY目标,避免同名文件相冲突,不会检查clean文件存在与否,都要执行清除操作
.PHONY:clean
clean:
rm*.o
rmfile
5.makefile函数
搜索当前目录,生成由*.c结尾的文件列表,wildcard--函数名
SOURCE=$(wildcard*.c)
用%.o替换$(SOURCE)中的%.c文件
OBJS=$(patsubst%.c,%.O,$(SOURCE))
6.产生新规则
SOURCE=$(wildcard*.c)
depends:$(SOURCE)
gcc-M$(SOURCE)>depends
(为每一个.c文件产生规则,c文件和相关头文件为依靠)
在makefile文件中:
includedepends
7.一个有效的makefile文件
可以完成大部分我们所需要的依靠检查,不用做太多的修改就可用在大多数项目里
功能:搜索当前目录,寻找源码文件,放入SOURCE变量里,利用patsubst产生目标文件(*.o)
CC=gcc
CFLAGS=-Wall-O-g
SOURCE=$(wildcard*.c,*.cc)
OBJS=$(patsubst%.c,%.o,$(patsubst,%.cc,%.o,$(SOURCE)))
file:$(OBJS)
$(CC)$^-o$@
用默认规则产生目标文件(*.o)
1:编译可执行程序。2:编译lib库3:编译so库
本博针对上面三种目的各自写出了makefile模版,希望对大家有所帮助。
一.编译可执行程序
当前目录下制定文件编译成可执行文件(连接外部库的话只需要更改INC和LIB即可)
CXX=g++
TARGET=bitmaploctest
C_FLAGS+=-g-Wall
LIB_FLAGS=-pthread
all:$(TARGET)
bitmaploctest:bitmaploctest.obitmaploc.ofile_lock.o
$(CXX)-o$@$^$(LIB_FLAGS)$(LIB)$(C_FLAGS)
.cpp.o:
$(CXX)-c-o$*.o$(INC)$(C_FLAGS)$*.cpp
.cc.o:
$(CXX)-c-o$*.o$(INC)$(C_FLAGS)$*.cc
clean:
-rm-f*.o$(TARGET)
二.编译成lib库
当前目录下指定文件编译成lib库(一般lib库在编译的时候不会将使用的外部库编译进来,而是等编译成可执行程序时或者.so时)
INC_DIR=./
SRC_DIR=./
OBJ_DIR=./
LIB_DIR=./
H_DIR=./
OBJ_EXT=.o
CXXSRC_EXT=.cpp
CSRC_EXT=.c
LIB_EXT=.a
H_EXT=.h
OBJECTS=$(OBJ_DIR)bitmaploc$(OBJ_EXT)\
$(OBJ_DIR)file_lock$(OBJ_EXT)
LIB_TARGET=$(LIB_DIR)libbitmaploc$(LIB_EXT)
$(OBJ_DIR)%$(OBJ_EXT):$(SRC_DIR)%$(CXXSRC_EXT)
@echo
@echo“Compiling$<==>$@…”
$(CXX)$(INC)$(C_FLAGS)-c$<-o$@
$(OBJ_DIR)%$(OBJ_EXT):$(SRC_DIR)%$(CSRC_EXT)
@echo
@echo“Compiling$<==>$@…”
$(CC)-I./$(INC)$(C_FLAGS)-c$<-o$@
all:$(LIB_TARGET)
$(LIB_TARGET):$(OBJECTS)
all:$(OBJECTS)
@echo
$(AR)rc$(LIB_TARGET)$(OBJECTS)
@echo“ok”
clean:
rm-f$(LIB_TARGET)$(OBJECTS)
三.编译成so库
当前目录下指定文件编译成so库(必须将所有引用的外部库都编译进来)
CC=gcc
CXX=g++
CFLAGS=-Wall-pipe-DDEBUG-D_NEW_LIC-g-D_GNU_SOURCE-shared-D_REENTRANT
LIB=-lconfig-ldl-lrt-L../../lib-lttc-g
INCLUDE=-I../spp_inc
OO=service.otinystr.otinyxml.otinyxmlerror.otinyxmlparser.ouin_conf.ostat.o
TARGETS=../../lib/libRanch.so
all:$(TARGETS)
stat:tool_stat.cpp
$(CXX)$(INCLUDE)tool_stat.cpp-otool_statstat.otinystr.otinyxml.otinyxmlerror.otinyxmlparser.o-g
cptool_stat../../bin
$(TARGETS):$(OO)
$(CXX)$(CFLAGS)$(INCLUDE)$(OO)-o$@$(LIBDIR)$(LIB)
.c.o:
$(CC)$(CFLAGS)-c$(INCLUDE)$<
echo$@
.cpp.o:
$(CXX)$(CFLAGS)-c$(INCLUDE)$<
echo$@
%:%.c
$(CC)$(CFLAGS)-o$@$<$(OO)$(LDFLAGS)
echo$@
clean:
rm-f*.o
rm-f$(TARGETS)
rm-ftool_stat
CC=cc-g
PROC=proc
CFLAGS=-DPRECOMP-I$(ORACLE_HOME)/precomp/public\
-I$(ORACLE_HOME)/xdk/include-I.
FLAGS=-D_ALL_SOURCE=1-D_LINUX-g-I../../incl-D_GNU_SOURCE-D_IS_EAB=1-D__USE_GNU=1-D__GCC_296-I/usr/include/libxml2-I../csrc-I../../csrc/-DPOSIX=1-DLINUX
LIBHOME=$(ORACLE_HOME)/lib
LLIBSQL=`cat$(LIBHOME)/sysliblist`\
`cat$(LIBHOME)/ldflags`\
-lclntsh
LIBS=-L$(LIBHOME)$(LLIBSQL)-lmylib
.SUFFIXES:.sqc.c.o
%.c:%.sqc
$(PROC)$(PROCPLSFLAGS)iname=$^hold_cursor=yes
%.o:%.c
$(CC)-c$(FLAGS)$(LIBS)$^
test:test.otest1.otest1.o
cc-o$@$(FLAGS)$(LIBS)$^
rm-rf$^
haha:test.otest1.otest1.o
@echo"+="$+
@echo"?="$?
@echo"^="$^
@echo"<="$<
@echo"@="$@
@echo"*="$*
@echo"%="$%
2.说明
2.1一般makefile编写有3个步骤
1.宏定义。主要功能是定义一些宏变量已替代较长的编译支持信息。一般情况下针对编译所需要得.h头文件,.a/.so的库文件路径。比如例子中的CFLAGS是oracle预编译需要数据库支持的头文件路径。LIBHOME是oracle环境编译需要数据库库文件路径。
2.源文件之间的相互依赖关系。列出需要产生目标文件编译依赖的文件。比如例子中的test目标,其产生时会检测(test.otest1.otest1.o)这些依赖文件的变化,如果依赖文件有变化会自动先编译依赖文件。
3.可执行的命令.即针对目标关系,所作出的编译行为。比如test其检测完依赖文件后执行(cc-o$@$(CFLAGS)$(LIBS)$^)编译链接产生目标执行文件test.
4.宏使用时用(),{}来确认宏名称例如${LIB}加{}会查找LIB的宏内容,$LIB会查找L的宏内容。
2.2:常用编译项说明
1.-I:制定头文件搜索的路径
2.-L:连接需要的库文件路径
3.–l:连接需要的库文件(比如:libmylib.so写作–lmylib)
2.3:自动化变量说明:
$+:所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$?:所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚
$^:所有的依赖文件,以空格分开,不包含重复的依赖文件。
$<:第一个依赖文件的名称。
$@:目标的完整名称。
$*:不包含扩展名的目标文件名称。
$%:如果目标是归档成员,则该变量表示目标的归档成员名称。
具体对照使用以上makefile,执行makehaha得到如下对照信息:
$makehaha
test.otest1.otest1.o
test.otest1.o
test.otest1.o
test.o
haha
2.4:后缀规则:
.SUFFIXES:.sqc.c.o制定新的后缀规则。(%.c:%.sqc),(%.o:%.c)即规则行为。就是将所有.sqc转为.c,.c再转为.o。
.c.o:等价于%.o:%.c
3.注意:
分行符\后面不能再有其他任何内容。
对齐行最好采用^I(tab键)
注释符号#
include包含编译文件
1.概述
Makefile,what??很多windows程序可能都没听说过
简单的说,Makefile是Unix/Linux环境下描述了整个工程的编译、连接等规则的文件,其主要包括三点:
1)工程中的哪些源文件需要编译以及如何编译
2)依赖库以及库所在的位置
3)想得到什么:可执行文件?静态库?动态库?
项目中,我们会有很多源文件、头文件、依赖库文件、配置文件等等,通过Makefile定义规则来制定编译顺序,编译规则,编译依赖,甚至更复杂的功能,将极大的方便我们的开发,其最大的好处就是”自动化编译“,通过‘make’就可以方便的进行整个项目的编译工作。
2.编译链接
从源码到可执行文件,具体步骤:
源码--->预处理--->编译--->汇编--->链接
我们常常把预处理、编译和汇编三个阶段统称为编译阶段,在这个阶段,编译器会检查程序语法、函数与变量是否声明等。
经过编译之后,unix/linux下,将得到.o文件(一般来说,每个源文件都能生成一个对应的.o文件),即objectfile(windows下即.obj文件),.o不能直接运行,我们需要将其合成可执行文件,这个过程就叫链接。在链接过程,链接器会在所有的.o文件中找寻函数的实现,如果找不到,则会报链接错误。
3.Makefile规则
Makefile只有一个规则:
target:prerequisites
command
target:即目标,它可以是可执行文件、可以是.o文件,也可以是一个标签,简单的说,它就是你要做的事情。
prerequisites:生成target所需要的条件,它可以是一个文件,也可以是另外一个target
command:具体执行的命令
解释如下:target这个目标依赖于prerequisites中的文件,其生成规则定义在command中。
更简单一点表达:如果prerequisites中任何一个文件的时间要比target文件更新的话,command所定义的命令就会执行。
eg:
=====makefile=====
#第一个规则
test:main.ohello.o
gccmain.ohello.o–otest
#第二个规则
main.o:main.c
gcc–cmain.c
#第三个规则
hello.o:hello.chello.h
gcc–chello.c
#第四个规则
clean:
rm–rf*.o
rm–rftest
=====makefile=====
第一个规则:
test就是target,main.o和hello.o是prerequisites,'gccmain.ohello.o–otest’是command。
即:要生成test,就需要有main.o和hello.o,如果main.o或者hello.o文件的时间比test新(或者test文件不存在),则会执行命令’gccmain.ohello.o–otest’,
第二个规则:
target是main.o,main.c是prerequisites,’gcc–cmain.c’是command
即:要生成test,就需要main.c,如果main.c文件的时间比main.o新,则会执行’gcc–cmain.c’
第三个规则和第二个规则类似
第四个规则:
这里,target是clean,此处,clean并不是一个文件,而是一个动作的名字,它的执行,需要显示的在make命令后制定,例如,此处执行‘makeclean’,将调用其后的command,即‘rm–rf*.orm–rftest’,另外,此处没有prerequisites,即任何时候都执行command
我们来看下如果执行'make'会做什么:
1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“test”这个文件,并把这个文件作为最终的目标文件。
3、如果test文件不存在,或是test所依赖的后面的[.o]文件的文件修改时间要比test这个文件新,那么,他就会执行后面所定义的命令来生成test这个文件。
4、如果test所依赖的.o文件存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。
5、依次类推,直到生成的所有的target都是最新的。
用户如果执行'makeclean',由于其后面没有依赖,则执行command所定义的命令。
如果我们修改了代码main.c,然后执行‘make’,由于main.c时间比main.o新,那么main.o会重新编译生成,由于main.o文件的时间比test新,那么test也会重新生成。
VS code怎么用
关于VisualStudioCode
VisualStudioCode(简称VSCode)是微软于2015年4月29日发布的轻体量但是功能强大的跨平台且免费的源代码编辑器。VSCode可以运行在Windows,Mac和Linux平台上。VSCode内建支持JavaScript、TypeScript和Node.js,并可通过强大的扩展机制支持其它编程语言(C/C++、C#、Java、Python、PHP和Go等),以及其它运行平台(.Net、Unity等)。截至目前,VSCode最新版本是1.21。
在StackOverflow举办的2018年开发者调查活动中,VSCode以34.9%的得票率高居最流行的开发环境工具榜首。
VSCode的源代码可以在GitHub上找到:
https://github.com/Microsoft/vscodeVisualStudioCode官方网站https://code.visualstudio.com概览:
https://code.visualstudio.com/docs下载:
https://code.visualstudio.com/#alt-downloads安装:
https://code.visualstudio.com/docs/setup/setup-overview技巧:
https://code.visualstudio.com/docs/getstarted/tips-and-tricks使用:
https://code.visualstudio.com/docs/editor/codebasics#editor-articlesVisualStudioCode中文手册(未完成)https://jeasonstudio.gitbooks.io/vscode-cn-doc/content/概览:
https://jeasonstudio.gitbooks.io/vscode-cn-doc/content/md/Overview.html安装:
https://jeasonstudio.gitbooks.io/vscode-cn-doc/content/md/%E7%BC%96%E8%BE%91%E5%99%A8/%E5%AE%89%E8%A3%85.html使用:
https://jeasonstudio.gitbooks.io/vscode-cn-doc/content/md/%E7%BC%96%E8%BE%91%E5%99%A8/%E5%AE%89%E8%A3%85.htmlmake找不到头文件定义函数
指定头文件目录,一般都是通过编译器参数-I(大写的I)来指定的,假设头文件目录在:/home/develop/include则可以通过:-I/home/develop/include在makefile中则可以这样写:
CFLAGS=-I/home/develop/include
在PHP中如何正确创建函数
tep1=>
php的扩展模块都放在ext/目录下,比如说snmp模块、mysql模块。我们要建立自己的模块,就要在ext目录下为自己的模块建一个目录。比如,我们要做一个分析config文件的模块,命名为pconfig模块(parseconfig的简写),需在ext下建立目录pconfig。将我写好的7个文件copy到该目录下,另外需对主目录下的configure和internal_functions.c作一些修改。
Step2=>
Makefile.amMakefile.in
是模板文件,用户执行configure时,会调用这两个文件,生成编译时所用的Makefile文件。修改时将小写的pconfig换成你自己的模块名,别忘了把大写的PCONFIG也替换掉(不要告诉我你不会vi的替换语句)。config.m4也是执行configure将会调用的检测脚本程序,以后我们来讨论这些脚本程序的更深入的修改。现在你只需要把pconfig该成你的模块就可以了。对config.h.stub和setup.stub也如法炮制。其实setup.stub也没什么用。
Step3=>
php3-pconfig.h头文件中
externphp3_module_entrypconfig_module_entry;
#definepconfig_module_ptr&pconfig_module_entry
#definephpext_pconfig_ptrpconfig_module_ptr
这几行定义了模块的入口,将入口注册到php后,php会通过模块入口找到你写的函数
下面几个函数定义是用宏进行定义的,展开以后其实就是php3_minit_pconfig,php3_rinit_pconfig……分别在你的模块初试化或结束时被调用,如果你的模块很简单,也就不需要这些定义了
externPHP_MINIT_FUNCTION(pconfig);
externPHP_RINIT_FUNCTION(pconfig);
externPHP_MSHUTDOWN_FUNCTION(pconfig);
PHP_MINFO_FUNCTION(pconfig);
这是你的函数声明,将来写在php脚本语句中的函数名就是在PHP_FUNCTION中定义的名字。
PHP_FUNCTION(pconfig_test);
如果有多个,还可以继续往下加
PHP_FUNCTION(pconfig_parsefile);
PHP_FUNCTION(pconfig_release);…….
Step4=>
接下来我们看最重点的C代码了
function_entrypconfig_functions[]={
PHP_FE(pconfig_test,NULL)
{NULL,NULL,NULL}
};
定义的是你的函数的入口(前面我们提到过模块的入口),按照格式将你在头文件中定义的函数写进去吧。注意,这是用宏定义的,不要管语法是否正确。以后我们具体讨论这些宏的用法。
php3_module_entrypconfig_module_entry={
"pconfig",pconfig_functions,PHP_MINIT(pconfig),PHP_MSHUTDOWN(pconfig),PHP_RINIT(pconfig),NULL,PHP_MINFO(pconfig),STANDARD_MODULE_PROPERTIES
};
注册模块的入口信息,比如模块名,函数接口,初试化模块将调用的函数等等,如果你的模块不执行复杂操作的话,可以忽略掉他们,写成
php3_module_entrypconfig_module_entry={
"pconfig",pconfig_functions,NULL,NULL,NULL,NULL,NULL,STANDARD_MODULE_PROPERTIES
};
Step5=>
写你自己的函数
在头文件和function_entry处,我们已经定义了自己的函数pconfig_test,现在我们就来实现pconfig_test的功能。就比如执行两个数相加的和吧。
staticvoid_php3_pconfig_test(INTERNAL_FUNCTION_PARAMETERS)
{......
}
PHP_FUNCTION(pconfig_test)
{
_php3_pconfig_test(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
当系统调用pconfig_test时,会调用你的_php3_pconfig_test函数,当然你也可以把_php3_pconfig_test里的内容直接写在PHP_FUNCTION(pconfig_test)中,这样做只是程序结构比较清晰。注意:不要将_php3_pconfig_test命名成php3_pconfig_test,PHP_FUNCTION(pconfig_test)宏展开后实际上就是php3_pconfig_test!
Step6=>
好了,现在我们开始修改configure,在echo$ac_n"checkingforMySQLsupport""...$ac_c"1>&6的前面(当然,如果你熟悉configure的话,可以加在任何合适的地方)加上下面几句话
iftest"${with_pconfig+set}"=set;then
withval="$with_pconfig"
#Addyourlibinhere
EXTRA_LIBS="$EXTRA_LIBS"
#Addyourincludepathinhere
INCLUDES="$INCLUDES"
EXT_SUBDIRS="$EXT_SUBDIRSpconfig"
EXT_LIBS="$EXT_LIBSpconfig/libphpext_pconfig.a"
EXTINFO_DEPS="$EXTINFO_DEPS../ext/pconfig/extinfo.c.stub"
EXT_STATIC="$EXT_STATICpconfig"
fi
修改internal_functions.c,在头文件定义中加入#include"ext/pconfig/php3_pconfig.h"
在zend_module_entry数组中加入phpext_pconfig_ptr,
Step7=>
从新configure,带上需要的参数,不要忘记的是在参数里加入--with-pconfig
Step8=>
index.php3
<?echopconfig_test(123,678)."
";?>
执行%>phpindex.php3
c语言ceil函数怎么使用
ceil函数是数学函数库中的一个函数,用于向上取整,即将一个小数向上取到最近的整数。下面是一些ceil函数的用法举例:
1.ceil(3.14)的值为4,因为3.14向上取整后为4。
2.ceil(2.5)的值为3,因为2.5向上取整后为3。
3.ceil(-2.5)的值为-2,因为-2.5向上取整后为-2。
4.ceil(0.01)的值为1,因为0.01向上取整后为1。
5.ceil(-0.01)的值为0,因为-0.01向上取整后为0。
需要注意的是,ceil函数只能对数值类型进行运算,如果输入的参数类型不是数值类型,会返回NaN(NotaNumber)。
makefile函数的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于makefile是shell脚本吗、makefile函数的信息别忘了在本站进行查找哦。