本記事について
Nimのクロスコンパイル環境をDocker上で構築したのでそれのまとめ.
基本的に今後の自分のためのまとめになりますが,他の人の参考になれれば幸いです.
利用する際には,rirycasals/nim-cross-compile-env をpullするか,RiRyCasals/nim-cross-compile-env にあるDockerfileをビルドしてください.
Dockerfile
FROM --platform=arm64 ubuntu:latest
ENV SDK_VERSION=11.3
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone &&\
apt update && apt upgrade -y &&\
apt install -y gcc clang cmake make automake autogen patch cpio gzip bzip2 vim wget git sed tar pip \
python xz-utils uuid-dev llvm-dev lzma-dev libxml2-dev libssl-dev libbz2-dev libtool \
gcc-x86-64-linux-gnu mingw-w64 binutils-mingw-w64 gcc-mingw-w64 g++-mingw-w64 &&\
git clone https://github.com/nim-lang/Nim /Nim &&\
echo 'export PATH=$PATH:/Nim/bin' >> ~/.bashrc &&\
cd /Nim &&\
sh build_all.sh &&\
git clone https://github.com/tpoechtrager/osxcross.git /osxcross &&\
wget -P /osxcross/tarballs https://github.com/phracker/MacOSX-SDKs/releases/download/${SDK_VERSION}/MacOSX${SDK_VERSION}.sdk.tar.xz &&\
cd /osxcross &&\
echo -e "\n" | ./build.sh &&\
echo 'export PATH=$PATH:/osxcross/target/bin' >> ~/.bashrc
WORKDIR /work
CMD ["bash"]
FROM --platform=arm64 ubuntu:latest
ベースイメージは Ubuntu.(本当はタグを指定すべきだと思う)
プラットフォームが arm64 なのは,後述する osxcross のビルドが amd64 上だとうまく行かなかったためである.
また,公式のnimlang/nim はアーキテクチャが amd64 で,上記と同じ理由で使用していない.
ENV SDK_VERSION=11.3
後述する MacOSX SDK のバージョンのための変数.
ENV TZ=Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone &&\
初回の apt install
のときにタイムゾーンの入力を求められたので,それに対する対応策.
apt update && apt upgrade -y &&\
apt install -y gcc clang cmake make automake autogen patch cpio gzip bzip2 vim wget git sed tar pip \
python xz-utils uuid-dev llvm-dev lzma-dev libxml2-dev libssl-dev libbz2-dev libtool \
gcc-x86-64-linux-gnu mingw-w64 binutils-mingw-w64 gcc-mingw-w64 g++-mingw-w64 &&\
gcc-x86_64-linux-gnu
は cpu アーキテクチャが am64/x86_64 の Linux に向けたクロスコンパイルを行う際に必要となる,クロスコンパイラツールチェーン.
mingw-w64 binutils-mingw-w64 gcc-mingw-w64 g++-mingw-w64
は cpu アーキテクチャが am64/x86_64 の Windows に向けたクロスコンパイルを行う際に必要となる,クロスコンパイラツールチェーン.
git clone https://github.com/nim-lang/Nim /Nim &&\
echo 'export PATH=$PATH:/Nim/bin' >> ~/.bashrc &&\
cd /Nim &&\
sh build_all.sh &&\
Nimのビルドインストール.
git clone https://github.com/tpoechtrager/osxcross.git /osxcross &&\
wget -P /osxcross/tarballs https://github.com/phracker/MacOSX-SDKs/releases/download/${SDK_VERSION}/MacOSX${SDK_VERSION}.sdk.tar.xz &&\
cd /osxcross &&\
echo -e "\n" | ./build.sh &&\
echo 'export PATH=$PATH:/osxcross/target/bin' >> ~/.bashrc
osxcross は MaxOSX へのクロスコンパイルを行うためのクロスコンパイルツールチェーンのビルド.
SDKのバージョンを ${SDK_VERSION}
で指定しているので,これ以外のバージョンへクロスコンパイルを行うためには Dockerfile を変更するか,立ち上げたコンテナ内で別のSDKをインストールし,ビルドし直す必要がある.
osxcross をビルドするためには MacOSX SDK をビルドして取り込む必要があるのだが,それを GitHub (MacOSX-SDKs) で公開してくれている人がいるので利用.
./build.sh
をすると,Enterの入力を求められるので,echo -e "\n" | ./build.sh &&\
として入力を渡してあげる.
WORKDIR /work
CMD ["bash"]
基本的にDockerの利用目的が開発環境の構築なので,いつも作業スペースとして /work
を用意し,コンテナ立ち上げ時には bash
に入るようにしている.
~.nim.cfg
クロスコンパイル時に使うコンパイラの指定をする.
nim.config
に直接記述する方法もあるとは思うが,ビルドしたいnimファイル名.cfg
で設定できる.
以降,コンパイル対象のファイルを hello.nim
,コンパイル設定ファイルを hello.nim.cfg
とする.
# for Linux
# amd64/x86_64
amd64.linux.gcc.path = "/usr/bin"
amd64.linux.gcc.exe = "x86_64-linux-gnu-gcc"
amd64.linux.gcc.linkerexe = "x86_64-linux-gnu-gcc"
# arm64/aarch64
arm64.linux.gcc.path = "/usr/bin"
arm64.linux.gcc.exe = "aarch64-linux-gnu-gcc"
arm64.linux.gcc.linkerexe = "aarch64-linux-gnu-gcc"
# for MacOSX
# amd64/x86_64
amd64.macosx.clang.path = "/osxcross/target/bin"
amd64.macosx.clang.exe = "x86_64-apple-darwin20.4-clang"
amd64.macosx.clang.linkerexe = "x86_64-apple-darwin20.4-clang"
# arm64/aarch64
arm64.macosx.clang.path = "/osxcross/target/bin"
arm64.macosx.clang.exe = "aarch64-apple-darwin20.4-clang"
arm64.macosx.clang.linkerexe = "aarch64-apple-darwin20.4-clang"
# for Windows
# amd64/x86_64
amd64.windows.gcc.path = "/usr/bin"
amd64.windows.gcc.exe = "x86_64-w64-mingw32-gcc"
amd64.windows.gcc.linkerexe = "x86_64-w64-mingw32-gcc"
# for Linux
# amd64/x86_64
amd64.linux.gcc.path = "/usr/bin"
amd64.linux.gcc.exe = "x86_64-linux-gnu-gcc"
amd64.linux.gcc.linkerexe = "x86_64-linux-gnu-gcc"
# arm64/aarch64
arm64.linux.gcc.path = "/usr/bin"
arm64.linux.gcc.exe = "aarch64-linux-gnu-gcc"
arm64.linux.gcc.linkerexe = "aarch64-linux-gnu-gcc"
x86_64-linux-gnu-gcc
は gcc-x86_64-linux-gnu
をインストールすることで利用できる.
aarch64-linux-gnu-gcc
は gcc
インストール時のデフォルト.(プラットフォームが arm64 だから)
# for MacOSX
# amd64/x86_64
amd64.macosx.clang.path = "/osxcross/target/bin"
amd64.macosx.clang.exe = "x86_64-apple-darwin20.4-clang"
amd64.macosx.clang.linkerexe = "x86_64-apple-darwin20.4-clang"
# arm64/aarch64
arm64.macosx.clang.path = "/osxcross/target/bin"
arm64.macosx.clang.exe = "aarch64-apple-darwin20.4-clang"
arm64.macosx.clang.linkerexe = "aarch64-apple-darwin20.4-clang"
x86_64-apple-darwin20.4-clang
と aarch64-apple-darwin20.4-clang
は osxcross のビルドに成功すれば利用できる.
# for Windows
# amd64/x86_64
amd64.windows.gcc.path = "/usr/bin"
amd64.windows.gcc.exe = "x86_64-w64-mingw32-gcc"
amd64.windows.gcc.linkerexe = "x86_64-w64-mingw32-gcc"
x86_64-w64-mingw32-gcc
は mingw-w64 binutils-mingw-w64 gcc-mingw-w64 g++-mingw-w64
をインストールすることで利用できる.
コンパイルコマンド
- Linux
- amd64/x86_64
nim c --os:linux --cpu:amd64 hello.nim
- amd64/x86_64
- Linux
- arm64/aarch64
nim c --os:linux --cpu:arm64 hello.nim
- arm64/aarch64
- MacOSX
- amd64/x86_64
nim c --os:macosx --cpu:amd64 hello.nim
- amd64/x86_64
- MacOSX
- arm64/aarch64
nim c --os:macosx --cpu:arm64 hello.nim
- arm64/aarch64
- Windows
- amd64/x86_64
nim c --os:windows --cpu:amd64 hello.nim
- amd64/x86_64