|
|
(10 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
| Makefiles are automation built around shellscripts,<br> | | Makefiles are automation built around shellscripts,<br> |
| they are normally used to codify build instructions, but can be used for anything. | | they are normally used to manage compilation of C/C++ projects, but can be used for anything. |
|
| |
|
| = Documentation = | | = Documentation = |
Line 8: |
Line 8: |
| | Gnu Makefile conventions || https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html | | | Gnu Makefile conventions || https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html |
| |- | | |- |
| | Text Function Reference (ex: <code>($shell ..) $(patsubst ..)</code>)|| https://www.gnu.org/software/make/manual/html_node/Text-Functions.html | | | Text Function Reference<br>(ex: <code>($shell ..) $(patsubst ..)</code>)|| https://www.gnu.org/software/make/manual/html_node/Text-Functions.html |
| |- | | |- |
| | Automatic Variables (ex: <code>$@, $<</code>) || https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables | | | Automatic Variables (ex: <code>$@, $<</code>) || https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables |
Line 32: |
Line 32: |
| |- | | |- |
| | [[make basics]] | | | [[make basics]] |
| | |- |
| | | [[make syntax]] |
| | |- |
| | | [[make conventions]] |
| |- | | |- |
| | [[make examples]] | | | [[make examples]] |
Line 38: |
Line 42: |
| </blockquote><!-- Notes --> | | </blockquote><!-- Notes --> |
|
| |
|
| | | = Other = |
| = Usage = | |
| <blockquote>
| |
| <syntaxhighlight lang="bash">
| |
| make ## compile
| |
| make -d v ## additional debug information
| |
| make clean ## delete all .o files and program
| |
| | |
| </syntaxhighlight>
| |
| | |
| </blockquote><!-- Usage -->
| |
| | |
| = Core Concepts =
| |
| <blockquote>
| |
| At it's core, a makefile is responsible for doing 3x things:
| |
| * configuring compiler to use, and compiler-flags
| |
| * defining program to compile, and all the object-files it is dependent on
| |
| * defining each object-file, it's cpp/header files, and all other dependent header files
| |
| </blockquote><!-- core concepts -->
| |
| | |
| = Examples =
| |
| <blockquote>
| |
| The following examples all make reference to a sourcetree that looks like the following.
| |
| | |
| <source lang="bash">
| |
| src/
| |
| libhello.h
| |
| libhello.c
| |
| main.c # includes libhello.h
| |
| </source>
| |
| | |
| Each example below is a little cleaner than the last, but a little more abstract.
| |
| | |
| <br>
| |
| <br>
| |
| | |
| == ex 1: compile everything, every time ==
| |
| <blockquote>
| |
| <div class="toccolours mw-collapsible mw-collapsed">
| |
| This will get the job done, but will recompile every file every time. Not very efficient.
| |
| <div class="mw-collapsible-content">
| |
| <source lang="makefile">
| |
| # =============
| |
| # configuration
| |
| # =============
| |
| | |
| # compiler
| |
| CC = gcc # compiler
| |
| DEBUG = -g # compiler's debug flag (so can use gdb)
| |
| STD = c99 # the C-standard to compile with
| |
| CFLAGS = -Wall $(DEBUG) # compile-executable flags
| |
| LFLAGS = -Wall -c $(DEBUG) # compile-object (.o) flags
| |
| | |
| | |
| # =============
| |
| # build targets
| |
| # =============
| |
| | |
| # default/implied 'make' argument
| |
| #
| |
| # target: depends1 depends2 ...
| |
| bin/main:
| |
| test -d bin || mkdir bin
| |
| $(CC) -std=$(STD) $(CFLAGS) build/main.c build/libhello.c -o bin/main
| |
| | |
| clean:
| |
| test -d bin && rm -rf bin
| |
| </source>
| |
| </div>
| |
| </div>
| |
| | |
| </blockquote><!-- compile every time -->
| |
| | |
| == ex 2: Compile .o for each file, then combine ==
| |
| <blockquote>
| |
| <div class="toccolours mw-collapsible mw-collapsed">
| |
| This is much more efficent. Every file gets compiled to .o (only as-needed),
| |
| then those .o files are built into your final executable.
| |
| | |
| My chief complaint here is that this makefile is going to require an exceptional
| |
| amount of maintenance, defining every single .o file.
| |
| <div class="mw-collapsible-content">
| |
| <source lang="makefile">
| |
| # =============
| |
| # configuration
| |
| # =============
| |
| | |
| # compiler
| |
| CC = gcc # compiler
| |
| DEBUG = -g # compiler's debug flag (so can use gdb)
| |
| STD = c99 # the C-standard to compile with
| |
| CFLAGS = -Wall $(DEBUG) # compile-executable flags
| |
| LFLAGS = -Wall -c $(DEBUG) # compile-object (.o) flags
| |
| | |
| | |
| # =============
| |
| # build targets
| |
| # =============
| |
| | |
| # default/implied 'make' argument
| |
| #
| |
| # target: depends1 depends2 ...
| |
| bin/main: build/main.o build/libhello.o
| |
| test -d bin || mkdir bin
| |
| $(CC) -std=$(STD) $(CFLAGS) build/main.o build/libhello.o -o bin/main
| |
| | |
| # other possible 'make' arguments
| |
| # ex: make clean
| |
| # ex: make build/main.o
| |
| build/main.o:
| |
| test -d build || mkdir build
| |
| $(CC) -std=$(STD) $(LFLAGS) src/main.c -o $@
| |
| | |
| build/libhello.o:
| |
| test -d build || mkdir build
| |
| $(CC) -std=$(STD) $(LFLAGS) src/libhello.c -o $@
| |
| | |
| clean:
| |
| test -d build && rm -rf build
| |
| test -d bin && rm -rf bin
| |
| | |
| | |
| </source>
| |
| </div>
| |
| </div>
| |
| | |
| | |
| </blockquote><!-- .o file intermediary -->
| |
| | |
| == ex 3: low-maintenance makefile ==
| |
| <blockquote>
| |
| | |
| <div class="toccolours mw-collapsible mw-collapsed">
| |
| This produces exactly the same result as the 2nd-example, but it performs
| |
| additional automation within the makefile.
| |
| | |
| * sourcfiles are found automatically
| |
| * .o file definitions and dependencies are produced automatically
| |
| <div class="mw-collapsible-content">
| |
| <source lang="makefile">
| |
| # =============
| |
| # configuration
| |
| # =============
| |
| | |
| # compiler
| |
| CC = gcc # compiler
| |
| DEBUG = -g # compiler's debug flag (so can use gdb)
| |
| STD = c99 # the C-standard to compile with
| |
| CFLAGS = -Wall $(DEBUG) # compile-executable flags
| |
| LFLAGS = -Wall -c $(DEBUG) # compile-object (.o) flags
| |
| | |
| # targets
| |
| SRCS = $(shell find src/ -type f -name '*.c')
| |
| OBJS = $(patsubst src/%,build/%,$(SRCS:.c=.o))
| |
| | |
| | |
| # =============
| |
| # build targets
| |
| # =============
| |
| | |
| # default/implied 'make' argument
| |
| #
| |
| # target: depends1 depends2 ...
| |
| bin/main: $(OBJS)
| |
| test -d bin || mkdir bin
| |
| @echo $(OBJS)
| |
| $(CC) -std=$(STD) $(CFLAGS) $(OBJS) -o bin/main ## IMPORTANT: if this is cpp, before $(OBJS) you must include the target's .cpp file
| |
| | |
| # .o-target for each .c-file
| |
| build/%.o: src/%.c
| |
| test -d build || mkdir build
| |
| $(CC) -std=$(STD) $(LFLAGS) -o $@ $<
| |
| | |
| # other 'make' arguments
| |
| clean:
| |
| test -d build && rm -rf build
| |
| test -d bin && rm -rf bin
| |
| </source>
| |
| | |
| * <code>$@</code> is the file being generated
| |
| * <code>$<</code> name of first prerequisite
| |
| | |
| See https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables
| |
| </div>
| |
| </div>
| |
| | |
| </blockquote><!-- low maintenance makefile -->
| |
| | |
| </blockquote><!-- Examples -->
| |
| | |
| = makefile =
| |
| <blockquote> | | <blockquote> |
| == Compiler ==
| | {{ TODO | |
| <blockquote>
| | expand in the ''syntax'' section, and remove from here |
| The makefile itself seems quite flexible with how you use it,
| | }} |
| but there seems to be an agreed-upon standard for what variables
| |
| refer to what. Here are some of the more common variables:
| |
|
| |
|
| <syntaxhighlight lang="bash">
| |
| PROG= ## name of output executable
| |
| OBJS= ## name of all *.o files to be included (?)
| |
|
| |
| CC= ## compiler name
| |
| DEBUG= ## compiler flags for debug-mode (allow use of gdb)
| |
| CFLAGS= ## compiler flags for *.o object-file compilation
| |
| LFLAGS= ## compiler flags to determine libraries (?)
| |
| </syntaxhighlight>
| |
| </blockquote><!-- compiler config -->
| |
|
| |
| == files/dependencies ==
| |
| <blockquote>
| |
| The majority of your makefile defines files to be compiled,
| |
| and their dependencies. You can define as many executables or *.o
| |
| as you like, but by default only the first program (and all
| |
| *.o files it is dependent on) are compiled.
| |
|
| |
| <syntaxhighlight lang="bash">
| |
| Movie.o: Movie.cpp Movie.h OtherModule.h
| |
| g++ -Wall -c Movie.cpp
| |
|
| |
| </syntaxhighlight>
| |
|
| |
| </blockquote><!-- files/dependencies -->
| |
| </blockquote><!-- makefile -->
| |
|
| |
| = Other =
| |
| <blockquote>
| |
| == make builtins == | | == make builtins == |
| <blockquote> | | <blockquote> |
Line 311: |
Line 94: |
| </blockquote><!-- echo variable --> | | </blockquote><!-- echo variable --> |
| </blockquote><!-- Other --> | | </blockquote><!-- Other --> |
|
| |
| = Sources =
| |
| <blockquote>
| |
| {|
| |
| | http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html
| |
| |-
| |
| | http://mrbook.org/blog/tutorials/make/
| |
| |}
| |
|
| |
| </blockquote><!-- sources -->
| |