1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
|
---
title: WTF is Linux
author: Rémi Nicole <remi.nicole@smile.fr>
date: 2020-10-13
slide-level: 2
aspectratio: 169
theme: metropolis
colortheme: owl
beameroption: "show notes on second screen=right"
toc: true
highlightstyle: breezedark
lang: en-US
bibliography: ../bibliography.bib
---
# Makefile primer
## Goal
Make is a tool to create files
::: notes
A Makefile is a file that will direct Make on how to create these files
:::
## Concepts---Rules[^rule-intro]
Target
: Usually the name of a file/directory that this rule creates
Prerequisites
: The files/directories that are needed to produce the target
Recipe
: The commands to execute in order to create the target
```make
my_executable: source_1.c source_2.c
gcc source_1.c source_2.c -o my_executable
```
[^rule-intro]: <https://www.gnu.org/software/make/manual/make.html#Rules>
::: notes
- The target can also be an action, but it is rarer
- If one of the prerequisite changes, Make figures out that the target needs to
be created again
:::
## Concepts---Variables[^variables]
Very similar to shell variables, but use `$(VAR)` to expand it.
```make
MY_SOURCES = source_1.c source_2.c
my_executable: $(MY_SOURCES)
gcc $(MY_SOURCES) -o my_executable
```
[^variables]: <https://www.gnu.org/software/make/manual/make.html#Using-Variables>
## Concepts---Implicit Variables[^implicit-variables]
Some variables are set implicitly by Make, for example:
`$(CC)`{.no_minted}
: The C compiler
`$(CXX)`{.no_minted} / `$(CPP)`{.no_minted}
: The C++ compiler
`$(RM)`{.no_minted}
: The `rm -f` command
`$(MAKE)`{.no_minted}
: The `make` command
[^implicit-variables]: <https://www.gnu.org/software/make/manual/make.html#Implicit-Variables>
::: notes
Yes, you can call "make" inside of a Makefile
:::
## Concepts--Automatic Variables[^automatic-variables]
Some variables are set automatically per-rule, for example:
`$@`{.no_minted}
: The target of the current rule
`$<`{.no_minted}
: The first prerequisite of the current rule
`$^`{.no_minted}
: All prerequisites of the current rule
...
[^automatic-variables]: <https://www.gnu.org/software/make/manual/make.html#Automatic-Variables>
## Our example redone
```make
MY_SOURCES = source_1.c source_2.c
my_executable: $(MY_SOURCES)
$(CC) $^ -o $@
```
## Relation with Buildroot
Buildroot uses Makefiles to:
- Figure out which packages to (re-)compile
- How to compile them
- Create the outputs (images, root filesystem, etc.) in general.
But it is heavily abstracted
# Setting up Buildroot for our modifications
## For additional packages
- We create the directory `package/<company>`
- We put our additional packages in it
- We create the `my_company.mk` and `Config.in` files[^adding-project-specific-packages]
- And include the new `Config.in` in `package/Config.in`
[^adding-project-specific-packages]:
<https://buildroot.org/downloads/manual/manual.html#customize-packages>
## Packages Makefile
```makefile
include $(sort $(wildcard package/my_company/*/*.mk))
```
## Packages configuration file
In `package/my_company/Config.in`:
```kconfig
source "package/my_company/my_package1/Config.in"
source "package/my_company/my_package2/Config.in"
source "package/my_company/.../Config.in"
# ...
```
## Packages configuration file inclusion
In `package/Config.in`:
```kconfig
# ---8<--- Rest of the configuration
# We add our own packages in our own submenu
menu "My Company packages"
# We just created this file
source "package/my_company/Config.in"
endmenu
endmenu # <-- Was here before, it's the "Target packages" submenu
```
## For everything else
- We create the directory `board/<company>/<board>`
- We put our additional files, patches, configurations, scripts, etc. in it
::: notes
In our case, the board would be `raspberrypi2`.
:::
# Adding single files
## Overlays
A file hierarchy from the root directory that is going to get copied on top of
the built system
Can be used for:
- Startup scripts
- Program configuration files
- Files containing data (like sound)
::: notes
However, if a startup script, configuration file, or data file is tied to
a given package, it is usually better to install it with the package, instead
of using an overlay.
Overlays are more meant for files that are not tied to any specific package.
:::
## How to add an overlay
- Create the directory `board/<company>/<board>/rootfs_overlay`
- Add your file in that directory, as if it were the root directory
- Configure Buildroot (`make menuconfig`) and set
`BR2_ROOTFS_OVERLAY`[^overlay-config] to
`board/<company>/<board>/rootfs-overlay`.
[^overlay-config]:
Under "System configuration", "Root filesystem overlay directories"
# Adding packages
## Packages---Structure
- Create the directory `package/<company>/<my-package>/`
- Create the file `package/<company>/<my-package>/Config.in`[^config-files]
- Create the file `package/<company>/<my-package>/<my-package>.mk`[^mk-files]
[^config-files]: <https://buildroot.org/downloads/manual/manual.html#_config_files>
[^mk-files]: <https://buildroot.org/downloads/manual/manual.html#_the_literal_mk_literal_file>
<!-- _____ -->
::: notes
- The `Config.in` will allow Buildroot to add an option to install your
package. This will also specify your dependencies (what is needed to build or
run your package).
- The `<my-package>.mk` is a Makefile which instructs how to compile and
install your package.
:::
## Packages---Configuration
Example configuration:
```kconfig
config BR2_PACKAGE_DUMMY_PACKAGE
bool "dummy package"
default n
depends on BR2_PACKAGE_BUSYBOX || BR2_PACKAGE_BASH
help
A dummy package for demonstration purposes
```
## Packages---Makefile
Example Makefile configuration:
```makefile
define DUMMY_PACKAGE_INSTALL_TARGET_CMDS
$(INSTALL) -m 0755 -D \
$(DUMMY_PACKAGE_PKGDIR)/dummy_script.sh \
$(TARGET_DIR)/usr/bin
endef
$(eval $(generic-package))
```
::: notes
- This "package" just installs a script that is in the same directory of the
`.mk` file
- It is important that all variables
:::
## Packages---More generic Makefile{.allowframebreaks}
```makefile
LIBFOO_VERSION = 1.0
LIBFOO_SOURCE = libfoo-$(LIBFOO_VERSION).tar.gz
LIBFOO_SITE = http://www.foosoftware.org/download
LIBFOO_LICENSE = GPL-3.0+
LIBFOO_CONFIG_SCRIPTS = libfoo-config
LIBFOO_DEPENDENCIES = host-libaaa libbbb
# ---8<---
```
\framebreak
If your package uses Makefiles to be built:
```makefile
# ---8<---
define LIBFOO_BUILD_CMDS
$(MAKE) $(TARGET_CONFIGURE_OPTS) -C $(@D) all
endef
# ---8<---
```
`$(@D)`{.makefile} is the directory containing the downloaded sources.
\framebreak
```makefile
define LIBFOO_INSTALL_TARGET_CMDS
$(MAKE) \
$(TARGET_CONFIGURE_OPTS) PREFIX=$(TARGET_DIR)/usr \
-C $(@D) \
install
# Or...
$(INSTALL) -D -m 0755 $(@D)/libfoo.so* $(TARGET_DIR)/usr/lib
$(INSTALL) -d -m 0755 $(TARGET_DIR)/etc/foo.d
endef
$(eval $(generic-packages))
```
::: notes
- In this instances, our package is called "libfoo"
- `TARGET_CONFIGURE_OPTS` sets options like the compiler to use, the
compilation flags and other things
:::
## Packages---Notes
- This was for a "generic package"
- For package using common build frameworks (e.g. python, autotools, cmake,
etc.), some things are already done for you[^mk-files]
- Don't forget to include the package's `Config.in` in
`package/my_company/Config.in`
# Adding a service
## Buildroot's Busybox init
Every script or executable that is named like `/etc/init.d/S<something>` is
going to be started on boot
Two solutions then:
- Add a script to the overlay (if not tied to one of your own package)
- Install it with your package in the `<PACKAGE>_INSTALL_TARGET_CMDS`
# Adding users
## Using the board directory
- Create the file `board/<company>/<board>/users.txt`[^adding-users]
- Fill it with lines using the "makeusers" syntax[^makeusers-syntax]
- Set `BR2_ROOTFS_USERS_TABLES`[^users-conf] to `board/<company>/<board>/users.tx`
[^adding-users]: <https://buildroot.org/downloads/manual/manual.html#customize-users>
[^makeusers-syntax]: <https://buildroot.org/downloads/manual/manual.html#makeuser-syntax>
[^users-conf]: Under "System Configuration", "Path to the users tables"
## Using the board directory---Example
```kconfig
# ,---------------------- name
# | ,------------- group
# | | ,------ password
# | | |
# vvv vvvvvv v
foo -1 libfoo -1 * - - - LibFoo daemon
# ^^ ^^ ^^^^^^^^^^^^^
# | | |
# | | '--- comment
# | '------------------- GID
# '----------------------------- UID
```
::: notes
- If UID or GID is "-1", buildroot will select an unused number
- If password is "\*", then there is no password you cannot login as this user
(but you can still execute programs as this user)
:::
## In a package
Inside the `.mk` file.
```makefile
define LIBFOO_USERS
foo -1 libfoo -1 * - - - LibFoo daemon
endef
```
# Saving the configuration
## Why it is important
- Right now, every modification to the configuration (added packages, overlay,
etc.) is only in the build directory
- We want to save it so that people cloning our modified Buildroot can have the
same configuration
- Please often verify that your modifications are saved by deleting your
`output` directory, or downloading and compiling or project again.
::: notes
- This is necessary for me (the reviewer) since I want to build exactly what you
have.
:::
## How to save the Buildroot configuration
Once you have done your configuration of Buildroot (`make menuconfig`), execute
these commands:
- Make sure the `BR2_DEFCONFIG` option[^defconfig-option] is set to
`configs/<my_company_board>_defconfig`
- Execute `make savedefconfig` to save it
And commit your changes
[^defconfig-option]: Under "Build options", "Location to save buildroot config"
# References
|