Files
u-boot/test/run
Simon Glass f457b31524 test/py: Add a test for ulib functionality
Provide a test that checks that ulib operates as expected.

Add a .gitignore file for the executables thus created

There is a strange interaction with PLATFORM_LIBS which can cause the
examples to fail to build via 'make qcheck':

- CI runs 'make qcheck'
- the main Makefile sets PLATFORM_LIBS
- test/run calls test.py
- at some point test_ulib_demos() starts, with PLATFORM_LIBS set
- the test calls 'make' on examples/ulib/Makefile
- PLATFORM_LIBS is left alone, since it already has a value
- lSDL ends up not being in the link line

Thank you to Claude for helping to debug this and figure out the
PLATFORM_LIBS interaction.

Series-to: concept
Series-cc: heinrich
Cover-letter:
ulib: Complete initial U-Boot library

This series completes support for building U-Boot as a shared or static
library, enabling reuse of U-Boot functionality in external programs and
test suites.

The U-Boot library (ulib) allows developers to:
- Link against U-Boot functionality without a full U-Boot image
- Use U-Boot's OS abstraction layer, drivers, and utility functions
- Build test programs that can exercise U-Boot code in isolation
- Create applications that benefit from U-Boot's hardware support

Key features:
- Builds both shared (libu-boot.so) and static (libu-boot.a) libraries
- Preserves U-Boot linker lists for proper driver/subsystem init
- Configurable symbol renaming to avoid conflicts with system libraries
- Generated API headers with renamed function declarations
- Documentation and working examples
- Currently only supports sandbox architecture

The series includes:
- More build-infrastructure and Makefile integration
- Python-based mechanism for symbol renaming and API generation
- Test programs demonstrating basic library usage
- A simple example program showing real-world usage patterns

Symbol renaming ensures that U-Boot functions don't conflict with system
libraries. For example, printf() remains the standard library function
while ub_printf() provides access to U-Boot's printf implementation.
This is handled automatically during the build process.

The library excludes main() to allow external programs to provide their own
entry points while still accessing U-Boot functionality through ulib_init()
and ulib_uninit().

For example:

    #include <u-boot-lib.h>
    #include <u-boot-api.h>

    int main(int argc, char *argv[])
    {
        if (ulib_init(argv[0]) < 0)
            return 1;

        ub_printf("Hello from U-Boot library!\n");

        ulib_uninit();

        return 0;
    }

License implications are documented - the GPL-2.0+ license applies to
any programs linked with the library, requiring source code distribution
for compliant usage.

Future work will look at expanding support to other architectures.
END

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <sjg@chromium.org>
2025-09-09 09:14:05 -06:00

132 lines
4.3 KiB
Bash
Executable File

#!/bin/bash
# Script to run all U-Boot tests that use sandbox.
# $1: tests to run (empty for all, 'quick' for quick ones only)
# Runs a test and checks the exit code to decide if it passed
# $1: Test name
# $2 onwards: command line to run
run_test() {
echo -n "$1: "
shift
"$@"
[ $? -ne 0 ] && failures=$((failures+1))
}
quiet=-q
# Clean up things the Makefile created
unset MAKE MAKEFLAGS MAKELEVEL MAKEOVERRIDES MAKE_TERMERR MAKE_TERMOUT
# Unset this since this script is generally run from 'make qcheck' et al, which
# targets are in no-dot-config-targets and thus dot-config is 0 and thus
# config.mk was not included in the main Makefile, thus PLATFORM_LIBS does not
# have the arch-specific settings (e.g. SDL libraries on sandbox). Better to
# leave it empty than have it be wrong. This particularly affects
# example/ulib/Makefile when called from 'make qcheck'
unset PLATFORM_LIBS
# Select test attributes
ut_mark_expr=test_ut
if [ "$1" = "quick" ]; then
mark_expr="not slow"
ut_mark_expr="test_ut and not slow"
skip=--skip-net-tests
fi
[ "$1" == "tools" ] && tools_only=y
if [ "$1" = "parallel" ]; then
if ! echo 'import xdist' | python3 2>/dev/null; then
echo "Please install python3-pytest-xdist - see doc/develop/py_testing.rst"
exit 1
fi
jobs="$(($(nproc) > 16 ? 16 : $(nproc)))"
para="-n${jobs} -q"
prompt="Building and..."
skip=--skip-net-tests
mark_expr="not slow and not bootstd and not spi_flash"
ut_mark_expr="test_ut and not slow and not bootstd and not spi_flash"
echo "Note: test log is garbled with parallel tests"
fi
failures=0
# Disable LTO as it messed up event_dump.py (fails to get some line numbers)
export NO_LTO=1
if [ -z "$tools_only" ]; then
# Run all tests that the standard sandbox build can support
echo "${prompt}"
run_test "sandbox" ./test/py/test.py --bd sandbox --build ${para} \
${quiet} -k "${mark_expr}"
# Run tests which require sandbox_spl
echo "${prompt}"
run_test "sandbox_spl" ./test/py/test.py --bd sandbox_spl \
--build ${para} ${quiet} \
-k 'test_ofplatdata or test_handoff or test_spl'
# Run the same tests with sandbox_noinst (i.e. without OF_PLATDATA_INST)
echo "${prompt}"
run_test "sandbox_noinst" ./test/py/test.py --bd sandbox_noinst \
--build ${para} ${quiet} \
-k 'test_ofplatdata or test_handoff or test_spl'
# Run tests which require sandbox_vpl
echo "${prompt}"
run_test "sandbox_vpl" ./test/py/test.py --bd sandbox_vpl \
--build ${para} ${quiet} \
-k 'vpl or test_spl'
# Run tests for the flat-device-tree version of sandbox. This is a special
# build which does not enable CONFIG_OF_LIVE for the live device tree, so we can
# check that functionality is the same. The standard sandbox build (above) uses
# CONFIG_OF_LIVE.
echo "${prompt}"
run_test "sandbox_flattree" ./test/py/test.py --bd sandbox_flattree \
--build ${para} ${quiet} \
-k "${ut_mark_expr}"
else
# Make sure sandbox_spl is built, as we need it from now on
./test/py/test.py --bd sandbox_spl --build -k none
fi
# Set up a path to dtc (device-tree compiler) and libfdt.py, a library it
# provides and which is built by the sandbox_spl config. Also set up the path
# to tools build by the build.
DTC_DIR=$(pwd)/build-sandbox_spl/scripts/dtc
export PYTHONPATH=${DTC_DIR}/pylibfdt
export DTC=${DTC_DIR}/dtc
TOOLS_DIR=$(pwd)/build-sandbox_spl/tools
# TOOLPATH may be defined to provide mkimage, cbfstool, etc.
export PATH=$PATH:${TOOLS_DIR}
run_test "binman" ./tools/binman/binman ${TOOLPATH} test
run_test "patman" ./tools/patman/patman test
run_test "u_boot_pylib" ./tools/u_boot_pylib/u_boot_pylib
run_test "buildman" ./tools/buildman/buildman -t ${skip}
run_test "fdt" ./tools/dtoc/test_fdt -t
run_test "dtoc" ./tools/dtoc/dtoc -t
run_test "hwids_to_dtsi" python3 ./test/scripts/test_hwids_to_dtsi.py
# This needs you to set up Python test coverage tools.
# To enable Python test coverage on Debian-type distributions (e.g. Ubuntu):
# $ sudo apt-get install python-pytest python-coverage
# Code-coverage tests cannot run in parallel, so skip them in that case
if [ -z "${para}" ]; then
run_test "binman code coverage" ./tools/binman/binman ${TOOLPATH} test -T
run_test "dtoc code coverage" ./tools/dtoc/dtoc -T
run_test "fdt code coverage" ./tools/dtoc/test_fdt -T
fi
if [ $failures == 0 ]; then
echo "Tests passed!"
else
echo "Tests FAILED"
exit 1
fi