
From: Simon Glass <sjg@chromium.org> Add an example Makefile which shows how to build against U-Boot from outside the U-Boot source tree. Signed-off-by: Simon Glass <sjg@chromium.org> --- Makefile | 17 +++++++++ examples/ulib/Makefile | 73 +++++++++++++++++++++++++++++++++++++++ examples/ulib/README | 74 ++++++++++++++++++++++++++++++++++++++++ examples/ulib/demo.c | 61 +++++++++++++++++++++++++++++++++ examples/ulib/static.lds | 19 +++++++++++ 5 files changed, 244 insertions(+) create mode 100644 examples/ulib/Makefile create mode 100644 examples/ulib/README create mode 100644 examples/ulib/demo.c create mode 100644 examples/ulib/static.lds diff --git a/Makefile b/Makefile index 2e2f276eee6..8d082d1ae81 100644 --- a/Makefile +++ b/Makefile @@ -1048,6 +1048,9 @@ ifneq ($(cc-name),clang) ifeq ($(NO_LIBS),) INPUTS-$(CONFIG_ULIB) += libu-boot.so test/ulib/ulib_test INPUTS-$(CONFIG_ULIB) += libu-boot.a test/ulib/ulib_test_static +ifdef CONFIG_EXAMPLES +INPUTS-$(CONFIG_ULIB) += examples_ulib +endif endif endif endif @@ -1911,6 +1914,18 @@ test/ulib/ulib_test_static: test/ulib/ulib_test.o libu-boot.a \ $(LIB_STATIC_LDS) FORCE $(call if_changed,ulib_test_static) +PHONY += examples_ulib +examples_ulib: libu-boot.a libu-boot.so FORCE + $(Q)$(MAKE) -C $(srctree)/examples/ulib \ + UBOOT_BUILD=$(abspath $(obj)) \ + EXAMPLE_DIR=. \ + OUTDIR=$(abspath $(obj)/examples/ulib) \ + srctree="$(srctree)" \ + CC="$(CC)" \ + CFLAGS="$(CFLAGS)" \ + PLATFORM_LIBS="$(PLATFORM_LIBS)" \ + LIB_STATIC_LDS="$(LIB_STATIC_LDS)" + quiet_cmd_sym ?= SYM $@ cmd_sym ?= $(OBJDUMP) -t $< > $@ u-boot.sym: u-boot FORCE @@ -2339,6 +2354,8 @@ $(clean-dirs): clean: $(clean-dirs) $(call cmd,rmdirs) $(call cmd,rmfiles) + @$(MAKE) -C $(srctree)/examples/ulib clean \ + OUTDIR=$(abspath $(obj)/examples/ulib) @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ -o -name '*.ko.*' -o -name '*.su' -o -name '*.pyc' \ diff --git a/examples/ulib/Makefile b/examples/ulib/Makefile new file mode 100644 index 00000000000..da788e5792f --- /dev/null +++ b/examples/ulib/Makefile @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Standalone Makefile for U-Boot library examples +# +# Copyright 2025 Canonical +# Written by Simon Glass <simon.glass@canonical.com> + +# This Makefile can be used to build the examples. See doc/develop/ulib.rst +# +# Usage: cd examples/ulib; make UBOOT_BUILD=/tmp/b/sandbox/ srctree=../.. +# +# This Makefile is also called from the main U-Boot Makefile when CONFIG_ULIB +# and CONFIG_EXAMPLES are enabled. It receives these variables, many of which +# are needed to ensure that the output goes to the right place: +# +# UBOOT_BUILD - Build directory (e.g., /tmp/b/sandbox) +# EXAMPLE_DIR - Source tree path for these examples +# OUTDIR - Output directory for object files and executables +# srctree - U-Boot source tree +# +# Also these may be provided: +# CC - C compiler +# CFLAGS - C compiler flags +# SDL_CONFIG - Name of sdl2-config program +# 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 ?= + +DEMO_SRC := $(EXAMPLE_DIR)/demo.c +DEMO_BINS := $(OUTDIR)/demo $(OUTDIR)/demo_static + +# Default target builds both programs +all: $(DEMO_BINS) + @echo "Build complete: demo and demo_static in $(OUTDIR)" + +# Create the output directory if it doesn't exist +$(OUTDIR): + @mkdir -p $@ + +# The U-Boot library must be built before we can link against it. This is +# signalled by the presence of the $(UBOOT_BUILD)/examples/ulib directory. +# This is an order-only prerequisite, so it does not trigger a rebuild if the +# timestamp of the directory changes. +$(DEMO_BINS): | $(UBOOT_BUILD)/examples/ulib $(OUTDIR) + +# Build demo (dynamically linked with libu-boot.so) +$(OUTDIR)/demo: $(DEMO_SRC) + $(CC) $(CFLAGS) \ + -idirafter$(srctree)/include -o $@ $< \ + -L$(UBOOT_BUILD) -lu-boot \ + -Wl,-rpath,$(UBOOT_BUILD) + +# Build demo_static (statically linked with libu-boot.a) +$(OUTDIR)/demo_static: $(DEMO_SRC) + $(CC) $(CFLAGS) \ + -idirafter$(srctree)/include -o $@ $< \ + -Wl,-T,$(LIB_STATIC_LDS) \ + -Wl,--whole-archive $(UBOOT_BUILD)/libu-boot.a -Wl,--no-whole-archive \ + -lpthread -ldl $(PLATFORM_LIBS) -Wl,-z,noexecstack + +clean: + $(Q)rm -f $(DEMO_BINS) + +.PHONY: all clean diff --git a/examples/ulib/README b/examples/ulib/README new file mode 100644 index 00000000000..e6f48bf79cd --- /dev/null +++ b/examples/ulib/README @@ -0,0 +1,74 @@ +U-Boot Library Example +====================== + +This directory contains example programs showing how to use the U-Boot library +(libu-boot.so) in external C programs. + +Building U-Boot Library +----------------------- + +First, build U-Boot with library support: + + make O=/tmp/b/sandbox -j$(nproc) sandbox_defconfig all + +This creates: +- /tmp/b/sandbox/libu-boot.so (shared library) +- /tmp/b/sandbox/libu-boot.a (static library) + +Example Programs +---------------- + +The examples are built automatically as part of the U-Boot build. So far there +is only one. + +**demo.c** - Demonstrates using U-Boot library functions + +- Shows how to init the library with ulib_init() +- Uses U-Boot's OS functions (os_open(), os_fgets(), os_close()) +- Reads and displays system information +- Shows the U-Boot version + +Building Examples +----------------- + +The examples are built automatically when U-Boot has these options enabled:: + + CONFIG_ULIB=y + CONFIG_EXAMPLES=y + +To build manually: + + # From this directory examples/ulib + make UBOOT_BUILD=/tmp/b/sandbox/ srctree=../.. + +Running Examples +---------------- + + # Run the demo + LD_LIBRARY_PATH=/tmp/b/sandbox ./demo + + # Run the demo (static version) + ./demo_static + +Key Points +---------- + +- Avoid including U-Boot headers that conflict with system headers. This + Makefile gives priority to the system headers +- Use ulib_init() to init the library +- Use ulib_uninit() to clean up +- Set LD_LIBRARY_PATH when running dynamically linked programs + +Copying for External Use +------------------------- + +This directory can be copied elsewhere and used independently: + + cp -r examples/ulib ~/my-project/ + cd ~/my-project/ulib + make UBOOT_BUILD=/path/to/u-boot-build srctree=/path/to/u-boot-source + +License +------- + +All examples are licensed under GPL-2.0+ diff --git a/examples/ulib/demo.c b/examples/ulib/demo.c new file mode 100644 index 00000000000..4b12e91b17e --- /dev/null +++ b/examples/ulib/demo.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Demo program showing U-Boot library functionality + * + * This demonstrates using U-Boot library functions in sandbox like os_* + * from external programs. + * + * Copyright 2025 Canonical + * Written by Simon Glass <simon.glass@canonical.com> + */ + +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include <os.h> +#include <u-boot-lib.h> +#include <version_string.h> + +int main(int argc, char *argv[]) +{ + int fd, lines = 0; + char line[256]; + + /* Init U-Boot library */ + if (ulib_init(argv[0]) < 0) { + fprintf(stderr, "Failed to initialize U-Boot library\n"); + return 1; + } + + printf("1U-Boot Library Demo\n"); + printf("================================\n"); + printf("U-Boot version: %s\n", version_string); + printf("\n"); + + /* Use U-Boot's os_open to open a file */ + fd = os_open("/proc/version", 0); + if (fd < 0) { + fprintf(stderr, "Failed to open /proc/version\n"); + ulib_uninit(); + return 1; + } + + printf("System version:\n"); + + /* Use U-Boot's os_fgets to read lines */ + while (os_fgets(line, sizeof(line), fd)) { + printf(" %s", line); + lines++; + } + + os_close(fd); + + printf("\nRead %d line(s) using U-Boot library functions.\n", lines); + + /* Clean up */ + ulib_uninit(); + + return 0; +} diff --git a/examples/ulib/static.lds b/examples/ulib/static.lds new file mode 100644 index 00000000000..c400fba4f2b --- /dev/null +++ b/examples/ulib/static.lds @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Linker script for ulib_test_static binary + * + * This ensures proper alignment for linker-lists when linking with libu-boot.a + */ + +SECTIONS +{ + /* Ensure proper alignment for linker lists */ + . = ALIGN(32); + __u_boot_list : { + __u_boot_list_start = .; + KEEP(*(SORT(__u_boot_list*))); + __u_boot_list_end = .; + } +} + +INSERT AFTER .rodata; -- 2.43.0