LUCKFOX PICO MINI rv1103脱离sdk的例程使用cmake编写工程
主要介绍了从阅读了LUCKFOX PICO MINI SDK的meidia模块编译流程到写自己的cmake文件的这个过程,注意这个的前提是自己已经编译成功过了sdk,因为你只有编程成功了sdk,在你的sdk out目录里才会有编译好的动态库、头文件等,这个文档主要是自己分析文件的过程,自己阅读编译流程的时候,要想好最后怎么化简这个编译流程,最后写到cmake文件里。luckfox 魔改的官方sdk里主要使用了大量的makefile来管理编译流程,咱们自己写代码可以根据它的编译流程来用cmake进行编译。 后边随着项目继续的进行,我也会继续分享,主要针对不了解rockchip平台的新手同志。
主要思路是从media模块的顶层makefile到rockit的example的最底层的cmake
media模块编译流程
在luckfox的SDK里,有单独编译media这么一个模块,下面来详细分析一下这个模块是如何编译的,编译过程中做了哪些控制,配置了哪些参数,便于以后修改。
目录结构
.
├── alsa-lib
├── avs
├── cfg
├── common_algorithm
├── isp
├── iva
├── ive
├── libdrm
├── libv4l
├── luckfox
├── Makefile
├── Makefile.param
├── mpp
├── out
├── readme_cn.txt
├── readme_en.txt
├── rga
├── rockit
├── samples
├── security
└── sysutils
看到这个目录首先就要看的是readme_cn.txt
如下:
readme文件
具体命令如下:
(1)编译整个media目录:
make clean
make
(2)查看编译配置
make info
(3)清除整个media目录的编译文件:
make clean
(4)单独编译各个模块:
举例:编译RKAIQ(即isp目录)模块
(4.1) 先确认cfg/cfg.mk 里已配置 CONFIG_RK_RKAIQ=y
(4.2) cd isp; make clean; make
- 编译生成的文件存放目录说明
out
├── avs_calib --------------------------------- 全景拼接标定数据
├── bin---------------------------------------- 各个模块的测试sample
├── include------------------------------------ 各个模块的头文件
├── isp_iqfiles-------------------------------- Camera Sensor的IQ文件
├── lib---------------------------------------- 各个模块的库件
├── root--------------------------------------- 必须放在根文件系统里的对应目录的文件
└── share-------------------------------------- 各个模块的配置文件
3. media目录结构说明:
media
├── alsa-lib----------------------------------- Advanced Linux Sound Architecture (ALSA) library
├── cfg/cfg.mk--------------------------------- 针对不同SOC平台配置不同模块
├── common_algorithm--------------------------- 音频3A算法、移动检测、遮挡检测
├── isp---------------------------------------- isp图像处理算法
├── libdrm------------------------------------- Direct Rendering Manager
├── libv4l------------------------------------- video4linux2设备用户层接口
├── Makefile----------------------------------- media Makefile
├── Makefile.param----------------------------- media Makefile的配置文件
├── out---------------------------------------- media 编译输出目录
├── rga---------------------------------------- RGA是一个独立的2D硬件加速器,可用于加速点和线绘制
│ 执行图像缩放、旋转、bitBlt、alpha混合等常见的2D图形操作
│
├── mpp---------------------------------------- 编解码接口,给rkmedia和rockit调用,不建议直接调用mpp
├── rkmedia------------------------------------ 多媒体处理框架,封装isp、rga、mpp等多媒体相关接口(适用部分平台)
└── rockit------------------------------------- 多媒体处理框架,和rkmedia是两套对外的接口
其中需要注意的是两个文件cfg.mk和Makefile.param两个文件,这两个文件一个是控制是否编译哪个模块,一个是用来配置编译过程中的一些参数,例如去哪找到编译过程中的动态库、头文件和工具链等。
然后其次要注意的是这个readme中写了rkmedia,这个rkmeida在这个平台并没有,一般rv1126用的比较多,现在rockchip主推的是rockit,rockit调用了mpp等较为底层的接口,可以实现媒体的一些操作,后续会进行讲解。
rga比较重要,这个可以实现硬件的一些图形操作,可以看到luckfox的sdk里是直接放了release版本的,并且在cfg.mk中有是否包含libdrm。其他的模块按照需要进行编译
下面开始分析主目录的makefile文件:
MAKEFILE_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
export LC_ALL=C
SHELL:=/bin/bash
MAKE=make
AT?=@
这几行比较常见,赋值了几个量
ifneq ($(RK_TOOLCHAIN_CROSS),)
RK_MEDIA_CROSS:= $(RK_TOOLCHAIN_CROSS)
endif
这个判断一下如果RK_TOOLCHAIN_CROSS不为空,RK_MEDIA_CROSS就为RK_TOOLCHAIN_CROSS,
前者在boadconfig中可以找到,
Target Toolchain Cross Compile
export RK_TOOLCHAIN_CROSS=arm-rockchip830-linux-uclibcgnueabihf
也就是RK_MEDIA_CROSS=arm-rockchip830-linux-uclibcgnueabihf
Public Configuraton
include $(MAKEFILE_DIR)/Makefile.param
media_src := $(wildcard ./*/Makefile)
media_src := $(dir $(media_src))
第一行包含参数文件,
第二行:找到当前目录下所有子目录中的 Makefile 文件。
第三行:从这些 Makefile 文件的路径中提取出它们的父目录路径。
这在Makefile中是一种常见的模式,用于处理文件集合,尤其是在需要对一组目录中的Makefile进行操作时
build target
这个Makefile片段定义了几个目标(targets),每个目标都对应一系列的命令,这些命令在执行make命令时可以被调用,主要就看all这个命令,可以看到是到每个文件夹下来执行make
all
all:
@rm -rf $(RK_MEDIA_OUTPUT)
$(foreach target,$(media_src),make -C $(target)||exit -1;)
$(call MAROC_COPY_PKG_TO_MEDIA_OUTPUT, $(RK_PROJECT_PATH_MEDIA), $(RK_MEDIA_OUTPUT))
首先,使用 rm -rf $(RK_MEDIA_OUTPUT)
删除输出目录,确保从干净的状态开始。
然后,使用 foreach 循环对 media_src 变量包含的每个目录执行make -C $(target)
命令,-C 参数指定了要切换到的目录。如果任何一个 make 命令失败(返回非0状态),则执行 exit -1 退出整个构建过程。
最后,调用 MAROC_COPY_PKG_TO_MEDIA_OUTPUT 函数,将构建产物复制到指定的输出目录。
参数文件
开始到25行左右主要配置了:
RK_MEDIA_CROSS
RK_MEDIA_CHIP
确保这两个已经定义并且没有问题
RK_MEDIA_OPTS := -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
这个参数主要是对大文件的支持,如果大于2GB需要这个参数
然后根据定义的工具链arm-rockchip830-linux-uclibcgnueabihf
RK_MEDIA_LIB_TYPE := uclibc
RK_MEDIA_ARCH_TYPE := arm
RK_MEDIA_CROSS_CFLAGS += -march=armv7-a -mfpu=neon -mfloat-abi=hard
uClibc是一个小型的C标准库,专为嵌入式Linux系统设计。它比GNU C Library(glibc)小得多,专注于嵌入式Linux,很多功能可以根据空间需求进行取舍,因为rv1103内存有限,不能用完整的glibc
翻到程序最后:
export RK_MEDIA_CHIP
export RK_MEDIA_CROSS
export RK_MEDIA_CROSS_CFLAGS
export RK_MEDIA_ARCH_TYPE
export RK_MEDIA_OPTS
export RK_MEDIA_OUTPUT
export RK_MEDIA_TOP_DIR
可以看到这个程序主要定义了这些的参数
RK_MEDIA_CHIP = rv1106 (它是由RK_CHIP决定的, boardconfig,虽然编译的rv1103但是也是按照rv1106来的)
RK_MEDIA_CROSS = arm-rockchip830-linux-uclibcgnueabihf
RK_MEDIA_CROSS_CFLAGS =-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -march=armv7-a -mfpu=neon -mfloat-abi=hard
RK_MEDIA_ARCH_TYPE = arm
RK_MEDIA_OPTS = -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
RK_MEDIA_OUTPUT = ./out
RK_MEDIA_TOP_DIR = ./
模块编译
rockit
先看makefile文件,
首先包含参数文件,然后指定包名,构建目录,输出目录,然后给RK_MEDIA_OPTS附加了几个参数
-Wl,-rpath-link,${RK_MEDIA_OUTPUT}/lib:$(RK_MEDIA_OUTPUT)/root/usr/lib
-Wl 表示后面跟随的是链接器的选项。
-rpath-link 后面通常会跟一个或多个目录路径,这些路径是链接器在链接过程中搜索库文件时应该考虑的。这与 -rpath 参数不同,-rpath 是用来设置程序运行时搜索库的路径,而 -rpath-link 仅影响链接时的行为。
然后设置的是PKG_CONF_OPTS
里边主要就是C和CXX的FLAGS,这俩是一样的现在来看
PKG_CONF_OPTS =
-DCMAKE_C_FLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-Wl,-rpath-link,${RK_MEDIA_OUTPUT}/lib:$(RK_MEDIA_OUTPUT)/root/usr/lib
-DCMAKE_CXX_FLAGS=-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-Wl,-rpath-link,${RK_MEDIA_OUTPUT}/lib:$(RK_MEDIA_OUTPUT)/root/usr/lib
-DRKPLATFORM=ON
-DARCH64=OFF
-DUSE_ROCKIT_TGI
在最后编译时参数如下:
-DCMAKE_C_COMPILER=$(RK_MEDIA_CROSS)-gcc \
-DCMAKE_CXX_COMPILER=$(RK_MEDIA_CROSS)-g++ \
-DCMAKE_INSTALL_PREFIX="$(CURRENT_DIR)/$(PKG_BIN)" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_COLOR_MAKEFILE=OFF \
-DBUILD_DOC=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_EXAMPLE=OFF \
-DBUILD_EXAMPLES=OFF \
-DBUILD_TESTS=OFF \
-DBUILD_TESTING=OFF \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_SYSTEM_NAME=Linux \
$(PKG_CONF_OPTS) \
-DARCH="$(RK_MEDIA_ARCH_TYPE)" ;\
然后开始看mpi的CMakeLists
最顶层的设置了以下:
ROCKIT_DEP_COMMON_LIBS
ROCKIT_DEP_COMMON_LIBS_STATIC
ROCKIT_FILE_LIBS
这三个参数的设置和是不是64位系统有关
ROCKIT_DUMPSYS_FILE
然后就进入到子目录进行编译
我们进入到example目录
首先添加一些编译参数
然后关键的就是ROCKIT_DEP_COMMON_LIBS
set(ROCKIT_DEP_COMMON_LIBS
${ROCKIT_DEP_COMMON_LIBS}
-lpthread
${RT_TEST_COMM_STATIC}
)
第一参数就是librockit.so的lib位置
第二参数就是-lpthread 线程支持
第三参数RT_TEST_COMM_STATIC 这个是common编译的库位置
因为rockit的测试用例里写了一些common函数,这些函数是test用例使用的
下面再进入到子目录进行编译
common
可以看到就编译了一个静态库,这个静态库最后不会拷贝到用户机器上,只在编译过程中用,如果脱离这个项目想使用这个库的话可以在sdk/luckfox-pico/media/rockit/build/mpi/example/common/librt_test_comm.a这个位置找到这个静态库
了解到这里以后就可以着手编写一个cmake文件来执行上边的一些编译过程从而可以单独编译一个应用文件而脱离sdk的编译过程
编译自己的CMAKE
目录设置
.
├── build
├── CMakeLists.txt
├── cross
├── main.c
└── readme.md
main.c
#include <stdio.h>
#include "rk_defines.h"
#include "rk_debug.h"
#include "rk_mpi_vi.h"
#include "rk_mpi_mb.h"
#include "rk_mpi_sys.h"
#include "rk_mpi_venc.h"
#include "rk_mpi_vpss.h"
#include "rk_mpi_vo.h"
#include "rk_mpi_rgn.h"
#include "rk_mpi_cal.h"
#include "rk_mpi_ivs.h"
#include "rk_common.h"
#include "rk_comm_rgn.h"
#include "rk_comm_vi.h"
#include "rk_comm_vo.h"
#include "rk_comm_ivs.h"
int main(){
RK_MPI_SYS_Init();
return 0;
}
cmakelists.txt
使用的时候记得替换你自己的sdk目录
cmake_minimum_required(VERSION 3.10)
set(SDK_PATH /home/eleclong/sdk)#记得替换成你自己的sdk地址
# 设置编译类型
set(CMAKE_BUILD_TYPE Release)
# 禁用颜色输出
set(CMAKE_COLOR_MAKEFILE OFF)
# 编译器设置,
set(RK_MEDIA_CROSS "${SDK_PATH}/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf")
set(CMAKE_C_COMPILER "${RK_MEDIA_CROSS}-gcc")
set(CMAKE_CXX_COMPILER "${RK_MEDIA_CROSS}-g++")
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_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT "${SDK_PATH}/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/arm-rockchip830-linux-uclibcgnueabihf/sysroot")
# 其他选项
set(RK_MEDIA_OUTPUT "${SDK_PATH}/luckfox-pico/output/out/media_out")
# set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${PKG_BIN}")
# 编译器标志
set(CMAKE_C_FLAGS "-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -march=armv7-a -mfpu=neon -mfloat-abi=hard -Wl,-rpath-link,${RK_MEDIA_OUTPUT}/lib:$(RK_MEDIA_OUTPUT)/root/usr/lib ")
set(CMAKE_CXX_FLAGS "-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -march=armv7-a -mfpu=neon -mfloat-abi=hard -Wl,-rpath-link,${RK_MEDIA_OUTPUT}/lib:$(RK_MEDIA_OUTPUT)/root/usr/lib ")
# 启用共享库的构建
set(BUILD_SHARED_LIBS ON)
# 其他定义
set(RKPLATFORM ON)
set(ARCH64 OFF)
set(USE_ROCKIT_TGI ON)
set(ARCH "arm")
# 如果是c++
# add_definitions(-fno-rtti)
# add_compile_options(-std=c++11)
# add_definitions(-std=c++11 -Wno-attributes -Wno-deprecated-declarations -DANDROID_STL=c++_shared)
project(MyProject VERSION 1.0)
set(PROJECT_NAME test)
set(SOURCE_FILES main.c)
include_directories(${RK_MEDIA_OUTPUT}/include
)
#如果要使用rockit demo中的comm里一些函数需要自己包含静态库
# set(RT_TEST_COMM_STATIC rt_test_comm)
set(ROCKIT_DEP_COMMON_LIBS
${RK_MEDIA_OUTPUT}/lib/librockit.so
)
#需要链接的库
set(MY_PROJECT_LIBS
${ROCKIT_DEP_COMMON_LIBS}
-lpthread
)
# 添加可执行文件
add_executable(${PROJECT_NAME} ${SOURCE_FILES})
# 链接动态库
target_link_libraries(${PROJECT_NAME}
${MY_PROJECT_LIBS}
)