tests/misc: Add llext EDK test

This test uses pytest to generate an EDK from a simple Zephyr
application, and uses this EDK to build a simple extension, to ensure
that EDK generation is sane.

Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
This commit is contained in:
Ederson de Souza 2024-03-01 17:34:25 -08:00 committed by Fabio Baltieri
commit a0ee472a6f
10 changed files with 195 additions and 0 deletions

View file

@ -36,3 +36,12 @@ foreach(file_name include/stddef.h)
list(APPEND NOSTDINC ${_OUTPUT})
endforeach()
list(APPEND LLEXT_EDK_REMOVE_FLAGS
--sysroot=.*
-fmacro-prefix-map=.*
)
list(APPEND LLEXT_EDK_APPEND_FLAGS
-nodefaultlibs
)

View file

@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(llext_edk_test LANGUAGES C)
target_sources(app PRIVATE src/main.c)
zephyr_include_directories(include)
zephyr_include_directories($ENV{ZEPHYR_BASE}/boards/native/common)

View file

@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.20.0)
project(extension)
include($ENV{LLEXT_EDK_INSTALL_DIR}/cmake.cflags)
# Add LLEXT_CFLAGS to our flags
add_compile_options(${LLEXT_CFLAGS})
add_compile_options("-Werror")
add_compile_options("-c")
# Get flags from COMPILE_OPTIONS
get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS)
add_custom_command(
OUTPUT
${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext
COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP}
-o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext
${PROJECT_SOURCE_DIR}/src/main.c
)
add_custom_target(extension ALL DEPENDS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext)

View file

@ -0,0 +1,17 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <app_api.h>
int start(void)
{
int bar = 42;
printk("foo(%d) is %d\n", bar, foo(bar));
return 0;
}

View file

@ -0,0 +1,22 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _TEST_EDK_H_
#define _TEST_EDK_H_
#include <zephyr/kernel.h>
#ifdef __cplusplus
extern "C" {
#endif
__syscall int foo(int bar);
#ifdef __cplusplus
}
#endif
#include <syscalls/app_api.h>
#endif /* _TEST_EDK_H_ */

View file

@ -0,0 +1,3 @@
CONFIG_APPLICATION_DEFINED_SYSCALL=y
#CONFIG_USERSPACE=y
CONFIG_LLEXT=y

View file

@ -0,0 +1,66 @@
# Copyright (c) 2024 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import logging
import os
import shutil
import tempfile
from pathlib import Path
from subprocess import check_output
from twister_harness import DeviceAdapter
logger = logging.getLogger(__name__)
def test_edk(dut: DeviceAdapter):
# Can we build the edk?
command = [
"west",
"build",
"-t",
"llext-edk",
"--build-dir",
dut.device_config.build_dir,
]
output = check_output(command, text=True)
logger.info(output)
# Install the edk to a temporary location
with tempfile.TemporaryDirectory() as tempdir:
# Copy the edk to the temporary directory using python methods
logger.debug(f"Copying llext-edk.tar.xz to {tempdir}")
edk_path = Path(dut.device_config.build_dir) / "zephyr/llext-edk.tar.xz"
shutil.copy(edk_path, tempdir)
# Extract the edk using tar
logger.debug(f"Extracting llext-edk.tar.xz to {tempdir}")
command = ["tar", "-xf", "llext-edk.tar.xz"]
output = check_output(command, text=True, cwd=tempdir)
logger.info(output)
# Copy the extension to another temporary directory to test out of tree builds
with tempfile.TemporaryDirectory() as tempdir_extension:
logger.debug(f"Copying extension to {tempdir_extension}")
ext_dir = Path(os.environ["ZEPHYR_BASE"]) / "tests/misc/llext-edk/extension"
shutil.copytree(ext_dir, tempdir_extension, dirs_exist_ok=True)
# Set the LLEXT_EDK_INSTALL_DIR environment variable so that the extension
# knows where the EDK is installed
edk_dir = Path(tempdir) / "llext-edk"
env = os.environ.copy()
env.update({"LLEXT_EDK_INSTALL_DIR": edk_dir})
# Build the extension using the edk
logger.debug(f"Building extension in {tempdir_extension} - cmake")
command = ["cmake", "-B", "build"]
output = check_output(command, text=True, cwd=tempdir_extension, env=env)
logger.info(output)
logger.debug(f"Building extension in {tempdir_extension} - make")
command = ["make", "-C", "build"]
output = check_output(command, text=True, cwd=tempdir_extension, env=env)
logger.info(output)
# Check if the extension was built
assert os.path.exists(Path(tempdir_extension) / "build/extension.llext")

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <app_api.h>
#include <app_api.h>
int z_impl_foo(int bar)
{
return bar * bar;
}
EXPORT_SYMBOL(z_impl_foo);
#ifdef CONFIG_USERSPACE
static inline int z_vrfy_foo(int bar)
{
/* Nothing to verify */
return z_impl_foo(bar);
}
#include <syscalls/foo_mrsh.c>
#endif

View file

@ -0,0 +1,14 @@
/*
* Copyright (c) 2024 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <app_api.h>
#include <zephyr/llext/llext.h>
int main(void)
{
return 0;
}

View file

@ -0,0 +1,9 @@
tests:
misc.edk.pytest:
harness: pytest
tags:
- pytest
- edk
platform_allow:
- native_sim
toolchain_exclude: llvm