搭建交叉编译环境--RK3588示范

Makefile交叉编译环境

1.环境脚本 buildenv.sh

# 1.代码路径
sourceDir=/home/liuj/3_work/ok3588-linux-source/

# 2.交叉编译 rootfs 链接库
syslib=$sourceDir/buildroot/output/OK3588-Ubuntu/target/lib
usrlib=$sourceDir/buildroot/output/OK3588-Ubuntu/target/usr/lib
export CROSS_LIB="-L$syslib -L$usrlib"

# 3.导出环境
export PATH=$sourceDir/buildroot/output/OK3588-Ubuntu/host/bin:$PATH
export CROSS_COMPILE=aarch64-linux-
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
export LD=${CROSS_COMPILE}ld
export AR=${CROSS_COMPILE}ar
export AS=${CROSS_COMPILE}as
export STRIP=${CROSS_COMPILE}strip
export ARCH=arm64

# CROSS_COMPILE 交叉编译
# AR   函数库打包程序,可创建静态库.a文档默认是"ar"
# AS   汇编程序默认是"as"
# CC   C编译程序默认是"cc"
# CXX  C++编译程序默认是"g++"
# CPP  C/C++预处理器默认是"$(CC) -E"
# FC   Fortran编译器默认是"f77"
# PC   Pascal语言编译器默认是"pc"
# YACC Yacc文法分析器默认是"yacc"

# ARFLAGS     函数库打包程序的命令行参数默认值是"rv"
# ASFLAGS     汇编程序的命令行参数
# CFLAGS      C编译程序的命令行参数
# CXXFLAGS    C++编译程序的命令行参数
# CPPFLAGS    C/C++预处理器的命令行参数
# FFLAGS      Fortran编译器的命令行参数
# PFLAGS      Pascal编译器的命令行参数
# YFLAGS      Yacc文法分析器的命令行参数
# LDFLAGS     链接器的命令行参数

初始化环境变量souce ./buildenv.sh

查看环境变量设置正确性
echo $CC

aarch64-linux-gcc –OK

echo $PATH

/home/liuj/3_work/ok3588-linux-source//buildroot/output/OK3588-Ubuntu/host/bin:/opt/ros/noetic/bin:/home/liuj/.vscode-server/bin/d045a5eda657f4d7b676dedbfa7aab8207f8a075/bin/remote-cli:/home/liuj/.local/bin:/home/liuj/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/liuj/bin:/home/liuj/bin

交叉变量变量gcc路径 添加到PATH中.

2.交叉编译-应用程序

hello.c

#include 

void main()
{
    printf("Hello world!!\n");
}

Makefile

default:
	$(CC) hello.c -o hello

clean:
	rm *.o $(target)

初始化环境变量souce ./buildenv.sh
编译 make

aarch64-linux-gcc hello.c -o hello

检测可执行文件 file hello

hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped

确认编译为 aarch64 的可执行文件.
拷贝到开发板运行正常.

3.交叉编译-内核模块

hello.c

#include 
#include 
#include 

static int __init init_my_module(void) {
  printk(KERN_INFO "Hello, my module!\n");
  return 0;
}

static void __exit exit_my_module(void) {
  printk(KERN_INFO "Bye, my module!\n");
}

module_init(init_my_module);
module_exit(exit_my_module);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("liu jiang");

Makefile
交叉编译内核模块,需要设置下面3个变量
KERNEL_DIR 内核代码位置
ARCH 平台架构
CROSS_COMPILE 交叉编译前缀

KERNEL_DIR=/home/liuj/3_work/ok3588-linux-source/kernel/
ARCH=arm64
CROSS_COMPILE=aarch64-linux-

obj-m += hello.o
all:
	make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL_DIR)/build M=$(PWD) modules
clean:
	make ARCH=$(ARCH) -C $(KERNEL_DIR)/build M=$(PWD) clean

初始化环境变量souce ./buildenv.sh
cd /hello-ko
make

make ARCH=arm64 -C /home/liuj/3_work/ok3588-linux-source/buildroot/output/OK3588-Ubuntu/target/lib/modules/5.10.66/build M=/home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko modules
make[1]: Entering directory ‘/home/liuj/3_work/ok3588-linux-source/kernel’
CC [M] /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/hello.o
MODPOST /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/Module.symvers
CC [M] /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/hello.mod.o
LD [M] /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/hello.ko
make[1]: Leaving directory ‘/home/liuj/3_work/ok3588-linux-source/kernel’

编译内核模块遇到的错误

make -C /home/liuj/3_work/ok3588-linux-source/buildroot/output/OK3588-Ubuntu/target/lib/modules/5.10.66/build M=/home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko modules
make[1]: Entering directory ‘/home/liuj/3_work/ok3588-linux-source/kernel’
CC [M] /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/hello.o
aarch64-none-linux-gnu-gcc: error: unrecognized argument in option ‘-mcmodel=kernel’
aarch64-none-linux-gnu-gcc: note: valid arguments to ‘-mcmodel=’ are: large small tiny
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-mno-sse’; did you mean ‘-fno-dse’?
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-mno-mmx’
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-mno-sse2’
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-mno-3dnow’
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-m64’
aarch64-none-linux-gnu-gcc: error: unrecognized command-line option ‘-mno-red-zone’
make[2]: *** [scripts/Makefile.build:273: /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko/hello.o] Error 1
make[1]: *** [Makefile:1915: /home/liuj/3_work/ok3588-linux-source/oem/kernel/hello-ko] Error 2
make[1]: Leaving directory ‘/home/liuj/3_work/ok3588-linux-source/kernel’
make: *** [Makefile:10: all] Error 2

解决方法
Makefile 添加ARCH=arm64, CROSS_COMPILE=aarch64-none-linux-gnu-

-- make -C $(KERNEL_DIR)/build M=$(PWD) modules
++ make ARCH=$(OEM_ARCH) CROSS_COMPILE=$(OEM_CROSS_COMPILE) -C $(KERNEL_DIR)/build M=$(PWD) modules

实例

1.RK3588适配RTL8821CU wifi模块驱动

代码: https://github.com/KwanWaiPang/8821cu.git
修改:
Makefile配置

# 选定wifi芯片
CONFIG_RTL8821C = y
# 选定USB接口模式
CONFIG_USB_HCI = y
# 选定arm64平台
CONFIG_PLATFORM_ARM64_RPI = y

Makefile修改
修改ARCH, CROSS_COMPILE, KSRC内核代码位置

ifeq ($(CONFIG_PLATFORM_ARM64_RPI), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
 EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
 EXTRA_CFLAGS += -fno-stack-protector
 ARCH ?= arm64
-CROSS_COMPILE ?=
+CROSS_COMPILE ?= aarch64-none-linux-gnu-
 KVER ?= $(shell uname -r)
-KSRC := /lib/modules/$(KVER)/build
-MODDESTDIR := /lib/modules/$(KVER)/kernel/drivers/net/wireless/
+# KSRC := /lib/modules/$(KVER)/build
+KSRC := /home/liuj/3_work/ok3588-linux-source/kernel
+MODDESTDIR := /lib/modules/5.10.66/kernel/drivers/net/wireless/
 INSTALL_PREFIX :=
 endif

检查Makefile参数

all: modules
modules:
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KSRC) M=$(shell pwd)  modules

souce ./buildenv.sh # 初始化环境变量
cd 8821cu # 进入8821 wifi驱动代码
make
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- -C /home/liuj/3_work/ok3588-linux-source/kernel M=/home/liuj/3_work/ok3588-linux-source/external/8821cu modules
make[1]: Entering directory ‘/home/liuj/3_work/ok3588-linux-source/kernel’

检查输出ARCH, CROSS_COMPILE, kernel目录 正确

示例: PC x86_64编译对比

make
make ARCH=x86_64 CROSS_COMPILE= -C /lib/modules/5.15.0-46-generic/build M=/home/liuj/3_work/8821cu modules

总结

1.待解决问题: 依赖其它库如何配置
如依赖libjson, libopenssl, libopencv2, 自己写得库

Makefile

  1. 配置编译选项 CFLAGS
    CFLAGS += -I buildr/rootfs/usr/include #指定生成头文件路径

gcc -o demo.o -c -I buildr/rootfs/usr/include demo.c
g++ -o demo.o -c -I buildr/rootfs/usr/include demo.cpp

  1. 配置链接选项 LDFLAGS
    -L 优先链接路径
    -l 库
    -Wl,-rpath 运行链接路径
    指定链接路径: -L build/rootfs/usr/lib
    指定运行链接路径: -Wl,-rpath=build/rootfs/usr/lib
    指定链接库: -ljson -l
    LDFLAGS = -L build/rootfs/usr/lib -Wl,-rpath=build/rootfs/usr/lib -ljson -l

示例
g++ -o demo demo.o $(LDFLAGS)

g++ -o demo demo.o -Wl,–copy-dt-needed-entries -Wl,-rpath=build/rootfs/usr/lib -L build/rootfs/usr/lib -ljson

示例:

LDFLAGS = -L./lib # 将当前目录下的 lib文件夹添加到库文件搜索目录
LDFLAGS += $(CROSS_LIB) # 将buildenv.sh 的rootfs lib usr/lib 库目录添加

cmake: 可以配置
LIBPATH : 链接库路径
LIBS : 链接库

scons配置

编译选项

env[‘CCFLAGS’] = ros_include
#调试选项开关
#env[‘CCFLAGS’] += ’ -ggdb3 -O0 -DDEBUG’

链接选项

env[‘LIBPATH’] = ros_libdir
env[‘LIBPATH’] += ‘-L/var/xxx/lib -L/opt/mysql/lib’
env[‘LIBS’] = ros_lib_dep
env[‘RPATH’] = ros_libdir
env[‘LINKFLAGS’] = ‘-Wl,–copy-dt-needed-entries’

还可以参考: scons 单独编译ros程序

2.搭建交叉编译环境,本质上是要熟悉编译,链接的过程,和gcc/g++, 编译链接的参数选项.


个人签名
一个linux-网络-系统-固件-内核驱动-嵌入式-机器人开发工程师

个人微信
搭建交叉编译环境--RK3588示范_第1张图片

你可能感兴趣的:(linux,各子系统,编译,linux,编译,交叉编译)