diff --git a/CODEOWNERS b/CODEOWNERS index 65a89c8a6231f..b142bc3dc3f15 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -217,6 +217,7 @@ arch/arm/include/cortex_m/cmse.h @ioannisg /lib/gui/ @vanwinkeljan /lib/os/ @andrewboie @andyross /lib/posix/ @pfalcon +/lib/libc/ @nashif @andrewboie /kernel/device.c @andrewboie @andyross @nashif /kernel/idle.c @andrewboie @andyross @nashif /samples/basic/servo_motor/*microbit* @jhe @@ -276,6 +277,7 @@ arch/arm/include/cortex_m/cmse.h @ioannisg /subsys/shell/ @jarz-nordic @nordic-krch /subsys/storage/ @nvlsianpu /subsys/usb/ @jfischer-phytec-iot @finikorg +/tests/application_development/libcxx/ @pabigot /tests/boards/native_posix/ @aescolar /tests/boards/intel_s1000_crb/ @rgundi @dcpleung @sathishkuttan /tests/bluetooth/ @sjanc @jhedberg @Vudentz diff --git a/lib/libc/newlib/CMakeLists.txt b/lib/libc/newlib/CMakeLists.txt index fd29879e71279..db8efa33d775c 100644 --- a/lib/libc/newlib/CMakeLists.txt +++ b/lib/libc/newlib/CMakeLists.txt @@ -3,18 +3,23 @@ zephyr_library() zephyr_library_sources(libc-hooks.c) +# Zephyr normally uses -ffreestanding, which with current GNU toolchains +# means that the flag macros used by newlib 3.x to signal +# support for PRI.64 macros are not present. To make them available we +# need to hook into the include path before the system files and +# explicitly include the newlib header that provides those macros. +zephyr_include_directories(include) + # LIBC_*_DIR may or may not have been set by the toolchain. E.g. when # using ZEPHYR_TOOLCHAIN_VARIANT=cross-compile it will be either up to the # toolchain to know where it's libc implementation is, or if it is # unable to, it will be up to the user to specify LIBC_*_DIR vars to -# point to a newlib implementation. +# point to a newlib implementation. Note that this does not change the +# directory order if LIBC_INCLUDE_DIR is already a system header +# directory. -# We need to make sure this is included before the standard system -# header include path's since we build with -ffreestanding and need -# our libc headers to be picked instead of the toolchain's ffreestanding -# headers. if(LIBC_INCLUDE_DIR) - zephyr_system_include_directories(${LIBC_INCLUDE_DIR}) + zephyr_include_directories(${LIBC_INCLUDE_DIR}) endif() if(LIBC_LIBRARY_DIR) diff --git a/lib/libc/newlib/include/stdint.h b/lib/libc/newlib/include/stdint.h new file mode 100644 index 0000000000000..a7d4874a4d9b8 --- /dev/null +++ b/lib/libc/newlib/include/stdint.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_LIB_LIBC_NEWLIB_INCLUDE_STDINT_H_ +#define ZEPHYR_LIB_LIBC_NEWLIB_INCLUDE_STDINT_H_ + +/* Work around -ffreestanding absence of defines required to support + * PRI.64 macros in by including the newlib header that + * provides the flag macros. + */ + +#include + +#ifdef __NEWLIB__ +/* Has this header. Older versions do it in . */ +#include +#endif /* __NEWLIB__ */ + +/* This should work on GCC and clang. + * + * If we need to support a toolchain without #include_next the CMake + * infrastructure should be used to identify it and provide an + * alternative solution. + */ +#include_next + +#endif /* ZEPHYR_LIB_LIBC_NEWLIB_INCLUDE_STDINT_H_ */ diff --git a/subsys/testsuite/ztest/include/ztest.h b/subsys/testsuite/ztest/include/ztest.h index 4d0dacaa1710e..e429e0a261526 100644 --- a/subsys/testsuite/ztest/include/ztest.h +++ b/subsys/testsuite/ztest/include/ztest.h @@ -20,10 +20,6 @@ #ifndef __ZTEST_H__ #define __ZTEST_H__ -#ifdef __cplusplus -extern "C" { -#endif - /** * @defgroup ztest Zephyr testing suite */ @@ -44,19 +40,22 @@ extern "C" { /* FIXME: Properly integrate with Zephyr's arch specific code */ #define CONFIG_X86 1 #define CONFIG_PRINTK 1 -#endif +#endif /* KERNEL */ #include #define PRINT printk #include - #include #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + void test_main(void); #ifdef __cplusplus diff --git a/subsys/testsuite/ztest/include/ztest_assert.h b/subsys/testsuite/ztest/include/ztest_assert.h index c163188149cb4..8d86e0b33a7c8 100644 --- a/subsys/testsuite/ztest/include/ztest_assert.h +++ b/subsys/testsuite/ztest/include/ztest_assert.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + void ztest_test_fail(void); #if CONFIG_ZTEST_ASSERT_VERBOSE == 0 @@ -186,4 +190,8 @@ static inline void zassert_mem_equal(void *buf, void *exp, size_t size, * @} */ +#ifdef __cplusplus +} +#endif + #endif /* __ZTEST_ASSERT_H__ */ diff --git a/subsys/testsuite/ztest/include/ztest_mock.h b/subsys/testsuite/ztest/include/ztest_mock.h index 65d535c453c12..8e4ac8fc5152c 100644 --- a/subsys/testsuite/ztest/include/ztest_mock.h +++ b/subsys/testsuite/ztest/include/ztest_mock.h @@ -91,6 +91,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + void z_init_mock(void); int z_cleanup_mock(void); @@ -101,6 +105,10 @@ void z_ztest_check_expected_value(const char *fn, const char *param, void z_ztest_returns_value(const char *fn, uintptr_t value); uintptr_t z_ztest_get_return_value(const char *fn); +#ifdef __cplusplus +} +#endif + #else /* !CONFIG_ZTEST_MOCKING */ #define z_init_mock() diff --git a/subsys/testsuite/ztest/include/ztest_test.h b/subsys/testsuite/ztest/include/ztest_test.h index 2caa21e9a606c..2aba108922664 100644 --- a/subsys/testsuite/ztest/include/ztest_test.h +++ b/subsys/testsuite/ztest/include/ztest_test.h @@ -15,6 +15,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + struct unit_test { const char *name; void (*test)(void); @@ -170,4 +174,8 @@ extern struct k_mem_domain ztest_mem_domain; * @} */ +#ifdef __cplusplus +} +#endif + #endif /* __ZTEST_ASSERT_H__ */ diff --git a/tests/application_development/libcxx/CMakeLists.txt b/tests/application_development/libcxx/CMakeLists.txt new file mode 100644 index 0000000000000..4fcc2391b6ddd --- /dev/null +++ b/tests/application_development/libcxx/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) +include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE) +project(cpp) + +FILE(GLOB app_sources src/*.cpp) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/application_development/libcxx/prj.conf b/tests/application_development/libcxx/prj.conf new file mode 100644 index 0000000000000..aade1fafb7d70 --- /dev/null +++ b/tests/application_development/libcxx/prj.conf @@ -0,0 +1,7 @@ +CONFIG_NEWLIB_LIBC=y +CONFIG_CPLUSPLUS=y +CONFIG_LIB_CPLUSPLUS=y +CONFIG_STD_CPP17=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 +CONFIG_ZTEST=y +CONFIG_ZTEST_STACKSIZE=2048 diff --git a/tests/application_development/libcxx/src/main.cpp b/tests/application_development/libcxx/src/main.cpp new file mode 100644 index 0000000000000..9bac859bf6f59 --- /dev/null +++ b/tests/application_development/libcxx/src/main.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +BUILD_ASSERT(__cplusplus == 201703); + +std::array array = {1, 2, 3, 4}; +std::vector vector; + +static void test_array(void) +{ + zassert_equal(array.size(), 4, "unexpected size"); + zassert_equal(array[0], 1, "array[0] wrong"); + zassert_equal(array[3], 4, "array[3] wrong"); + + std::array local = {1, 2}; + zassert_equal(local.size(), 2, "unexpected size"); + zassert_equal(local[0], 1, "local[0] wrong"); + zassert_equal(local[1], 2, "local[1] wrong"); +} + +static void test_vector(void) +{ + zassert_equal(vector.size(), 0, "vector init nonzero"); + for (auto v : array) { + vector.push_back(v); + } + zassert_equal(vector.size(), array.size(), "vector store failed"); +} + +void test_main(void) +{ + TC_PRINT("version %u\n", (u32_t)__cplusplus); + ztest_test_suite(libcxx_tests, + ztest_unit_test(test_array), + ztest_unit_test(test_vector) + ); + + ztest_run_test_suite(libcxx_tests); +} diff --git a/tests/application_development/libcxx/testcase.yaml b/tests/application_development/libcxx/testcase.yaml new file mode 100644 index 0000000000000..17cdd168c54de --- /dev/null +++ b/tests/application_development/libcxx/testcase.yaml @@ -0,0 +1,5 @@ +tests: + misc.app_dev.libcxx: + arch_exclude: posix + platform_exclude: qemu_x86_coverage qemu_x86_64 + tags: cpp