Intro
This makefile will always run. The default target is some_binary, because it is first.

some_binary:
echo "nothing"

Intro
This file will make some_binary the first time, and the second time notice it’s already made, resulting in make: 'some_binary' is up to date.

some_binary:
touch some_binary

Intro
Alternative syntax: same line

some_binary: ; touch some_binary

Intro
\ gives us multilines

some_binary:
touch \
some_binary

Intro
Will call other.txt target if it is newer than the some_binary file, or it doesn’t exist. It will call the other.txt rule first.

some_binary: other.txt
touch some_binary other.txt:
touch other.txt

Intro
This will always make both targets, because some_binary depends on other.txt, which is never created.

some_binary: other.txt
touch some_binary other.txt:
echo "nothing"

Intro “clean” is not a special word. If there’s a file called clean that is made, then “make clean” won’t have to do anything. Similarly, if the clean file is older than the some_binary file, the clean rule will not be called.

some_binary: clean
touch some_binary clean:
touch clean actual_clean:
rm some_binary
rm clean # Adding PHONY to a target will prevent make from confusing the phony target with a file name.
# In this example, if clean is created, make clean will still be run.
# PHONY is great to use, but I'll skip it in the rest of the examples for simplicity.
some_binary:
touch some_binary
touch clean .PHONY: clean
clean:
rm some_binary
rm clean

2.4:
Variables can only be strings. Here’s an example:

files = file1 file2
some_binary: $(files)
echo "Look at this variable: " $(files)
touch some_binary file1:
touch file1
file2:
touch file2 clean:
rm file1 file2 some_binary

Here’s a blah.c file that some examples below require

#include<stdio.h>
#include <string.h> int main()
{
#printf("hello there\n");
#return 0;
}

2.5:
Example requires: blah.c
If we have a target that is a “.c” file, there is an implicit command that will be “cc -c file.c -o file.o”.

# Implicit command of: "cc -c blah.c -o blah.o"
# Note: 1) Do not put a comment inside of the blah.o rule; the implicit rule will not run!
# 2) If there is no blah.c file, the implicit rule will not run and will not complain.
blah.o: clean:
rm blah.o

4.1
Print literal ‘$’

some_binary:
echo $$

4.2
We can use wildcards in the target, prerequisits, or commands.
Valid wildcards are *, ?, [...]

some_binary: *.c
# create the binary *.c:
touch f1.c
touch f2.c clean:
rm *.c

4.2.3
We CANNOT use wildcards in other places, like variable declarations or function arguments
Use the wildcard function instead.

wrong = *.o # Wrong
objects := $(wildcard *.c) # Right
some_binary:
touch f1.c
touch f2.c
echo $(wrong)
echo $(objects) clean:
rm *.c

4.3.2
Use vpath to specify where some set of prerequisites exist. The format is vpath <pattern> <directories, space/colon seperated>
<pattern> can have a %, which matches any zero or more characters.
You can also do this globallyish with the variable VPATH

vpath %.h ../headers ../other-directory

some_binary: ../headers blah.h
touch some_binary ../headers:
mkdir ../headers blah.h:
touch ../headers/blah.h clean:
rm -rf ../headers
rm some_binary

4.4
Making multiple targets? Make a phony ‘all’!
Note here PHONY is after all, because the target is seen as ‘all’ instead of PHONY,
giving better error dumps.

all: one two three
PHONY: all one:
touch one
two:
touch two
three:
touch three clean:
rm one two three

4.8
Multiple Targets: the rule will be run for each target
$@ is a automatic variable that contains the target name.

all: f1.o f2.o

f1.o f2.o:
echo $@
# Equivalent to:
# f1.o
# echo $@
# f2.o
# echo $@ clean:
rm *.c

4.8
Multiple Targets: We can use the wildcard % in targets, that captures zero or more of any character
Note
1) We do not use *.o, because that is just the string *.o, which might be useful in the commands,
but is only one target and does not expand.
2) PHONY is needed because otherwise make will create an automatic rule of “cc all.o f1.o f2.o -o all
TODO why was this not a problem when I didn’t use the % wildcard?

all: f1.o f2.o
.PHONY: all %.o:
echo $@ clean:
rm *.c

4.10
Static Pattern Rules: each .o file has a prereq of the corresponding .c name
Run “make init” first to make the .c files

objects = foo.o bar.o

all: $(objects)

# targets ...: target-pattern: prereq-patterns ...
$(objects): %.o: %.c
echo "make file" $@ "with prereqs" $< init:
touch foo.c
touch bar.c clean:
rm foo.c bar.c

4.10
filter can be used in Static pattern rules to match the correct files
Run “make init” first to make the necessary files

files = foo.elc bar.o lose.o
src_files = foo.el bar.c lose.c all: $(files) $(filter %.o,$(files)): %.o: %.c
echo "target: " $@ "prereq: " $<
$(filter %.elc,$(files)): %.elc: %.el
echo "target: " $@ "prereq: " $< init:
touch $(src_files) clean:
rm $(src_files)

4.11
Double-Colon Rules are rarely used, but allow the same target to run commands from multiple targets.
If these were single colons, an warning would be printed and only the second set of commands would run.

all: blah

blah::
echo "hello" blah::
echo "hello again" clean:
rm $(src_files)

4.12
Example requires: blah.c
Generating prereqs automatically
This makes one small makefile per source file
Notes:
1) , with escaping. We use it to make a temporary file, that doesn’t
interfere with others if there is some parallel builds going on.
2) cc -MM outputs a makefile line. This is the magic that generates prereqs automatically, by looking at the code itself
3) The purpose of the sed command is to translate (for example):
main.o : main.c defs.h
into:
main.o main.d : main.c defs.h
4) Running make clean will rerun the rm -f … rule because
the include line wants to include an up to date version of the file.
There is such a target that updates it, so it runs that rule before
including the file.

all: blah.d

clean:
rm blah.d %.d: %.c
rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$ sources = blah.c include $(sources:.c=.d)

5.1
Add an @ before a command to stop it from being printed
You can also run make with -s to add an @ before each line

all:
@echo "This make line will not be printed"
echo "But this will"

5.2
Each command is run in a new shell (or at least the affect is as such)

all:
cd ..
# The cd above does not affect this line, because each command is effectively run in a new shell
echo `pwd` # This cd command affects the next because they are on the same line
cd ..;echo `pwd` # Same as above
cd ..; \
echo `pwd`

5.2
Note only: the default shell is /bin/sh. You can change this by changing the variable SHELL

5.4
Make stops running a rule (and will propogate back to prerequisites) if a command returns a nonzero exit status.
DELETE_ON_ERROR will delete the target of a rule if the
rule fails in this manner. This will happen for all targets, not just
the one it is before like PHONY. It’s a good idea to always use this,
even though make does not for historical reasons.
Add “-k” when running make to continue running even in the face of
errors. Helpful if you want to see all the errors of Make at once.

.DELETE_ON_ERROR:
all: one two one:
touch one
false two:
touch two
false

5.4
Add a “-“ before a command to suppress the error
Add “-i” to make to have this happen for every command.

one:
false
touch one

5.5
Note only: If you ctrl+c make, it will delete the newer targets it just made.

5.6
Recursively call a makefile. Use the special $(MAKE) instead of “make”
because it will pass the make flags for you and won’t itself be affected by them.

new_contents = "\
hello:\\n\
\\ttouch inside_file"
all:
mkdir -p subdir
echo $(new_contents) | sed -e 's/^ //' > subdir/makefile
cd subdir && $(MAKE) clean:
rm -rf subdir

5.6
The export directive takes a variable and makes it accessible to sub-make commands.
In this example, “cooly” is exported such that the makefile in subdir can use it.

Recursively call a makefile. Use the special $(MAKE) instead of “make”
because it will pass the make flags for you and won’t itself be affected by them.

Note: export has the same syntax as sh, but it they aren’t related (although similar in function)

new_contents = "\
hello:\\n\
\\techo \$$(cooly)" all:
mkdir -p subdir
echo $(new_contents) | sed -e 's/^ //' > subdir/makefile
@echo "---MAKEFILE CONTENTS---"
@cd subdir && cat makefile
@echo "---END mAKEFILE CONTENTS---"
cd subdir && $(MAKE) # Note that variables and exports. They are set/affected globally.
cooly = "The subdirectory can see me!"
export cooly
# This would nullify the line above: unexport cooly clean:
rm -rf subdir

5.6
You need to export variables to have them run in the shell as well.

one=this will only work locally
export two=we can run subcommands with this .PHONY: all
all:
@echo $(one)
@echo $$one
@echo $(two)
@echo $$two

5.6 EXPORT_ALL_VARIABLES does what you might expect

.EXPORT_ALL_VARIABLES:
new_contents = "\
hello:\\n\
\\techo \$$(cooly)" cooly = "The subdirectory can see me!"
# This would nullify the line above: unexport cooly all:
mkdir -p subdir
echo $(new_contents) | sed -e 's/^ //' > subdir/makefile
@echo "---MAKEFILE CONTENTS---"
@cd subdir && cat makefile
@echo "---END mAKEFILE CONTENTS---"
cd subdir && $(MAKE) clean:
rm -rf subdir

5.7
You can make a list of commands like so:

define sweet
echo "hello"
echo "target:" $@
echo "prereqs:" $<
endef .PHONY: all
all: one
$(sweet)
# Append @ here to append @ to all the commands in sweet: @$(sweet) one:
touch one clean:
rm -f one

6.1
Reference variables using ${} or $()

x = dude

.PHONY: all
all:
echo $(x)
echo ${x} # Bad practice, but works
echo $x

6.2
Two flavors of variables:
recursive - only looks for the variables when the command is used, not when it’s defined.
simply expanded - like normal imperative programming – only those defined so far get expanded

# This will print "later" at the end
one = one ${later_variable}
# This will not
two := two ${later_variable} later_variable = later .PHONY: all
all:
echo $(one)
echo $(two)

6.2
Simply expanded allows you to append to a variable. Recursive definitions will give an infinite loop error.

one = hello
one := ${one} there .PHONY: all
all:
echo $(one)

6.2
?= only sets variables if they have not yet been set

one = hello
one ?= will not be set
two ?= will be set .PHONY: all
all:
echo $(one)
echo $(two)

6.2
Spaces at the end of a line are not stripped, ones at the start are
To make a variable with a single space, have a variable guard

with_spaces = hello   # end of line
after = $(with_spaces)there nullstring =
space = $(nullstring) # end of line .PHONY: all
all:
echo "$(after)"
echo start"$(space)"end

6.3
You can text replace at the end of each space seperated word using $(var:a=b)
Note: don’t put spaces in between anything; it will be seen as a search or replacement term
Note: This is shorthand for using the “patsubst” expansion function

foo := a.o b.o c.o
bar := $(foo:.o=.c) .PHONY: all
all:
echo $(bar)

6.3
You can use % as well to grab some text!

foo := a.o b.o c.o
bar := $(foo:%.o=%) .PHONY: all
all:
echo $(bar)

6.5
An undefined variable is actually an empty string :o

.PHONY: all
all:
echo $(nowhere)

6.6
Use += to append

foo := start
foo += more .PHONY: all
all:
echo $(foo)

6.7
You can override variables that come from the command line by using “override”.
Here we ran make with make some_option=hi

override some_option += additional
.PHONY: all
all:
echo $(some_option)

6.8 “define” is actually just a multiline variable defintion. It has nothing with being a function.
Note here that it’s a bit different than having a semi-colon between commands, because each is run
in a seperate shell, as expected.

one = export blah="I was set!"; echo $$blah

define two
export blah=set
echo $$blah
endef .PHONY: all
all:
@echo "This prints I was set:"
@$(one)
@echo "This does not:"
@$(two)

6.10
Variables can be assigned for specific targets

all: one = cool

.PHONY: all
all:
echo one is defined: $(one) .PHONY: other
other:
echo one is nothing: $(one)

6.11
You can assign variables for specific target patterns

%.c: one = cool

blah.c:
echo one is defined: $(one) .PHONY: other
other:
echo one is nothing: $(one)

7.1
Conditional/If statements

foo = ok

all:
ifeq ($(foo), ok)
echo "foo equals ok"
else
echo "nope"
endif

7.2
Check if variable is empty

nullstring =
foo = $(nullstring) # end of line; there is a space here all:
ifeq ($(strip $(foo)),)
echo "foo is empty"
endif
ifeq ($(foo),)
echo "foo doesn't even have spaces?"
endif

7.2
ifdef does not expand variable references; it just sees if something is defined at all

bar =
foo = $(bar) all:
ifdef foo
echo "foo is defined"
endif
ifdef bar
echo "but bar is not"
endif

7.3
Search for a MAKEFLAG

bar =
foo = $(bar) all:
# Search for the "-i" flag. MAKEFLAGS is just a list of single characters, one per flag. So look for "i" in this case.
ifneq (,$(findstring i, $(MAKEFLAGS)))
echo "i was passed to MAKEFLAGS"
endif

8.1
Call functions with $(fn, arguments) or $(fn, arguments)

bar := $(subst not, totally, "I am not superman")
bar2 := $(subst not, totally, "I am not superman")
.PHONY: all
all:
@echo $(bar)
@echo $(bar2)

8.1
If you want to replace spaces or commas, use variables

comma := ,
empty:=
space := $(empty) $(empty)
foo := a b c
bar := $(subst $(space),$(comma),$(foo)) .PHONY: all
all:
@echo $(bar)

8.1
Do NOT include spaces in the arguments after the first. That will be seen as part of the string.

comma := ,
empty:=
space := $(empty) $(empty)
foo := a b c
bar := $(subst $(space), $(comma) , $(foo)) .PHONY: all
all:
# Output is ", a , b , c". Notice the spaces introduced
@echo $(bar) 8.2, 8.3, 8.9 TODO do something about the fns
TODO 8.7 origin fn? Better in documentation?

8.4
foreach takes:
$(foreach var,list,text) and sets var to each word in list, and outputs
outputs that into a “list” of words in text. By list I mean a space
seperated sentence of words.
This appends an exclamation after each word

foo := who are you
bar := $(foreach wrd,$(foo),$(wrd)!) .PHONY: all
all:
@echo $(bar)

8.5
If: (in a function instead of normal.. call this the functional style)
Checks if the first argument is nonempty. If so runs the second argument, otherwise runs the third.

foo := $(if this-is-not-empty,then!,else!)
empty :=
bar := $(if $(empty),then!,else!) .PHONY: all
all:
@echo $(foo)
@echo $(bar)

8.6
Call: $(call variable,param,param)
Sets each of the params as $(1), $(2), etc.
$(0) is set as the variable name

sweet_new_fn = Variable Name: $(0)$ First: $(1) Second: $(2) Empty Variable: $(3)

.PHONY: all
all:
@echo $(call sweet_new_fn, go, tigers)

8.8
shell - This calls the shell, but it removes newlines!

.PHONY: all
all:
@echo $(shell ls -la) # Very ugly because the newlines are gone!

9

  • There’s a nice list of commands that can be run from make. Check out --dry-run, --touch, --old-file.
  • You can have multiple targets to make, i.e. make clean run test runs the ‘clean’ goal, then ‘run’, and then ‘test’.

[转]http://makefiletutorial.com/的更多相关文章

随机推荐

  1. 【Android】Spinner使用

    Spinner:下拉列表,主要用于显示一些选项供用户选择,类似PC应用程序里面的Combobox. 使用Spinner需要以下条件: 1.一个 Spinner 控件 2.数据 3.一个Adapter ...

  2. CUBRID学习笔记 48查询优化

    cubrid的中sql查询语法 查询优化 c#,net,cubrid,教程,学习,笔记欢迎转载 ,转载时请保留作者信息.本文版权归本人所有,如有任何问题,请与我联系wang2650@sohu.com ...

  3. python成长之路【第七篇】:面向对象

    概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发“更快更好更强...” 面向对象三大特性 面向 ...

  4. Android Studio - HPROF文件查看和分析工具

    Android Studio 翻译的官方文章 原文链接 当你在Android Studio中使用Android Monitor里的Memory Monitor工具监视内存使用情况时,可以把Java堆快 ...

  5. checkbox 设置不可更改

    readonly="readonly" 设置不起作用   用 onclick="return false;"

  6. Oracle新增客户端网络配置使用scott出现错误

    错误一   测试提示用户密码过期 解决方法:使用sys用户登录数据库 sqlplus sys/密码  as sysdba; 修改scott用户密码 alter user scott identifie ...

  7. Unity5 GI与PBS渲染从用法到着色代码

    http://www.cnblogs.com/zhouxin/p/5168632.html 本文主要介绍Untiy5以后的GI,PBS,以及光源探头,反射探头的用法以及在着色器代码中如何发挥作用,GI ...

  8. 解决在国内更新android sdk时连不到服务器的问题

    修改hosts文件 Windows下:打开C:\Windows\System32\drivers\etc\hosts Linux下:vi /etc/hosts 在文件尾加入如下两行: 74.125.2 ...

  9. ijg库解码超大型jpeg图片

    1. ijg库解码超大型jpeg图片(>100M)的时候,如何避免内存溢出. 采用边解码边压缩的策略,每次解码一行或者若干行图片数据,然后对于这些解码的数据,进行DQT(量化处理,过滤掉高频的数 ...

  10. PowerDesigner导出建表sql脚本

    1 按照数据库类型,切换数据库. Database-> Change Current DBMS... 2.设置保存路径和文件名称