Skip to content

Commit 0592f46

Browse files
committed
Make build system fully configurable
With the inclusion of kconfiglib [1], the build system is now fully configurable like "menuconfig" when building the Linux kernel. It allows users to select the desired backend, choose whether to build applications, and specify supported image loaders. This flexibility is also useful for developers to integrate additional backends such as Linux framebuffer and DRM device support. [1] https://pypi.org/project/kconfiglib/
1 parent 9ec45b4 commit 0592f46

File tree

19 files changed

+11240
-16
lines changed

19 files changed

+11240
-16
lines changed

.github/workflows/main.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ jobs:
4545
sudo apt install libsdl2-dev libjpeg-dev libpng-dev
4646
shell: bash
4747
- name: default build
48-
run: make
48+
run: |
49+
tools/kconfig/defconfig.py --kconfig configs/Kconfig configs/defconfig
50+
tools/kconfig/genconfig.py configs/Kconfig
51+
make
4952
5053
coding-style:
5154
needs: [detect-code-related-file-changes]

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ libbackend.a
99
.libbackend.a
1010
libapps.a
1111
.libapps.a
12+
.config
13+
.config.old
14+
config.h
15+
__pycache__
16+
*.pyc
1217

1318
# Tools
1419
tools/ttf/twin-ttf

Makefile

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1-
# FIXME: make these entries configurable
2-
CONFIG_BACKEND_SDL ?= y
3-
CONFIG_LOADER_JPEG ?= y
4-
CONFIG_LOADER_PNG ?= y
1+
-include .config
2+
3+
check_goal := $(strip $(MAKECMDGOALS))
4+
ifneq ($(check_goal), config)
5+
ifneq "$(CONFIG_CONFIGURED)" "y"
6+
$(error You must first run 'make config')
7+
endif
8+
endif
59

610
# Rules
711

812
target-y :=
913
target.o-y :=
1014
TARGET_LIBS :=
1115

12-
target.a-y = \
13-
libapps.a \
14-
libtwin.a
16+
target.a-y :=
17+
target.a-$(CONFIG_DEMO_APPLICATIONS) += libapps.a
18+
target.a-y += libtwin.a
1519

1620
# Core library
1721

@@ -68,17 +72,18 @@ endif
6872

6973
# Applications
7074

71-
libapps.a_files-y = \
72-
apps/calc.c \
73-
apps/spline.c \
74-
apps/clock.c \
75-
apps/line.c \
76-
apps/hello.c \
77-
apps/demo.c
75+
libapps.a_files-y := apps/dummy.c
76+
libapps.a_files-$(CONFIG_DEMO_MULTI) += apps/demo.c
77+
libapps.a_files-$(CONFIG_DEMO_HELLO) += apps/hello.c
78+
libapps.a_files-$(CONFIG_DEMO_CLOCK) += apps/clock.c
79+
libapps.a_files-$(CONFIG_DEMO_CALCULATOR) += apps/calc.c
80+
libapps.a_files-$(CONFIG_DEMO_LINE) += apps/line.c
81+
libapps.a_files-$(CONFIG_DEMO_SPLINE) += apps/spline.c
7882

7983
libapps.a_includes-y := include
8084

8185
# Graphical backends
86+
8287
BACKEND := none
8388

8489
ifeq ($(CONFIG_BACKEND_SDL), y)
@@ -88,13 +93,27 @@ libtwin.a_cflags-y += $(shell sdl2-config --cflags)
8893
TARGET_LIBS += $(shell sdl2-config --libs)
8994
endif
9095

91-
# Platform-specific executables
96+
# Standalone application
97+
98+
ifeq ($(CONFIG_DEMO_APPLICATIONS), y)
9299
target-y += demo-$(BACKEND)
93100
demo-$(BACKEND)_depends-y += $(target.a-y)
94101
demo-$(BACKEND)_files-y = apps/main.c
95102
demo-$(BACKEND)_includes-y := include
96103
demo-$(BACKEND)_ldflags-y := \
97104
$(target.a-y) \
98105
$(TARGET_LIBS)
106+
endif
107+
108+
CFLAGS += -include config.h
99109

110+
check_goal := $(strip $(MAKECMDGOALS))
111+
ifneq ($(check_goal), config)
100112
include mk/common.mk
113+
endif
114+
115+
# Menuconfig
116+
.PHONY: config
117+
config: configs/Kconfig
118+
@tools/kconfig/menuconfig.py $<
119+
@tools/kconfig/genconfig.py $<

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ have the [SDL2 library](https://www.libsdl.org/), [libjpeg](https://www.ijg.org/
6262
* macOS: `brew install sdl2 jpeg libpng`
6363
* Ubuntu Linux / Debian: `sudo apt install libsdl2-dev libjpeg-dev libpng-dev`
6464

65+
Configure via [Kconfiglib](https://pypi.org/project/kconfiglib/)
66+
```shell
67+
$ make config
68+
```
69+
6570
Build the library and demo program.
6671
```shell
6772
$ make

apps/dummy.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/* Placeholder */

apps/main.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Twin - A Tiny Window System
3+
* Copyright (c) 2024 National Cheng Kung University, Taiwan
34
* Copyright (c) 2004 Keith Packard <keithp@keithp.com>
45
* All rights reserved.
56
*/
@@ -33,6 +34,7 @@
3334
static twin_pixmap_t *load_background(twin_screen_t *screen,
3435
const char *filename)
3536
{
37+
#if defined(CONFIG_LOADER_PNG)
3638
twin_pixmap_t *raw_background = twin_png_to_pixmap(filename, TWIN_ARGB32);
3739
if (!raw_background) /* Fallback to a default pattern */
3840
return twin_make_pattern();
@@ -65,6 +67,9 @@ static twin_pixmap_t *load_background(twin_screen_t *screen,
6567
twin_pixmap_destroy(raw_background);
6668

6769
return scaled_background;
70+
#else
71+
return twin_make_pattern();
72+
#endif
6873
}
6974

7075
static twin_context_t *tx = NULL;
@@ -99,12 +104,24 @@ int main(void)
99104
twin_screen_set_background(
100105
tx->screen, load_background(tx->screen, ASSET_PATH "/tux.png"));
101106

107+
#if defined(CONFIG_DEMO_MULTI)
102108
apps_demo_start(tx->screen, "Demo", 100, 100, 400, 400);
109+
#endif
110+
#if defined(CONFIG_DEMO_HELLO)
103111
apps_hello_start(tx->screen, "Hello, World", 0, 0, 200, 200);
112+
#endif
113+
#if defined(CONFIG_DEMO_CLOCK)
104114
apps_clock_start(tx->screen, "Clock", 10, 10, 200, 200);
115+
#endif
116+
#if defined(CONFIG_DEMO_CALCULATOR)
105117
apps_calc_start(tx->screen, "Calculator", 100, 100, 200, 200);
118+
#endif
119+
#if defined(CONFIG_DEMO_LINE)
106120
apps_line_start(tx->screen, "Line", 0, 0, 200, 200);
121+
#endif
122+
#if defined(CONFIG_DEMO_SPLINE)
107123
apps_spline_start(tx->screen, "Spline", 20, 20, 400, 400);
124+
#endif
108125

109126
twin_dispatch();
110127

configs/Kconfig

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
mainmenu "Mado System Configuration"
2+
3+
config CONFIGURED
4+
bool
5+
default y
6+
7+
choice
8+
prompt "Backend Selection"
9+
default BACKEND_SDL
10+
11+
config BACKEND_FBDEV
12+
bool "Linux framebuffer support"
13+
14+
config BACKEND_SDL
15+
bool "SDL video output support"
16+
17+
endchoice
18+
19+
menu "Image Loaders"
20+
21+
config LOADER_PNG
22+
bool "Enable PNG loader"
23+
default y
24+
25+
config LOADER_JPEG
26+
bool "Enable JPEG loader"
27+
default y
28+
29+
endmenu
30+
31+
menu "Demo Applications"
32+
33+
config DEMO_APPLICATIONS
34+
bool "Build demo applications"
35+
default y
36+
37+
config DEMO_MULTI
38+
bool "Build multi demo"
39+
default y
40+
depends on DEMO_APPLICATIONS
41+
42+
config DEMO_HELLO
43+
bool "Build Hello world demo"
44+
default y
45+
depends on DEMO_APPLICATIONS
46+
47+
config DEMO_CLOCK
48+
bool "Build clock demo"
49+
default y
50+
depends on DEMO_APPLICATIONS
51+
52+
config DEMO_CALCULATOR
53+
bool "Build calculator demo"
54+
default y
55+
depends on DEMO_APPLICATIONS
56+
57+
config DEMO_LINE
58+
bool "Build line demo"
59+
default y
60+
depends on DEMO_APPLICATIONS
61+
62+
config DEMO_SPLINE
63+
bool "Build spline demp"
64+
default y
65+
depends on DEMO_APPLICATIONS
66+
67+
endmenu

configs/defconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
CONFIG_CONFIGURED=y
2+
# CONFIG_BACKEND_FBDEV is not set
3+
CONFIG_BACKEND_SDL=y
4+
5+
#
6+
# Image Loaders
7+
#
8+
CONFIG_LOADER_PNG=y
9+
CONFIG_LOADER_JPEG=y
10+
# end of Image Loaders
11+
12+
#
13+
# Demo Applications
14+
#
15+
CONFIG_DEMO_APPLICATIONS=y
16+
CONFIG_DEMO_MULTI=y
17+
CONFIG_DEMO_HELLO=y
18+
CONFIG_DEMO_CLOCK=y
19+
CONFIG_DEMO_CALCULATOR=y
20+
CONFIG_DEMO_LINE=y
21+
CONFIG_DEMO_SPLINE=y
22+
# end of Demo Applications

tools/kconfig/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*.py[co]
2+
build/
3+
*.egg-info/
4+
dist/

tools/kconfig/LICENSE

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2011-2019, Ulf Magnusson <ulfalizer@gmail.com>
2+
3+
Permission to use, copy, modify, and/or distribute this software for any purpose
4+
with or without fee is hereby granted, provided that the above copyright notice
5+
and this permission notice appear in all copies.
6+
7+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
9+
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
11+
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
12+
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
13+
THIS SOFTWARE.

tools/kconfig/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Kconfiglib
2+
3+
A flexible Python 2/3 Kconfig implementation and library.
4+
5+
Taken from https://github.com/ulfalizer/Kconfiglib

tools/kconfig/defconfig.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (c) 2019, Ulf Magnusson
4+
# SPDX-License-Identifier: ISC
5+
6+
"""
7+
Reads a specified configuration file, then writes a new configuration file.
8+
This can be used to initialize the configuration from e.g. an arch-specific
9+
configuration file. This input configuration file would usually be a minimal
10+
configuration file, as generated by e.g. savedefconfig.
11+
12+
The default output filename is '.config'. A different filename can be passed in
13+
the KCONFIG_CONFIG environment variable.
14+
"""
15+
import argparse
16+
17+
import kconfiglib
18+
19+
20+
def main():
21+
parser = argparse.ArgumentParser(
22+
formatter_class=argparse.RawDescriptionHelpFormatter,
23+
description=__doc__)
24+
25+
parser.add_argument(
26+
"--kconfig",
27+
default="Kconfig",
28+
help="Top-level Kconfig file (default: Kconfig)")
29+
30+
parser.add_argument(
31+
"config",
32+
metavar="CONFIGURATION",
33+
help="Input configuration file")
34+
35+
args = parser.parse_args()
36+
37+
kconf = kconfiglib.Kconfig(args.kconfig, suppress_traceback=True)
38+
print(kconf.load_config(args.config))
39+
print(kconf.write_config())
40+
41+
42+
if __name__ == "__main__":
43+
main()

0 commit comments

Comments
 (0)