makefile

makefile 编译的时候进2次,第一次解析makefile内容,第二次才是找目标进行编译。

48. -Wp,-MD,.$@.d  
参考解决C文件包含的头文件修改了,但C文件不重新编译的问题_c++头文件更改后编译总是忽略-CSDN博客

添加编译文件的依赖,即便头文件修改了,也不用makeclean。

47.将编译输出与源码分离:

MAKE_PWD=$(shell pwd)
COMPILE_TIME = $(shell date +"%Y%m%d%H%M%S")

WORK_SUB_DIRS=$(shell ls ./)

BUILD_ROOT_DIR=./builddir/
PROJ_WORK_VERSION=$(BUILD_ROOT_DIR)projVersFile.txt

WORK_INCLUDE_DIRS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then echo -I./$(n); fi;))
# WORK_SUB_DIR_SRCS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then echo $(n)/*.cpp; fi;))
WORK_SUB_DIR_SRCS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then ls $(n)/*.cpp 2> /dev/null; fi;))
BUILD_SUB_DIRS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then echo $(BUILD_ROOT_DIR)$(n); fi;))
$(info WORK_SUB_DIR_SRCS = $(WORK_SUB_DIR_SRCS))
$(info WORK_INCLUDE_DIRS = $(WORK_INCLUDE_DIRS))



CFLAGS   = -Wall -I./ $(WORK_INCLUDE_DIRS)

SRCS = $(wildcard *.cpp)
SRCS += $(WORK_SUB_DIR_SRCS)
TARGET = $(BUILD_ROOT_DIR)test
$(info srcs: $(SRCS))
OBJS = $(patsubst %.cpp,$(BUILD_ROOT_DIR)%.o,$(SRCS))
$(info objs: $(OBJS))


all:makeBuildingDirs versionWrite $(OBJS) $(C_OBJS)
	$(CXX) -o $(TARGET) $(C_OBJS) $(OBJS) $(CFLAGS)
	# $(STRIP) $(TARGET)
	# $(STRIP) $(TARGET)

$(OBJS):$(BUILD_ROOT_DIR)%.o:%.cpp
	$(CXX) -c $^ -o $@ $(COMMON_OPT_FLAG) $(CFLAGS) $(COMPILE_USR_FLAGS) -DNOSSL -g -rdynamic

$(C_OBJS):%.o:%.c
	$(CC) -c $^ -o $@ -fPIC $(CFLAGS) $(COMPILE_FLAG)

makeBuildingDirs:
	echo mkdir -p $(BUILD_SUB_DIRS)
	mkdir -p $(BUILD_SUB_DIRS)

versionWrite:
	@echo "----$(COMPILE_TIME)----"
	@echo proj-V1.1.1.$(COMPILE_TIME) > $(PROJ_WORK_VERSION)

clean:
	rm -rf *.o $(TARGET) $(OBJS) $(SMP_OBJS) $(PROJ_WORK_VERSION) $(BUILD_ROOT_DIR)

cleandir:clean
	rm -rf *.db *.log *.properties *.txt $(BUILD_ROOT_DIR)

46.直接编译本目录和子目录CPP源文件:

include ../../common/mkCommon/compile.mk
MAKE_PWD=$(shell pwd)
COMPILE_TIME = $(shell date +"%Y%m%d%H%M%S")

WORK_SUB_DIRS=$(shell ls ./)
WORK_INCLUDE_DIRS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then echo -I./$(n); fi;))
WORK_SUB_DIR_SRCS=$(foreach n,$(WORK_SUB_DIRS),$(shell if [ -d $(n) ]; then echo $(n)/*.cpp; fi;))
$(info WORK_SUB_DIR_SRCS = $(WORK_SUB_DIR_SRCS))
$(info WORK_INCLUDE_DIRS = $(WORK_INCLUDE_DIRS))

CFLAGS   = -Wall -I./ $(WORK_INCLUDE_DIRS)

SRCS = $(wildcard *.cpp)
SRCS += $(WORK_SUB_DIR_SRCS)
TARGET = test
$(info srcs: $(SRCS))
OBJS = $(patsubst %.cpp,%.o,$(SRCS))
$(info objs: $(OBJS))


all:versionWrite $(OBJS) $(C_OBJS)
	$(CC) -o $(TARGET) $(C_OBJS) $(OBJS) $(CFLAGS) -Wl,-dn $(COMPILE_USR_FLAGS) -latomic -Wl,-dy -lpthread -ldl -lm -levent_pthreads -lstdc++ -g -rdynamic
	$(STRIP) $(TARGET)
	# $(STRIP) $(TARGET)
$(OBJS):%.o:%.cpp
	$(CXX) -c $^ -o $@ $(COMMON_OPT_FLAG) $(CFLAGS) $(COMPILE_USR_FLAGS) -DNOSSL -g -rdynamic

$(C_OBJS):%.o:%.c
	$(CC) -c $^ -o $@ -fPIC $(CFLAGS) $(COMPILE_FLAG)


versionWrite:
	@echo "----$(COMPILE_TIME)----"
	@echo $(COMPILE_TIME) > ./compiletime.txt

clean:
	rm -f *.o $(TARGET) $(OBJS) *.log *.properties $(SMP_OBJS) ./compiletime.txt
cleanall:clean
	rm -rf *.db

45.编译工程,判断版本号:make或者用make version=v1或者make version=v4来判断make正确性

SURPPORT_VERSION_LIST := v1 v2 v3
define detectValidVersion2
	@mytmpval=; \
	echo "tv=$$mytmpval; input version=$1"; \
	echo "out tv: $$mytmpval"; \
	for ver in $2;do \
		echo "input=$1: list=$$ver"; \
		if [ "$1" = "$$ver" ]; then \
			echo "version=$1 is surpport!!"; \
			mytmpval=$$ver; \
		fi; \
	done; \
	if [ "$$mytmpval" = "" ]; then \
		echo "note: can not find version!!!!"; \
		echo "please use: >>>> make version=v1 <<< !!!!!!!"; \
		echo "surpport version list is:"; \
		echo "$2"; \
		exit 1; \
	else \
		echo ""; \
		exit 0; \
	fi;
endef

all:detectValidVersion
	
detectValidVersion:
	@echo "input version = $(version)"
	$(call detectValidVersion2,$(version), $(SURPPORT_VERSION_LIST))

     需要主要的地方:

     a.函数内的变量用$$来获得其值

     b.想要变量mytmpval有效,需要用\(\表示这句话还没写完)来连续写,否则mytmpval值为空。如果"@mytmpval=; \"改为"@mytmpval=;",后面的mytmpval会得到空,而不是我们想要的值。

     c.自定义函数中@开头,用于不打印执行语句

     d.$(call detectValidVersion2,$(version))中,如果$(version)前面有空格,空格也会带入函数

     e.exit 1表示错误,用于停止makefile;exit 0表示正常,继续makefile

     f.echo "tv=$$mytmpval; input version=$1";需要使用""双引号才能打印mytmpval的值,如果使用''单引号不能打印mytmpval的值

     g.if[ = ]语句是shell语句,"="只能判断字符串相等,两个变量不能判断!数字相等用:-eq

     h.if[ "a" = "b" ];then echo "123"; fi;中echo "123"; 必须带分号,否则报错

     i.很多问题可能都是因为没有加分号,可以每句都加上";"分号即可!!!!!!echo "123" \ echo "333";不加分号打印有问题

44、让子目录Makefile能获得环境变量:export ROOT_DIR=$(shell pwd)

或者include文件中添加(include对应文件会放在MAKEFILE_LIST最后,lastword 相对路径,abspath 绝对路径,dir获得目录部分):CONFIG_PATH = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

43.编译本目录下所有目录,其中:make -C \$\$subdir $1 || exit \$\$?;编译错误直接退出编译!

WORK_SPACE_FILES=$(shell ls ./)

WORK_SPACE_DIRS=$(foreach n,$(WORK_SPACE_FILES),$(shell if [ -d $(n) ]; then echo $(n); fi;))
$(info WORK_SPACE_DIRS = $(WORK_SPACE_DIRS))
define make_subdir
        for subdir in $(WORK_SPACE_DIRS);do \
                if [ -f $$subdir/Makefile ]; then \
                        echo ">>>>>make in dir: make -C $$subdir $1>>>>: "; \
                        make -C $$subdir $1 || exit $$?; \
                else \
                        echo "===dir have not Make: make -C $$subdir $1==: "; \
                fi; \
        done
endef

all:
        $(call make_subdir,)
clean:
        $(call make_subdir,clean)

42.在bootloader里面有:

hi3519v101_config: unconfig
    @$(MKCONFIG) $(@:_config=) arm hi3519v101 hi3519v101 NULL hi3519v101

$(@:_config=)中,$@是目标项,功能是把hi3519v101_config中的_config=空,得到hi3519v101.而$(MKCONFIG)就是mkcofig

所以有:mkcofig hi3519v101 arm hi3519v101 hi3519v101 NULL hi3519v101

41.$(LIBRARY_LIBS):    workdir = $(@D)

$@不是表示目标么,那么$(@D)就表示$@的目录。比如说哦:$@=./test/xxx.o,那么$(@D)=./test/

40.makefile 中必须在(如all:)目标下面加打印,但是这次发现一个新的方法:$(info 我们要打印的内容),如39例子

$(info makefile_list            = $(MAKEFILE_LIST))

39.MAKECMDGOALS参考38.看多个目标$(targetfile): %.o: %.c的用法:

$(targetfile): %.o: %.c表示targetfile的内容1.o 2.o 3.o分别对应相应的的1.c 2.c 3.c

$(sourcefile): %.c : mkfile也必须遵循*.c的规则

例子:

$(info makefile_list            = $(MAKEFILE_LIST))
all:
        @echo test makefile MAKECMDGOALS!default make..
        @echo MAKECMDGOALS = $(MAKECMDGOALS)

clean:
        @rm -f *.c
        @echo test makefile ----clean....
        @echo MAKECMDGOALS = $(MAKECMDGOALS)

targetfile = 1.o 2.o 3.o
sourcefile = $(patsubst %.o,%.c,$(targetfile))
$(sourcefile): %.c : mkfile
        @echo touch file $@
        @[ -e $@ ] || touch $@
mkfile:
#       @echo touch onefile     

$(targetfile): %.o: %.c
        @echo test $< to $@
mytarget=2.o
target: clean $(targetfile)
        @echo test makefile -----3......
        @echo MAKECMDGOALS = $(MAKECMDGOALS)

target1: $(mytarget)
        @echo test makefile -----4......
        @echo MAKECMDGOALS = $(MAKECMDGOALS)
 

测试

supass@supass-virtual-machine:~/workspace/test/makefile_test/make_MAKECMDGOALS$ make target
makefile_list            =
test makefile ----clean....
MAKECMDGOALS = target
touch file 1.c
test 1.c to 1.o
touch file 2.c
test 2.c to 2.o
touch file 3.c
test 3.c to 3.o
test makefile -----3......
MAKECMDGOALS = target

supass@supass-virtual-machine:~/workspace/test/makefile_test/make_MAKECMDGOALS$ make target1
makefile_list            =
touch file 2.c
test 2.c to 2.o
test makefile -----4......
MAKECMDGOALS = target1
 

1. include ./abc.mak ./folder/xxx                    Makefile需要包含的头文件,一些宏定义,一些配置什么的。
2. MY_DEFINE += -DDEFINE1                        自定义宏(-D)。用的时候如:g++ -o main $(MY_DEFINE) main.cpp
3. MY_HEAD += -I./test1.h -I../test2/test2.h                自定义头文件路径(-I)。用法如2。头文件和宏可以用一个宏都可以
4. MY_LIB += -lrt -l../xxx.lib -l m(数学库) -l pthread            指定库(-l)。-L指定库路径。gcc -lmylib -L./mylibdir -o test test.c 当前路径下有个mylibdir目录,目录有个libmylib.a库
5. VALUE +=$(shell ls /etc/*.c)                        使用shell语句
6. $@                                    目标文件集
7. $^                                    依赖文件集
8. $<                                    $@--目标文件,$^--所有的依赖文件,$<--第一个依赖文件。
9. $*                                    $*表示目标名(.)之前的字符,目标名没有.为空。main: @echo $* 为空,main.o:@echo $* 为main
6-8使用:
O_OBJ = main.o test1.o test2.o test3.o
main:$(O_OBJ)
    g++ -o $@ $^                            $@=main,$^=$(O_OBJ)=main.o ...
main.o:main.cpp test1.cpp
    g++ -c $<
9. 在执行行中可以直接使用shell语法:
clean:
    rm -f *.o

10. echo @echo
    echo 会打印两条语句,而@echo打印一条语句
main: main.o c1.o
        @echo $(OURI_D)
        g++ -o main main.o c1.o
使用echo:
echo -I./head_dir -I./head_dir2 -DMYDEFINE -DMY123
-I./head_dir -I./head_dir2 -DMYDEFINE -DMY123
使用@echo只打印:-I./head_dir -I./head_dir2 -DMYDEFINE -DMY123

11.使用shell语法:&& ||
    &&    只有在 && 左边的命令返回真(命令返回值 $? == 0)
    ||    只有在 || 左边的命令返回假(命令返回值 $? == 1),|| 右边的命令才会被执行。
distclean-generic:
        -test -z "$(FILES)" || rm -f $(FILES)        
    如果FILES不为空,删除掉
        -test . = "$(srcdir)" || test -z "$(FILES)" || rm -f $(FILES)
    如果    srcdir!=.    ,再测试FILES不为空,删除掉

1)判断表达式
if test  (表达式为真)
if test !表达式为假
test 表达式1 –a 表达式2                  两个表达式都为真
test 表达式1 –o 表达式2                 两个表达式有一个为真

2)判断字符串
test –n 字符串                                   字符串的长度非零
test –z 字符串                                    字符串的长度为零
test 字符串1=字符串2                    字符串相等
test 字符串1!=字符串2               字符串不等

3)判断整数
test 整数1 –eq 整数2                        整数相等
test 整数1 –ge 整数2                        整数1大于等于整数2
test 整数1 –gt 整数2                         整数1大于整数2
test 整数1 –le 整数2                         整数1小于等于整数2
test 整数1 –lt 整数2                          整数1小于整数2
test 整数1 –ne 整数2                        整数1不等于整数2

4)判断文件
test  File1 –ef  File2                            两个文件具有同样的设备号和i结点号
test  File1 –nt  File2                            文件1比文件2 新
test  File1 –ot  File2                            文件1比文件2 旧
test –b File                                           文件存在并且是块设备文件
test –c File                                           文件存在并且是字符设备文件
test –d File                                           文件存在并且是目录
test –e File                                           文件存在
test –f File                                            文件存在并且是正规文件
test –g File                                           文件存在并且是设置了组ID
test –G File                                           文件存在并且属于有效组ID
test –h File                                           文件存在并且是一个符号链接(同-L)
test –k File                                           文件存在并且设置了sticky位
test –b File                                           文件存在并且是块设备文件
test –L File                                           文件存在并且是一个符号链接(同-h)
test –o File                                           文件存在并且属于有效用户ID
test –p File                                           文件存在并且是一个命名管道
test –r File                                            文件存在并且可读
test –s File                                           文件存在并且是一个套接字
test –t FD                                             文件描述符是在一个终端打开的
test –u File                                           文件存在并且设置了它的set-user-id位
test –w File                                          文件存在并且可写
test –x File                                           文件存在并且可执行
注释:这里为什么有-test待查阅

12.    .PHONY:.PHONY修饰的目标就是只有规则没有依赖。   用于避免目标和文件名冲突。下面的例子如果去掉.PHONY: clean,使用make clean也是不行的。
    没有.PHONY修饰:如果文件夹中出现了(该命令同名的)目标文件,在make的时候不会去执行该命令。修饰之后便可以执行。如:
include head_dir/makefile.mak makefile-n.mak            包含依赖文件DEFINES在这里面定义了
#include makefile-n.mak
HEAD_DIR = -I./head_dir -I./head_dir2
OURI_D += $(HEAD_DIR)                        头文件
OURI_D += $(DEFINES)                        宏定义
all: main clean                            all只是一个目标,没有特殊含义

main: main.o c1.o
        @echo $(OURI_D)
        g++ -o main main.o c1.o

main.o: main.cpp
        g++ $(OURI_D) -c main.cpp

c1.o: c1.cpp
        g++ $(OURI_D) -c c1.cpp
.PHONY: clean                            这里使用来.PHONY修饰,即使本文件夹中出现来clean的文件,也会去执行。注释后出现来clean文件,不去执行clean目标。
clean:
        rm -rf *.o

13:    all可以包含多个终极目标

14:shell参数
脚本内容如下:
 
#!/bin/sh
echo "number:$#"
echo "scname:$0"
echo "first :$1"
echo "second:$2"
echo "argume:$@"
echo "show parm list:$*"
echo "show process id:$$"
echo "show precomm stat: $?"
保存退出
 
赋予脚本执行权限
 
# chmod +x variable
 
执行脚本
 
# ./variable aa bb
number:2
scname:./variable
first:aa
second:bb
argume:aa bb
show parm list:aa bb
show process id:24544
show precomm stat:0
 
通过显示结果可以看到:
 
$# 是传给脚本的参数个数
$0 是脚本本身的名字
$1 是传递给该shell脚本的第一个参数
$2 是传递给该shell脚本的第二个参数
$@ 是传给脚本的所有参数的列表
$* 是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
$$ 是脚本运行的当前进程ID号
$? 是显示最后命令的退出状态,0表示没有错误,其他表示有错误

16.make ./ees/ -f makefile.txt DEFINEA=1 指定makefile,加参数进去

17.
.cpp.o:                                #"."开头不会自动执行,同        xxx.o : xxx.cpp

    g++ -lrt -Dmydef -I./ -c $<(或者$*.cpp)
main:main.o                            #依赖文件.o存在,往下执行;不存在,执行.cpp.o:
    g++ -o $@ $^

执行步骤:.xxx不会去执行,执行main时,先执行main.o,通过.cpp.o:得到。
这里.cpp.o是老式的“后缀规则”,编译器将会自动将.cpp识别为源文件后缀,而.o识别为输出文件后缀。特别需要注意的是,后缀规则不允许任何依赖文件,但也不能没有命令。


参考:
#include head_dir/makefile.mak makefile-n.mak
include makefile-n.mak
include head_dir/makefile.mak
HEAD_DIR = -I./head_dir -I./head_dir2
OURI_D += $(HEAD_DIR)
OURI_D += $(DEFINES)

.mymake.p:
        @echo my make begin
        @echo $*
.cpp.o :
        @echo $*
        @echo $<
        rm -f $@
        g++ $(OURI_D) -c $*.cpp -o $*.o

all: main clean
        @echo all did

main: main.o c1.o
        @echo $(OURI_D)
        @echo $*
        g++ -o main main.o c1.o

#main.o: main.cpp
#       @echo gcc main.cpp
#       g++ $(OURI_D) -c main.cpp

#c1.o: c1.cpp
#       g++ $(OURI_D) -c c1.cpp
.PHONY: clean
clean:
        -rm -rf *.o


18.    make是执行第一个xxx:目标文件,而不是.xxx:目标
如17。

19. ar 编译库
如:
mylib.a : a.o b.o c.o...
    ar cq $@ $^                                编译成静态库
    ranlib $@ mylib.a                            更新库,让调用他的能找到新添内容

ar 编译库的选项。
    d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。
    m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'i'任选项移动到指定的位置。
    p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。
    q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'i'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。
    r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。
    t:显示库的模块表清单。一般只显示模块名。
    x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。

    a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。
    b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。
    c:创建一个库。不管库是否存在,都将创建。
    f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。
    i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。
    l:暂未使用
    N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。
    o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。
    P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。
    s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。
    S:不创建目标文件索引,这在创建较大的库时能加快时间。
    u:一般说来,命令ar r...插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。
    v:该选项用来显示执行操作选项的附加信息。
    V:显示ar的版本。

19.1). ranlib xxx.a
前边提到过,静态库文件需要使用“ar”来创建和维护。当给静态库增建一个成员时(加入一 个.o文件到静态库中),“ar”可直接将需要增加的.o文件简单的追加到静态库的末尾。之后当我们使用这个库进行连接生成可执行文件时,链接程序 “ld”却提示错误,这可能是:主程序使用了之前加入到库中的.o文件中定义的一个函数或者全局变量,但连接程序无法找到这个函数或者变量。
这 个问题的原因是:之前我们将编译完成的.o文件直接加入到了库的末尾,却并没有更新库的有效符号表。连接程序进行连接时,在静态库的符号索引表中无法定位 刚才加入的.o文件中定义的函数或者变量。这就需要在完成库成员追加以后让加入的所有.o文件中定义的函数(变量)有效,完成这个工作需要使用另外一个工 具“ranlib”来对静态库的符号索引表进行更新。
我们所使用到的静态库(文档文件)中,存在这样一个特殊的成员,它的名字是 “__.SYMDEF”。它包含了静态库中所有成员所定义的有效符号(函数名、变量名)。因此,当为库增加了一个成员时,相应的就需要更新成员 “__.SYMDEF”,否则所增加的成员中定义的所有的符号将无法被连接程序定位。完成更新的命令是:
ranlib   ARCHIVEFILE
通常在Makefile中我们可以这样来实现:
libfoo.a:   libfoo.a(x.o)   libfoo.a(y.o)   ...
ranlib   libfoo.a
它 所实现的是在更新静态库成员“x.o”和“y.o”之后,对静态库的成员“__.SYMDEF”进行更新(更新库的符号索引表)。
如果 我们使用GNU   ar工具来维护、管理静态库,我们就不需要考虑这一步。GNU   ar本身已经提供了在更新库的同时更新符号索引表的功能(这是默认行为,也可以通过命令行选项控制ar的具体行为。可参考   GNU   ar工具的man手册)。
参考:
CXX = g++
AR = ar cq
rm = /bin/rm -f
RANLIB = ranlib
LIBNAME = libDCAS.a
INCLUDES =  -I../../Include/ -I../openssl/include
SHOW_COMMAND = @
TARGET_BOARD = YES
ifeq ($(TARGET_BOARD), YES)
DEFINES += -DTARGET_BOARD
endif
DEFINES+= $(INCLUDES) $(DEFS) -DSYS_UNIX=1
CFLAGS+= $(DEFINES)

SRCS = ./DCAS.cpp ./LFSR.cpp
OBJS = ./DCAS.o ./LFSR.o

.cpp.o:                                                    3
        $(rm) -f $@                                            (4)//可能执行可能不执行
        $(SHOW_COMMAND)echo -=--=--=- [$*.cpp] -=--=--=--=--=--=--=--=--=-                (5)
        $(SHOW_COMMAND)$(CXX) $(CFLAGS) -c $*.cpp                            (6)

all: $(LIBNAME)                                                入口,10

$(LIBNAME) : $(OBJS)                                            2
        $(rm) $@                                            7
        $(AR) $@ $(OBJS)                                        8
        $(RANLIB) $@                                            9


20. $(CURDIR)表示当前路径,$(MAKE)表示make

21.set -e            在"set -e"之后出现的代码,一旦出现了返回值非零,整个脚本就会立即退出。
SUBDIRS = dir1 dir2 dir3
set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i; done

set -e; for i in $(CLEAN_SUBDIRS); do $(MAKE) clean -C $$i; done; rm -rf ../lib/*

set -e;
for i in $(MINICLEAN_SUBDIRS);
do $(MAKE) miniclean -C $$i;
done;
rm -rf ../lib/*
注意i相当于指针的指针


22.set -o pipefail
set -o pipefail
ls ./a.txt |echo "hi" >/dev/null
echo $?

运行test.sh,因为当前目录并不存在a.txt文件,输出:
ls: ./a.txt: No such file or directory
1 #设置了set -o pipefail,返回从右往左第一个非零返回值,即ls的返回值1

注释掉set -o pipefail这一行,再次运行,输出:
ls: ./a.txt: No such file or directory
0 # 没有set -o pipefail,默认返回最后一个管道命令的返回值    

23.makefile有些函数:
ifneq ($(filter APCFG_APP_RECORDABLE,$(subst |, ,$(APCFG_FLAGS))),)
http://os.chinaunix.net/a2007/0428/970/000000970195.shtml

24.file main
main: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x4d296e5078fda2257bcb0b8ef9d525f96d590c2e, not stripped
Intel 80386,表示main执行文件是由X86编译生成。..ARM..说明时ARM交叉编译工具生成。

25.$(MAKE)=make

26.sed
因为Makefile经常用到shell脚本

sed -e "/deleteword/d" -e "/printword/p" -e "s/source/target/g" soursefile.txt > targetfile.txt
-e多重操作,"/xxx/d"删除,p打印,s替换,g全部,soursefile.txt被操作文件

27.预定义
ifeq ($(TARGET_BOARD), YES)            ifeq /*这里必须有空格*/($(TARGET_BOARD), YES)
DEFINES += -DTARGET_BOARD
endif

28.shell里面的

echo "${x:-default}"                如果$x不为空,返回$x,为空返回default

29.条件语句
    a.写成一条语句
    b.小心空格,if,\的空格
        if [ -f mytest.tar ]; then \            注意空格,'if'后面'['后面']'前面。由于这里需要写成一行。因此用'\',注意'\'后面不能有空格,注意有个逗号
                cd . && \
                tar xzvf mytest.tar && \
                echo "lsfjsek ksjf le" && \
                rm -f mytest.tar; \
        else \
                echo yufa wrong; \
        fi

30.for语句和if差不多
    for cc in `ls .`; \
        do \
                echo $$cc; \
        done

31. make param=xxx参数可以用到Makefile内部的make里面。

32. find . -name "xxx" -exect rm -rf {} \;       或者: find . -name "xxx" | xargs rm -rf

33. Makefile定义的变量===c语言的宏,不能修改

34. 变量赋值"="递归; ":="简单递归。意思就是被赋值改变了:=不会跟随变化,而=会跟随后面的参数变化。如:

a :=123

b = $(a)

a+=321

c = $(a)会导致b和c的值一样的都是: 123 321

而使用:=

a :=123

b := $(a)

a+=321

c := $(a)这样b就是123,c就是123 321

35.shell:   cat<< eof > xxxxx 表示输入数据,遇到eof终止,输入内容输出到xxxxx文件中。

36.每一次编译之前会执行的目标,通过"include 目标"来指定。如:(-include和include我还没用到-include与include不同之处,-include也是包含外部文件)

PHONY: mustTar
mustTar:
        echo [surpas]__LINE__
        cp inc.mk inc.mk-bak
-include mustTar

37:MK_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST))))

在make过程中,make会读两次makefile,第一次读内容,第二次运行。第一次读取过程会将makefile,和include文件的相对路径包含到MAKEFILE_LIST环境变量中。lastword取最后一个相对路径文件名,dir取该文件的目录部分,patsubst是替换后缀,比如:../../mydir/ 用了patsubst后,变成../../mydir

38: MAKECMDGOALS保存的是make 后面跟的目标:比如make clean mytarge version=1;对应的MAKECMDGOALS=clean mytarge
 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值