クロスコンパイル環境構築でglibcのmakeが失敗する

投稿者: Anonymous

目的

http://inaz2.hatenablog.com/entry/2015/12/01/204201
を再現したい(クロスコンパイル環境構築

環境

  • Vagrant box: ubuntu/xenial64
  • provisioner: ansible_localによりgccをソースからコンパイルするのに必要なg++, bison, flex, texinfoを追加インストール済み
  • Vagrantfile

    Vagrant.configure("2") do |config|
      config.ssh.insert_key = false
      config.vm.box = "ubuntu/xenial64"
      config.vm.box_check_update = false
      config.vm.synced_folder "C:\(Vagrantfileの場所)\synced_folder", "/vagrant_data"
    
      config.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
      end
    
      config.vm.provision "ansible_local" do |ansible|
          ansible.playbook = "playbook.yml"
          ansible.verbose = true
      end
    end
    
  • playbook.yml

    - hosts: all
      become: yes
      user: ubuntu
      tasks:
        - name: Install packages
          apt: pkg={{item}} force=yes update_cache=yes
          with_items:
            # to build compiler
            - g++
            - bison
            - flex
            - texinfo
    

実行したこと

C:(Vagrantfileの場所)
λ vagrant up

[email protected]:~$sudo apt-get update
[email protected]:~$sudo apt-get upgrade

手動でglibcだけのmakeが成功するか検証しようとすると

[email protected]:~/build-glibc-aarch64-linux-gnu$ ../glibc-2.22/configure --prefix=/opt/cross/aarch64-linux-gnu --build=$MACHTYPE --host=aarch64-linux-gnu --target=aarch64-linux-gnu --with-headers=/opt/cross/aarch64-linux-gnu/include --disable-multilib --disable-nls libc_cv_forced_unwind=yes
略
checking installed Linux kernel header files... missing or too old!
configure: error: GNU libc requires kernel header files from
Linux 2.6.32 or later to be installed before configuring.

ということで、エラーの検証は前提として、binutils-2.25、linux-3.16のkernel headers、gcc-5.2.0(ライブラリを除く)のmake installまで完了する必要がありそうである。(少なくともLinux kernel headerはmake install済みである必要がありそう)

[email protected]:~$ sudo ./download.sh

download.sh

#!/bin/bash
set -e

BINUTILS_VERSION=binutils-2.25
LINUX_KERNEL_VERSION=linux-3.16
GCC_VERSION=gcc-5.2.0
GLIBC_VERSION=glibc-2.22

wget -nc http://ftpmirror.gnu.org/binutils/$BINUTILS_VERSION.tar.gz
wget -nc https://www.kernel.org/pub/linux/kernel/v3.x/$LINUX_KERNEL_VERSION.tar.xz
wget -nc http://ftpmirror.gnu.org/gcc/$GCC_VERSION/$GCC_VERSION.tar.gz
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 # windowsとの共有ディレクトリ/vagrant_dataで実行していると、この行でシンボリックリンクが張られるときに管理権限がなくて失敗するので、スクリプトはその以外の場所で実行する
cd ..
[email protected]:~/cross$ sudo mkdir -p /opt/cross
[email protected]:~/cross$ sudo chown ubuntu /opt/cross
[email protected]:~$ sudo ./build.sh

build.sh(エラーが出る直前まで)

#!/bin/bash
set -e

PREFIX=/opt/cross

PARALLEL_MAKE=-j4
CONFIGURATION_OPTIONS="--disable-multilib --disable-nls"

BINUTILS_VERSION=binutils-2.25
LINUX_KERNEL_VERSION=linux-3.16
GCC_VERSION=gcc-5.2.0
GLIBC_VERSION=glibc-2.22

TERMCAP_VERSION=termcap-1.3.1
GDB_VERSION=gdb-7.3.1

mkdir -p $PREFIX
chown ubuntu $PREFIX

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
}

build aarch64-linux-gnu arm64

ここまで実行した上で、上記スクリプト中の make $PARALLEL_MAKE csu/subdir_lib、つまり

[email protected]:~/cross/build-glibc-aarch64-linux-gnu$ sudo make -j4 csu/subdir_lib

が失敗するので、 これを成功させたい というのが今回の質問です。

実行したときのエラーログは
http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/#IDComment1016903189
のvenkateshさんと似ている。以下エラーログです。

ここまで文字数制限のため省略
In file included from ../sysdeps/aarch64/nptl/tls.h:47:0,
                 from ../include/errno.h:27,
                 from check_fds.c:18:
check_fds.c: In function ‘check_one_fd’:
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:203:17: error: invalid register name for ‘_x0’
   register long _x0 asm ("x0");
                 ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:206:3: note: in expansion of macro ‘LOAD_ARGS_0’
   LOAD_ARGS_0 ()    
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:210:3: note: in expansion of macro ‘LOAD_ARGS_1’
   LOAD_ARGS_1 (x0)    
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:214:3: note: in expansion of macro ‘LOAD_ARGS_2’
   LOAD_ARGS_2 (x0, x1)    
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:218:3: note: in expansion of macro ‘LOAD_ARGS_3’
   LOAD_ARGS_3 (x0, x1, x2)   
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:179:8: note: in expansion of macro ‘LOAD_ARGS_4’
        LOAD_ARGS_##nr (args)     
        ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:164:34: note: in expansion of macro ‘INTERNAL_SYSCALL’
   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); 
                                  ^
../sysdeps/unix/sysv/linux/not-cancel.h:36:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (openat, 4, AT_FDCWD, name, flags, mode)
    ^
check_fds.c:64:20: note: in expansion of macro ‘open_not_cancel’
       int nullfd = open_not_cancel (name, mode, 0);
                    ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:211:17: error: invalid register name for ‘_x1’
   register long _x1 asm ("x1") = _x1tmp;
                 ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:214:3: note: in expansion of macro ‘LOAD_ARGS_2’
   LOAD_ARGS_2 (x0, x1)    
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:218:3: note: in expansion of macro ‘LOAD_ARGS_3’
   LOAD_ARGS_3 (x0, x1, x2)   
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:179:8: note: in expansion of macro ‘LOAD_ARGS_4’
        LOAD_ARGS_##nr (args)     
        ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:164:34: note: in expansion of macro ‘INTERNAL_SYSCALL’
   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); 
                                  ^
../sysdeps/unix/sysv/linux/not-cancel.h:36:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (openat, 4, AT_FDCWD, name, flags, mode)
    ^
check_fds.c:64:20: note: in expansion of macro ‘open_not_cancel’
       int nullfd = open_not_cancel (name, mode, 0);
                    ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:215:17: error: invalid register name for ‘_x2’
   register long _x2 asm ("x2") = _x2tmp;
                 ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:218:3: note: in expansion of macro ‘LOAD_ARGS_3’
   LOAD_ARGS_3 (x0, x1, x2)   
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:179:8: note: in expansion of macro ‘LOAD_ARGS_4’
        LOAD_ARGS_##nr (args)     
        ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:164:34: note: in expansion of macro ‘INTERNAL_SYSCALL’
   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); 
                                  ^
../sysdeps/unix/sysv/linux/not-cancel.h:36:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (openat, 4, AT_FDCWD, name, flags, mode)
    ^
check_fds.c:64:20: note: in expansion of macro ‘open_not_cancel’
       int nullfd = open_not_cancel (name, mode, 0);
                    ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:219:17: error: invalid register name for ‘_x3’
   register long _x3 asm ("x3") = _x3tmp;
                 ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:179:8: note: in expansion of macro ‘LOAD_ARGS_4’
        LOAD_ARGS_##nr (args)     
        ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:164:34: note: in expansion of macro ‘INTERNAL_SYSCALL’
   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); 
                                  ^
../sysdeps/unix/sysv/linux/not-cancel.h:36:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (openat, 4, AT_FDCWD, name, flags, mode)
    ^
check_fds.c:64:20: note: in expansion of macro ‘open_not_cancel’
       int nullfd = open_not_cancel (name, mode, 0);
                    ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:180:22: error: invalid register name for ‘_x8’
        register long _x8 asm ("x8") = (name);   
                      ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:164:34: note: in expansion of macro ‘INTERNAL_SYSCALL’
   ({ unsigned long _sys_result = INTERNAL_SYSCALL (name, , nr, args); 
                                  ^
../sysdeps/unix/sysv/linux/not-cancel.h:36:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (openat, 4, AT_FDCWD, name, flags, mode)
    ^
check_fds.c:64:20: note: in expansion of macro ‘open_not_cancel’
       int nullfd = open_not_cancel (name, mode, 0);
                    ^
../o-iterator.mk:9: recipe for target '/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/check_fds.o' failed
make[2]: *** [/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/check_fds.o] Error 1
make[2]: *** Waiting for unfinished jobs....
In file included from ../sysdeps/aarch64/nptl/tls.h:47:0,
                 from ../include/link.h:45,
                 from ../include/dlfcn.h:4,
                 from ../sysdeps/generic/ldsodefs.h:32,
                 from ../sysdeps/aarch64/ldsodefs.h:46,
                 from ../sysdeps/gnu/ldsodefs.h:46,
                 from ../sysdeps/unix/sysv/linux/ldsodefs.h:22,
                 from ../sysdeps/unix/sysv/linux/aarch64/ldsodefs.h:22,
                 from libc-start.c:22:
libc-start.c: In function ‘__libc_start_main’:
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:203:17: error: invalid register name for ‘_x0’
   register long _x0 asm ("x0");
                 ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:206:3: note: in expansion of macro ‘LOAD_ARGS_0’
   LOAD_ARGS_0 ()    
   ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:179:8: note: in expansion of macro ‘LOAD_ARGS_1’
        LOAD_ARGS_##nr (args)     
        ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/exit-thread.h:36:7: note: in expansion of macro ‘INTERNAL_SYSCALL’
       INTERNAL_SYSCALL (exit, err, 1, 0);
       ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:180:22: error: invalid register name for ‘_x8’
        register long _x8 asm ("x8") = (name);   
                      ^
../sysdeps/unix/sysv/linux/aarch64/sysdep.h:189:2: note: in expansion of macro ‘INTERNAL_SYSCALL_RAW’
  INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args)
  ^
../sysdeps/unix/sysv/linux/exit-thread.h:36:7: note: in expansion of macro ‘INTERNAL_SYSCALL’
       INTERNAL_SYSCALL (exit, err, 1, 0);
       ^
In file included from ../include/link.h:45:0,
                 from ../include/dlfcn.h:4,
                 from ../sysdeps/generic/ldsodefs.h:32,
                 from ../sysdeps/aarch64/ldsodefs.h:46,
                 from ../sysdeps/gnu/ldsodefs.h:46,
                 from ../sysdeps/unix/sysv/linux/ldsodefs.h:22,
                 from ../sysdeps/unix/sysv/linux/aarch64/ldsodefs.h:22,
                 from libc-start.c:22:
../sysdeps/aarch64/nptl/tls.h:105:21: error: __builtin_thread_pointer is not supported on this target
  ((struct pthread *)__builtin_thread_pointer () - 1)
                     ^
libc-start.c:279:30: note: in expansion of macro ‘THREAD_SELF’
       struct pthread *self = THREAD_SELF;
                              ^
../o-iterator.mk:9: recipe for target '/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/libc-start.o' failed
make[2]: *** [/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/libc-start.o] Error 1
In file included from ../include/errno.h:27:0,
                 from ../csu/libc-tls.c:19,
                 from ../sysdeps/aarch64/libc-tls.c:19:
../sysdeps/aarch64/libc-tls.c: In function ‘__tls_get_addr’:
../sysdeps/aarch64/nptl/tls.h:101:19: error: __builtin_thread_pointer is not supported on this target
   (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
                   ^
../sysdeps/aarch64/libc-tls.c:30:16: note: in expansion of macro ‘THREAD_DTV’
   dtv_t *dtv = THREAD_DTV ();
                ^
/home/ubuntu/build-glibc-aarch64-linux-gnu/sysd-rules:1347: recipe for target '/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/libc-tls.o' failed
make[2]: *** [/home/ubuntu/build-glibc-aarch64-linux-gnu/csu/libc-tls.o] Error 1
make[2]: Leaving directory '/home/ubuntu/glibc-2.22/csu'
Makefile:213: recipe for target 'csu/subdir_lib' failed
make[1]: *** [csu/subdir_lib] Error 2
make[1]: Leaving directory '/home/ubuntu/glibc-2.22'
Makefile:9: recipe for target 'csu/subdir_lib' failed
make: *** [csu/subdir_lib] Error 2
[email protected]:~/build-glibc-aarch64-linux-gnu$ 

解決

ビルドを始める前に、クロスコンパイルするターゲット用のバイナリが置かれる場所を $PATH に追加してください。

具体的には、今回の場合、

PATH="${PREFIX}/bin:${PATH}"

を行ってください。おそらくこれをしておかないと、たとえば gcc をビルドする際にクロスコンパイル用の gcc (今回の場合 aarch64-linux-gnu-gcc) を見つけてくれません。

他の方法として、 gcc のビルドオプションにおいて “Cross-Compiler-Specific Options” に分類されているオプションを使ってパスを指定してあげることによっても解決できるかもしれません。これらのオプションについてはこのマニュアルをご参照ください。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *