工程框架编写
本文档基于wu的 wuwusama_icar_project , 实现添加动态库、输出多个可执行文件、编译完成自动下载到开发板功能。
下载源码,后进入工程,用 code 打开
git clone https://gitee.com/Wuwu129/SmartCar_99Pai_OpenSource.git
cd ./SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project
code .
1 、 安装必要的软件
vscode 提示安装 CMake Tools ----------- 安装
安装 Ninja库,专门用于加速构建过程,与其他生成工具(如CMake)配合使用。安装命令:
sudo apt-get install -y ninja-build
交叉编译 libserial生成 libserial库(前人已经编译好了)
交叉编译 OpenCV , 生成 opencv库
交叉编译 json, 生成 json库
交叉编译 ncnn, 生成 ncnn库
2、修改工程
1 、 使用Ninja 编译 添加预配置
在根目录下新建CMakeUserPresets.json文件。它是CMake 从 3.21 开始支持的一个配置文件,其允许我们在项目目录下自定义构建配置,而不需要每次手动输入命令行参数。这里我们用它来配置编译器99pi.cmake 生成可执行文件 目录 out.
CMakeUserPresets.json文件内容:
{
"version": 8,
"configurePresets": [
{
"name": "Configure preset using toolchain file",
"displayName": "Configure preset using toolchain file",
"description": "Sets Ninja generator, build and install directory",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": "99pi.cmake",
"CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}"
}
}
]
}
与交叉编译工具相关的放到 99pi.cmake
# 交叉编译工具链配置 99pi.cmake
# 设置为 ON 表示交叉编译,OFF 表示本地编译
option(CROSS_COMPILE "Enable cross-compilation" ON)
if(CROSS_COMPILE)
# 基本系统信息
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR loongarch64)
# 工具链路径
set(TOOLCHAIN_DIR /opt/loongson-gnu-toolchain-13.2/)#交叉编译器目录
# 编译器路径
set(CMAKE_C_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_DIR}/bin/loongarch64-unknown-linux-gnu-g++)
# 系统根目录设置
set(CMAKE_FIND_ROOT_PATH "${TOOLCHAIN_DIR}")
# 查找规则设置
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)
endif()
这样就只需要修改99pi.cmake 的工具链的位置了。
修改好工程后,点击铁三角,点击配置 [选择工具包] 中右边的笔, 配置由Nijia生成

最后到项目大纲 ,点击图标生成main

最终的项目结构

2 、 单独输出 可执行文件 /out/bin
由于可执行文件不需要与二进制文件混合存放,在 main 程序的 CMakeLists.txt 文件顶部,添加以下语句,实现所有的可执行文件的单独存放。
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/bin)
3 、添加测试代码文件,可 编译多个可执行文件
不习惯 复制替换 main.c , 这里根据 修改添加测试工程, 添加子目录 test,
修改生成 main 程序的 CMakeLists.txt, 在底部添加:
# 添加所有子目录 (使用变量 )
set(SUBDIRS
test )
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()
将所有的测试文件 复制到 test目录下:
├── smartCar
│ ├── code
│ │ ├── 本文件夹说明.txt
│ │ ├── music.cc
│ │ └── music.h
│ ├── include
│ │ ├── font.h
│ │ ├── ......
│ │ ├── ww_timerThread.h
│ │ └── ww_vl53l0x.h
│ ├── main.cc
│ └── wuwu_library
│ ├── font.cc
│ ├── ww_brushless.cc
│ ├── ......
│ └── ww_vl53l0x.cc
└── test
├── buzzer_main.cc
├── camera_server_main.cc
├── CMakeLists.txt
├── encoder_main.cc
├── icm42688_main.cc
├── Lcd_main.cc
├── Motor_main.cc
├── ncnn_yolov5n_example
│ ├── CMakeLists.txt
│ ├── test.jpg
│ ├── yolov5n.ncnn.bin
│ ├── yolov5n_ncnn_main.cc
│ └── yolov5n.ncnn.param
├── tcp_client_main.cc
└── test_hello.cpp
test目录下添加 CmakeLists.txt
# 添加所有文件 (使用变量 )
file(GLOB_RECURSE MYSRC
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cc
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.c
${PROJECT_SOURCE_DIR}/smartCar/code/*.cc
${PROJECT_SOURCE_DIR}/smartCar/code/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/code/*.c
)
# 添加所有库 (使用变量 )
set(SUBLIB
opencv_core
opencv_imgcodecs
opencv_imgproc
opencv_videoio
jsoncpp
ncnn
serial
gomp )
add_executable(test_hello test_hello.cpp )
target_link_libraries(test_hello PRIVATE
${SUBLIB})
add_executable(buzzer_main buzzer_main.cc ${MYSRC})
target_link_libraries(buzzer_main PRIVATE
${SUBLIB})
# 后面可生成若干个 可执行文件
用图标来执行编译

4 . 编译完成即自动上传
修改生成 main 程序的 CMakeLists.txt, 在底部添加:
# ===================== 编译完成后 自动执行SCP上传 核心配置 =====================
# 配置开发板的SSH信息【修改这3个参数为你的开发板信息即可!】
set(BOARD_IP "192.168.3.99") # 你的开发板/龙芯设备的IP地址
set(BOARD_USER "root") # 开发板的登录用户名 (一般是root)
set(BOARD_TARGET_DIR "/root/app") # 上传到开发板的目标目录
# 编译主程序smartcar完成后,自动执行scp上传
add_custom_command(
TARGET main # 绑定你的主程序目标名,编译完这个程序就执行下面的命令
POST_BUILD # 执行时机:编译完成后(POST_BUILD),编译失败则不执行
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
COMMENT "编译完成!正在自动上传 main 到开发板: ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}"
)
5 、添加库
在编译时使用了动态链接库,即 cross_lib下的 *.so 文件; 最后把交叉编译环境下(PC 端)的所有依赖动态链接库,完整复制到开发板,并让开发板系统成功识别、加载这些库,最终让程序能正常运行。
查看编译成功的 main 是否共享库:
$ loongarch64-unknown-linux-gnu-objdump -x main | grep -i opencv
NEEDED libopencv_core.so.410
NEEDED libopencv_imgcodecs.so.410
NEEDED libopencv_imgproc.so.410
NEEDED libopencv_videoio.so.410
RPATH
/loongarch64-unknown-linux-gnu/lib:
/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/opencv/lib:
/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/json/lib:
/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/ncnn/lib:
/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/libserial/lib
loongarch64-unknown-linux-gnu-objdump -x main | grep -i json
NEEDED libjsoncpp.so.27
RPATH /loongarch64-unknown-linux-gnu/lib:/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/opencv/lib:/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/json/lib:/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/ncnn/lib:/home/wuwu/Downloads/SmartCar_99Pai_OpenSource/WuwuSama_Icar_Project/cross_lib/libserial/lib
在根文件系统的 opt目录 ,存放着编译完成的 动态库
这里添加一个新库 : libserial

3 最后main.cc 同级目录 CMakeLists.txt 如下
cmake_minimum_required(VERSION 3.10)
project(SMARTCAR)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/out/bin)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
# 查找线程库
find_package(Threads REQUIRED)
include_directories(${PROJECT_SOURCE_DIR}/smartCar/code)
include_directories(${PROJECT_SOURCE_DIR}/smartCar/include)
include_directories(${PROJECT_SOURCE_DIR}/smartCar/wuwu_library)
#编译的库已经放在工程里啦
include_directories(${PROJECT_SOURCE_DIR}/cross_lib/opencv/include/opencv4)
include_directories(${PROJECT_SOURCE_DIR}/cross_lib/json/include)
include_directories(${PROJECT_SOURCE_DIR}/cross_lib/ncnn/include/ncnn)
include_directories(${PROJECT_SOURCE_DIR}/cross_lib/libserial/include/libserial)
file(GLOB_RECURSE MYSRC
${PROJECT_SOURCE_DIR}/smartCar/*.cc
${PROJECT_SOURCE_DIR}/smartCar/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/*.c
)
link_directories(${CROSSTOOL_DIR}/loongarch64-unknown-linux-gnu/lib)
link_directories(${PROJECT_SOURCE_DIR}/cross_lib/opencv/lib)
link_directories(${PROJECT_SOURCE_DIR}/cross_lib/json/lib)
link_directories(${PROJECT_SOURCE_DIR}/cross_lib/ncnn/lib)
link_directories(${PROJECT_SOURCE_DIR}/cross_lib/libserial/lib)
add_executable(main ${MYSRC})
target_link_libraries(main PRIVATE
opencv_core
opencv_imgcodecs
opencv_imgproc
opencv_videoio
jsoncpp
ncnn
gomp
serial) #添加了serial库
# 添加所有子目录 (使用变量 )
set(SUBDIRS
test
test/ncnn_yolov5n_example)
foreach(subdir ${SUBDIRS})
add_subdirectory(${subdir})
endforeach()
# ===================== 编译完成后 自动执行SCP上传 核心配置 =====================
# 配置开发板的SSH信息【修改这3个参数为你的开发板信息即可!】
set(BOARD_IP "192.168.3.99") # 你的开发板/龙芯设备的IP地址
set(BOARD_USER "root") # 开发板的登录用户名 (一般是root)
set(BOARD_TARGET_DIR "/root/app") # 上传到开发板的目标目录
# 编译主程序smartcar完成后,自动执行scp上传
add_custom_command(
TARGET main # 绑定你的主程序目标名,编译完这个程序就执行下面的命令
POST_BUILD # 执行时机:编译完成后(POST_BUILD),编译失败则不执行
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
COMMENT "编译完成!正在自动上传 main 到开发板: ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}"
)
test目录下的CMakeLists.txt
# 添加所有文件 (使用变量 )
file(GLOB_RECURSE MYSRC
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cc
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.c
${PROJECT_SOURCE_DIR}/smartCar/code/*.cc
${PROJECT_SOURCE_DIR}/smartCar/code/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/code/*.c
)
# 添加所有库 (使用变量 )
set(SUBLIB
opencv_core
opencv_imgcodecs
opencv_imgproc
opencv_videoio
jsoncpp
ncnn
serial
gomp )
add_executable(test_hello test_hello.cpp )
target_link_libraries(test_hello PRIVATE
${SUBLIB})
add_executable(buzzer_main buzzer_main.cc ${MYSRC})
target_link_libraries(buzzer_main PRIVATE
${SUBLIB})
add_executable(camera_server_main camera_server_main.cc ${MYSRC})
target_link_libraries(camera_server_main PRIVATE
${SUBLIB})
add_executable(encoder_main encoder_main.cc ${MYSRC})
target_link_libraries(encoder_main PRIVATE
${SUBLIB})
add_executable(icm42688_main icm42688_main.cc ${MYSRC})
target_link_libraries(icm42688_main PRIVATE
${SUBLIB})
add_executable(Lcd_main Lcd_main.cc ${MYSRC})
target_link_libraries(Lcd_main PRIVATE
${SUBLIB})
add_executable(Motor_main Motor_main.cc ${MYSRC})
target_link_libraries(Motor_main PRIVATE
${SUBLIB})
add_executable(tcp_client_main tcp_client_main.cc ${MYSRC})
target_link_libraries(tcp_client_main PRIVATE
${SUBLIB})
# ===================== 编译完成后 自动执行SCP上传 =====================
set(BOARD_IP "192.168.3.99")
set(BOARD_USER "root")
set(BOARD_TARGET_DIR "/root/test")
add_custom_command(
TARGET test_hello
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test_hello ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET buzzer_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/buzzer_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET camera_server_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/camera_server_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET encoder_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/encoder_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET icm42688_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/icm42688_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET Lcd_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Lcd_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET Motor_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Motor_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
add_custom_command(
TARGET tcp_client_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/tcp_client_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
nccn目录下的 CMakeList.txt如下:
# 添加所有文件 (使用变量 )
file(GLOB_RECURSE MYSRC
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cc
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/wuwu_library/*.c
${PROJECT_SOURCE_DIR}/smartCar/code/*.cc
${PROJECT_SOURCE_DIR}/smartCar/code/*.cpp
${PROJECT_SOURCE_DIR}/smartCar/code/*.c
)
# 添加所有库 (使用变量 )
set(SUBLIB
opencv_core
opencv_imgcodecs
opencv_imgproc
opencv_videoio
jsoncpp
ncnn
serial
gomp )
add_executable(yolov5n_ncnn_main yolov5n_ncnn_main.cc )
target_link_libraries(yolov5n_ncnn_main PRIVATE
${SUBLIB})
# ===================== 编译完成后 自动执行SCP上传 核心配置 =====================
set(BOARD_IP "192.168.3.99")
set(BOARD_USER "root")
set(BOARD_TARGET_DIR "/root/test")
add_custom_command(
TARGET yolov5n_ncnn_main
POST_BUILD
COMMAND scp ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/yolov5n_ncnn_main ${BOARD_USER}@${BOARD_IP}:${BOARD_TARGET_DIR}/
)
本工程的下载链接: https://download.csdn.net/download/sundm75/92552226
参考文献:
1 https://gitee.com/Wuwu129/SmartCar_99Pai_OpenSource
231

被折叠的 条评论
为什么被折叠?



