1. 序章

最近では、64ビットシステムで32ビットプログラムを実行するのが便利で実用的です。 つまり、これを行う必要がある状況がいくつかあります。 たとえば、64ビットバージョンのアプリケーションが利用できないか、まだ移植されていない可能性があります。 同様に、Windowsアプリケーションを使用するか、Wine互換性レイヤーを使用して古いゲームをプレイする必要がある場合があります。 つまり、一部のアプリケーションでは32ビットOSのサポートが必要です。

この記事では、 gcc コンパイラを使用して、64ビットLinuxシステムで32ビットプログラムをコンパイルする方法について説明します。 また、64ビットシステムで32ビットバイナリをビルドするためのシステム要件と、CMakeを使用してこれらのビルドを自動化する方法についても学習します。

2. 開発ツール

開始する前に、コンパイルバイナリビルドプロセスで使用されるすべての開発ツールがシステムにインストールされていることを確認します。 まず、GCC GNUコンパイラコレクションが必要です。 第二に、 binutils は、リンカーやアセンブラーなどのバイナリプログラムを作成および管理するためのツールのセットです。 さらに、 Make – ビルド自動化ツール–とC標準ライブラリg libcをインストールする必要があります。

最も重要なことは、 Multilibをインストールする必要があります。これにより、32ビットプログラムを64ビットシステムで実行できます。また、32ビットライブラリと64ビットライブラリを同じシステムで共存できるようになります。 32ビットプログラムには32ビットライブラリが必要なため、これが必要になります。

Ubuntuを含むDebianのようなディストリビューションでは、 gcc コンパイラ、Cライブラリ、および Makeツールがビルドエッセンシャルパッケージに含まれています。 aptを使用してbuild-essentialおよびbinutilsパッケージをインストールする必要があります。

$ sudo apt -y update
$ sudo apt -y install build-essential binutils

同様に、 gcc-multilib パッケージをインストールして、Multilibメカニズムをシステムに追加します。

$ sudo apt -y install gcc-multilib

Fedora、Redhat、またはCentOSを実行している場合は、 dnf を使用して、 gcc コンパイラ、M ake、、および binutils[ X136X]:

$ sudo dnf -y install gcc binutils make

同様に、Redhatのようなディストリビューションに32ビットのサポートを追加するには、次のコマンドを実行します。

$ sudo dnf -y install glibc-devel.i686

3. コンパイラは32ビットですか64ビットですか?

それでは、unameコマンドを使用してハードウェア情報を確認しましょう。

$ uname -m 
x86_64

デフォルトでは、コンパイラはアーキテクチャに適したバイナリファイルを生成します。したがって、64ビットプロセッサを使用している場合は、64ビットバイナリを生成します。

それでは、gccのインストールを確認しましょう。

$ gcc -v

Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/10/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl --enable-offload-targets=nvptx-none --without-cuda-driver --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.3.1 20210422 (Red Hat 10.3.1-1) (GCC) 

ご覧のとおり、ターゲットはx86_64 です。これは、64ビットプロセッサ(AMDまたはIntel)用のLinuxシステムのアーキテクチャ名です。

4. 64ビットシステムでの32ビットプログラムのコンパイル

前に見たように、コンパイラはターゲットアーキテクチャのバイナリを生成します。この場合はx86_64です。

$ gcc prog.c -o prog

コンパイルプロセスによって生成されたファイルのタイプを確認するには、ファイルツールを使用します。

$ file prog
prog: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=07a13c851f21019b160a777a8ac047bed3a06489, for GNU/Linux 3.2.0, not stripped

システムを32ビット構成と互換性のあるものにせずに32ビットプログラムをコンパイルしようとすると、次のエラーが発生します。

$ $ gcc -m32 prog.c -o prog
In file included from /usr/include/features.h:489,
                 from /usr/include/bits/libc-header-start.h:33,
                 from /usr/include/stdio.h:27,
                 from menu.c:1:
/usr/include/gnu/stubs.h:7:11: fatal error: gnu/stubs-32.h: No such file or directory
    7 | # include <gnu/stubs-32.h>
      |           ^~~~~~~~~~~~~~~~
compilation terminated.

それでは、-m32オプションを使用して32ビットプログラムをコンパイルしましょう

$ gcc -m32 prog.c -o prog

ここでは、互換性のあるシステムで32ビットプログラムを正常にコンパイルしました。 file コマンドを使用して、バイナリを確認できます。

$ file prog
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=a711fe476bf35d8e36ff6d5370ac384e3a84539d, for GNU/Linux 3.2.0, not stripped

5. CMakeの使用

それでは、CMakeを使用してコンパイルを自動化しましょう 。 CMakeは、さまざまなシステムでのコンパイルを自動化するように設計されたソフトウェアです。 プロジェクトをビルドするには、makeツールとCまたはC++コンパイラの両方が必要です。

DebianおよびUbuntuディストリビューションにCMakeをインストールする方法を見てみましょう。

$ sudo apt -y install cmake

FedoraやRedhatのようなシステムにCMakeをインストールするには、次のコマンドを実行します。

$ sudo dnf install cmake

CMakeを使用して32ビットプロジェクトをビルドするには、 main.c、prog.c prog.hの3つのファイルで構成されるサンプルプロジェクトを使用します。

$ ls project/
main.c prog.c prog.h

まず、 gccオプションを渡すためのCmakeLists.txtファイルを作成する必要があります

cmake_minimum_required(VERSION 3.19)
set(GCC_COVERAGE_COMPILE_FLAGS "-m32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
project(prog)
add_executable(prog main.c prog.c)

また、プロジェクトをビルドするには、buildディレクトリを作成する必要があります。

$ cd project && mkdir build && cd build

その後、buildディレクトリからcmakeを実行して、プロジェクトのMakefileを生成します。

$ cmake ..
-- The C compiler identification is GNU 10.3.1
-- The CXX compiler identification is GNU 10.3.1
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/baeldung/CMake/project/build

最後に、makeツールを使用して Makefileを実行し、実行可能プログラムを生成します。

$ make
scanning dependencies of target prog
[ 33%] Building C object CMakeFiles/hello.dir/main.c.o
[ 66%] Building C object CMakeFiles/hello.dir/prog.c.o
[100%] Linking C executable prog
[100%] Built target prog

その後、fileコマンドを使用してバイナリを確認しましょう。

$ file prog 
prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=21edad69c38b540f9d3dd508a78509bc2d8c61d8, for GNU/Linux 3.2.0, not stripped

その結果、32ビットのCライブラリにリンクされた32ビットの実行可能プログラムができました。

6. 結論

古いアプリケーションを64ビットシステムに移植するのにかなりの時間と労力を費やすことなく、必要に応じて64ビットシステムで32ビットプログラムを実行できると、私たちにとって有利です。

つまり、開発ツールをインストールして、システムを32ビットプログラムと互換性のあるものにする方法を見てきました。 最後に、CMakeを使用してコンパイルを自動化する方法について説明しました。