From 2df986746b4010a24def7369f356b50e52bda50d Mon Sep 17 00:00:00 2001 From: Adrian Freihofer Date: Thu, 7 Dec 2023 21:52:49 +0100 Subject: oe-selftest: add a cpp-example recipe This simple C++ project supports compilation with CMake and Meson. (Autotool support could be added later on.) It's supposed to be used with oe-selftest. An artificial project has several advantages over compiling a normal CMake or Meson based project for testing purposes: - It is much faster because it can be kept minimalistic - It can cover multiple odd corner cases - No one will change it in an unpredictable way - It can support multiple build tools with only one C++ codebase (From OE-Core rev: 4904e772470b0d6e5d98ef0344b3f2bf54214661) Signed-off-by: Adrian Freihofer Signed-off-by: Alexandre Belloni Signed-off-by: Richard Purdie --- meta-selftest/recipes-test/cpp/.gitignore | 1 + meta-selftest/recipes-test/cpp/cmake-example.bb | 25 +++++++++ .../recipes-test/cpp/cmake-example/run-ptest | 10 ++++ meta-selftest/recipes-test/cpp/cpp-example.inc | 24 +++++++++ .../recipes-test/cpp/files/CMakeLists.txt | 61 ++++++++++++++++++++++ .../recipes-test/cpp/files/cpp-example-lib.cpp | 33 ++++++++++++ .../recipes-test/cpp/files/cpp-example-lib.hpp | 21 ++++++++ .../recipes-test/cpp/files/cpp-example.cpp | 18 +++++++ meta-selftest/recipes-test/cpp/files/meson.build | 38 ++++++++++++++ meta-selftest/recipes-test/cpp/files/meson.options | 3 ++ .../recipes-test/cpp/files/test-cpp-example.cpp | 25 +++++++++ meta-selftest/recipes-test/cpp/meson-example.bb | 27 ++++++++++ .../recipes-test/cpp/meson-example/run-ptest | 10 ++++ 13 files changed, 296 insertions(+) create mode 100644 meta-selftest/recipes-test/cpp/.gitignore create mode 100644 meta-selftest/recipes-test/cpp/cmake-example.bb create mode 100644 meta-selftest/recipes-test/cpp/cmake-example/run-ptest create mode 100644 meta-selftest/recipes-test/cpp/cpp-example.inc create mode 100644 meta-selftest/recipes-test/cpp/files/CMakeLists.txt create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp create mode 100644 meta-selftest/recipes-test/cpp/files/cpp-example.cpp create mode 100644 meta-selftest/recipes-test/cpp/files/meson.build create mode 100644 meta-selftest/recipes-test/cpp/files/meson.options create mode 100644 meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp create mode 100644 meta-selftest/recipes-test/cpp/meson-example.bb create mode 100644 meta-selftest/recipes-test/cpp/meson-example/run-ptest diff --git a/meta-selftest/recipes-test/cpp/.gitignore b/meta-selftest/recipes-test/cpp/.gitignore new file mode 100644 index 0000000000..30d388a12b --- /dev/null +++ b/meta-selftest/recipes-test/cpp/.gitignore @@ -0,0 +1 @@ +build* \ No newline at end of file diff --git a/meta-selftest/recipes-test/cpp/cmake-example.bb b/meta-selftest/recipes-test/cpp/cmake-example.bb new file mode 100644 index 0000000000..aecfcf780a --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cmake-example.bb @@ -0,0 +1,25 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +SUMMARY = "A C++ example compiled with cmake." + +require cpp-example.inc + +SRC_URI += "file://CMakeLists.txt" + +inherit cmake-qemu + +PACKAGECONFIG[failing_test] = "-DFAILING_TEST=ON" + +FILES:${PN}-ptest += "${bindir}/test-cmake-example" + +do_run_tests () { + bbnote ${DESTDIR:+DESTDIR=${DESTDIR} }${CMAKE_VERBOSE} cmake --build '${B}' --target test -- ${EXTRA_OECMAKE_BUILD} + eval ${DESTDIR:+DESTDIR=${DESTDIR} }${CMAKE_VERBOSE} cmake --build '${B}' --target test -- ${EXTRA_OECMAKE_BUILD} +} +do_run_tests[doc] = "Run cmake --target=test using qemu-user" + +addtask do_run_tests after do_compile diff --git a/meta-selftest/recipes-test/cpp/cmake-example/run-ptest b/meta-selftest/recipes-test/cpp/cmake-example/run-ptest new file mode 100644 index 0000000000..94b620a198 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cmake-example/run-ptest @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +test-cmake-example + +# Note: run-ptests exits with exit value from test-cmake-example diff --git a/meta-selftest/recipes-test/cpp/cpp-example.inc b/meta-selftest/recipes-test/cpp/cpp-example.inc new file mode 100644 index 0000000000..ad374be9d0 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/cpp-example.inc @@ -0,0 +1,24 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +DEPENDS += "json-c" + +PV = "1.0" + +SRC_URI = "\ + file://cpp-example.cpp \ + file://cpp-example-lib.hpp \ + file://cpp-example-lib.cpp \ + file://test-cpp-example.cpp \ + file://run-ptest \ +" + +S = "${WORKDIR}" + +inherit ptest diff --git a/meta-selftest/recipes-test/cpp/files/CMakeLists.txt b/meta-selftest/recipes-test/cpp/files/CMakeLists.txt new file mode 100644 index 0000000000..6fa6917d89 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/CMakeLists.txt @@ -0,0 +1,61 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +cmake_minimum_required(VERSION 3.22) + +project(cmake-example + VERSION 1.0.0 + LANGUAGES CXX +) + +option(BUILD_SHARED_LIBS "Build using shared libraries" ON) +option(FAILING_TEST "Compile a failing unit test to test the test infrastructure" OFF) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED On) +set(CMAKE_CXX_EXTENSIONS Off) + +include(GNUInstallDirs) + +# Linking a small library makes the example more useful for testing. +find_package(json-c) + +# A simple library linking json-c library found by pkgconfig +add_library(cmake-example-lib cpp-example-lib.cpp cpp-example-lib.hpp) +set_target_properties(cmake-example-lib PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) +target_link_libraries(cmake-example-lib PRIVATE json-c::json-c) + +install(TARGETS cmake-example-lib + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +# A simple executable linking the library +add_executable(cmake-example cpp-example.cpp) +target_link_libraries(cmake-example PRIVATE cmake-example-lib) + +install(TARGETS cmake-example + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +# A simple test executable for testing the library +add_executable(test-cmake-example test-cpp-example.cpp) +target_link_libraries(test-cmake-example PRIVATE cmake-example-lib) + +if (FAILING_TEST) + target_compile_definitions(test-cmake-example PRIVATE FAIL_COMPARISON_STR="foo") +endif(FAILING_TEST) + +install(TARGETS test-cmake-example + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +include(CTest) +add_test(NAME test-cmake-example COMMAND test-cmake-example) diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp new file mode 100644 index 0000000000..d3dc976864 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.cpp @@ -0,0 +1,33 @@ +/* + * Copyright OpenEmbedded Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include "cpp-example-lib.hpp" + +const std::string &CppExample::get_string() +{ + return test_string; +} + +const char *CppExample::get_json_c_version() +{ + return json_c_version(); +} + +void CppExample::print_json() +{ + struct json_object *jobj; + const int flag = JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY; + + jobj = json_object_new_object(); + json_object_object_add(jobj, "test_string", json_object_new_string(test_string.c_str())); + + std::cout << json_object_to_json_string_ext(jobj, flag) << std::endl; + + json_object_put(jobj); // Delete the json object +} diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp new file mode 100644 index 0000000000..0ad9e7b7b2 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example-lib.hpp @@ -0,0 +1,21 @@ +/* + * Copyright OpenEmbedded Contributors + * + * SPDX-License-Identifier: MIT + */ + +#pragma once + +#include + +struct CppExample +{ + inline static const std::string test_string = "cpp-example-lib Magic: 123456789"; + + /* Retrieve a constant string */ + const std::string &get_string(); + /* Retrieve a constant string from a library */ + const char *get_json_c_version(); + /* Call a more advanced function from a library */ + void print_json(); +}; diff --git a/meta-selftest/recipes-test/cpp/files/cpp-example.cpp b/meta-selftest/recipes-test/cpp/files/cpp-example.cpp new file mode 100644 index 0000000000..9889554e0c --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/cpp-example.cpp @@ -0,0 +1,18 @@ +/* + * Copyright OpenEmbedded Contributors + * + * SPDX-License-Identifier: MIT + */ + +#include "cpp-example-lib.hpp" + +#include + +int main() +{ + auto cpp_example = CppExample(); + std::cout << "C++ example linking " << cpp_example.get_string() << std::endl; + std::cout << "Linking json-c version " << cpp_example.get_json_c_version() << std::endl; + cpp_example.print_json(); + return 0; +} diff --git a/meta-selftest/recipes-test/cpp/files/meson.build b/meta-selftest/recipes-test/cpp/files/meson.build new file mode 100644 index 0000000000..0e2b55f3a2 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/meson.build @@ -0,0 +1,38 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +project('meson-example', 'cpp', + version: '1.0.0', + default_options: ['cpp_std=c++17'] + ) + +jsoncdep = dependency('json-c') + +if get_option('FAILING_TEST').enabled() + add_project_arguments('-DFAIL_COMPARISON_STR=foo', language: 'cpp') +endif + +mesonexlib = shared_library('mesonexlib', + 'cpp-example-lib.cpp', 'cpp-example-lib.hpp', + version: meson.project_version(), + soversion: meson.project_version().split('.')[0], + dependencies : jsoncdep, + install : true + ) + +executable('mesonex', + 'cpp-example.cpp', + link_with : mesonexlib, + install : true + ) + +test_mesonex = executable('test-mesonex', + 'test-cpp-example.cpp', + link_with : mesonexlib, + install : true +) + +test('meson example test', test_mesonex) diff --git a/meta-selftest/recipes-test/cpp/files/meson.options b/meta-selftest/recipes-test/cpp/files/meson.options new file mode 100644 index 0000000000..58a0bf9e61 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/meson.options @@ -0,0 +1,3 @@ + +option('FAILING_TEST', type : 'feature', value : 'disabled', + description : 'Compile a failing unit test to test the test infrastructure') diff --git a/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp b/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp new file mode 100644 index 0000000000..83c9bfa844 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/files/test-cpp-example.cpp @@ -0,0 +1,25 @@ +/* +* Copyright OpenEmbedded Contributors +* +* SPDX-License-Identifier: MIT +*/ + +#include "cpp-example-lib.hpp" + +#include + +/* This is for creating a failing test for testing the test infrastructure */ +#ifndef FAIL_COMPARISON_STR +#define FAIL_COMPARISON_STR "" +#endif + +int main() { + auto cpp_example = CppExample(); + auto ret_string = cpp_example.get_string(); + if(0 == ret_string.compare(CppExample::test_string + FAIL_COMPARISON_STR)) { + std::cout << "PASS: " << ret_string << " = " << CppExample::test_string << std::endl; + } else { + std::cout << "FAIL: " << ret_string << " != " << CppExample::test_string << std::endl; + return 1; + } +} diff --git a/meta-selftest/recipes-test/cpp/meson-example.bb b/meta-selftest/recipes-test/cpp/meson-example.bb new file mode 100644 index 0000000000..14a7ca8dc9 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/meson-example.bb @@ -0,0 +1,27 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +SUMMARY = "A C++ example compiled with meson." + +require cpp-example.inc + +SRC_URI += "\ + file://meson.build \ + file://meson.options \ +" + +inherit pkgconfig meson + +PACKAGECONFIG[failing_test] = "-DFAILING_TEST=enabled" + +FILES:${PN}-ptest += "${bindir}/test-mesonex" + +do_run_tests () { + meson test -C "${B}" --no-rebuild +} +do_run_tests[doc] = "Run meson test using qemu-user" + +addtask do_run_tests after do_compile diff --git a/meta-selftest/recipes-test/cpp/meson-example/run-ptest b/meta-selftest/recipes-test/cpp/meson-example/run-ptest new file mode 100644 index 0000000000..b1804f0096 --- /dev/null +++ b/meta-selftest/recipes-test/cpp/meson-example/run-ptest @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +test-mesonex + +# Note: run-ptests exits with exit value from test-mesonex -- cgit v1.2.3-54-g00ecf