urasue
2023年1月5日 17時34分
いつもお世話になっております。
C言語で書かれたソースをATDE9でクロスコンパイルしたものをA6Eに転送し、
実行しようとしていますが、ライブラリが無いと言われます。
gcc:arm-linux-gnueabihf-gcc
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> int main(int argc,char *argv[]) { struct stat f_st; stat("hoge.txt",&f_st); return 0; }
armadillo:/home/atmark# ldd ./ini_test /lib/ld-linux-armhf.so.3 (0xb6eb3000) libc.so.6 => /lib/ld-linux-armhf.so.3 (0xb6eb3000) Error relocating ./ini_test: __xstat: symbol not found
stat関数を利用する場合、リンクするライブラリが必要なのでしょうか。
コメント
urasue
koga
2023年1月8日 9時56分
アットマークテクノの古賀です。
urasueさん:
>C言語で書かれたソースをATDE9でクロスコンパイルしたものをA6Eに転送し、
>実行しようとしていますが、ライブラリが無いと言われます。
…
>stat関数を利用する場合、リンクするライブラリが必要なのでしょうか。
いえ。これは、Base OS がベースにしている Alpine Linux の標準 C ライブラリが、Debian などで現在一般的なものとは異なるためです。Alpine Linux では、標準 C ライブラリに musl libc を使用しています:
https://ja.wikipedia.org/wiki/Musl
https://musl.libc.org/
そのため、Base OS 上で直接動作させるプログラムや、A6E 標準搭載のゲートウェイコンテナなどの Alpine コンテナ上で動作するプログラムを、C 言語で実装する場合は、musl libc をリンクするようにビルドしないといけません(ゲートウェイコンテナは、Alpine Linux のユーザーランドを使用しています)。
musl libc をリンクするようにビルドする方法としては、A6E 用や G4 用に提供している「Alpine Linuxルートファイルシステムビルドツール」のスクリプトを使い、開発環境入りの armv7 アーキテクチャ用 Apline コンテナをセットアップして、そのコンテナ上でビルドする、というのがお手軽です。
https://armadillo.atmark-techno.com/resources/software/armadillo-iot-a6…
ビルド環境をコンテナにすることで、コンテナのホスト環境(ここでは ATDE)を「汚さず」に、開発用のライブラリなどをコンテナ内に封じ込め、持ち運びが簡単になります。仮想マシンに基づく環境である ATDE よりも、コンテナの方が軽量だからです。
「Alpine Linuxルートファイルシステムビルドツール」(build-rootfs)を使った、開発環境入りの Alpine コンテナのセットアップ手順は、次の通りです:
1.) 弊社サイトの「Armadillo-IoT ゲートウェイ A6E 開発用ツール」のページから、「Alpine Linuxルートファイルシステムビルドツール」のアーカイブを ATDE にダウンロードする:
https://armadillo.atmark-techno.com/resources/software/armadillo-iot-a6…
2.) ダウンロードしたアーカイブを展開して、セットアップスクリプトを実行する:
これにより、Base OS 搭載の Armadillo シリーズの各 CPU アーキテクチャごとの、開発環境入り Alpine コンテナのコンテナイメージがセットアップされます。docker の image ls コマンドを実行すると、セットアップされたコンテナイメージ一覧を表示できます:
このうち、'alpine-3.16-armv7' が、A6E の CPU アーキテクチャに対応した Alipne コンテナイメージです(※'3.16' の部分は、今後、ベースの Alpine Linux のバージョンが更新されると変わります)。また、お手元の ATDE で、既に「Alpine Linuxルートファイルシステムビルドツール」を使ってルートファイルシステムをビルドしていらっしゃる場合には、コンテナイメージがセットアップされていますので、上記の build.sh の実行は不要です。
このコンテナイメージを使ってコンテナインスタンスを作成・起動すると、QEMU を使ってコンテナインスタンスが動作します。つまり、alpine-xx-armv7 のコンテナイメージであれば、QEMU の armv7 エミュレータで動作しますから、コンテナ上で armv7 アーキテクチャのプログラムが動作しますし、クロスビルドではなく、セルフビルドで armv7 用のプロブラムをビルドできる、というわけです。実機に依存しない動作のプログラムであれば、動作確認もコンテナ上で行うことができます。
以下は、"a6edev" という名前のコンテナインスタンスを作って、そのコンテナ内でプログラムをビルド・実行する場合の手順例です:
上記例で作成したコンテナインスタンスは、以後 docker start と docker exec で再び起動できます。
いかがでしょうか?
【補足】ところで、arm-linux-gnueabihf-gcc を使い、ATDE 上で直接クロスビルドして出来た、libc.so をリンクしたバイナリを A6E 上で動かす方策として、A6E に Debian のコンテナイメージをセットアップして Debian コンテナ内で動かす、というのがあります。Debian のコンテナイメージは大きいので、最初に動かす際にイメージをダウンロードするのに時間がかかりますが、イメージのセットアップ後は、Alpine ベースのコンテナと同様に動かせます。
例として、Base OS の /mnt ディレクトリを同じパス名でマウントして使用する Debian bullseye コンテナを動かす場合は、A6E (Base OS) の /etc/atmark/containere/ に次の内容の conf ファイルを作り、podman_start を実行すればよいです:
この conf ファイルの名前が debian.conf であれば、'podman_start debian' を実行するとコンテナインスタンスが作成・起動します。そして、ATDE でクロスビルドしたバイナリを USB メモリに入れて、Base OS の /mnt にマウントしておけば、同じパスでコンテナ内からアクセスできます。
以上、参考になりましたら幸いです。