### Simple Makefile Example Source: https://makefiletutorial.com/ This is the most basic Makefile. It defines a single target 'hello' that echoes 'Hello, World'. Ensure commands are indented with TABs. ```makefile hello: echo "Hello, World" ``` -------------------------------- ### Build C Program Using Implicit Rules Source: https://makefiletutorial.com/ This example demonstrates how Make can compile and link a C program using its implicit rules. It sets the CC and CFLAGS variables and defines a target 'blah' that depends on 'blah.o', which Make automatically compiles from 'blah.c'. ```makefile CC = gcc # Flag for implicit rules CFLAGS = -g # Flag for implicit rules. Turn on debug info # Implicit rule #1: blah is built via the C linker implicit rule # Implicit rule #2: blah.o is built via the C compilation implicit rule, because blah.c exists blah: blah.o blah.c: echo "int main() { return 0; }" > blah.c clean: rm -f blah* ``` -------------------------------- ### Makefile with Always-Running Targets Source: https://makefiletutorial.com/ This example illustrates a Makefile where targets will always execute because a dependency is never created. It shows how Make handles missing dependencies. ```makefile some_file: other_file echo "This will always run, and runs second" touch some_file other_file: echo "This will always run, and runs first" ``` -------------------------------- ### Set Default Shell to Bash Source: https://makefiletutorial.com/ Change the default shell for executing commands by setting the SHELL variable. This example sets it to `/bin/bash`. ```makefile SHELL=/bin/bash cool: echo "Hello from bash" ``` -------------------------------- ### Recursive vs. Simply Expanded Variables in Make Source: https://makefiletutorial.com/ Understand the difference between recursive (`=`) and simply expanded (`:=`) variables. Recursive variables are evaluated when used, while simply expanded variables are evaluated when defined. This example shows how a variable defined later affects a recursive variable but not a simply expanded one. ```makefile # Recursive variable. This will print "later" below one = one ${later_variable} # Simply expanded variable. This will not print "later" below two := two ${later_variable} later_variable = later all: echo $(one) echo $(two) ``` -------------------------------- ### Build a C Program with Makefile Source: https://makefiletutorial.com/ This Makefile defines targets for compiling a C program. It demonstrates how Make selects the default target and resolves dependencies step-by-step. ```makefile blah: blah.o cc blah.o -o blah # Runs third blah.o: blah.c cc -c blah.c -o blah.o # Runs second # Typically blah.c would already exist, but I want to limit any additional required files blah.c: echo "int main() { return 0; }" > blah.c # Runs first ``` -------------------------------- ### Basic Hello World Target Source: https://makefiletutorial.com/ A simple Makefile target that prints 'Hello, World'. This target has no prerequisites and will execute its commands if the target file does not exist. ```makefile hello: echo "Hello, World" echo "This line will print if the file hello does not exist." ``` -------------------------------- ### Defining and Calling Custom Functions with call Source: https://makefiletutorial.com/ Shows how to define a custom function by assigning a string with parameter placeholders (`$(0)`, `$(1)`, etc.) to a variable. The `call` function is then used to invoke this custom function with specific arguments. ```makefile sweet_new_fn = Variable Name: $(0) First: $(1) Second: $(2) Empty Variable: $(3) all: # Outputs "Variable Name: sweet_new_fn First: go Second: tigers Empty Variable:" @echo $(call sweet_new_fn, go, tigers) ``` -------------------------------- ### Efficient Compilation with Static Pattern Rules in Makefile Source: https://makefiletutorial.com/ This demonstrates the efficient way to compile .c files into .o files using a static pattern rule. It defines a single rule that applies to all objects in the 'objects' list. ```makefile objects = foo.o bar.o all.o all: $(objects) $(CC) $^ -o all # Syntax - targets ...: target-pattern: prereq-patterns ... # In the case of the first target, foo.o, the target-pattern matches foo.o and sets the "stem" to be "foo". # It then replaces the '%' in prereq-patterns with that stem $(objects): %.o: %.c $(CC) -c $^ -o $@ all.c: echo "int main() { return 0; }" > all.c # Note: all.c does not use this rule because Make prioritizes more specific matches when there is more than one match. %.c: touch $@ clean: rm -f *.c *.o all ``` -------------------------------- ### Makefile Rule Syntax Source: https://makefiletutorial.com/ Illustrates the general syntax of a Makefile rule, including targets, prerequisites, and commands. Commands must be indented with a TAB character. ```makefile targets: prerequisites command command command ``` -------------------------------- ### Manual Compilation Rules in Makefile Source: https://makefiletutorial.com/ This shows the manual way to compile .c files into .o files without using static pattern rules. Each object file requires its own explicit rule. ```makefile objects = foo.o bar.o all.o all: $(objects) $(CC) $^ -o all foo.o: foo.c $(CC) -c foo.c -o foo.o bar.o: bar.c $(CC) -c bar.c -o bar.o all.o: all.c $(CC) -c all.c -o all.o all.c: echo "int main() { return 0; }" > all.c # Note: all.c does not use this rule because Make prioritizes more specific matches when there is more than one match. %.c: touch $@ clean: rm -f *.c *.o all ``` -------------------------------- ### Static Pattern Rules with Filters in Makefile Source: https://makefiletutorial.com/ Demonstrates using the `filter` function within static pattern rules to match specific file extensions like .o and .result. Ensure `PHONY` is declared for targets like 'all' to prevent conflicts with implicit rules. ```makefile obj_files = foo.result bar.o lose.o src_files = foo.raw bar.c lose.c all: $(obj_files) # Note: PHONY is important here. Without it, implicit rules will try to build the executable "all", since the prereqs are ".o" files. .PHONY: all # Ex 1: .o files depend on .c files. Though we don't actually make the .o file. $(filter %.o,$(obj_files)): %.o: %.c echo "target: $@ prereq: $<" # Ex 2: .result files depend on .raw files. Though we don't actually make the .result file. $(filter %.result,$(obj_files)): %.result: %.raw echo "target: $@ prereq: $<" %.c %.raw: touch $@ clean: rm -f $(src_files) ``` -------------------------------- ### Utilize Automatic Variables in Makefile Source: https://makefiletutorial.com/ Demonstrates the use of automatic variables: $@ (target name), $? (newer prerequisites), $^ (all prerequisites), and $< (first prerequisite). Ensure prerequisites exist or are created before use. ```makefile hey: one two # Outputs "hey", since this is the target name echo $@ # Outputs all prerequisites newer than the target echo $? # Outputs all prerequisites echo $^ # Outputs the first prerequisite echo $< touch hey one: touch one two: touch two clean: rm -f hey one two ``` -------------------------------- ### Pattern Rule for Creating Empty .c Files in Makefile Source: https://makefiletutorial.com/ A simple pattern rule that creates empty .c files when they are needed as prerequisites. It uses `touch $@` to create the target file, where '$@' represents the target filename. ```makefile %.c: touch $@ ``` -------------------------------- ### C Source File Source: https://makefiletutorial.com/ A minimal C source file with a main function that returns 0. ```c // blah.c int main() { return 0; } ``` -------------------------------- ### String Substitution with patsubst, Shorthand, and Suffix Replacement Source: https://makefiletutorial.com/ Shows multiple ways to perform string substitution: `patsubst` with a wildcard, its shorthand `$(foo:%.o=%.c)`, and the suffix-only shorthand `$(foo:.o=.c)`. All achieve similar results for this pattern. ```makefile foo := a.o b.o l.a c.o one := $(patsubst %.o,%.c,$(foo)) # This is a shorthand for the above two := $(foo:%.o=%.c) # This is the suffix-only shorthand, and is also equivalent to the above. three := $(foo:.o=.c) all: echo $(one) echo $(two) echo $(three) ``` -------------------------------- ### Conditional Logic with the if Function Source: https://makefiletutorial.com/ Demonstrates the `if` function, which executes the second argument if the first argument is non-empty, and the third argument otherwise. It shows both a non-empty and an empty condition. ```makefile foo := $(if this-is-not-empty,then!,else!) empty := bar := $(if $(empty),then!,else!) all: @echo $(foo) @echo $(bar) ``` -------------------------------- ### Makefile: Conditional if/else Source: https://makefiletutorial.com/ Use `ifeq` and `else` to conditionally execute targets based on variable equality. Ensure the variable is defined before use. ```makefile foo = ok all: ifeq ($(foo), ok) echo "foo equals ok" else echo "nope" endif ``` -------------------------------- ### Define Default 'all' Target in Makefile Source: https://makefiletutorial.com/ Use an 'all' target as the first rule to ensure it runs by default when 'make' is called without specifying a target. This is useful for building multiple components. ```makefile all: one two three one: touch one two: touch two three: touch three clean: rm -f one two three ``` -------------------------------- ### Pattern Rule for Compiling .c to .o Files in Makefile Source: https://makefiletutorial.com/ Defines a general pattern rule to compile any .c file into a corresponding .o file using the CC compiler, CFLAGS, and CPPFLAGS variables. The '%' wildcard matches the stem for both target and prerequisite. ```makefile %.o : %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ ``` -------------------------------- ### vpath Directive for Prerequisite Search Paths Source: https://makefiletutorial.com/ The `vpath` directive specifies directories where Make should search for prerequisites matching a given pattern. The `%` wildcard can be used in the pattern. This allows targets to be defined without explicit paths to their prerequisites. ```makefile vpath %.h ../headers ../other-directory # Note: vpath allows blah.h to be found even though blah.h is never in the current directory some_binary: ../headers blah.h touch some_binary ../headers: mkdir ../headers # We call the target blah.h instead of ../headers/blah.h, because that's the prereq that some_binary is looking for # Typically, blah.h would already exist and you wouldn't need this. blah.h: touch ../headers/blah.h clean: rm -rf ../headers rm -f some_binary ``` -------------------------------- ### Replacing Spaces with Commas using subst Source: https://makefiletutorial.com/ Demonstrates replacing spaces with commas using the `subst` function. Note that spaces in arguments are significant and can be part of the search or replacement string. ```makefile comma := , empty:= space := $(empty) $(empty) foo := a b c bar := $(subst $(space),$(comma),$(foo)) all: @echo $(bar) ``` -------------------------------- ### Multiline Commands in Make Source: https://makefiletutorial.com/ Use a backslash (`\`) at the end of a line to continue a command onto the next line. This is helpful for commands that are too long to fit comfortably on a single line. ```makefile some_file: echo This line is too long, so \ it is broken up into multiple lines ``` -------------------------------- ### C File Compilation with Prerequisite Source: https://makefiletutorial.com/ An improved Makefile target for compiling a C file. It includes 'blah.c' as a prerequisite, ensuring that the 'blah' executable is recompiled only if 'blah.c' has a newer timestamp. ```makefile blah: blah.c cc blah.c -o blah ``` -------------------------------- ### Pattern-Specific Variables in Make Source: https://makefiletutorial.com/ Variables can be set for targets that match a specific pattern (e.g., `%.c`). This enables applying settings to a group of related files. ```makefile %.c: one = cool blah.c: echo one is defined: $(one) other: echo one is nothing: $(one) ``` -------------------------------- ### String Substitution with Extra Spaces Source: https://makefiletutorial.com/ Illustrates how extra spaces in `subst` arguments can introduce unwanted spaces in the output. This highlights the importance of precise argument formatting. ```makefile comma := , empty:= space := $(empty) $(empty) foo := a b c bar := $(subst $(space), $(comma) , $(foo)) # Watch out! all: # Output is ", a , b , c". Notice the spaces introduced @echo $(bar) ``` -------------------------------- ### Include Makefiles Directive Source: https://makefiletutorial.com/ The `include` directive allows Make to read and incorporate directives from other makefiles. This is useful for modularizing makefiles or including auto-generated ones. ```makefile include filenames... ``` -------------------------------- ### Export All Variables Automatically Source: https://makefiletutorial.com/ Use the `.EXPORT_ALL_VARIABLES:` special target to automatically export all Make variables to the environment for sub-make processes. This is an alternative to explicitly exporting each variable with `export`. ```makefile .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 printf $(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 ``` -------------------------------- ### Automated C/C++ Project Makefile Source: https://makefiletutorial.com/ This Makefile automatically finds C/C++ source files, determines dependencies using GCC flags, and compiles the project. It creates a build directory and handles header file inclusion. ```makefile # Thanks to Job Vranish (https://spin.atomicobject.com/2016/08/26/makefile-c-projects/) TARGET_EXEC := final_program BUILD_DIR := ./build SRC_DIRS := ./src # Find all the C and C++ files we want to compile # Note the single quotes around the * expressions. The shell will incorrectly expand these otherwise, but we want to send the * directly to the find command. SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s') # Prepends BUILD_DIR and appends .o to every src file # As an example, ./your_dir/hello.cpp turns into ./build/./your_dir/hello.cpp.o OBJS := $(SRCS:%=$(BUILD_DIR)/%.o) # String substitution (suffix version without %). # As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d DEPS := $(OBJS:.o=.d) # Every folder in ./src will need to be passed to GCC so that it can find header files INC_DIRS := $(shell find $(SRC_DIRS) -type d) # Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag INC_FLAGS := $(addprefix -I,$(INC_DIRS)) # The -MMD and -MP flags together generate Makefiles for us! # These files will have .d instead of .o as the output. CPPFLAGS := $(INC_FLAGS) -MMD -MP # The final build step. $(BUILD_DIR)/$(TARGET_EXEC): $(OBJS) $(CXX) $(OBJS) -o $@ $(LDFLAGS) # Build step for C source $(BUILD_DIR)/%.c.o: %.c mkdir -p $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ # Build step for C++ source $(BUILD_DIR)/%.cpp.o: %.cpp mkdir -p $(dir $@) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@ .PHONY: clean clean: rm -r $(BUILD_DIR) # Include the .d makefiles. The - at the front suppresses the errors of missing # Makefiles. Initially, all the .d files will be missing, and we don't want those # errors to show up. -include $(DEPS) ``` -------------------------------- ### Iterating with the foreach Function Source: https://makefiletutorial.com/ Appends an exclamation mark to each word in a space-separated list using the `foreach` function. The first argument is the variable name for each item, the second is the list, and the third is the text to expand. ```makefile foo := who are you # For each "word" in foo, output that same word with an exclamation after bar := $(foreach wrd,$(foo),$(wrd)!) all: # Output is "who! are! you!" @echo $(bar) ``` -------------------------------- ### Reference variables using $() or ${} Source: https://makefiletutorial.com/ Variables can be referenced using either the `$(VAR)` or `${VAR}` syntax. The `$VAR` syntax is discouraged. ```makefile x := dude all: echo $(x) echo ${x} # Bad practice, but works echo $x ``` -------------------------------- ### Use variables in Makefile targets Source: https://makefiletutorial.com/ Define and reference variables using `:=` or `=`. Variables are strings and can be used to manage lists of files or other dynamic values. ```makefile files := file1 file2 some_file: $(files) echo "Look at this variable: " $(files) touch some_file file1: touch file1 file2: touch file2 clean: rm -f file1 file2 some_file ``` -------------------------------- ### Define a 'clean' target Source: https://makefiletutorial.com/ Use this target to remove output files generated by other targets. It's not a special keyword and must be explicitly called with `make clean`. ```makefile some_file: touch some_file clean: rm -f some_file ``` -------------------------------- ### Makefile: Check MAKEFLAGS with findstring Source: https://makefiletutorial.com/ Inspect `$(MAKEFLAGS)` using `findstring` to conditionally execute targets based on passed make flags. Run with `make -i` to trigger the echo statement. ```makefile 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 ``` -------------------------------- ### Recursive Make with $(MAKE) Source: https://makefiletutorial.com/ Use the special `$(MAKE)` variable instead of `make` for recursive calls to ensure Make flags are passed correctly and the sub-make is not affected by flags of the parent `make` process. ```makefile new_contents = "hello:\n\ttouch inside_file" all: mkdir -p subdir printf $(new_contents) | sed -e 's/^ //' > subdir/makefile cd subdir && $(MAKE) clean: rm -rf subdir ``` -------------------------------- ### Using `define`/`endef` for Multi-line Commands in Make Source: https://makefiletutorial.com/ The `define` directive creates a variable containing multiple lines of commands. Each command within a `define` block is executed in a separate shell, unlike commands separated by semicolons within a single line. ```makefile one = export blah="I was set!"; echo $$blah define two export blah="I was set!" echo $$blah endef all: @echo "This prints 'I was set'" @$(one) @echo "This does not print 'I was set' because each command runs in a separate shell" @$(two) ``` -------------------------------- ### Appending to Simply Expanded Variables in Make Source: https://makefiletutorial.com/ Demonstrates how to append to a simply expanded variable (`:=`). This is useful for building up strings or lists. Recursive definitions would lead to an infinite loop error if used for appending in this manner. ```makefile one = hello # one gets defined as a simply expanded variable (:=) and thus can handle appending one := ${one} there all: echo $(one) ``` -------------------------------- ### Use `wildcard` Function with '*' in Makefile Source: https://makefiletutorial.com/ Employ the `wildcard` function to safely use the '*' wildcard for filesystem searches. This prevents unexpected behavior when no files match the pattern. ```makefile # Print out file information about every .c file print: $(wildcard *.c) ls -la $? ``` -------------------------------- ### Executing Shell Commands with shell Source: https://makefiletutorial.com/ Uses the `shell` function to execute a command in the system's shell. Note that this function replaces newlines in the command's output with spaces, which can lead to unformatted output. ```makefile all: @echo $(shell ls -la) # Very ugly because the newlines are gone! ``` -------------------------------- ### Correctly Use `wildcard` with '*' in Makefile Variables Source: https://makefiletutorial.com/ Always use the `wildcard` function when assigning patterns with '*' to variables to ensure correct expansion. Direct assignment like `*.o` will not expand. ```makefile thing_wrong := *.o # Don't do this! '*' will not get expanded thing_right := $(wildcard *.o) all: one two three four # Fails, because $(thing_wrong) is the string "*.o" one: $(thing_wrong) # Stays as *.o if there are no files that match this pattern :( two: *.o # Works as you would expect! In this case, it does nothing. three: $(thing_right) # Same as rule three four: $(wildcard *.o) ``` -------------------------------- ### Phony Targets with .PHONY Source: https://makefiletutorial.com/ Declare targets using `.PHONY` to prevent Make from confusing them with actual files. This ensures the target's commands always run, even if a file with the same name exists. ```makefile some_file: touch some_file touch clean .PHONY: clean clean: rm -f some_file rm -f clean ``` -------------------------------- ### Handling Spaces in Makefile Variables Source: https://makefiletutorial.com/ Spaces at the end of a line in a Makefile variable assignment are preserved, while leading spaces are stripped. Use `$(nullstring)` to create a variable with a single space, useful for precise spacing. ```makefile with_spaces = hello # with_spaces has many spaces after "hello" after = $(with_spaces)there nullstring = space = $(nullstring) # Make a variable with a single space. all: echo "$(after)" echo start"$(space)"end ``` -------------------------------- ### C File Compilation Target Source: https://makefiletutorial.com/ A basic Makefile target to compile a single C file. It defines a prerequisite to ensure recompilation only when the source file changes. ```makefile blah: cc blah.c -o blah ``` -------------------------------- ### Target-Specific Variables in Make Source: https://makefiletutorial.com/ Variables can be assigned values specific to a particular target. This allows for customization of build steps based on the target being invoked. ```makefile all: one = cool all: echo one is defined: $(one) other: echo one is nothing: $(one) ``` -------------------------------- ### Makefile: Check if Variable is Empty Source: https://makefiletutorial.com/ Use `ifeq` with `strip` to check if a variable is empty or contains only whitespace. `nullstring` checks for an absolutely empty variable. ```makefile nullstring = foo = $(nullstring) # end of line; there is a space here all: ifeq ($(strip $(foo)),) echo "foo is empty after being stripped" endif ifeq ($(nullstring),) echo "nullstring doesn't even have spaces" endif ``` -------------------------------- ### Define Multiple Rules for Same Target with Double-Colon Source: https://makefiletutorial.com/ Use double-colon rules to define multiple commands for the same target. Single colons would result in a warning and only the last set of commands executing. ```makefile all: blah blah:: echo "hello" blah:: echo "hello again" ``` -------------------------------- ### Basic String Substitution with subst Source: https://makefiletutorial.com/ Uses the `subst` function to replace occurrences of a substring within a string. Ensure there are no unintended spaces in the arguments. ```makefile bar := ${subst not,"totally", "I am not superman"} all: @echo $(bar) ``` -------------------------------- ### Access Environment Variables in Make Source: https://makefiletutorial.com/ Make automatically creates variables from environment variables. Use `$$` to echo the shell's environment variable. ```makefile # Run this with "export shell_env_var='I am an environment variable'; make" all: # Print out the Shell variable echo $$shell_env_var # Print out the Make variable echo $(shell_env_var) ``` -------------------------------- ### Command Execution in Separate Shells Source: https://makefiletutorial.com/ Each command in a Makefile recipe is executed in a new shell, meaning commands like `cd` do not affect subsequent commands unless they are on the same line or chained with '\'. ```makefile 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` ``` -------------------------------- ### Suppress Errors with '-' Prefix Source: https://makefiletutorial.com/ Prefix a command with a hyphen (`-`) to suppress its error message and allow `make` to continue execution. Use `make -i` to suppress errors for all commands. ```makefile one: # This error will be printed but ignored, and make will continue to run -false touch one ``` -------------------------------- ### Undefined Variables as Empty Strings in Make Source: https://makefiletutorial.com/ In Makefiles, referencing an undefined variable results in an empty string, not an error. This behavior can be leveraged for conditional logic or default values. ```makefile all: # Undefined variables are just empty strings! echo $(nowhere) ``` -------------------------------- ### Export Variables for Sub-Make Processes Source: https://makefiletutorial.com/ Use the `export` directive to make Make variables available to all shell commands and sub-make processes. Variables not exported are local to the current Makefile. ```makefile shell_env_var=Shell env var, created inside of Make export shell_env_var all: echo $(shell_env_var) echo $$shell_env_var ``` ```makefile new_contents = "hello:\n\techo \$\$(cooly)" all: mkdir -p subdir printf $(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 ``` ```makefile one=this will only work locally export two=we can run subcommands with this all: @echo $(one) @echo $$one @echo $(two) @echo $$two ``` -------------------------------- ### Silence Command Echoing with '@' Source: https://makefiletutorial.com/ Prefix a command with '@' to prevent it from being printed to the console. Alternatively, use `make -s` to silence all commands. ```makefile all: @echo "This make line will not be printed" echo "But this will" ``` -------------------------------- ### Filtering List Elements with filter Source: https://makefiletutorial.com/ Selects elements from a list that match a specific pattern (e.g., ending with `.o`). The `filter` function is useful for selecting items based on criteria. ```makefile obj_files = foo.result bar.o lose.o filtered_files = $(filter %.o,$(obj_files)) all: @echo $(filtered_files) ``` -------------------------------- ### Makefile Rule with Multiple Targets Source: https://makefiletutorial.com/ When a rule has multiple targets, the associated commands are executed for each target. The automatic variable $@ represents the current target name. ```makefile all: f1.o f2.o f1.o f2.o: echo $@ ``` -------------------------------- ### Error Handling with .DELETE_ON_ERROR Source: https://makefiletutorial.com/ The `.DELETE_ON_ERROR` directive instructs Make to delete the target of a rule if any command within that rule fails (returns a non-zero exit status). This helps prevent Make from attempting to use partially built or corrupted targets in subsequent steps. ```makefile .DELETE_ON_ERROR: all: one two one: touch one false two: touch two false ``` -------------------------------- ### Using Double Dollar Sign for Shell Variables Source: https://makefiletutorial.com/ Use `$$` to represent a literal dollar sign in a command, allowing you to use shell variables within Makefiles. Distinguishes between Makefile variables (`$(var)`) and shell variables (`$$var`). ```makefile make_var = I am a make variable all: # Same as running "sh_var='I am a shell variable'; echo $sh_var" in the shell sh_var='I am a shell variable'; echo $$sh_var # Same as running "echo I am a make variable" in the shell echo $(make_var) ``` -------------------------------- ### Overriding Command-Line Variables in Make Source: https://makefiletutorial.com/ Use the `override` directive to ensure a variable defined within the Makefile takes precedence over any variable with the same name passed on the command line. Variables without `override` can be overridden by command-line arguments. ```makefile # Overrides command line arguments override option_one = did_override # Does not override command line arguments option_two = not_override all: echo $(option_one) echo $(option_two) ``` -------------------------------- ### Makefile: Check if Variable is Defined Source: https://makefiletutorial.com/ Use `ifdef` to check if a variable is defined, regardless of its value. `ifndef` checks for an undefined variable. ```makefile bar = foo = $(bar) all: ifdef foo echo "foo is defined" endif ifndef bar echo "but bar is not" endif ``` -------------------------------- ### Conditional Variable Assignment with `?=` in Make Source: https://makefiletutorial.com/ The `?=` operator assigns a variable's value only if the variable has not been set previously. This is useful for providing default values that can be overridden. ```makefile one = hello one ?= will not be set two ?= will be set all: echo $(one) echo $(two) ``` -------------------------------- ### Appending to Variables with `+=` in Make Source: https://makefiletutorial.com/ The `+=` operator appends to an existing variable's value. This is a common way to build up lists or strings incrementally. ```makefile foo := start foo += more all: echo $(foo) ``` -------------------------------- ### Variable assignment with quotes Source: https://makefiletutorial.com/ Single and double quotes are treated as literal characters by Make and do not affect variable assignment. They are primarily for shell commands. ```makefile a := one two# a is set to the string "one two" b := 'one two' # Not recommended. b is set to the string "'one two'" all: printf '$a' printf $b ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.