# 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中.
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 的可执行文件.
拷贝到开发板运行正常.
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
代码: 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
gcc -o demo.o -c -I buildr/rootfs/usr/include demo.c
g++ -o demo.o -c -I buildr/rootfs/usr/include demo.cpp
示例
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 : 链接库
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-网络-系统-固件-内核驱动-嵌入式-机器人开发工程师