首先写一个自己的库:

  1. #include "../MyAPI.h"
  2. #include <cstdlib>
  3. #include <ctime>
  4. int getRandom(int boundary)
  5. {
  6. if (boundary <= 0 )
  7. {
  8. return 0;
  9. }
  10. srand((unsigned)time(NULL));
  11. return rand() % boundary;
  12. }

这里的MyAPI.h是库对应的头文件(这里用../MyAPI.h是因为库文件源代码在lib目录下,而头文件跟lib目录在同级目录):

  1. int getRandom(int boundary);

2. 接着要编译这个库,在这之前需要将源文件编译成.o文件:

3. 之后再将.o文件打包成lib,在类Unix系统中,静态库是.a文件:

4. 之后就是使用这个lib库了,下面是使用该库的源代码:

  1. #include "basic.h"
  2. int main()
  3. {
  4. cout << getRandom(20) << endl;
  5. }

5. 源代码中只需要包含头文件就可以了,重点在于编译的时候,下面是编译命令:

这里需要注意两点:

1) -L参数指定包含lib的目录;-l指定lib名;

2)lib名也需要注意,名称是libMyAPI.a,但是使用时不需要加lib和.a后缀。

当然也可以不使用-L -l等选项,直接使用lib全称:

之后生成的a.out就可以使用了。

这里之所以提到-L和-l参数,原因是在写makefile时,-L和-l会带来更多的便利。

以上是一个简单的例子。

也可以写一个makefile文件来做这个,下面是一个makefile的例子:

  1. #####################################################################
  2. ## file        : test makefile for build current dir .cpp          ##
  3. ## author      :                                                   ##
  4. ## date-time   :                                                   ##
  5. #####################################################################
  6. CC      = gcc
  7. CPP     = g++
  8. RM      = rm -rf
  9. ## debug flag
  10. DBG_ENABLE   = 1
  11. ## source file path
  12. SRC_PATH   := .
  13. ## target exec file name
  14. TARGET     := test
  15. ## get all source files
  16. SRCS         += $(wildcard $(SRC_PATH)/*.cpp)
  17. ## all .o based on all .c
  18. OBJS        := $(SRCS:.cpp=.o)
  19. ## need libs, add at here
  20. LIBS := MyApi
  21. ## used headers  file path
  22. INCLUDE_PATH := .
  23. ## used include librarys file path
  24. LIBRARY_PATH := lib
  25. ## debug for debug info, when use gdb to debug
  26. ifeq (1, ${DBG_ENABLE})
  27. CFLAGS += -D_DEBUG -O0 -g -DDEBUG=1
  28. endif
  29. ## get all include path
  30. CFLAGS  += $(foreach dir, $(INCLUDE_PATH), -I$(dir))
  31. ## get all library path
  32. LDFLAGS += $(foreach lib, $(LIBRARY_PATH), -L$(lib))
  33. ## get all librarys
  34. LDFLAGS += $(foreach lib, $(LIBS), -l$(lib))
  35. ## c++11 support
  36. CFLAGS += -std=c++11
  37. all: build
  38. build:
  39. $(CPP) -c $(CFLAGS) $(SRCS)
  40. $(CPP) $(CFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)
  41. $(RM) $(OBJS)
  42. clean:
  43. $(RM) $(OBJS) $(TARGET)
运行make命令之后,make程序会在当前目前下寻找Makefile文件,根据Makefile文件中的内容执行具体的操作。
执行make命令后的结果如下:
Makefile的基础是如下的部分:
  1. targets:prerequisites
  2. commands

如上例所示:

a.out是targets,目标;
main.c是prerequisites,依赖;
剩余的部分开头是一个TAB,他们是命令;
make执行命令的条件是依赖比目标要新。
如果在上例执行后再运行make,结果如下:

这是因为main.c没有修改过,它比a.out要旧。
需要注意,目标和依赖都可以是多个,而只要任意依赖新于目标,都会导致命令重新执行。
 
以上示例中,目标是一个文件,但是它还可以是其它的。比如一个标签:
all就是一个标签。
标签永远比依赖要旧,即其下的命令一直会执行:
甚至可以没有依赖:
all对应命令也会一直执行。
标签可以有多个,但是它并不是顺序执行,make只会执行第一个遇到的标签。如下面的Makefile文件:
执行make的结果如下:
可以看到只有all标签会被执行。如果要执行bll,就需要显式地指定:
标签之间可以互相依赖:
执行的结果如下:
因为all依赖于bll,而bll又依赖于main.c,因此这里的执行顺序就是先执行bll对应的命令,然后再执行all对应的命令。
 
还有一种情况,如果在标签之前加上“.”,则make的时候会跳过它,即使它是第一个遇到的标签:
make执行结果如下:
 
标签在Makefile文件中又称为伪目标,不应该与真正的目标文件具有相同的名字,而为了避免这种情况,Makefile提供了一个关键字.PHONY,用于声明伪目标。
像下面这个样子:
 

变量

Makefile文件中的变量就是一个个的字符串。
访问变量使用$(xx),其中xx是变量名。
下面是一个例子:
执行的结果是:
变量的赋值可以使用普通的"=",它有一个特点,如下例所示:
执行的结果是:
即,Makefile中使用=定义的变量可以访问到之后定义的变量。使用=得到的变量称为recursively expanded variable。
它有一个缺点就是会导致循环赋值,比如下面的例子:
为了避免这种情况,Makefile提供了另一个赋值操作符":=",称为Simply expanded variables。
它更接近于一般意义上的赋值,当:=右边引用了其它的变量,而该变量还没有定义或者要到之后才会定义,那么返回的就是空字符串。
另外的赋值操作符还有:
“+=”:这是给变量追加值。
"?=":首先判断变量是否存在,如果不存在就赋值成右边的值,如果存在了,就什么也不做。
 
与变量赋值相关的还有几个指示符:
override:这个指示符出现的原因是,一般定义的变量会被make命令行中的参数覆盖,而使用了override的变量则不会。下面是一个例子:
在未使用override的情况下:
可以看到FLAG参数被make命令行中的参数替代了。
如果在定义变量的时候使用了override的话:
变量的值将不会受到make命令行参数的影响。
export:用于向下层的Makefile文件传递参数。默认情况下,只有在make命令行中的参数才会向下传递,但是使用export之后,在当前Makefile文件中定义的变量也会向下传递了。
 
Makefile中还存在几类特殊的变量:
系统环境变量:make执行时会引入部分的环境变量,它们在Makefile中可以访问:
从结果可以看到Makefile中可以识别HOME这个系统环境变量。
需要注意的是,并不是所有的系统环境变量都可以在Makefile中使用,比如BASH就不行。具体怎么区分的,不知道。
目标变量:它是针对某一个目标存在的变量,可以算作是局部变量。它的定义如下:
  1. targets:xx=yy

下面是一个例子:


从中可以看到FLAG只针对all存在,在bll中无法访问到。
还需要注意,FLAG不仅只在all中生效,它引发的所有的规则中FLAG都存在。
模式变量:它其实是目标变量的延伸。其中定义的变量对满足模式的所有目标都可见。下面是一个例子:
上例中的a.out满足%.out的模式,所以FLAG有效,而对于main.o就无效了。
自动化变量:它们是一组样式奇怪的变量,也属于局部变量,下面是其中的几个:
$@ :表示目标集;
$< :表示依赖中的第一个名字,如果依赖是模式的话,则表示满足模式的所有依赖;
$? :表示所有比目标新的依赖集;
$^ :表示依赖集;
$(@D) :表示$@的目录部分;(还有其它版本的,如$(<D),略)
$(@F) :表示$@的文件部分;(还有其它版本的,如$(<F),略)
自动化变量还有很多,不一一介绍了。
还有一个类型的变量,属于make执行时可以使用的与命令相关的变量,比如如下的:
执行的结果如下:
这类变量还有很多,这里不一一说明。
 

函数

函数的格式如下:
  1. $(<fucn><params>)

函数名与参数间用空格隔开,参数之间用逗号隔开。

以下是一个简单的示例:

make后得到的结果是goodbye world。
Makefile中的函数将在Makefile基础——函数中详细介绍。
 

控制语句

Makefile中的控制语句有以下的一些:
  1. ifeq/ifneq
  2. else
  3. endif

举例:

  1. ifdef/ifndef
  2. else
  3. endif

举例:

函数的基础请参考Makefile基础

字符串处理函数

  1. $(subst <from>,<to>,<text>)

作用:将text中的from替换成to,并返回修改后的text(当然也有可能没有被修改)。

  1. $(patsubst <pattern>,<replacement>,<text>)

作用:基本同subst,只是这里变成了对满足模式的字符串的替换。

  1. $(strip <string>)

作用:将string前后的空格去掉并返回修改后的string(当然也有可能没有被修改)。

  1. $(findstring <find>,<in>)

作用:在in中找字符串find,如果找到了就返回find,否则返回空。

  1. $(filter <pattern...>,<text>)

作用:过滤text字符串,只保留符合模式的字符串,pattern可以有多个。

  1. $(filter-out <pattern...>,<text>)

作用:同filter刚好相反,这里删除符合模式的字符串。

  1. $(sort <list>)

作用:升序排序list里面的单词。

  1. $(word <n>,<text>)

作用:取text中的第n个单词,从1开始算。

  1. $(wordlist <s>,<e>,<text>)

作用:取text中第s个开始到第e个为止的单词,包括第e个单词。

  1. $(words <text>)

作用:返回text中的单词数。

  1. $(firstword <text>)

作用:返回text中的第一个单词。

文件名操作

  1. $(dir <names...>)

作用:取names中的目录部分。

  1. $(nodir <names...>)

作用:取names中的非目录部分。

  1. $(suffix <names...>)

作用:取names中的后缀部分,比如main.c就取得.c部分。

  1. $(basename <names...>)

作用:取names中的前面部分,比如main.c就取得main部分。

  1. $(addsuffix <suffix>,<names...>)

作用:给names中的每一个成员加后缀suffix。

  1. $(addprefix <prefix>,<names...>)

作用:给names中的每一个成员加前缀prefix。

  1. $(join <list1>,<list2>)

作用:将list1中的单词加到list2对应位置的单词之后。没有对应的就不管了。

  1. $(abspath <names...>)

作用:返回绝对路径。

结构函数

  1. $(foreach <var>,<list>,<text>)

作用:取出list中的每一个单词并赋值给var,再执行text语句。

  1. $(if <condition>,<then-part>,<else-part>)

作用:判断condition条件,满足条件就执行then-part,否则执行else-part。两个part都可以是空。

call函数

  1. $(call <expression>,<param1>,<param2>...)

作用:执行expression,后面的是参数,它们在expression中用$(1)$(2)...表示。

origin函数

  1. $(origin <var>)

作用:确定var的来源,是undefined?default?environment?file?command line?override?automatic?

shell函数

  1. $(shell <cmd>)

作用:执行cmd命令。相当于`cmd`。

eval函数

  1. $(eval <text>)

作用:不明。

似乎是展开text,作为Makefile的一部分。但是为什么要这么做,为什么不直接写text,不明白。。。

告警/错误函数

  1. $(error <tetx>)

作用:显示错误并停止执行。

  1. $(warning <text>)

作用:显示告警,但是会继续执行。

wildcard函数

  1. $(wildcard pattern...)

作用:返回工作目录下满足pattern的所有文件名,多个文件名之间用空格隔开。

运行make之后的结果:

Makefile基础---编译的更多相关文章

  1. Makefile基础学习

    Makefile基础学习 理论知识 makefile关系到了整个工程的编译规则.一个工程中的源文件不计其数,并且按类型.功能.模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文 ...

  2. Makefile基础(三)

    第一章:C语言之Makefile基础(一) 第二章:C语言之Makefile基础(二) 再来看一个简单的例子: [root@localhost linux_c]# cat Makefile foo = ...

  3. Makefile基础(二)

    上一章:C语言之Makefile基础(一) 上一章的Makefile写的中规中矩,比较繁琐,是为了讲清楚基本概念,其实Makefile有很多灵活的写法,可以写的更简洁,同时减少出错的可能 一个目标依赖 ...

  4. C编译: makefile基础

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在编译一个大型项目的时候,往往有很多目标文件.库文件.头文件以及最终的可执行文件. ...

  5. Linux学习二:Makefile基础

    文首感谢http://www.chinaunix.net 作者:gunguymadman的分享 makefile关系到了整个工程的编译规则.一个工程中的源文件不计数,其按类型.功能.模块分别放在若干个 ...

  6. 5、Makefile基础知识汇总(转自陈皓总述)

    一.Makefile里有什么? Makefile里主要包含了五个东西:显式规则.隐晦规则.变量定义.文件指示和注释. 1.显式规则.显式规则说明了,如何生成一个或多的的目标文件.这是由Makefile ...

  7. makefile 和 编译条件 的简略总结

    #-g gdb可看代码 #-fPIC -fPIC 的使用,会生成 PIC 代码,.so 要求为 PIC,以达到动态链接的目的,否则,无法实现动态链接. -fPIC 作用于编译阶段,告诉编译器产生与位置 ...

  8. [转] Makefile 基础 (4) —— Makefile 书写命令

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

  9. [转] Makefile 基础 (2) —— Makefile 总述

    该篇文章为转载,是对原作者系列文章的总汇加上标注. 支持原创,请移步陈浩大神博客:(最原始版本) http://blog.csdn.net/haoel/article/details/2886 我转自 ...

随机推荐

  1. 如何优化你的布局层级结构之RelativeLayout和LinearLayout及FrameLayout性能分析

    转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/51159419 如何优化你的布局层级结构之RelativeLayout和LinearLa ...

  2. 菜鸟玩云计算之廿二: saltstack 配置

    菜鸟玩云计算之廿二: saltstack 配置 要求环境: RHEL6.4+ >=Python2.6.6, < Python 3.0 关闭salt-master/minion服务:   # ...

  3. C++大小写转换和性能

    p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; text-align: justify; f ...

  4. Unable To Import Or Enter Sale Order - ORA-20001: APP-FND-01564: ORACLE error - 1422 in get_seq_info

    In this Document   Symptoms   Cause   Solution APPLIES TO: Oracle Order Management - Version 12.0.4 ...

  5. TCP/IP概述

    1) 链路层,有时也称作数据链路层或网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡.它们一起处理与电缆(或其他任何传输媒介)的物理接口细节. 2) 网络层,有时也称作互联网层, ...

  6. ssh命令大全

    常用格式:ssh [-l login_name] [-p port] [user@]hostname 更详细的可以用ssh -h查看. 举例 不指定用户: ssh 192.168.0.11 指定用户: ...

  7. Systemc在VC++2010安装方法及如何在VC++2010运行Noxim模拟器

    Systemc在VC++2010的安装方法可以参考文档"Systemc with Microsoft Visual Studio 2008.pdf".本文档可以在"htt ...

  8. Gradle 1.12用户指南翻译——第三十五章. Sonar 插件

    本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  9. 安卓笔记-- ListView点击和长按监听

    其中点击监听为setOnItemClickListener() 具体实现代码如下 listView.setOnItemClickListener(new AdapterView.OnItemClick ...

  10. 粒子滤波(PF:Particle Filter)

    先介绍概念:来自百科 粒子滤波指:通过寻找一组在状态空间中传播的随机样本来近似的表示概率密度函数,再用样本均值代替积分运算,进而获得系统状态的最小方差估计的过程,波动最小,这些样本被形象的称为&quo ...