原文链接
前言
首先这里建议从Ubuntu 20.04
镜像开始,目前相对最稳定的版本,无论是CentOS
还是其他版本的Ubuntu
多多少少都会遇到各种很烦的问题,虽然说不是解决不了,但是从Ubuntu 20.04
容器镜像开始是最节省时间的方式,Docker
默认情况下会让容器使用宿主机的大部分资源,包括CPU
和内存,虽然具体的占用情况取决于宿主机的硬件资源和Docker
配置,但是容器本身没有严格的资源限制,因此会尽可能地使用宿主机上的所有可用资源,所以不用担心编译性能问题。如果不能直接拉取镜像参考无法使用DockerPull正常拉取镜像解决方案
环境构建
拉取乌班图镜像后,这里给出基本交叉编译的镜像构建:
FROM ubuntu:20.04
RUN apt update && apt upgrade -y \
&& apt install -y build-essential curl wget git vim python python3 libz-dev \
&& apt install -y gcc-arm-linux-gnueabihf \
&& apt install -y g++-arm-linux-gnueabihf \
&& apt install -y g++-8-arm-linux-gnueabihf \
&& apt install -y gcc-8-arm-linux-gnueabihf \
&& apt install -y libc6-dev-armhf-cross \
&& apt install -y libc6-dev-arm64-cross \
&& apt clean
# 这里请求资源不一定稳定,方便重新获取资源,分开运行,再次build就不需要重新构建处理原生包了
RUN mkdir -p /data/gcc-8.3.0 \
&& cd /data/gcc-8.3.0 \
&& wget -O 1.tar.xz https://developer.arm.com/-/media/Files/downloads/gnu-a/8.3-2019.03/binrel/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf.tar.xz \
&& tar -xf 1.tar.xz -C ./ \
&& rm -rf 1.tar.xz \
&& mv * src
ENV PATH=/data/gcc-8.3.0/src/bin:$PATH
CMD ["/bin/bash"]
大家根据自己需要自行调整,增加或者删减包,我这里额外处理GCC 8.3.0
的交叉编译工具链,因为我的目标机器是这个版本的GLIBC
,所以这里增加了对这个部分
如果习惯容器在非交互时也保持活跃状态可以改成CMD ["tail", "-f", "/dev/null"]
,如果习惯使用交互式的就保持CMD ["/bin/bash"]
Dockerfile
写完之后执行构建新镜像,docker build -t cc-ubuntu:20.04 .
,然后我们需要定义一个映射目录,方便文件操作,所以这里我们最好再写一个docker-compose.yml
处理:
version: "3.9"
services:
ccu:
image: cc-ubuntu:20.04
hostname: 'ccu'
container_name: 'ccu'
working_dir: /data
tty: true
stdin_open: true
volumes:
- /to/your/path/data/src:/data/src
对于stdin_open: true
和tty: true
增加这两个参数可以创建一个为伪终端,让容器保持活跃并能够通过 docker attach
或 docker exec
进入,允许你将输入流保持打开,使得容器在没有交互的情况下也能接受命令或其他输入,最后docker compose up -d
启动,docker exec -it ccu /bin/bash
即可进入
本文以及后续相关内容都在该容器中处理,命令行内容除非特殊说明,否则都在该容器执行
资源限制
前文说了,容器会尽可能使用宿主机的资源,所以如果希望限制的小伙伴,可以通过docker run --cpus="2.0" image
限制使用2个CPU
核心,使用--memory="4g"
限制使用4G内存,对于docker-compose.yml
,使用mem_limit: 4g
和cpus: "2.0"
达到相同目的,属性和image
同级。通过docker stats
观察资源使用情况
Qt
如果你的目标机器本身带Qt
库,那么你需要确认下目标机器的版本,然后选择相应的Qt
库版本。以5.12.2举例,下载之后tar -xf name.tar.xz
进行解压
由于Qt
已经将交叉编译的脚本写好,我们这里只需要指定环境,如果需要调整进入qtbase/mkspecs
在相应的工具链目录调整。这里我们的目标机器是使用硬件浮点,即linux-arm-gnueabihf-g++
,而Qt
自带的工具链只有软浮点,不过问题不大基本都是一样,我们只需要进入软浮点目录将内容改成硬浮点即可,vim qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
将gnueabi
改为gnueabihf
或者你的指定路径。执行./configure -release -opensource -confirm-license -xplatform linux-arm-gnueabi-g++ -prefix /data/src/Qt5.12.2/_install -nomake examples -no-opengl -skip qtlocation
./configure
:配置脚本,用于设置Qt
的构建选项和环境,生成Makefile
-release
:相比debug
文件更小,性能更高-opensource
:开源许可-confirm-license
:自动确认开源许可条款-xplatform linux-aarch64-gnu-g++
: 指定平台-prefix /path/to/your/qt-app-version
:安装路径-nomake examples
:不编译example
-no-opengl
:禁用OpenGL,使用软件渲染而不是硬件渲染-slient
:静默,减少输出打印-static
:生成静态库。如果不想遇到各种兼容性问题,对于应用程序的大小的不是特别敏感的小伙伴,可以使用静态库,尤其是在初期调试调研功能性方案的时候
Makefile
生成完成后,执行make -j 24 && make install
即可在/path/to/your/qt-app-version
看到arm64
架构的指定版本Qt
注意:部分版本可能会编译报错,此时的处理方案有两个。要么换版本,选择更高的稳定的子版本号,要么对于报错的模块取消编译,比如5.15.2
版本的qtlocation
模块,使用-skip qtlocation
跳过该模块的编译
项目使用上举例CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
project(demo)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(QT5_ROOT /data/src/Qt5.12.2/_install/lib/cmake/Qt5)
set(CMAKE_PREFIX_PATH
"${QT5_ROOT}"
)
find_package(Qt5 REQUIRED COMPONENTS Core Widgets)
message(STATUS "C Compiler: ${CMAKE_C_COMPILER}")
message(STATUS "C++ Compiler: ${CMAKE_CXX_COMPILER}")
add_executable(Demo main.cpp)
target_link_libraries(Demo PRIVATE
Qt5::Core Qt5::Widgets
)
当然,还需要指定交叉编译工具链:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
此时就正常构建即可mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake .. && make
Boost
官网地址,这里我们以写作的时候最新版本1.87.0为例,下载源码后解压wget -O boost.tar.gz https://archives.boost.io/release/1.87.0/source/boost_1_87_0.tar.gz && tar -xf boost.tar.gz
,命令行位置进入解压后的文件夹下,cd /data/src/boost/boost_1_87_0
,这里我们是交叉编译,所以需要先安装B2
:
cd tools/build
./bootstrap.sh
./b2 install --prefix=/data/src/boost/_b2install
export PATH=/data/src/boost/_b2install/bin:$PATH
cd /data/src/boost/boost_1_87_0
安装完成之后,配置交叉编译工具echo "using gcc : arm : arm-linux-gnueabihf-g++ ;" >> $HOME/user-config.jam
,完成之后执行编译即可,b2 install --toolset=gcc-arm --prefix="/data/src/boost/_install"
,如果只希望编译某个模块使用b2 install --with-json --toolset=gcc-arm --prefix="/data/src/boost/_install"
,使用b2 toolset=gcc-arm --show-libraries
查看你可构建模块
项目使用上举例CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
project(demo)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(BOOST_ROOT /data/src/boost/_install)
set(CMAKE_PREFIX_PATH
"${BOOST_ROOT}"
)
find_package(Boost REQUIRED COMPONENTS json)
message(STATUS "Boost library dirs: ${Boost_LIBRARY_DIRS}")
message(STATUS "Boost include dirs: ${Boost_INCLUDE_DIRS}")
add_executable(Demo main.cpp)
target_include_directories(Demo PUBLIC
${Boost_INCLUDE_DIRS}
)
target_link_libraries(Demo PRIVATE
Boost::json
)
交叉编译工具链配置同上,此时正常构建即可mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=../toolchain.cmake .. && make