ulib: Provide an example of how to build with ulib

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>
This commit is contained in:
Simon Glass
2025-09-04 13:55:33 -06:00
parent 06b55de903
commit f2c378f0f9
5 changed files with 244 additions and 0 deletions

View File

@@ -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,19 @@ test/ulib/ulib_test_static: test/ulib/ulib_test.o libu-boot.a \
$(LIB_STATIC_LDS) FORCE
$(call if_changed,ulib_test_static)
# abspath is used since many paths are relative
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="$(abspath $(srctree))" \
CC="$(CC)" \
CFLAGS="$(CFLAGS)" \
PLATFORM_LIBS="$(PLATFORM_LIBS)" \
LIB_STATIC_LDS="$(abspath $(LIB_STATIC_LDS))"
quiet_cmd_sym ?= SYM $@
cmd_sym ?= $(OBJDUMP) -t $< > $@
u-boot.sym: u-boot FORCE
@@ -2339,6 +2355,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' \

72
examples/ulib/Makefile Normal file
View File

@@ -0,0 +1,72 @@
# 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)
# 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

74
examples/ulib/README Normal file
View File

@@ -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+

61
examples/ulib/demo.c Normal file
View File

@@ -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;
}

19
examples/ulib/static.lds Normal file
View File

@@ -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;