github:
https://github.com/csh2077/docker_practice.git
思路:
运行build.sh脚本可以完成交叉编译
- build.sh脚本自动部署docker环境并运行容器
- 在容器中执行compile_inside_docker_env.sh脚本实现编译
- 编译指令 ./build.sh linux_arm 和 ./build.sh linux_x86
build.sh脚本解析
- 初始化脚本变量
#!/bin/bash PLATFORM=${1:-linux_arm} DOCKER_FILE="buildScript/Dockerfile" DOCKER_FILE_HASH="buildScript/dockerfile_hash.txt" DOCKER_FILE_HASH_PREV="buildScript/dockerfile_hash_prev.txt" IMAGE_NAME="docker_env" CONTAINER_NAME="running_docker_env_container"
- 检查当前liunx是否安装docker
if ! command -v docker &> /dev/null; then echo "Docker could not be found, please install Docker first." exit 1 fi
- 构建当前Dockerfile镜像
sha256sum "$DOCKER_FILE" > "$DOCKER_FILE_HASH" if [[ -f "$DOCKER_FILE_HASH_PREV" ]] && cmp --silent "$DOCKER_FILE_HASH" "$DOCKER_FILE_HASH_PREV"; then echo "Docker configuration has not changed." else echo "Docker configuration has changed or has not been deployed. Rebuilding..." docker build -t "$IMAGE_NAME" ./buildScript || { echo "ERROR: Docker build failed for image $IMAGE_NAME" >&2 exit 1 } fi cp "$DOCKER_FILE_HASH" "$DOCKER_FILE_HASH_PREV"
- 运行docker镜像,并在容器中启动编译脚本
if [ "$(docker ps -q -f name=^${CONTAINER_NAME}$)" ]; then echo "already running docker env..." docker exec -it $CONTAINER_NAME /bin/bash -c "cd /app && ./buildScript/compile_inside_docker_env.sh $PLATFORM" || { echo "ERROR: Failed to execute compile script in running parts." >&2 exit 1 } else echo "docker env will run..." docker rm $CONTAINER_NAME docker run -it --name "$CONTAINER_NAME" -v "$(pwd)":/app "$IMAGE_NAME" /bin/bash -c "cd /app && ./buildScript/compile_inside_docker_env.sh $PLATFORM" || { echo "ERROR: Failed to run compile script in new container." >&2 exit 1 } fi
Dockerfile解析
- base的基础镜像是ubuntu 20.04
FROM ubuntu:20.04
- 关闭交互选项,防止镜像在安装需要用户操作的库卡住
ARG DEBIAN_FRONTEND=noninteractive
- 在镜像中安装编译所需库
RUN apt-get update && apt-get install -y \ build-essential \ cmake \ gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \ openssl \ libssl-dev \ wget \ # zlib1g zlib1g-dev \ && rm -rf /var/lib/apt/lists/*
- 在镜像中编译安装arm版本的openssl
RUN wget https://www.openssl.org/source/openssl-1.1.1.tar.gz \ && tar -xzf openssl-1.1.1.tar.gz \ && cd openssl-1.1.1 \ && ./Configure linux-aarch64 --prefix=/usr/local/arm-ssl --openssldir=/usr/local/arm-ssl shared \ && make CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ \ && make install \ && cd .. \ && rm -rf openssl-1.1.1.tar.gz openssl-1.1.1
- 指定工作路径
WORKDIR /app
compile_inside_docker_env.sh脚本解析
-
初始化变量
#!/bin/bash PLATFORM=$1 SRC_DIR="../" BUILD_DIR="build" OUTPUT_DIR="output" SCRIPT_PATH=$(dirname $(readlink -f $0)) echo "The target OS is: $PLATFORM"
-
生成编译中间产物路径和输出路径
if [ -d "$BUILD_DIR" ]; then rm -rf $BUILD_DIR fi mkdir -p "${BUILD_DIR}" if [ -d "$OUTPUT_DIR" ]; then rm -rf $OUTPUT_DIR fi mkdir -p "${OUTPUT_DIR}" cd "${BUILD_DIR}"
-
依据参数选择平台并使用cmake编译
case $PLATFORM in linux_arm) echo "Running Linux arm commands" cmake -DARCH_TAG=linux_arm "${SRC_DIR}" ;; linux_x86) echo "Running Linux x86 commands" cmake -DARCH_TAG=linux_x86 "${SRC_DIR}" ;; *) echo "Invalid platform! Please specify either 'linux_arm', 'linux_x86'." exit 1 ;; esac # cmake --build . --target cpplint make -j5
CmakeLists.txt脚本解析
- 依据平台参数初始化编译器配置
cmake_minimum_required(VERSION 3.5) if (${ARCH_TAG} STREQUAL "linux_x86") message("---- Build for linux_x86 ----") set(ARCH_TAG "linux") set(CMAKE_STRIP "strip") elseif (${ARCH_TAG} STREQUAL "linux_arm") message("---- Build for linux_arm ----") set(CMAKE_C_COMPILER "aarch64-linux-gnu-gcc") set(CMAKE_CXX_COMPILER "aarch64-linux-gnu-g++") set(ARCH_TAG "arm") include_directories("/usr/local/arm-ssl/include") set(OPENSSL_ROOT_DIR "/usr/local/arm-ssl") set(CMAKE_STRIP "aarch64-linux-gnu-strip") else() message(FATAL_ERROR "Unknown target platform: ${ARCH_TAG}") endif ()
- 设置cmake路径和头文件路径
project(Demo) set(PROJECT_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CMAKE_CURRENT_BINARY_DIR}/..) set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/build/bin) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}) include_directories(${PROJECT_INCLUDE_DIRS})
- 编译工程
add_executable(Demo demo.cpp) find_package(OpenSSL REQUIRED) target_link_libraries(Demo OpenSSL::SSL OpenSSL::Crypto )
- 去除符号信息并移动编译产物到output
add_custom_command(TARGET Demo POST_BUILD COMMAND ${CMAKE_STRIP} ${CMAKE_SOURCE_DIR}/build/bin/Demo -o ${CMAKE_SOURCE_DIR}/output/Demo-${ARCH_TAG} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})