Mac上で動作するVirtualBoxのUbuntu上でGccクロスコンパイル環境をDockerで構築


Mac上で動作するVirtualBoxのUbuntu上でGccクロスコンパイル環境をDockerで構築

Gccのクロスコンパイル環境をMacOSで起動したVirtualbox上のUbuntuのDockerで構築しました。

なんでこんな複雑な構成にしているかというと、環境/作業によるかと思いますが、体感的にはMacOSのDockerより早い気がしているため。

構成

レイヤー 動作環境 OS
Docker Ubuntu18.04(ここに構築)
VirtualBox Ubuntu18.04
Macboo MacOS

Docker環境のインストール

リンク先を参照ください。
MacOS の VirtualBox Ubntu上にDocker環境を構築

VirtualBox上のUbuntu18.4環境

tagucchan@tagvbbuntugcc:~$ uname -a
Linux tagvbbuntugcc 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
tagucchan@tagvbbuntugcc:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:    18.04
Codename:   bionic
tagucchan@tagvbbuntugcc:~$ sudo docker version
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b7f0
 Built:             Wed Mar 11 01:25:46 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       afacb8b7f0
  Built:            Wed Mar 11 01:24:19 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Ubuntu18.04イメージをプル

tagucchan@tagvbbuntugcc:~$ sudo docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
5bed26d33875: Pull complete 
f11b29a9c730: Pull complete 
930bda195c84: Pull complete 
78bf9a5ad49e: Pull complete 
Digest: sha256:bec5a2727be7fff3d308193cfde3491f8fba1a2ba392b7546b43a051853a341d
Status: Downloaded newer image for ubuntu:18.04
docker.io/library/ubuntu:18.04
tagucchan@tagvbbuntugcc:~$ sudo docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              18.04               4e5021d210f6        7 days ago          64.2MB
hello-world         latest              fce289e99eb9        15 months ago       1.84kB

Dockerでubuntu 18.04のコンテナを作成

tagucchan@tagvbbuntugcc:~$ sudo docker run -it -d --name gcc-ubuntu ubuntu:18.04 
af48c1a975a26096ca8b0df01bd33f1c083604916f23c562607635f03548deb0

tagucchan@tagvbbuntugcc:~$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
af48c1a975a2        ubuntu:18.04        "/bin/bash"         2 minutes ago       Up 2 minutes                            gcc-ubuntu

"/bin/bash”を起動

tagucchan@tagvbbuntugcc:~$ sudo docker exec -it gcc-ubuntu /bin/bash
root@af48c1a975a2:/# 

Dockerの基本的な使い方

docker ps -a
docker start <CONTAINER IDまたはNAME> # コンテナの起動
docker stop <CONTAINER IDまたはNAME> # コンテナの停止

クロスコンパイラのビルドに必要なパッケージをインストール

root@af48c1a975a2:/# apt-get update
root@af48c1a975a2:/# apt-get upgrade
root@af48c1a975a2:/# apt-get install build-essential texinfo gawk
root@af48c1a975a2:/# apt-get install vim-tiny less wget rsync

bisonをインストール

root@af48c1a975a2:/# mkdir ~/dev
root@af48c1a975a2:/# mkdir ~/dev/bison
root@af48c1a975a2:/# cd ~/dev/bison

GUN M4をインストール

root@af48c1a975a2:/# wget https://ftp.gnu.org/gnu/m4/m4-1.4.18.tar.gz
root@af48c1a975a2:/# tar xf m4-1.4.18.tar.gz
root@af48c1a975a2:/# cd m4-1.4.18
root@af48c1a975a2:/# ./configure --prefix=/usr/local
root@af48c1a975a2:/# make
root@af48c1a975a2:/# make install
root@af48c1a975a2:/# cd ..

bisonをインストール

root@af48c1a975a2:/# wget https://ftp.gnu.org/gnu/bison/bison-3.5.tar.gz
root@af48c1a975a2:/# tar xf bison-3.5.tar.gz
root@af48c1a975a2:/# cd bison-3.5
root@af48c1a975a2:/# ./configure --prefix=/usr/local
root@af48c1a975a2:/# make
root@af48c1a975a2:/# make install

VirtualBoxのUbuntu内Dockerの情報

root@af48c1a975a2:/# gcc --version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

root@af48c1a975a2:/# uname -a
Linux af48c1a975a2 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

root@af48c1a975a2:/# lsb_release -a
bash: lsb_release: command not found
root@af48c1a975a2:/# apt-get install lsb-release
root@af48c1a975a2:/# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.4 LTS
Release:    18.04
Codename:   bionic

root@af48c1a975a2:/# /lib/x86_64-linux-gnu/libc
libc-2.27.so  libc.so.6     
root@af48c1a975a2:/# /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1) stable release version 2.27.
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 7.3.0.
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

物理 CPU、CPU コア、および論理 CPU の数を確認

root@af48c1a975a2:~/dev/xgcc# grep physical.id /proc/cpuinfo | sort -u | wc -l
1

シェルスクリプトを作成

root@af48c1a975a2:/# mkdir ~/dev/xgcc
root@af48c1a975a2:/# cd ~/dev/xgcc

シェルスクリプト(ソースコードをダウンロード)

root@af48c1a975a2:~/dev/xgcc# vi ~/dev/xgcc/xgcc_download.sh
xgcc_download.sh
#!/bin/bash

set -e

BINUTILS_VERSION=binutils-2.34
GCC_VERSION=gcc-7.3.0
LINUX_KERNEL_VERSION=linux-5.3
GLIBC_VERSION=glibc-2.27

wget -nc http://ftpmirror.gnu.org/binutils/$BINUTILS_VERSION.tar.gz
wget -nc http://ftpmirror.gnu.org/gcc/gcc-7.3.0/$GCC_VERSION.tar.gz
wget -nc https://www.kernel.org/pub/linux/kernel/v5.x/$LINUX_KERNEL_VERSION.tar.xz
wget -nc http://ftpmirror.gnu.org/glibc/$GLIBC_VERSION.tar.xz

for f in *.tar*; do
    tar xfk $f
done

cd $GCC_VERSION
./contrib/download_prerequisites

シェルスクリプト(ソースコードをビルド)

root@af48c1a975a2:~/dev/xgcc# vi ~/dev/xgcc/xgcc_build.sh
xgcc_build.sh
#!/bin/bash

set -e

PREFIX=/usr/local
# CPU 1
PARALLEL_MAKE=
#CONFIGURATION_OPTIONS="--disable-multilib --disable-nls"
CONFIGURATION_OPTIONS="--disable-multilib --disable-nls --disable-libmpx"

BINUTILS_VERSION=binutils-2.34
GCC_VERSION=gcc-7.3.0
LINUX_KERNEL_VERSION=linux-5.3
GLIBC_VERSION=glibc-2.27

build() {
    local TARGET="$1"
    local LINUX_ARCH="$2"

    # Step 1. Binutils
    mkdir -p build-binutils-$TARGET
    cd build-binutils-$TARGET
    ../$BINUTILS_VERSION/configure --prefix=$PREFIX --target=$TARGET $CONFIGURATION_OPTIONS
    make $PARALLEL_MAKE
    make install
    cd ..

    # Step 2. Linux Kernel Headers
    cd $LINUX_KERNEL_VERSION
    make ARCH=$LINUX_ARCH INSTALL_HDR_PATH=$PREFIX/$TARGET headers_install
    cd ..

    # Step 3. C/C++ Compilers
    mkdir -p build-gcc-$TARGET
    cd build-gcc-$TARGET
    ../$GCC_VERSION/configure --prefix=$PREFIX --target=$TARGET --enable-languages=c,c++ $CONFIGURATION_OPTIONS
    make $PARALLEL_MAKE gcc_cv_libc_provides_ssp=yes all-gcc
    make install-gcc
    cd ..

    # Step 4. Standard C Library Headers and Startup Files
    mkdir -p build-glibc-$TARGET
    cd build-glibc-$TARGET
    ../$GLIBC_VERSION/configure --prefix=$PREFIX/$TARGET --build=$MACHTYPE --host=$TARGET --target=$TARGET --with-headers=$PREFIX/$TARGET/include $CONFIGURATION_OPTIONS libc_cv_forced_unwind=yes
    make install-bootstrap-headers=yes install-headers
    make $PARALLEL_MAKE csu/subdir_lib
    install csu/crt1.o csu/crti.o csu/crtn.o $PREFIX/$TARGET/lib
    $TARGET-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o $PREFIX/$TARGET/lib/libc.so
    touch $PREFIX/$TARGET/include/gnu/stubs.h
    cd ..

    # Step 5. Compiler Support Library
    cd build-gcc-$TARGET
    make $PARALLEL_MAKE all-target-libgcc
    make install-target-libgcc
    cd ..

    # Step 6. Standard C Library & the rest of Glibc
    cd build-glibc-$TARGET
    make $PARALLEL_MAKE
    make install
    cd ..

    # Step 7. Standard C++ Library & the rest of GCC
    cd build-gcc-$TARGET
    make $PARALLEL_MAKE all
    make install
    cd ..

    rm -rf build-binutils-$TARGET build-gcc-$TARGET build-glibc-$TARGET
}

build i686-linux-gnu x86
build arm-linux-gnueabi arm
build arm-linux-gnueabihf arm
build aarch64-linux-gnu arm64
build mips-linux-gnu mips
build mipsel-linux-gnu mips
build mips64el-linux-gnuabi64 mips

# 以下は私の環境ではエラーが出て駄目でした。
#build powerpc-linux-gnu powerpc
#build powerpc64le-linux-gnu powerpc
#build alpha-linux-gnu alpha
#build s390x-linux-gnu s390
#build m68k-linux-gnu m68k

# 以下は不要のため試していません
#build x86_64-linux-gnu x86
#build sparc-linux-gnu sparc
#build sparc64-linux-gnu sparc
#build cris-linux-gnu cris
#build sh4-linux-gnu sh

シェルスクリプト(各アーキテクチャのbinutilsをビルド)

root@af48c1a975a2:~/dev/xgcc# vi ~/dev/xgcc/xgcc_build_all_binutils.sh
xgcc_build_all_binutils.sh
#!/bin/bash
# build-binutils-all.sh

set -e

PREFIX=/usr/local
# cpu 1
PARALLEL_MAKE=
CONFIGURATION_OPTIONS="--disable-multilib --disable-nls"

BINUTILS_VERSION=binutils-2.34

mkdir -p build_all_binutils
cd build_all_binutils
../$BINUTILS_VERSION/configure --prefix=$PREFIX --enable-targets=all --enable-64-bit-bfd --program-prefix=all- $CONFIGURATION_OPTIONS
make $PARALLEL_MAKE
make install
cd ..

rm -rf build_all_binutils

スクリプトを実行

要:かなりの時間とディスク容量

root@af48c1a975a2:~/dev/xgcc# cd ~/dev/xgcc
root@af48c1a975a2:~/dev/xgcc# bash xgcc_download.sh
root@af48c1a975a2:~/dev/xgcc# nohup bash xgcc_build.sh &
root@af48c1a975a2:~/dev/xgcc# nohup bash xgcc_build_all_binutils.sh &

動作テスト(MIPS向けのアセンブリ出力)

root@af48c1a975a2:~/dev/xgcc#  mkdir test
root@af48c1a975a2:~/dev/xgcc# cd test
root@af48c1a975a2:~/dev/xgcc/test# vi main.c
main.c
#include <stdio.h>
int main(void) {
   printf("Hellow");
   return 0;
}

実行例

root@af48c1a975a2:~/dev/xgcc/test# mips-linux-gnu-gcc -S main.c
root@af48c1a975a2:~/dev/xgcc/test# cat main.s 
    .file   1 "main.c"
    .section .mdebug.abi32
    .previous
    .nan    legacy
    .module fp=32
    .module nooddspreg
    .abicalls
    .text
    .rdata
    .align  2
$LC0:
    .ascii  "Hellow\000"
    .text
    .align  2
    .globl  main
    .set    nomips16
    .set    nomicromips
    .ent    main
    .type   main, @function
main:
    .frame  $fp,32,$31      # vars= 0, regs= 2/0, args= 16, gp= 8
    .mask   0xc0000000,-4
    .fmask  0x00000000,0
    .set    noreorder
    .set    nomacro
    addiu   $sp,$sp,-32
    sw  $31,28($sp)
    sw  $fp,24($sp)
    move    $fp,$sp
    lui $28,%hi(__gnu_local_gp)
    addiu   $28,$28,%lo(__gnu_local_gp)
    .cprestore  16
    lui $2,%hi($LC0)
    addiu   $4,$2,%lo($LC0)
    lw  $2,%call16(printf)($28)
    nop
    move    $25,$2
    .reloc  1f,R_MIPS_JALR,printf
1:  jalr    $25
    nop

    lw  $28,16($fp)
    move    $2,$0
    move    $sp,$fp
    lw  $31,28($sp)
    lw  $fp,24($sp)
    addiu   $sp,$sp,32
    jr  $31
    nop

    .set    macro
    .set    reorder
    .end    main
    .size   main, .-main
    .ident  "GCC: (GNU) 7.3.0"
root@af48c1a975a2:~/dev/xgcc/test# 

Dockerコンテナを停止

exit  # Ubuntuのshellから抜ける
docker stop gcc-ubuntu # コンテナが停止
docker ps -a # 停止確認