ulib: Refactor the Makefile to support multiple programs

The current Makefile for the ulib examples is not very easy to modify.

Split it into three parts:
- config.mk containing the variables used by the build tools
- a list of programs and the objects in each one
- rules.mk with some rules to make it all work

Use sys-objs to indicate objects which should be built with system
headers. Use U-Boot headers by default.

With this it is fairly simply to add a new program. Of course we could
make use of U-Boot's kbuild implementation to tidy this up, but the
purpose of the examples is to show how to do things outside the U-Boot
build system.

Co-developed-by: Claude <noreply@anthropic.com>
Co-developed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-09-09 16:51:38 -06:00
parent cd20477293
commit 4ba77a661f
3 changed files with 97 additions and 61 deletions

View File

@@ -25,72 +25,22 @@
# PLATFORM_LIBS - Platform-specific libraries
# LIB_STATIC_LDS - Linker script for static library
# For standalone builds, provide default values
EXAMPLE_DIR ?= .
OUTDIR ?= .
CC ?= gcc
SDL_CONFIG ?= sdl2-config
PLATFORM_LIBS ?= $(shell $(SDL_CONFIG) --libs)
LIB_STATIC_LDS ?= static.lds
# The main Makefile passes in Q=@ for quiet output
Q ?=
# Include configuration and helper functions
include config.mk
# Common compiler flags for programs using system headers first
SYSTEM_CFLAGS := -I$(UBOOT_BUILD)/include -idirafter$(srctree)/include \
-include $(srctree)/include/linux/compiler_attributes.h
# Programs to build
progs := demo
# Common compiler flags for programs using U-Boot headers first (like U-Boot
# internal build)
UBOOT_CFLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include) \
-I$(UBOOT_BUILD)/include \
-I$(srctree)/include \
-I$(srctree)/arch/sandbox/include \
-include $(UBOOT_BUILD)/include/config.h \
-include $(srctree)/include/linux/kconfig.h \
-I$(srctree)/dts/upstream/include \
-D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0
# Program definitions - list of object files for each program
demo_objs := demo.o demo_helper.o
SHARED_LDFLAGS := -L$(UBOOT_BUILD) -lu-boot -Wl,-rpath,$(UBOOT_BUILD)
# Objects that need system headers (default is U-Boot headers)
sys-objs := demo_helper.o
STATIC_LDFLAGS := -Wl,-T,$(LIB_STATIC_LDS) \
-Wl,--whole-archive $(UBOOT_BUILD)/libu-boot.a -Wl,--no-whole-archive \
-lpthread -ldl $(PLATFORM_LIBS) -Wl,-z,noexecstack
# Program definitions - can be single file or multi-object
DEMO_SRC := $(EXAMPLE_DIR)/demo.c
demo-objs := demo.o demo_helper.o
DEMO_BINS := $(OUTDIR)/demo $(OUTDIR)/demo_static
ALL_BINS := $(DEMO_BINS)
# Default target builds both programs
all: $(ALL_BINS)
# Create the output directory if it doesn't exist
$(OUTDIR):
@mkdir -p $@
# Pattern rule for building object files with system headers first (default)
$(OUTDIR)/%.o: $(EXAMPLE_DIR)/%.c | $(OUTDIR)
$(CC) $(CFLAGS) $(SYSTEM_CFLAGS) -c -o $@ $<
# Pattern rule for building object files with U-Boot headers first
$(OUTDIR)/%_uboot.o: $(EXAMPLE_DIR)/%.c | $(OUTDIR)
$(CC) $(CFLAGS) $(UBOOT_CFLAGS) -c -o $@ $<
# The U-Boot library must be built before we can link against it
# Order-only prerequisites ensure libraries exist before linking
$(ALL_BINS): | $(UBOOT_BUILD)/libu-boot.a $(UBOOT_BUILD)/libu-boot.so $(OUTDIR)
# Build demo (dynamically linked with libu-boot.so)
$(OUTDIR)/demo: $(if $(demo-objs),$(addprefix $(OUTDIR)/,$(demo-objs)),$(DEMO_SRC))
$(if $(demo-objs),$(CC) $(CFLAGS) -o $@ $^ $(SHARED_LDFLAGS),$(CC) $(CFLAGS) $(SYSTEM_CFLAGS) -o $@ $< $(SHARED_LDFLAGS))
# Build demo_static (statically linked with libu-boot.a)
$(OUTDIR)/demo_static: $(if $(demo-objs),$(addprefix $(OUTDIR)/,$(demo-objs)),$(DEMO_SRC))
$(if $(demo-objs),$(CC) $(CFLAGS) -o $@ $^ $(STATIC_LDFLAGS),$(CC) $(CFLAGS) $(SYSTEM_CFLAGS) -o $@ $< $(STATIC_LDFLAGS))
# Include build rules (must come after variable definitions)
include rules.mk
clean:
$(Q)rm -f $(DEMO_BINS)
$(Q)rm -f $(all_bins) $(OUTDIR)/*.o
.PHONY: all clean

47
examples/ulib/config.mk Normal file
View File

@@ -0,0 +1,47 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Configuration and helpers for U-Boot library examples
#
# Copyright 2025 Canonical Ltd.
# Written by Simon Glass <simon.glass@canonical.com>
# For standalone builds, provide default values
EXAMPLE_DIR ?= .
OUTDIR ?= .
CC ?= gcc
SDL_CONFIG ?= sdl2-config
PLATFORM_LIBS ?= $(shell $(SDL_CONFIG) --libs)
LIB_STATIC_LDS ?= static.lds
# The main Makefile passes in Q=@ for quiet output
Q ?=
# Common compiler flags for programs using system headers
SYSTEM_CFLAGS := -I$(UBOOT_BUILD)/include \
-idirafter$(srctree)/include \
-include $(srctree)/include/linux/compiler_attributes.h
# Common compiler flags for programs using U-Boot headers (these match the
# U-Boot internal build)
UBOOT_CFLAGS := -nostdinc \
-isystem $(shell $(CC) -print-file-name=include) \
-I$(UBOOT_BUILD)/include \
-I$(srctree)/include \
-I$(srctree)/arch/sandbox/include \
-include $(UBOOT_BUILD)/include/config.h \
-include $(srctree)/include/linux/kconfig.h \
-I$(srctree)/dts/upstream/include \
"-DMBEDTLS_CONFIG_FILE=\"mbedtls_def_config.h\"" \
-I$(srctree)/lib/mbedtls \
-I$(srctree)/lib/mbedtls/port \
-I$(srctree)/lib/mbedtls/external/mbedtls \
-I$(srctree)/lib/mbedtls/external/mbedtls/include \
-Wno-builtin-declaration-mismatch \
-D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0
# Linking flags
SHARED_LDFLAGS := -L$(UBOOT_BUILD) -lu-boot -Wl,-rpath,$(UBOOT_BUILD)
STATIC_LDFLAGS := -Wl,-T,$(LIB_STATIC_LDS) \
-Wl,--whole-archive $(UBOOT_BUILD)/libu-boot.a \
-Wl,--no-whole-archive \
-lpthread -ldl $(PLATFORM_LIBS) -Wl,-z,noexecstack

39
examples/ulib/rules.mk Normal file
View File

@@ -0,0 +1,39 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Build rules for U-Boot library examples
#
# Copyright 2025 Canonical Ltd.
# Written by Simon Glass <simon.glass@canonical.com>
# Generate normal and statically linked binary names from progs variable
all_bins := $(foreach prog,$(progs),$(OUTDIR)/$(prog) \
$(OUTDIR)/$(prog)_static)
# Default target builds both programs
all: $(all_bins)
# System headers rule for objects that need system APIs
$(foreach obj,$(sys-objs),$(eval $(OUTDIR)/$(obj): \
$(EXAMPLE_DIR)/$(obj:.o=.c) | $(OUTDIR) ; \
$$(CC) $$(CFLAGS) $$(SYSTEM_CFLAGS) -c -o $$@ $$<))
# Automatic build rules for all programs
$(foreach prog,$(progs),$(eval $(OUTDIR)/$(prog): \
$$(addprefix $(OUTDIR)/,$$($(prog)_objs)) ; \
$$(CC) $$(CFLAGS) -o $$@ $$^ $$(SHARED_LDFLAGS)))
$(foreach prog,$(progs),$(eval $(OUTDIR)/$(prog)_static: \
$$(addprefix $(OUTDIR)/,$$($(prog)_objs)) ; \
$$(CC) $$(CFLAGS) -o $$@ $$^ $$(STATIC_LDFLAGS)))
# Create the output directory if it doesn't exist
$(OUTDIR):
@mkdir -p $@
# Default rule: compile with U-Boot headers
$(OUTDIR)/%.o: $(EXAMPLE_DIR)/%.c | $(OUTDIR)
$(CC) $(CFLAGS) $(UBOOT_CFLAGS) -c -o $@ $<
# The U-Boot library must be built before we can link against it
# Order-only prerequisites ensure libraries exist before linking
$(all_bins): | $(UBOOT_BUILD)/libu-boot.a $(UBOOT_BUILD)/libu-boot.so \
$(OUTDIR)