cpp_cmake.rst 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. .. include:: /substitutions.rst
  2. .. _cpp_cmake:
  3. C++ Example using CMake
  4. =======================
  5. In some situations, developers intend to implement software using the NuttX platform in
  6. a previously set hardware and configuration where it is not possible or allowed to make
  7. changes. In such situations, less contact with the operating source tree is better, where
  8. it is only used for the application.
  9. Some approaches are possible to do that today:
  10. * https://cwiki.apache.org/confluence/display/NUTTX/Building+NuttX+with+Applications+Outside+of+the+Source+Tree
  11. * https://www.programmersought.com/article/61604062421/
  12. We have been seen the increase of the use of C++ language in embedded systems application. And
  13. CMake (https://www.cmake.org) is the preferred build system used to build C++ projects. NuttX
  14. support C++ based projects.
  15. Using the 'build as a library' procedure of NuttX, it is possible to build NuttX
  16. applications using C++ language and also the cmake build tool.
  17. This document will show how to reimplement the hellocpp project using this cmake.
  18. Preparation
  19. -----------
  20. #. Base NuttX compilation changes
  21. For this example, load the configuration 'stm32f4discovery:testlibcxx' for building
  22. .. code-block:: console
  23. $ cd nuttx
  24. $ ./tools/configure.sh stm32f4discovery:testlibcxx
  25. In menuconfig, the main points to be changed on a typical NuttX configuration are the following:
  26. * Set RTOS Features -> Tasks and Scheduling -> Application entry point to 'hellocpp_main'
  27. * Build NuttX and generate the export
  28. .. code-block:: console
  29. $ make export
  30. Creating the project
  31. --------------------
  32. #. Create your project file structure
  33. The project structure is organized as follow:
  34. .. code-block:: console
  35. hellocpp/
  36. hellocpp/CMakeLists.txt
  37. hellocpp/cmake/stm32f4discovery.cmake
  38. hellocpp/nuttx-export-10.0.1/
  39. hellocpp/src/CMakeLists.txt
  40. hellocpp/src/main.cpp
  41. hellocpp/src/HelloWorld.h
  42. hellocpp/src/HelloWorld.cpp
  43. The directory 'nuttx-export-10.0.1' is the unzipped content from the file created during
  44. make export procedure done before.
  45. #. File contents
  46. * hellocpp/CMakeLists.txt
  47. .. code-block:: cmake
  48. cmake_minimum_required(VERSION 3.2...3.15)
  49. project(HelloCpp
  50. VERSION 1.0
  51. DESCRIPTION "Hello world C++ NuttX"
  52. )
  53. set(CMAKE_CXX_STANDARD 17)
  54. set(CMAKE_CXX_STANDARD_REQUIRED ON)
  55. # set(CMAKE_CXX_EXTENSIONS OFF)
  56. set(CMAKE_C_STANDARD 99)
  57. set(NUTTX_PATH "${CMAKE_SOURCE_DIR}/nuttx-export-10.0.1")
  58. include(cmake/stm32f4discovery.cmake)
  59. set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -fno-builtin -Wall -Wshadow -Wundef -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer -Os")
  60. set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -D_DEBUG -D_LIBCPP_BUILD_STATIC -D_LIBCPP_NO_EXCEPTIONS ")
  61. set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -fno-exceptions -fcheck-new -fno-rtti -pedantic ")
  62. set(AC_COMMON_FLAGS "${AC_COMMON_FLAGS} -nostdinc++")
  63. set(AC_DEFINES "${AC_DEFINES} -DCONFIG_WCHAR_BUILTIN")
  64. include_directories(
  65. src
  66. ${NUTTX_PATH}/include
  67. ${NUTTX_PATH}/include/libcxx
  68. ${NUTTX_PATH}/arch/chip
  69. )
  70. set(EXE_NAME hellocpp)
  71. set(CMAKE_CXX_FLAGS "${AC_HW_FLAGS} ${AC_DEFINES} ${AC_COMMON_FLAGS} ${AC_CXX_EXTRA_FLAGS}")
  72. if (PARAM_DEBUG)
  73. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
  74. endif()
  75. set(CMAKE_SKIP_RPATH ON)
  76. set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_LINKER} ${AC_LINKER_FLAGS} -o ${EXE_NAME}.elf <OBJECTS> <LINK_LIBRARIES>")
  77. set(BUILD_SHARED_LIBS OFF)
  78. add_subdirectory(src)
  79. * hellocpp/cmake/stm32f4discovery.cmake
  80. .. code-block:: cmake
  81. set(CMAKE_SYSTEM_NAME Generic)
  82. set(CMAKE_SYSTEM_PROCESSOR arm)
  83. set(MCU_LINKER_SCRIPT "${NUTTX_PATH}/scripts/ld.script")
  84. set(COMPILER_PREFIX arm-none-eabi-)
  85. # cmake-format: off
  86. set(CMAKE_C_COMPILER ${COMPILER_PREFIX}gcc)
  87. set(CMAKE_CXX_COMPILER ${COMPILER_PREFIX}g++)
  88. set(CMAKE_AR ${COMPILER_PREFIX}ar)
  89. set(CMAKE_RANLIB ${COMPILER_PREFIX}ranlib)
  90. set(CMAKE_LINKER ${COMPILER_PREFIX}ld)
  91. set(CMAKE_ASM_COMPILER ${COMPILER_PREFIX}gcc)
  92. set(CMAKE_OBJCOPY ${COMPILER_PREFIX}objcopy)
  93. set(CMAKE_OBJDUMP ${COMPILER_PREFIX}objdump)
  94. set(CMAKE_SIZE ${COMPILER_PREFIX}size)
  95. set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
  96. set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
  97. set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
  98. set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
  99. set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
  100. set(AC_HW_FLAGS "-mcpu=cortex-m4 -mthumb -mfloat-abi=soft ")
  101. set(AC_HW_FLAGS "${AC_HW_FLAGS} -isystem ${NUTTX_PATH}/include")
  102. set(AC_HW_FLAGS "${AC_HW_FLAGS} -pipe -D__NuttX__")
  103. set(AC_LINKER_FLAGS "--entry=__start -nostartfiles -nodefaultlibs -T${MCU_LINKER_SCRIPT}")
  104. * hellocpp/src/CMakeLists.txt
  105. .. code-block:: cmake
  106. set(HEADER_FILES
  107. HelloWorld.h
  108. )
  109. set(SOURCE_FILES
  110. HelloWorld.cpp
  111. )
  112. link_directories(${EXE_NAME} ${NUTTX_PATH}/libs)
  113. add_executable(${EXE_NAME} ${SOURCE_FILES} main.cpp ${HEADER_FILES})
  114. add_custom_command(
  115. TARGET ${EXE_NAME}
  116. POST_BUILD
  117. COMMAND ${CMAKE_OBJCOPY} ARGS -S -O binary ${CMAKE_BINARY_DIR}/${EXE_NAME}.elf ${CMAKE_BINARY_DIR}/${EXE_NAME}.bin
  118. )
  119. target_link_libraries(${EXE_NAME} --start-group)
  120. target_link_libraries(${EXE_NAME} sched)
  121. target_link_libraries(${EXE_NAME} drivers)
  122. target_link_libraries(${EXE_NAME} boards)
  123. target_link_libraries(${EXE_NAME} c)
  124. target_link_libraries(${EXE_NAME} mm)
  125. target_link_libraries(${EXE_NAME} arch)
  126. target_link_libraries(${EXE_NAME} xx)
  127. target_link_libraries(${EXE_NAME} apps)
  128. target_link_libraries(${EXE_NAME} fs)
  129. target_link_libraries(${EXE_NAME} binfmt)
  130. target_link_libraries(${EXE_NAME} board)
  131. target_link_libraries(${EXE_NAME} gcc)
  132. target_link_libraries(${EXE_NAME} supc++)
  133. target_link_libraries(${EXE_NAME} --end-group)
  134. * hellocpp/src/main.cpp
  135. .. code-block:: c++
  136. #include "HelloWorld.h"
  137. #include <nuttx/config.h>
  138. extern "C"
  139. {
  140. int hellocpp_main(void)
  141. {
  142. CHelloWorld *pHelloWorld = new CHelloWorld();
  143. pHelloWorld->HelloWorld();
  144. CHelloWorld helloWorld;
  145. helloWorld.HelloWorld();
  146. delete pHelloWorld;
  147. return 0;
  148. }
  149. }
  150. * hellocpp/src/HelloWorld.h
  151. .. code-block:: c++
  152. #ifndef HELLOWORLD_H_
  153. #define HELLOWORLD_H_
  154. #include "nuttx/config.h"
  155. class CHelloWorld
  156. {
  157. public:
  158. CHelloWorld();
  159. ~CHelloWorld();
  160. bool HelloWorld(void);
  161. private:
  162. int mSecret;
  163. };
  164. #endif
  165. * hellocpp/src/HelloWorld.cpp
  166. .. code-block:: c++
  167. #include <cstdio>
  168. #include <string>
  169. #include "HelloWorld.h"
  170. CHelloWorld::CHelloWorld() {
  171. mSecret = 42;
  172. std::printf("Constructor: mSecret=%d\n",mSecret);
  173. }
  174. CHelloWorld::~CHelloWorld() {
  175. }
  176. bool CHelloWorld::HelloWorld(void) {
  177. std::printf("HelloWorld: mSecret=%d\n",mSecret);
  178. std::string sentence = "Hello";
  179. std::printf("TEST=%s\n",sentence.c_str());
  180. if (mSecret == 42) {
  181. std::printf("CHelloWorld: HelloWorld: Hello, world!\n");
  182. return true;
  183. }
  184. else {
  185. std::printf("CHelloWorld: HelloWorld: CONSTRUCTION FAILED!\n");
  186. return false;
  187. }
  188. }
  189. Building
  190. --------
  191. To launch build, you use the cmake procedure:
  192. .. code-block:: console
  193. $ mkdir build
  194. $ cd build
  195. $ cmake ..
  196. $ make
  197. And finally a bin file will be created to be loaded on the board.