Rumah > Artikel > Operasi dan penyelenggaraan > Apa itu gmake dalam linux
Di Linux, gmake ialah GUN make, yang merupakan program yang popular dan biasa digunakan untuk membina perisian bahasa C Ia digunakan untuk membina kernel Linux dan program dan perpustakaan perisian GNU/Linux lain yang biasa digunakan. GNU Make ialah program yang boleh mengautomasikan perintah shell dan membantu melaksanakan tugas berulang-ulang ia sering digunakan untuk menukar fail ke dalam bentuk lain, seperti menyusun fail kod sumber ke dalam program atau perpustakaan.
Persekitaran pengendalian tutorial ini: sistem linux7.3, komputer Dell G3.
gmake ialah GUN make, kerana pada platform selain Linux, make biasanya diduduki, jadi GUN make perlu dipanggil gmake.
GNU Make ialah program yang popular dan biasa digunakan untuk membina perisian bahasa C. Digunakan untuk membina kernel Linux dan program dan perpustakaan perisian GNU/Linux lain yang biasa digunakan.
Kebanyakan pembangun perisian terbenam akan menggunakan GNU Make pada satu ketika dalam kerjaya mereka, sama ada menggunakannya untuk menyusun perpustakaan kecil atau untuk membina keseluruhan projek. Walaupun terdapat banyak, banyak alternatif untuk Make, ia masih sering dipilih sebagai sistem binaan untuk perisian baharu kerana set ciri dan sokongan yang luas.
Artikel ini menerangkan konsep dan ciri umum GNU Make dan termasuk nasihat tentang cara memanfaatkan sepenuhnya binaan Make anda Ini ialah pengenalan ringkas kepada konsep dan ciri Make kegemaran saya.
Apakah GNU Make?
GNU Make ialah program yang boleh mengautomasikan arahan shell dan membantu melaksanakan tugas berulang. Ia sering digunakan untuk menukar fail ke dalam bentuk lain, seperti menyusun fail kod sumber ke dalam program atau perpustakaan.
Ia melakukan ini dengan menjejaki prasyarat dan melaksanakan hierarki arahan untuk menjana sasaran.
Walaupun manual GNU Make agak panjang, saya syorkan membacanya kerana ia adalah rujukan terbaik yang saya temui: https://www.gnu.org/software/make/manual/html_node/index
Bila Memilih Buat
Make sesuai untuk membina projek C/c kecil atau perpustakaan yang akan disertakan dalam satu lagi binaan projek sistem. Kebanyakan sistem binaan mempunyai cara untuk menyepadukan subprojek berasaskan buatan.
Untuk projek yang lebih besar, anda mungkin mendapati sistem binaan yang lebih moden lebih mudah digunakan.
Saya mengesyorkan menggunakan sistem binaan bukan Buat dalam situasi berikut:
Apabila bilangan sasaran (atau fail) yang dibina ialah (atau akhirnya akan menjadi) ratusan. Langkah "konfigurasi" diperlukan, yang menetapkan dan menyimpan pembolehubah, definisi sasaran dan konfigurasi persekitaran. Projek ini akan kekal secara dalaman atau peribadi dan tidak perlu dibina oleh pengguna akhir. Anda mungkin mendapati bahawa penyahpepijatan boleh menjadi usaha yang mengecewakan. Perkara yang anda perlu bina ialah merentas platform dan boleh dibina pada macOS, Linux dan Windows. Dalam kes ini, anda mungkin mendapati bahawa menggunakan CMake, Bazel, Meson atau sistem binaan moden yang lain adalah pengalaman yang lebih menyenangkan.
Memanggil Make
Running make akan memuatkan fail bernama Makefile dari direktori semasa dan cuba mengemas kini sasaran lalai (lebih lanjut mengenainya kemudian ) matlamat pengenalan).
Make akan mencari fail bernama GNUmakefile, makefile dan makefile dalam urutan
Anda boleh menentukan makefile tertentu menggunakan parameter -f/--file:
$ make - f foo.mk Anda boleh menentukan sebarang bilangan sasaran, menyenaraikannya sebagai argumen kedudukan:
# sasaran biasa $ make clean all Anda boleh lulus direktori Make dengan argumen -C dan ia akan menjalankan Make seperti itu melakukan cd Pertama ke direktori itu.
$ buat -C beberapa/sub/direktori Fakta menarik: git juga boleh dijalankan dengan -C untuk mencapai kesan yang sama
Panggilan selari
Make boleh menjalankan kerja secara selari jika pilihan -j atau -l disediakan. Satu garis panduan kepada saya adalah untuk menetapkan had kerja kepada 1.5 kali ganda bilangan teras pemproses: #mesin dengan 4 teras:buat -j buat -j Menariknya, saya mendapati bahawa menggunakan pilihan "had beban" -l memberikan penggunaan CPU yang lebih baik sedikit daripada menggunakan pilihan "job" -j. Walau bagaimanapun, YMMV
Terdapat beberapa cara untuk mencari kiraan CPU mesin semasa secara pemrograman. Kaedah mudah ialah menggunakan fungsi python multiprocessing.cpu_count() untuk mendapatkan bilangan utas yang disokong oleh sistem (perhatikan bahawa dengan sistem hyper-threaded, ini akan menggunakan banyak sumber komputer, tetapi mungkin lebih baik daripada membiarkan sistem menjana kerja tanpa had). #Panggil fungsi cpu_count() python dalam subkulitmake -l (python -c "import multiprocessing;print (multiprocessing.cpu_count())")
Output semasa panggilan selari
Jika arahan Make laksana secara selari mempunyai banyak output, anda mungkin melihat output berperingkat pada stdout. Untuk menangani masalah ini, Make mempunyai pilihan - output -sync.Saya mengesyorkan menggunakan --output-sync=recurse, yang akan mencetak keseluruhan output resipi apabila setiap matlamat selesai tanpa mengalihkan perhatian daripada output resipi lain.
Jika resipi menggunakan Make rekursif, ia juga akan mengeluarkan output keseluruhan Make rekursif bersama-sama.
Anatomi Makefile Makefile mengandungi peraturan untuk menjana sasaran. Beberapa komponen asas Makefile adalah seperti berikut:
#Comments are prefixed with the '#' symbol
#A variable assignment
FOO = "hello there!"
#A rule creating target "test", with "test.c" as a prerequisite
test: test.c
# The contents of a rule is called the "recipe", and is
# typically composed of one or more shell commands.
# It must be indented from the target name (historically with
# tabs, spaces are permitted)
# Using the variable "FOO"
echo $(FOO)
# Calling the C compiler using a predefined variable naming
# the default C compiler, '$(CC)'
$(CC) test.c -o test
Mari kita lihat setiap bahagian contoh di atas.
Pembolehubah
Pembolehubah menggunakan sintaks $(FOO), dengan FOO ialah nama pembolehubah.
Pembolehubah mengandungi rentetan biasa kerana Make tidak mempunyai jenis data lain. Melampirkan pada pembolehubah akan menambah ruang dan kandungan baharu:
FOO = one
FOO += two
# FOO is now "one two"
FOO = one
FOO = $(FOO)two
# FOO is now "onetwo"
Tugasan pembolehubah
dalam GNU In Buat sintaks, terdapat dua cara untuk menetapkan pembolehubah:
Ungkapan di sebelah kanan ditugaskan kepada pembolehubah secara literal - ini sangat serupa dengan makro dalam C/c, yang menilai ungkapan apabila menggunakan pembolehubah. :
FOO = 1
BAR = $(FOO)
FOO = 2
# prints BAR=2
$(info BAR=$(BAR))
Tugaskan hasil ungkapan kepada pembolehubah; Fungsi $(info...) di atas digunakan untuk mencetak ungkapan, yang sangat mudah apabila menyahpepijat makefiles!*'
FOO = 1
BAR := $(FOO)
FOO = 2
# prints BAR=1
$(info BAR=$(BAR))
Pembolehubah persekitaran dibawa ke dalam persekitaran pelaksanaan Make. Ambil makefile berikut sebagai contoh:
Jika kami menetapkan YOLO pembolehubah dalam arahan shell semasa menjalankan make, kami akan menetapkan nilai ini:
$(info YOLO variable = $(YOLO))
Nota: Jadikan cetakan ralat "Tiada sasaran" kerana fail make kami tidak mempunyai sasaran yang disenaraikan
$ YOLO="hello there!" make
YOLO variable = hello there!
make: *** No targets. Stop.
Kemudian kita boleh menulis semula $(CC) dalam makefile:
#默认CC为gcc
CC ? = gcc
Satu lagi corak biasa ialah membenarkan pemasukan bendera tambahan. Dalam makefile, kami akan menambahkan pembolehubah dan bukannya memberikannya secara langsung.
$ CC=clang make
Ini membolehkan bendera tambahan dihantar dari persekitaran:
CFLAGS = -Wall
Ini sangat berguna!
$ CFLAGS='-Werror=conversion -Werror=double-promotion' make
Kategori khas pembolehubah yang digunakan dipanggil pembolehubah mengatasi. Menggunakan pilihan baris arahan ini akan mengatasi nilai yang ditetapkan dalam persekitaran atau Makefile!Makefile:
Arahan:
# any value set elsewhere
YOLO = "not overridden"
$(info $(YOLO))
# setting "YOLO" to different values in the environment + makefile + overriding
# variable, yields the overriding value
$ YOLO="environment set" make YOLO='overridden!!'
overridden!!
make: *** No targets. Stop.
Pembolehubah ini hanya tersedia dalam konteks resipi. Mereka juga berfungsi dengan mana-mana resipi yang mesti ada
# set the -g value to CFLAGS
# applies to the prog.o/foo.o/bar.o recipes too!
prog : CFLAGS = -g
prog : prog.o foo.o bar.o
echo $(CFLAGS) # will print '-g'
Ini dibuat oleh Make Dipratentukan (melainkan diganti dengan mana-mana jenis pembolehubah lain dengan nama yang sama). Beberapa contoh biasa:
$(CC) - the C compiler (gcc)
$(AR) - archive program (ar)
$(CFLAGS) - flags for the C compiler
Full list here:
https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
Ini ialah pembolehubah khas yang ditetapkan oleh Make, dalam Available in konteks resipi. Ia berguna untuk menghalang nama pendua (Jangan Ulangi Sendiri). Beberapa pembolehubah automatik biasa:
# $@ : the target name, here it would be "test.txt"
test.txt:
echo HEYO > $@
# $^ : name of all the prerequisites
all.zip: foo.txt test.txt
# run the gzip command with all the prerequisites "$^", outputting to the
# name of the target, "$@"
gzip -c $^ > $@
See more at: https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html
sasaran ialah sebelah kiri sintaks peraturan:
sasaran hampir selalu menamakan fail. Ini kerana Make menggunakan masa pengubahsuaian terakhir untuk menjejaki sama ada sasaran itu lebih baharu atau lebih lama daripada prasyaratnya dan sama ada ia perlu dibina semula
arget: prerequisite
recipe
如果您没有在命令中指定目标,Make将使用makefile中指定的第一个目标,称为“默认目标”(如果需要,也可以覆盖默认目标)。
虚假phony目标
有时候设置元目标是很有用的,比如all, clean, test等等。在这些情况下,您不希望Make检查名为all/clean等的文件。
Make提供.PHONY目标语法,将目标标记为不指向文件:
假设我们的项目构建了一个程序和一个库foo和foo.a;如果我们想要 在默认情况下,我们可以创建一个'all'规则来构建两者 .PHONY:all all : foo foo.a
如果你有多个假目标,一个好的模式可能是将每个目标都附加到定义它的.PHONY中:
# the 'all' rule that builds and tests. Note that it's listed first to make it
# the default rule
.PHONY: all
all: build test
# compile foo.c into a program 'foo'
foo: foo.c
$(CC) foo.c -o foo
# compile foo-lib.c into a library 'foo.a'
foo.a: foo-lib.c
# compile the object file
$(CC) foo-lib.c -c foo-lib.o
# use ar to create a static library containing our object file. using the
# '$@' variable here to specify the rule target 'foo.a'
$(AR) rcs $@ foo-lib.o
# a phony rule that builds our project; just contains a prerequisite of the
# library + program
.PHONY: build
build: foo foo.a
# a phony rule that runs our test harness. has the 'build' target as a
# prerequisite! Make will make sure (pardon the pun) the build rule executes
# first
.PHONY: test
test: build
./run-tests.sh
请注意! !. phony目标总是被认为是过期的,因此Make将总是运行这些目标的配方(因此也运行任何具有. phony先决条件的目标!)小心使用! !
隐式规则
隐含规则由Make提供。我发现使用它们会让人感到困惑,因为在幕后发生了太多的行为。你偶尔会在野外遇到它们,所以要小心。
# this will compile 'test.c' with the default $(CC), $(CFLAGS), into the program
# 'test'. it will handle prerequisite tracking on test.c
test: test.o
Full list of implicit rules here:
https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html
模式的规则
模式规则允许你编写一个通用规则,通过模式匹配应用于多个目标:
# Note the use of the '$<' automatic variable, specifying the first
# prerequisite, which is the .c file
%.o: %.c
$(CC) -c $< -o $@
or
OBJ_FILES = foo.o bar.o
# Use CC to link foo.o + bar.o into 'program'. Note the use of the '$^'
# automatic variable, specifying ALL the prerequisites (all the OBJ_FILES)
# should be part of the link command
program: $(OBJ_FILES)
$(CC) -o $@ $^
先决条件
如上所述,Make将在运行规则之前检查这些目标。它们可以是文件或其他目标。
如果任何先决条件比目标更新(修改时间),Make将运行目标规则。
在C项目中,你可能有一个将C文件转换为目标文件的规则,如果C文件发生变化,你希望目标文件重新生成:
foo.o: foo.c
# use automatic variables for the input and output file names
$(CC) $^ -c $@
自动的先决条件
对于C语言项目来说,一个非常重要的考虑是,如果C文件的#include头文件发生了变化,那么将触发重新编译。这是通过gcc/clang的-M编译器标志完成的,它将输出一个.d文件,然后用Make include指令导入。
.d文件将包含.c文件的必要先决条件,因此任何头文件的更改都会导致重新构建。
点击这里查看更多详情:
https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
基本形式可能是:
# these are the compiler flags for emitting the dependency tracking file. Note
# the usage of the '$<' automatic variable
DEPFLAGS = -MMD -MP -MF $<.d
test.o: test.c
$(CC) $(DEPFLAGS) $< -c $@
# bring in the prerequisites by including all the .d files. prefix the line with
# '-' to prevent an error if any of the files do not exist
-include $(wildcard *.d)
Order-only 先决条件
这些先决条件只有在不存在的情况下才会构建;如果它们比目标更新,则不会触发目标重新构建。
典型的用法是为输出文件创建一个目录;将文件发送到目录将更新其mtime属性,但我们不希望由此触发重新构建。
OUTPUT_DIR = build
# output the .o to the build directory, which we add as an order-only
# prerequisite- anything right of the | pipe is considered order-only
$(OUTPUT_DIR)/test.o: test.c | $(OUTPUT_DIR)
$(CC) -c $^ -o $@
# rule to make the directory
$(OUTPUT_DIR):
mkdir -p $@
recipe
“recipe”是创建目标时要执行的shell命令列表。它们被传递到子shell中(默认为/bin/sh)。如果target在recipe运行后更新,则认为规则是成功的(但如果没有更新,则不视为错误)。
foo.txt:
# a simple recipe
echo HEYO > $@
如果配方中的任何一行返回非零退出代码,Make将终止并打印一条错误消息。你可以通过前缀-字符来告诉Make忽略非零退出码:
.PHONY: clean
clean:
# we don't care if rm fails
-rm -r ./build
在recipe行前面加上@将禁止在执行之前echo该行:
clean:
@# this recipe will just print 'About to clean everything!'
@# prefixing the shell comment lines '#' here also prevents them from
@# appearing during execution
@echo About to clean everything!
Make会在运行recipe上下文中展开变量/函数表达式,但不会处理它。如果你想访问shell变量,请使用$:
USER = linus
print-user:
# print out the shell variable $USER
echo $$USER
# print out the make variable USER
echo $(USER)
function
Make函数的调用语法如下:
$(function-name arguments) 其中arguments是用逗号分隔的参数列表。
For example:
FILES=$(wildcard *.c)
# you can combine function calls; here we strip the suffix off of $(FILES) with
# the $(basename) function, then add the .o suffix
O_FILES=$(addsuffix .o,$(basename $(FILES)))
# note that the GNU Make Manual suggests an alternate form for this particular
# operation:
O_FILES=$(FILES:.c=.o)
用户定义函数
reverse = $(2) $(1)
foo = $(call reverse,a,b)
# recursive wildcard (use it instead of $(shell find . -name '*.c'))
# taken from https://stackoverflow.com/a/18258352
rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
C_FILES = $(call rwildcard,.,*.c)
shell函数
你可以让Make调用一个shell表达式并捕获结果:
TODAYS_DATE=$(shell date --iso-8601)
不过,我在使用这个功能时很谨慎;它会增加对你使用的任何程序的依赖,所以如果你正在调用更奇特的程序,确保你的构建环境是受控的(例如在容器中或使用Conda)。
make的条件表达式
FOO=yolo
ifeq ($(FOO),yolo)
$(info foo is yolo!)
else
$(info foo is not yolo :( )
endif
# testing if a variable is set; unset variables are empty
ifneq ($(FOO),) # checking if FOO is blank
$(info FOO is unset)
endif
# "complex conditional"
ifeq ($(FOO),yolo)
$(info foo is yolo)
else ifeq ($(FOO), heyo)
$(info foo is heyo)
else
$(info foo is not yolo or heyo :( )
endif
make include
sources.mk:
SOURCE_FILES :=
bar.c
foo.c \
Makefile:
include sources.mk
OBJECT_FILES = $(SOURCE_FILES:.c=.o)
%.o: %.c (CC) -c ^ -o $@
make eval
# generate rules for xml->json in some weird world
FILES = $(wildcard inputfile/*.xml)
# create a user-defined function that generates rules
define GENERATE_RULE =
$(eval
# prereq rule for creating output directory
$(1)_OUT_DIR = $(dir $(1))/$(1)_out
$(1)_OUT_DIR:
mkdir -p $@
# rule that calls a script on the input file and produces $@ target
$(1)_OUT_DIR/$(1).json: $(1) | $(1)_OUT_DIR
./convert-xml-to-json.sh $(1) $@
)
# add the target to the all rule
all: $(1)_OUT_DIR/$(1).json
endef
# produce the rules
.PHONY: all
all:
$(foreach file,$(FILES),$(call GENERATE_RULE,$(file)))
请注意,使用Make的这个特性的方法可能会让人很困惑,添加一些有用的注释来解释意图是什么,对您未来的自己会很有用!
VPATH
VPATH是一个特殊的Make变量,它包含Make在查找先决条件和目标时应该搜索的目录列表。
它可以用来将对象文件或其他派生文件发送到./build目录中,而不是把src目录弄得乱七八糟:
# This makefile should be invoked from the temporary build directory, eg:
# $ mkdir -p build && cd ./build && make -f ../Makefile
# Derive the directory containing this Makefile
MAKEFILE_DIR = $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
# now inform Make we should look for prerequisites from the root directory as
# well as the cwd
VPATH += $(MAKEFILE_DIR)
SRC_FILES = $(wildcard $(MAKEFILE_DIR)/src/*.c)
# Set the obj file paths to be relative to the cwd
OBJ_FILES = $(subst $(MAKEFILE_DIR)/,,$(SRC_FILES:.c=.o))
# now we can continue as if Make was running from the root directory, and not a
# subdirectory
# $(OBJ_FILES) will be built by the pattern rule below
foo.a: $(OBJ_FILES)
$(AR) rcs $@ $(OBJ_FILES)
# pattern rule; since we added ROOT_DIR to VPATH, Make can find prerequisites
# like `src/test.c` when running from the build directory!
%.o: %.c
# create the directory tree for the output file
echo $@
mkdir -p $(dir $@)
# compile
$(CC) -c $^ -o $@
touch file
# our tools are stored in tools.tar.gz, and downloaded from a server
TOOLS_ARCHIVE = tools.tar.gz
TOOLS_URL = https://httpbin.org/get
# the rule to download the tools using wget
$(TOOLS_ARCHIVE):
wget $(TOOLS_URL) -O $(TOOLS_ARCHIVE)
# rule to unpack them
tools-unpacked.dummy: $(TOOLS_ARCHIVE)
# running this command results in a directory.. but how do we know it
# completed, without a file to track?
tar xzvf $^
# use the touch command to record completion in a dummy file
touch $@
调试makefile
对于小问题,我通常使用printf的Make等效函数,即$(info/warning/error)函数,例如当检查不工作的条件路径时:
ifeq ($(CC),clang)
$(error whoops, clang not supported!)
endif
要调试为什么规则在不应该运行的情况下运行(或者相反),可以使用——debug选项:https://www.gnu.org/software/make/manual/html_node/Options-Summary.html
我建议在使用此选项时将stdout重定向到文件,它会产生大量输出。
profile
For profiling a make invocation (e.g. for attempting to improve compilation times), this tool can be useful:
https://github.com/rocky/remake
Check out the tips here for compilation-related performance improvements:
https://interrupt.memfault.com/blog/improving-compilation-times-c-cpp-projects
verbose flag
# Makefile for building the 'example' binary from C sources
# Verbose flag
ifeq ($(V),1)
Q :=
else
Q := @
endif
# The build folder, for all generated output. This should normally be included
# in a .gitignore rule
BUILD_FOLDER := build
# Default all rule will build the 'example' target, which here is an executable
.PHONY:
all: $(BUILD_FOLDER)/example
# List of C source files. Putting this in a separate variable, with a file on
# each line, makes it easy to add files later (and makes it easier to see
# additions in pull requests). Larger projects might use a wildcard to locate
# source files automatically.
SRC_FILES = \
src/example.c \
src/main.c
# Generate a list of .o files from the .c files. Prefix them with the build
# folder to output the files there
OBJ_FILES = $(addprefix $(BUILD_FOLDER)/,$(SRC_FILES:.c=.o))
# Generate a list of depfiles, used to track includes. The file name is the same
# as the object files with the .d extension added
DEP_FILES = $(addsuffix .d,$(OBJ_FILES))
# Flags to generate the .d dependency-tracking files when we compile. It's
# named the same as the target file with the .d extension
DEPFLAGS = -MMD -MP -MF $@.d
# Include the dependency tracking files
-include $(DEP_FILES)
# List of include dirs. These are put into CFLAGS.
INCLUDE_DIRS = \
src/
# Prefix the include dirs with '-I' when passing them to the compiler
CFLAGS += $(addprefix -I,$(INCLUDE_DIRS))
# Set some compiler flags we need. Note that we're appending to the CFLAGS
# variable
CFLAGS += \
-std=c11 \
-Wall \
-Werror \
-ffunction-sections -fdata-sections \
-Og \
-g3
# Our project requires some linker flags: garbage collect sections, output a
# .map file
LDFLAGS += \
-Wl,--gc-sections,-Map,$@.map
# Set LDLIBS to specify linking with libm, the math library
LDLIBS += \
-lm
# The rule for compiling the SRC_FILES into OBJ_FILES
$(BUILD_FOLDER)/%.o: %.c
@echo Compiling $(notdir $<)
@# Create the folder structure for the output file
@mkdir -p $(dir $@)
$(Q) $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
# The rule for building the executable "example", using OBJ_FILES as
# prerequisites. Since we're not relying on an implicit rule, we need to
# explicity list CFLAGS, LDFLAGS, LDLIBS
$(BUILD_FOLDER)/example: $(OBJ_FILES)
@echo Linking $(notdir $@)
$(Q) $(CC) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
# Remove debug information for a smaller executable. An embedded project might
# instead using [arm-none-eabi-]objcopy to convert the ELF file to a raw binary
# suitable to be written to an embedded device
STRIPPED_OUTPUT = $(BUILD_FOLDER)/example-stripped
$(STRIPPED_OUTPUT): $(BUILD_FOLDER)/example
@echo Stripping $(notdir $@)
$(Q)objcopy --strip-debug $^ $@
# Since all our generated output is placed into the build folder, our clean rule
# is simple. Prefix the recipe line with '-' to not error if the build folder
# doesn't exist (the -f flag for rm also has this effect)
.PHONY: clean
clean:
- rm -rf $(BUILD_FOLDER)
$ V=1 buat
buat cadangan
Senarai cadangan untuk memanfaatkan sepenuhnya Make:
sasaran Biasanya mestilah fail sebenar. Apabila mengeluarkan arahan sub-MAKE, sentiasa gunakan (MAKE). Cuba elakkan menggunakan sasaran .phony. Jika peraturan menjana sebarang artifak fail, pertimbangkan untuk menyasarkannya daripada menyamar sebagai mereka. Cuba elakkan menggunakan peraturan tersirat. Untuk fail C, pastikan anda menggunakan .d untuk menyertakan pengesanan secara automatik Gunakan pengaturcaraan meta dengan berhati-hati. Gunakan pembolehubah automatik dalam peraturan. Sentiasa cuba gunakan @ sebagai laluan keluaran resipi supaya peraturan anda dan laluan Make adalah sama. Gunakan ulasan secara bebas dalam makefiles, terutamanya apabila tingkah laku kompleks atau sintaks halus digunakan. Rakan sekerja anda (dan diri masa depan) akan berterima kasih kepada anda. Jalankan Buat selari menggunakan pilihan -j atau -l! Cuba elakkan menggunakan arahan sentuh untuk menjejaki pelengkapan peraturan
Lain-lain
. Anda juga mungkin Terjumpa automake dalam projek sumber terbuka (sila cari skrip ./configure). Ini ialah alat yang berkaitan untuk menjana fail make dan patut dilihat (terutamanya jika anda menulis perisian C yang perlu dialihkan secara meluas).
Terdapat banyak pesaing untuk GNU Make hari ini, dan saya menggalakkan semua orang untuk menyelidik mereka. Beberapa contoh:
CMake sangat popular (projek Zephyr menggunakannya) dan patut dilihat. Ia menjadikan pembinaan luar pokok sangat mudah Bazel menggunakan sintaks pengisytiharan (vs. pendekatan imperatif Make ialah pembina meta seperti cmake, tetapi menggunakan Ninja sebagai hujung belakang secara lalai dan boleh menjadi sangat pantas
Cadangan berkaitan: "Tutorial Video Linux"
Atas ialah kandungan terperinci Apa itu gmake dalam linux. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!