Giter Site home page Giter Site logo

makefiletutorial's Introduction

Makefile Tutorial by Example

This is a single page website. It's built by metalsmith, and the generated files are in docs (picked because Github Pages only supports / and /docs as directories to serve from).

To run this locally:

  • yarn install (If this fails to build node-sass, I've had luck with node v12.10.0)
  • yarn dev

To deploy:

  • Make changes
  • yarn build (or yarn dev)
  • Commit changes
  • git push

makefiletutorial's People

Contributors

arve0 avatar castielwong avatar chinwendu20 avatar dtgriscom avatar gllera avatar iain-s avatar in0x avatar isidroas avatar jasper1378 avatar jxu avatar mattpopovich avatar musicpiano avatar nazar01 avatar saikuron avatar sdrzazga-nsd avatar shukryzablah avatar silopolis avatar theicfire avatar vipranarayan14 avatar williamholtam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

makefiletutorial's Issues

Cookbook string substitution

Hi, thank you very much for the tutorial,

I am trying to adapt the cookbook so that object files are put into a seperate obj directory.
The following section gives me trouble:

# Find all the C and C++ files we want to compile
# Note the single quotes around the * expressions. Make will incorrectly expand these otherwise.
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')

# String substitution for every C/C++ file.
# As an example, hello.cpp turns into ./build/hello.cpp.o
OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)

The example you give here for what the substitution does seems correct but given that SRCS is not of the format 'hello.cpp' but rather './src/hello.cpp' the output will be 'BUILD_DIR/./src/hello.cpp' and this of course applies to my attempts at having all object files in another directory as well.
Aside from this being (IMO) ugly it also, considering the mismatch between the example and what happens, seems rather unintended.

Specify Make Version

Great tutorial!

I suggest adding right at the beginning which major make version the tutorial targets — i.e. v3 or v4?

One of the most confusing aspects of make to me is that some projects rely on make v3.x, while others rely on v4.x, which introduces some syntax incompatibility issues — especially under Windows, where the official make for Windows from GNU is still v3, whereas the version bundled with MinGW is v4 (mingw32-make.exe).

Unfortunately. most make tutorials omit mentioning the version they are targeting.

By stating right at the beginning which make version the tutorial was written for could avoid confusion right away.

Also, it might be worth spending a few paragraphs on the differences between make v3 and v4 and the fact that they are both currently used by many projects — and maybe also mention they key aspects in which they differ and how to write Makefiles that would work with both version?

I still don't know what they key differences between these two major versions are, and their coexistence in everyday use has been an obstacle in learning Make, which is why I'd definitely appreciate a tutorial which explains the issue (couldn't easily find a dedicated article on this).

Error in multiple target eaxmple

I think there is an error in multiple-targets chapter(https://makefiletutorial.com/#multiple-targets), miss : after f1.o and f2.o, here is the screenshot:

image

should be:

# f1.o:
#	 echo $@
# f2.o:
#	 echo $@

and I think this will be more clear to show When there are multiple targets for a rule, the commands will be run for each target and the meaning of $@:

# f1.o:
#	 echo f1.o
# f2.o:
#	 echo f2.o

Beginner example still too complex

The beginner example is introduced with 3 rules. Following this dependency chain requires recursing two levels deep. I believe a simpler example would first introduce a trivial makefile with no dependency to get used to invoking compilation

blah:
    cc -o blah blah.c

and then maybe just two rules with one dependency, for example

blah: blah.o
	cc blah.o -o blah # Runs second

blah.o: blah.c
	cc -c blah.c -o blah.o # Runs first

where blah.c exists; the echo is confusing because blah.c source would normally exist already.

Also there should be a separator between examples since the article immediately jumps to a new example with "This makefile has a single target..."

Section 4.10

find some bugs:
all: $(obj_files) -> all: $(src_files)
touch %@ -> touch $@

Issue for The Wildcard Function (Section 4.2.3)

I got the opposite result, "wrong" can be printed while "objects" can't be printed.

zhuangyan@n25-146-090:~/coding/c/blah$ make --version
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

zhuangyan@n25-146-090:~/coding/c/blah$ cat Makefile
wrong = *.o # Wrong
objects := $(wildcard *.c) # Right
some_binary:
	touch f1.c
	touch f2.c
	echo $(objects)
	echo $(wrong)

clean:
	rm -f *.c

zhuangyan@n25-146-090:~/coding/c/blah$ make
touch f1.c
touch f2.c
echo

echo *.o
*.o

Static Pattern Rules and Filter --- errors: are they intentional

When trying this in a Makefile:

obj_files = foo.result bar.o lose.o
src_files = foo.raw bar.c lose.c

all: $(obj_files)

$(filter %.o,$(obj_files)): %.o: %.c
echo "target: $@ prereq: $&lt;"
$(filter %.result,$(obj_files)): %.result: %.raw
echo "target: $@ prereq: $&lt;"

%.c %.raw:
touch $@

clean:
rm -f $(src_files)`

I get the following output:

$ make
touch foo.raw
echo "target: foo.result prereq: foo.raw"
target: foo.result prereq: foo.raw
touch bar.c
echo "target: bar.o prereq: bar.c"
target: bar.o prereq: bar.c
touch lose.c
echo "target: lose.o prereq: lose.c"
target: lose.o prereq: lose.c
touch all.c
cc -c -o all.o all.c
cc all.o foo.result bar.o lose.o -o all
cc: error: foo.result: No such file or directory
cc: error: bar.o: No such file or directory
cc: error: lose.o: No such file or directory
make: *** [: all] Error 1
rm all.o all.c

Is this intended output?

Infinite redirects prevent access to site

I tried to visit the site today and encountered a redirect loop—https://makefiletutorial.com/ 301s to itself:

$ curl --HEAD 'https://makefiletutorial.com/'
HTTP/2 301
date: Fri, 22 Sep 2023 16:03:53 GMT
content-type: text/html
location: https://makefiletutorial.com/
x-github-request-id: 7628:2424:A71BCB:F7B4DE:650DADA1
accept-ranges: bytes
via: 1.1 varnish
age: 3400
x-served-by: cache-chi-klot8100057-CHI
x-cache: HIT
x-cache-hits: 1
x-timer: S1695398634.956117,VS0,VE1
vary: Accept-Encoding
x-fastly-request-id: 1d429a81f19b38b5e0684ec0315709a1cf0afc9c
cf-cache-status: DYNAMIC
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=%2FCopSq2xMM83HLSoN10nQdyRmcegqQXn1rzerlfWD5G58%2BvXaRoPuIR7z4CjkfdoPrsWyGTTk5zhMiBlNrBpK8AvqcC%2FXnXT9yJI4DOkeekAJdU2QUp%2FM4eLS1b%2FSwwRu2ba%2FUctjw%3D%3D"}],"group":"cf-nel","max_age":604800}
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
server: cloudflare
cf-ray: 80abc7d6281510d3-ORD
alt-svc: h3=":443"; ma=86400

(https://www.makefiletutorial.com/ redirects to the above, as do (ultimately) the two domains over plaintext HTTP, so none of those works either.)

The Wayback Machine had a successful capture on Sept. 9, so the breaking change must have been relatively recent.

Comment error in the cookbook.

Very great tutorial!
But I'd like to point out a small error in comments of the cookbook.
In line 8 and line 9, you said:

# Note the single quotes around the * expressions. Make will incorrectly expand these otherwise.
SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')

Of course you need the single quotes. However, without them, it is not Make which expands the wildcard *, and actually it is your shell.
In GNU make docs, 4.4 Using Wildcard Characters in File Names said:

Wildcard expansion is performed by make automatically in targets and in prerequisites. In recipes, the shell is responsible for wildcard expansion. In other contexts, wildcard expansion happens only if you request it explicitly with the wildcard function.

and 4.4.3 The Function wildcard said:

But wildcard expansion does not normally take place when a variable is set, or inside the arguments of a function.

As part of argument of function shell, GNU make will not expand *, which is passed to your shell literally.
So why is there single quotes necessary? The reasons are as follows.
Before shell invokes command find, it will execute filename expansion. I use bash for example here.
In GNU bash manual, 3.5.8 Filename Expansion said:

Bash scans each word for the characters ‘*’, ‘?’, and ‘[’. If one of these characters appears, and is not quoted, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of filenames matching the pattern (see Pattern Matching).

Then *.cpp will expand to c++ source files in current working directory, which is undesirable because command find would not get the asterisk. Therefore, you need single quotes to prevent shell from filename expansion.

Slightly confusing command in hello world example

Right now the hello world example includes echo "This line will always print, because the file hello does not exist." which is misleading because the file hello could exist.

I propose changing the second echo to echo "This line will print if the file hello does not exist". This is explained in the explanation below the code.

Point out that this is GNU make

Hello, first this site is an awesome tutorial.

However, it doesn't point out the fact that functions like wildcard are exclusive to GNU make and won't work on BSD make for example.

I suggest adding a note on the top that this assumes GNU make which might be available in your packages/ports as gmake and you should go for that instead if certain examples don't work.

Add small caveat about compilation for pedantic JavaScript developers

I would propose this addition (in bold):

Interpreted languages like Python, Ruby, and Javascript don't require an analogue to Makefiles. The goal of Makefiles is to compile whatever files need to be compiled, based on what files have changed. But when files in interpreted languages change, nothing needs to get recompiled. When the program runs, the most recent version of the file is used. (There are some exceptions, like transpiling Typescript files to Javascript)

Static Pattern Rules and Filter -- Errors and naive fix

Issue: part Static Pattern Rules and Filter example not works well, refer to issue 40.

Refer issue 40 and the issue was fixed by commmit b7e9438.

However, the code was reversed after the new design commitment.
May the code change to this below due to 54?

obj_files = foo.result bar.o lose.o
src_files = foo.raw bar.c lose.c

all: $(obj_files)

$(filter %.o,$(obj_files)): %.o: %.c
	cc -c $< -o $@
	echo "target: $@ prereq: $<"
$(filter %.result,$(obj_files)): %.result: %.raw
	cc -c $< -o $@
	echo "target: $@ prereq: $<" 

$(src_files):
	touch $@

clean:
	rm -f $(src_files) $(obj_files)

But unfortunately, the implicit rule failed to work in this example, and no X.result file is generated.

Mobile version of the site has no side margins

In the mobile (and technically the desktop) versions of the site, there is no inline margin. This makes it annoying to read as the text goes all the way to the edge of the page.

Here's an example from the developer tools:

image

This could be solved by adding a 1em or so inline margin on the main element. I feel this would improve the reading experience for mobile users.

Translations Of The Site

What do you think about translating the site to the other languages? Do you have plan or direction for this? I really want to contribute by translating the site into Turkish.

a typo error

Hi, In Website , Chapter Implicit Rules
in CPPFLAGS: Extra flags to give to the C preprosessor , I guess that you want to say preprocessor. :)
Thanks to your article, it helps me a lot!

A typo

Append should be Prepend
image

Add pointer to the referenced Makefile Cookbook

As a web search returns this project page as first result and no entry clearly identified as "Makefile Cookbook", it would be nice to add the link to it.

If you mostly understand Make, consider checking out the Makefile Cookbook, which has a template for medium sized projects with ample comments about what each part of the Makefile is doing.

Error in cookbook example

Website's very helpful, but I think there's an error in the cookbook example that should be fixed:

SRCS := $(shell find $(SRC_DIRS) -name *.cpp -or -name *.c)

*.cpp and *.c should be wrapped in single quotes, or GNU make will expand the wildcard expression before passing to find, which is unintended.

If you have a single .cpp file, you'll be running find ./src -name foobar.cpp, which will most likely only return that one file.
If you have multiple files with the .cpp extension, you'll be passing multiple files after -name to find, e.g. find ./src -name foo.cpp bar.cpp and it will throw an error like this:

find: paths must precede expression: `bar.cpp'
find: possible unquoted pattern after predicate `-name'?

If you go to the bottom of the comments where the example was pulled, you'll find someone who encountered this exact issue:
https://spin.atomicobject.com/2016/08/26/makefile-c-projects/

Request/Suggestion

Can you include an example of how to use of MAKEFILE_LIST?

From the book in your link:

3.5 The Variable MAKEFILE_LIST
As make reads various makefiles, including any obtained from the MAKEFILES variable, the com- mand line, the default files, or from include directives, their names will be automatically appended to the MAKEFILE_LIST variable. They are added right before make begins to parse them.
This means that if the first thing a makefile does is examine the last word in this variable, it will be the name of the current makefile. Once the current makefile has used include, however, the last word will be the just-included makefile.
If a makefile named Makefile has this content:

name1 := $(lastword $(MAKEFILE_LIST))
    include inc.mk
name2 := $(lastword $(MAKEFILE_LIST)) all:
    @echo name1 = $(name1) 
    @echo name2 = $(name2)

then you would expect to see this output:
name1 = Makefile name2 = inc.mk

What would you have to have in inc.mk for this example to run?

Thanks for sharing.

Prerequisite target for compiling % wildcard

In chapter https://makefiletutorial.com/#automatic-variables-and-wildcards I can not find an example how to require some other target before processing % pattern rule.

For example, I want to execute bootstrap rule before passing .in files to echo.

default: *.txt

bootstrap: boot.txt

# Define a pattern rule that compiles every .in file into a .txt file
%.txt: bootstrap %.in
        echo $^ $@

This executes the command passing "bootstrap" string to it, which I did not expect.

echo bootstrap xxx.in xxx.txt

Request pdf and epub output

Request pdf and epub output

Hello, thank you for your training. If possible, please insert the pdf and epub output. Unfortunately, the system browser cannot print properly from the site.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.