首页 > 其他分享 >交叉编译项目设置

交叉编译项目设置

时间:2023-11-26 12:22:37浏览次数:31  
标签:交叉 AbsoluteSrcPath TargetObjPath 编译 设置 PATH DEC OS

交叉编译项目设置

编译目录结构

build               主目录
├── deb             存放打包脚本所生成的deb包
├── deps            存放系统驱动头文件
├── obj             存放交叉编译产生的中间文件
├── output          存放交叉编译产生的目标文件
├── scripts         存放交叉编译脚本和打包脚本
└── src             存放项目源码

实现的要求

1:将项目编译所生成的中间文件和目标文件与源码分离

2:使用同一份源码调用相应的编译环境生成不同架构的驱动和应用

交叉编译脚本CrossedCompile.sh

#!/bin/bash

BUILD_PATH=$([[ "$0" = /* ]] && echo "$(realpath $(dirname $0)/../)" || echo "$(realpath $(dirname $PWD/$0)/../)")
DEPS_PATH=${BUILD_PATH}/deps
OBJ_PATH=${BUILD_PATH}/obj
SRC_PATH=${BUILD_PATH}/src
OUTPUT_PATH=${BUILD_PATH}/output

MKDIR="mkdir -p"
RMDIR="rm -rf"
LINK="ln -sf"
QMAKE=qmake
MAKE="make -j16"

function CompileApplication()
{
    case ${1} in
    x86_64)
        QMAKE="qmake_x86_64";;
    aarch64)
        QMAKE="qmake_aarch64";;
    loongarch64)
        QMAKE="qmake_loongarch64";;
    mips64)
        QMAKE="qmake_mips64";;
    *)
    return 1;;
    esac
    local AbsoluteSrcPath=${2}
    if [[ "${AbsoluteSrcPath}" = /* ]]; then
        AbsoluteSrcPath=$(realpath -s ${AbsoluteSrcPath})
    else
        AbsoluteSrcPath=$(realpath -s $(dirname ${PWD}/${AbsoluteSrcPath}))
    fi
    local TargetObjPath=$(echo ${AbsoluteSrcPath} | sed "s#${SRC_PATH}#${OBJ_PATH}/${1}#")
    local TargetOutputPath=$(echo ${AbsoluteSrcPath} | sed "s#${SRC_PATH}#${OUTPUT_PATH}/${1}#")
    if [ -d ${AbsoluteSrcPath} ]; then
        if [ -f ${AbsoluteSrcPath}/*.pro ]; then
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            cd ${TargetObjPath} && ${QMAKE} "DESTDIR=${TargetOutputPath}" "LIBS+=-L${TargetOutputPath}" -o Makefile $(ls ${AbsoluteSrcPath}/*.pro) && make
        elif [ -f $(ls ${AbsoluteSrcPath}/Makefile) ]; then
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            ${LINK} ${AbsoluteSrcPath}/Makefile ${TargetObjPath}
            cd ${TargetObjPath} && ${MAKE} ARCH=${1} OBJ_PATH=${TargetObjPath} OUTPUT_PATH=${TargetOutputPath}
        else
            echo "编译失败: 目录(${AbsoluteSrcPath})没有可编译的项目"
            return 1
        fi
    elif [ -f ${AbsoluteSrcPath} ]; then
        if [[ "${AbsoluteSrcPath}" = *.pro ]]; then
            TargetObjPath=$(dirname ${TargetObjPath})
            TargetOutputPath=$(dirname ${TargetOutputPath})
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            cd ${TargetObjPath} && ${QMAKE} "DESTDIR=${TargetOutputPath}" "LIBS+=-L${TargetOutputPath}" -o Makefile ${AbsoluteSrcPath} && make
        elif [[ "${AbsoluteSrcPath}" = */Makefile ]]; then
            TargetObjPath=$(dirname ${TargetObjPath})
            TargetOutputPath=$(dirname ${TargetOutputPath})
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            ${LINK} ${AbsoluteSrcPath} ${TargetObjPath}
            cd ${TargetObjPath} && ${MAKE} ARCH=${1} OBJ_PATH=${TargetObjPath} OUTPUT_PATH=${TargetOutputPath}
        else
            echo "编译失败: 项目文件(${AbsoluteSrcPath})无可用编译应用"
            return 1
        fi
    else
        echo "编译失败: 路径(${AbsoluteSrcPath})不存在"
        return 1
    fi
}

function CompileDriver()
{
    local AbsoluteSrcPath=${3}
    local Arch=${1}

    case ${1} in
    x86_64)
        Arch="x86";;
    aarch64)
        Arch="arm64";;
    loongarch64)
        Arch="loongarch64";;
    mips64)
        Arch="mips";;
    *)
    return 1;;
    esac
    

    if [[ "${AbsoluteSrcPath}" = /* ]]; then
        AbsoluteSrcPath=$(realpath -s ${AbsoluteSrcPath})
    else
        AbsoluteSrcPath=$(realpath -s $(dirname ${PWD}/${AbsoluteSrcPath}))
    fi

    local TargetObjPath=$(echo ${AbsoluteSrcPath} | sed "s#${SRC_PATH}#${OBJ_PATH}/${1}#")
    local TargetOutputPath=$(echo ${AbsoluteSrcPath} | sed "s#${SRC_PATH}#${OUTPUT_PATH}/${1}#")
    if [ -d ${AbsoluteSrcPath} ]; then
        if [ -f ${AbsoluteSrcPath}/Makefile ]; then
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            ${LINK} ${AbsoluteSrcPath}/Makefile ${TargetObjPath}
            cd ${TargetObjPath} && ${MAKE} DEC_OS_DRIVER_ARCH=${Arch} DEC_OS_HEADER_PATH=${2} DEC_OS_CROSS_COMPILE=${1}-linux-gnu- DEC_OS_OUTPUT_PATH=${TargetOutputPath}
        else
            echo "编译失败: 目录(${AbsoluteSrcPath})没有可编译的驱动"
            return 1
        fi
    elif [ -f ${AbsoluteSrcPath} ]; then
        if [[ "${AbsoluteSrcPath}" = */Makefile ]]; then
            TargetObjPath=$(dirname ${TargetObjPath})
            TargetOutputPath=$(dirname ${TargetOutputPath})
            ${MKDIR} ${TargetObjPath} ${TargetOutputPath}
            ${LINK} ${AbsoluteSrcPath} ${TargetObjPath}
            cd ${TargetObjPath} && ${MAKE} DEC_OS_DRIVER_ARCH=${Arch} DEC_OS_HEADER_PATH=${2} DEC_OS_CROSS_COMPILE=${1}-linux-gnu- DEC_OS_OUTPUT_PATH=${TargetOutputPath}
        else
            echo "编译失败: 项目文件(${AbsoluteSrcPath})无可用编译策略"
            return 1
        fi
    else
        echo "编译失败: 路径(${AbsoluteSrcPath})不存在"
        return 1
    fi
}


argv=()
argc=1

argv[0]=${0}
for value in ${@}
do
    argv[argc]=${value}
    let argc++
done

if [ ${argc} -gt 4 ] && [ "${1}" = "km" ]; then
    for ((i=4; i<${argc}; ++i))
    do
        printf "编译驱动 %12s架构 系统头文件路径(%s) 源码路径(%s)\n" ${argv[2]} ${argv[3]} ${argv[${i}]}
        CompileDriver ${argv[2]} ${argv[3]} ${argv[${i}]}
    done 
elif [ ${argc} -gt 3 ] && [ "${1}" = "um" ]; then
    for ((i=3; i<${argc}; ++i))
    do
        printf "编译应用 %12s架构 源码路径(%s)\n" ${argv[2]} ${argv[${i}]}
        CompileApplication ${argv[2]} ${argv[${i}]}
    done 
else
    echo "编译驱动: ${argv[0]} km 系统架构(x86_64/aarch64/loongarch64) 系统头文件路径 源码路径1 源码路径2 源码路径3 ..."
    echo "编译应用: ${argv[0]} um 系统架构(x86_64/aarch64/loongarch64) 源码路径1 源码路径2 源码路径3 ..."
fi

作用:

编译应用和驱动时,由源码路径确定中间文件和目标文件在obj和output目录的相应位置,并传给Makefile或qmake实现中间文件和目标文件与源码分离,并加入架构参数实现同一份源码在使用不同架构的编译环境时,目标文件和中间文件相隔离。

参数 1: um(编译应用) 或 km(编译驱动)

参数2: x86_64、 aarch64 、 loongarch64 或 mips64

参数3:编译应用时可输入源码文件夹的绝对路径,pro文件的绝对路径或Makefile的绝对路径。

​ 编译驱动时可输入源码文件夹的绝对路径或Makefile的绝对路径。

注意事项:

编译应用时:

若参数3输入的是pro文件的绝对路径,则会调用相应建构的qmake程序在obj目录的对应子目录底下生成Makefile文件。

若参数3输入的是Makefile文件的绝对路径,则会在obj目录的对应子目录底下生成所指定的Makefile文件的软连接。

若参数3输入的源码文件夹的绝对路径,则会优先使用源码文件夹中的pro文件,因此需要保证源码文件夹中只存在一个pro文件

若pro文件中不存在pro文件,则会查找源码文件夹中的Makefile文件。

编译驱动时:

若参数3输入的是Makefile文件的绝对路径,则会在obj目录的对应子目录底下生成所指定的Makefile文件的软连接。

若参数3输入的源码文件夹的绝对路径,则会查找源码文件夹中的Makefile文件。
由于目标文件被分离到output目录,因此若pro工程中要使用内部库,则要对pro文件的内部库路径设置进行修改,增加exists函数对内部库的路径进行判断。
exists($$OUT_PWD/../deccryptobase/libdeccryptobase.a): {
    unix:!macx: LIBS += -L$$OUT_PWD/../deccryptobase/ -ldeccryptobase
    unix:!macx: PRE_TARGETDEPS += $$OUT_PWD/../deccryptobase/libdeccryptobase.a
}

exists($$DESTDIR/libdeccryptobase.a): {
    unix:!macx: LIBS += -L$$DESTDIR/ -ldeccryptobase
    unix:!macx: PRE_TARGETDEPS += $$DESTDIR/libdeccryptobase.a
}

Makefile示例

编译应用

ARCH        ?= $(shell arch)
SOURCE_PATH ?= $(shell realpath $(dir $(shell realpath `pwd`/Makefile)))
OBJ_PATH    ?= $(shell pwd)
OUTPUT_PATH ?= $(shell pwd)
TARGET      ?= $(shell echo $(SOURCE_PATH) | awk -F '/' '{ print $$NF }')

CC     := ${ARCH}-linux-gnu-gcc
CXX    := ${ARCH}-linux-gnu-g++
LINKER := $(CC)

CC_FLAGS  := -I$(SOURCE_PATH)
CXX_FLAGS := -I$(SOURCE_PATH)

DIRS 	   := $(shell find $(SOURCE_PATH) -maxdepth 1 -type d)
C_SOURCE   := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))
CXX_SOURCE := $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp))


C_OBJS   := $(patsubst $(SOURCE_PATH)%.c,$(OBJ_PATH)%-c.o,$(C_SOURCE))
CXX_OBJS := $(patsubst $(SOURCE_PATH)%.cpp,$(OBJ_PATH)%-cxx.o,$(CXX_SOURCE))


target: $(C_OBJS) $(CXX_OBJS)
	if [ ! -d $(OUTPUT_PATH) ]; then mkdir -p $(OUTPUT_PATH); fi
	${LINKER} -o $(OUTPUT_PATH)/$(TARGET) $(C_OBJS) $(CXX_OBJS) $(CC_FLAGS) 

$(OBJ_PATH)/%-c.o : $(SOURCE_PATH)/%.c
	if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
	${CC}  -c $(CC_FLAGS)  -o $@ $<

$(OBJ_PATH)/%-cxx.o : $(SOURCE_PATH)/%.cpp
	if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
	${CXX} -c $(CXX_FLAGS) -o $@ $<
	LINKER=$(CXX)

test:
	@echo "C_SOURCE:    $(C_SOURCE)"
	@echo "CXX_SOURCE:  $(CXX_SOURCE)"
	@echo "C_OBJS:      $(C_OBJS)"
	@echo "CXX_OBJS:    $(CXX_OBJS)"
	@echo "SOURCE_PATH: $(SOURCE_PATH)"
	@echo "OBJ_PATH:    $(OBJ_PATH)"
	@echo "OUTPUT_PATH: $(OUTPUT_PATH)"
	@echo "TARGET:      $(TARGET)"

clean:
	rm -f $(OUTPUT_PATH)/${TARGET} $(C_OBJS) $(CXX_OBJS)

介绍

自动搜索当前目录及其目录底下的cpp文件和c文件并在OBJ_PATH目录底下生成中间文件,在OUTPUT_PATH底下生成目标文件。ARCH、SOURCE_PATH、OBJ_PATH、OUTPUT_PATH 和 TARGET由交叉编译脚本传入,若不设置则使用默认值。

编译驱动

DEC_OS_DRIVER_ARCH   ?= x86
DEC_OS_HEADER_PATH   ?= /lib/modules/`uname -r`/build
DEC_OS_CROSS_COMPILE ?= `arch`-linux-gnu-
DEC_OS_OUTPUT_PATH   ?= `pwd`

SOURCE_PATH := $(dir $(shell realpath `pwd`/Makefile))

MOD_NAME := target
obj-m := $(MOD_NAME).o
$(MOD_NAME)-objs := a.o b.o c.o

all:
	make -C $(DEC_OS_HEADER_PATH) M=`pwd` src=$(SOURCE_PATH) modules ARCH=$(DEC_OS_DRIVER_ARCH) CROSS_COMPILE=${DEC_OS_CROSS_COMPILE} && mv -f ${MOD_NAME}.ko ${DEC_OS_OUTPUT_PATH}
clean:
	make -C $(DEC_OS_HEADER_PATH) M=`pwd` src=$(SOURCE_PATH) clean   ARCH=$(DEC_OS_DRIVER_ARCH) CROSS_COMPILE=${DEC_OS_CROSS_COMPILE}
test:
	${DEC_OS_CROSS_COMPILE}gcc $(SOURCE_PATH)/testko.c -o testko

介绍

DEC_OS_DRIVER_ARCH、DEC_OS_HEADER_PATH、DEC_OS_CROSS_COMPILE 和 DEC_OS_OUTPUT_PATH由交叉编译脚本传入,若为空则使用默认值,使用时只需将$(MOD_NAME)-objs变量修改为各个驱动工程实际所需编译的的.o文件。

交叉编译环境目录结构设计

x86_64架构

/usr/bin/x86_64-linux-gnu-*

qmake_x86_64 -> /opt/x86_64/qt-5.12.12
             -> /opt/x86_64/qt-5.14.2

aarch64架构

软连接在编译脚本中根据需求修改软连接的指向切换7.5、8.3和9.2版本的编译器
                                             |->/opt/aarch64/gcc-7.5
/usr/bin/aarch64-linux-gnu-* -> /opt/aarch64/gcc/bin/aarch64-linux-gnu-*
                                             |->/opt/aarch64/gcc-8.3
                                             |->/opt/aarch64/gcc-9.2

/usr/bin/qmake_aarch64 -> /opt/aarch64/qt-5.12.12/bin/qmake
                                            |->/opt/aarch64/qt-5.12.12-7.5
                                            |->/opt/aarch64/qt-5.12.12-8.3

loongarch64架构

软连接在编译脚本中根据需求修改软连接的指向的编译器
/usr/bin/loongarch64-linux-gnu-* -> /opt/aarch64/gcc/bin/loongarch64-linux-gnu-*
                                                 |->/opt/aarch64/gcc-8.3

/usr/bin/qmake_loongarch64 -> /opt/loongarch64/qt-5.12.12/bin/qmake
                                                    |->/opt/loongarch64/qt-5.12.12-8.3

mips64架构

软连接在编译脚本中根据需求修改软连接的指向切换7.3和8版本的编译器
/usr/bin/mips64-linux-gnu-* -> /opt/mips/gcc/bin/mips-linux-gnu-*
                                         |->/opt/mips/gcc-7.3
                                         |->/opt/mips/gcc-8
 /usr/bin/mips-linux-gnu-gcc -mabi=64 $@
 /usr/bin/mips-linux-gnu-g++ -mabi=64 $@
 
mips为32位与64位通用编译器,默认生成32位程序,要生成64位程序添加"-mabi=64"选项

/usr/bin/qmake_mips64 -> /opt/mips64/qt-5.12.12/bin/qmake

交叉编译驱动设置

使用非x86_64架构的头文件时需要替换原架构头文件路径中的部分可执行文件,以保证在x86_64架构下进行交叉编译。

#!/bin/bash

MAX_WIDTH=25
FileArray=(
"scripts/mod/modpost"
"scripts/basic/fixdep"
"scripts/recordmcount"
"scripts/genksyms/genksyms"
)

DirArray=(
"kylin-headers-4.4.131-20200422-generic"
"kylin-headers-4.4.131-20200429-generic"
"kylin-headers-4.4.131-20200529-generic"
"kylin-headers-4.4.131-20200704-generic"
"kylin-headers-4.4.131-20200710-generic"
"kylin-headers-4.4.131-20200821-generic"
"kylin-headers-4.4.131-20200901-generic"
"kylin-headers-4.4.131-20210120-generic"
"kylin-headers-4.4.131-20210727-generic"
)

for file in ${FileArray[@]}
do
	for dir in ${DirArray[@]}
	do
		printf "cp -f linux-4.4.131/%-${MAX_WIDTH}s    ../${dir}/%s\n" ${file} ${file}
		cp -f linux-4.4.131/${file}    ../${dir}/${file}
	done
done

例如以上替换4.4内核头文件的脚本先下载linux对应版本的内核源码,运行make出现的选项选择默认,以此生成一些可执行文件,然后用生成的可执行文件替换原架构头文件目录底下对应的可执行文件,目前交叉编译sigfs、sigdisk和sigspy需要替换modpost、fixdep、genksyms和recordmcount这四个可执行文件。

标签:交叉,AbsoluteSrcPath,TargetObjPath,编译,设置,PATH,DEC,OS
From: https://www.cnblogs.com/yuanhaoblog/p/17856719.html

相关文章

  • Debian12安装必要的设置
    允许root远程登录(可选)https://www.cnblogs.com/tothk/p/16441361.html配置镜像源https://www.cnblogs.com/tothk/p/16298181.html修改系统时区https://www.cnblogs.com/tothk/p/16368444.html最后编辑时间:2023年11月26日10:43:43......
  • python 对象 初始化并设置默认值
    Python对象初始化并设置默认值的实现步骤在Python中,我们经常需要为对象设置默认值。这些默认值可以在对象初始化时被设置,并在对象的方法中使用。本文将介绍如何使用Python的类和对象来实现对象初始化并设置默认值的功能。我们将根据以下步骤来完成这个任务:创建一个类定义初始......
  • 【前端VUE】Vue3路由设置(Typescript版本)
    新建项目npmcreatevite@latest安装vue-routercd.\my-web\npminstallvue-router在src->components下新增(Home.vue)<template><h1>我是主页</h1></template>在src->components下新增(Register.vue)<template><h1>用户......
  • 编译原理实验
       掌握了LR法进行语法分析的原理,掌握了语法分析器的设计与调试......
  • vue 根据js的变量来设置css 里面的属性的属性值
    1.通过动态绑定style,声明css变量"--fontColor",把变量”fontColor”赋给“--fontColor”2.在css中使用var函数读取“--fontColor”变量点击查看代码<template><divclass="wen_style":style="{'--fontColor':fontColor}">当前字体的颜色......
  • 8-Linux系统安装conda,镜像设置,环境变量
      1,我们现在学习Linux系统,首先得有个服务器的账号,这个要看自己的学校里面有没有专门做生信的课题组问问,或者去淘宝买,或者去那个组学大讲堂公众号里面有服务器租借的(没广告),租个好点的服务器,价格估计5000-10000半年不等的价格,能处理一些转录组等大数据,也可以做WGCNA等其他的大......
  • python 设置镜像
    清华镜像源pipconfigsetglobal.index-urlhttps://pypi.tuna.tsinghua.edu.cn/simple>WritingtoC:\Users\Administrator\AppData\Roaming\pip\pip.ini临时包设置pipconfigsetindex-urlhttps://pypi.tuna.tsinghua.edu.cn/simple 中科大镜像https://mirrors.ustc.......
  • 【Lustre相关】应用部署-01-源码编译IB驱动及lustre软件包
    一、编译安装系统版本:CentOSLinuxrelease7.9.2009(Core)内核版本:3.10.0-1160.el7.x86_64网卡型号:MellanoxTechnologiesMT2892Family[ConnectX-6Dx]软件版本:lfs2.12.9ib注:使用CentOS-7-x86_64-Everything-2009ISO,选择Minimalinstall安装,勾选Debugging......
  • 奇怪编译报错!
    #defineLOGE(fmt,...)do{\ char*buf=(char*)malloc(1024);\ if(buf){\ char*file;\ memset(buf,0,1024);\ file=(char*)strrchr(__FILE__,'/');\ if(!file){\ file=(char*)strrchr(__FILE__,'\\');\ }\ ......
  • 关于编译形状和字体文件
    关于编译形状和字体文件AutoCAD2018Help|AboutCompilingShapeandFontFiles|Autodesk可以定义、创建和编译形状和字体文件,以便在图形中使用自定义符号和文本字体。 形状是像块一样使用的对象。块比形状更通用,更易于使用和插入。但是,对于程序来说,形状的存储和绘制效......