123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- .. include:: /substitutions.rst
- .. _cpp_cmake:
- C++ Example using CMake
- =======================
- In some situations, developers intend to implement software using the NuttX platform in
- a previously set hardware and configuration where it is not possible or allowed to make
- changes. In such situations, less contact with the operating source tree is better, where
- it is only used for the application.
- Some approaches are possible to do that today:
- * https://cwiki.apache.org/confluence/display/NUTTX/Building+NuttX+with+Applications+Outside+of+the+Source+Tree
- * https://www.programmersought.com/article/61604062421/
- We have been seen the increase of the use of C++ language in embedded systems application. And
- CMake (https://www.cmake.org) is the preferred build system used to build C++ projects. NuttX
- support C++ based projects.
- Using the 'build as a library' procedure of NuttX, it is possible to build NuttX
- applications using C++ language and also the cmake build tool.
- This document will show how to reimplement the hellocpp project using this cmake.
- Preparation
- -----------
- #. Base NuttX compilation changes
- For this example, load the configuration 'stm32f4discovery:testlibcxx' for building
- .. code-block:: console
- $ cd nuttx
- $ ./tools/configure.sh stm32f4discovery:testlibcxx
- In menuconfig, the main points to be changed on a typical NuttX configuration are the following:
- * Set RTOS Features -> Tasks and Scheduling -> Application entry point to 'hellocpp_main'
- * Build NuttX and generate the export
- .. code-block:: console
- $ make export
- Creating the project
- --------------------
- #. Create your project file structure
- The project structure is organized as follow:
- .. code-block:: console
- hellocpp/
- hellocpp/CMakeLists.txt
- hellocpp/cmake/stm32f4discovery.cmake
- hellocpp/nuttx-export-10.0.1/
- hellocpp/src/CMakeLists.txt
- hellocpp/src/main.cpp
- hellocpp/src/HelloWorld.h
- hellocpp/src/HelloWorld.cpp
- The directory 'nuttx-export-10.0.1' is the unzipped content from the file created during
- make export procedure done before.
- #. File contents
- * hellocpp/CMakeLists.txt
- .. code-block:: cmake
- cmake_minimum_required(VERSION 3.2...3.15)
- project(HelloCpp
- VERSION 1.0
- DESCRIPTION "Hello world C++ NuttX"
- )
- set(CMAKE_CXX_STANDARD 17)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
- # set(CMAKE_CXX_EXTENSIONS OFF)
- set(CMAKE_C_STANDARD 99)
- set(NUTTX_PATH "${CMAKE_SOURCE_DIR}/nuttx-export-10.0.1")
- include(cmake/stm32f4discovery.cmake)
- set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -fno-builtin -Wall -Wshadow -Wundef -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer -Os")
- set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -D_DEBUG -D_LIBCPP_BUILD_STATIC -D_LIBCPP_NO_EXCEPTIONS ")
- set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -fno-exceptions -fcheck-new -fno-rtti -pedantic ")
- set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -nostdinc++")
- set(AC_DEFINES "${AC_DEFINES} -DCONFIG_WCHAR_BUILTIN")
- include_directories(
- src
- ${NUTTX_PATH}/include
- ${NUTTX_PATH}/include/libcxx
- ${NUTTX_PATH}/arch/chip
- )
- set(EXE_NAME hellocpp)
- set(CMAKE_CXX_FLAGS "${AC_HW_FLAGS} ${AC_DEFINES} ${AC_COMMON_FLAGS} ${AC_CXX_EXTRA_FLAGS}")
- if (PARAM_DEBUG)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
- endif()
- set(CMAKE_SKIP_RPATH ON)
- set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_LINKER} ${AC_LINKER_FLAGS} -o ${EXE_NAME}.elf <OBJECTS> <LINK_LIBRARIES>")
- set(BUILD_SHARED_LIBS OFF)
- add_subdirectory(src)
- * hellocpp/cmake/stm32f4discovery.cmake
- .. code-block:: cmake
-
- set(CMAKE_SYSTEM_NAME Generic)
- set(CMAKE_SYSTEM_PROCESSOR arm)
- set(MCU_LINKER_SCRIPT "${NUTTX_PATH}/scripts/ld.script")
- set(COMPILER_PREFIX arm-none-eabi-)
- # cmake-format: off
- set(CMAKE_C_COMPILER ${COMPILER_PREFIX}gcc)
- set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}g++)
- set(CMAKE_AR ${COMPILER_PREFIX}ar)
- set(CMAKE_RANLIB ${COMPILER_PREFIX}ranlib)
- set(CMAKE_LINKER ${COMPILER_PREFIX}ld)
- set(CMAKE_ASM_COMPILER ${COMPILER_PREFIX}gcc)
- set(CMAKE_OBJCOPY ${COMPILER_PREFIX}objcopy)
- set(CMAKE_OBJDUMP ${COMPILER_PREFIX}objdump)
- set(CMAKE_SIZE ${COMPILER_PREFIX}size)
- set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
- set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
- set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
- set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
- set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
- set(AC_HW_FLAGS "-mcpu=cortex-m4 -mthumb -mfloat-abi=soft ")
- set(AC_HW_FLAGS "${AC_HW_FLAGS} -isystem ${NUTTX_PATH}/include")
- set(AC_HW_FLAGS "${AC_HW_FLAGS} -pipe -D__NuttX__")
- set(AC_LINKER_FLAGS "--entry=__start -nostartfiles -nodefaultlibs -T${MCU_LINKER_SCRIPT}")
- * hellocpp/src/CMakeLists.txt
- .. code-block:: cmake
-
- set(HEADER_FILES
- HelloWorld.h
- )
- set(SOURCE_FILES
- HelloWorld.cpp
- )
- link_directories(${EXE_NAME} ${NUTTX_PATH}/libs)
- add_executable(${EXE_NAME} ${SOURCE_FILES} main.cpp ${HEADER_FILES})
- add_custom_command(
- TARGET ${EXE_NAME}
- POST_BUILD
- COMMAND ${CMAKE_OBJCOPY} ARGS -S -O binary ${CMAKE_BINARY_DIR}/${EXE_NAME}.elf ${CMAKE_BINARY_DIR}/${EXE_NAME}.bin
- )
- target_link_libraries(${EXE_NAME} --start-group)
- target_link_libraries(${EXE_NAME} sched)
- target_link_libraries(${EXE_NAME} drivers)
- target_link_libraries(${EXE_NAME} boards)
- target_link_libraries(${EXE_NAME} c)
- target_link_libraries(${EXE_NAME} mm)
- target_link_libraries(${EXE_NAME} arch)
- target_link_libraries(${EXE_NAME} xx)
- target_link_libraries(${EXE_NAME} apps)
- target_link_libraries(${EXE_NAME} fs)
- target_link_libraries(${EXE_NAME} binfmt)
- target_link_libraries(${EXE_NAME} board)
- target_link_libraries(${EXE_NAME} gcc)
- target_link_libraries(${EXE_NAME} supc++)
- target_link_libraries(${EXE_NAME} --end-group)
- * hellocpp/src/main.cpp
- .. code-block:: c++
- #include "HelloWorld.h"
- #include <nuttx/config.h>
- extern "C"
- {
- int hellocpp_main(void)
- {
- CHelloWorld *pHelloWorld = new CHelloWorld();
- pHelloWorld->HelloWorld();
- CHelloWorld helloWorld;
- helloWorld.HelloWorld();
- delete pHelloWorld;
- return 0;
- }
- }
- * hellocpp/src/HelloWorld.h
- .. code-block:: c++
- #ifndef HELLOWORLD_H_
- #define HELLOWORLD_H_
- #include "nuttx/config.h"
- class CHelloWorld
- {
- public:
- CHelloWorld();
- ~CHelloWorld();
- bool HelloWorld(void);
- private:
- int mSecret;
- };
- #endif
- * hellocpp/src/HelloWorld.cpp
- .. code-block:: c++
- #include <cstdio>
- #include <string>
- #include "HelloWorld.h"
- CHelloWorld::CHelloWorld() {
- mSecret = 42;
- std::printf("Constructor: mSecret=%d\n",mSecret);
- }
- CHelloWorld::~CHelloWorld() {
- }
- bool CHelloWorld::HelloWorld(void) {
- std::printf("HelloWorld: mSecret=%d\n",mSecret);
- std::string sentence = "Hello";
- std::printf("TEST=%s\n",sentence.c_str());
- if (mSecret == 42) {
- std::printf("CHelloWorld: HelloWorld: Hello, world!\n");
- return true;
- }
- else {
- std::printf("CHelloWorld: HelloWorld: CONSTRUCTION FAILED!\n");
- return false;
- }
- }
- Building
- --------
- To launch build, you use the cmake procedure:
- .. code-block:: console
- $ mkdir build
- $ cd build
- $ cmake ..
- $ make
- And finally a bin file will be created to be loaded on the board.
|