지난번, IBM i (AS/400)에서 Google Gen AI SDK를 pip install하려고 했으나 pydantic-core의 Rust 빌드를 할 수 없어서, 결국 REST API를 직접 호출하여 IBM i에서 Gemini를 사용하도록 했습니다.
그 후 IBM Open SDK for Rust on AIX 1.92.0을 발견했으므로, IBM i 7.6 PASE에서 다시 한번 Google Gen AI SDK를 시도해 보고자 합니다.
BASE=https://public.dhe.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc-7.3/rust
mkdir -p /tmp/rustrpm
cd /tmp/rustrpm
...
공식 절차는 Fix Central + rustndi이지만, Fix Pack 단독으로는 완결되지 않으며 GA tarball이 필요합니다. 하지만 Fix Pack 1 출시 이후에는 Fix Central에서 GA 링크가 사라져 입수가 불가능합니다. 그래서 AIX Toolbox에 rpm이 그대로 올라와 있어 이쪽에서 취득했습니다.
cd /tmp/xl
zcat IBM_OPEN_XL_CPP_RUNTIME_17.1.4.0_AIX.tar.Z | tar -xvf -
restore -xqf libunwind.rte
...
rustc / cargo는 libunwind.a(libunwind.so.1)와 libc++.a(shr2_64.o)를 요구하지만, AIX 7.3에서는 IBM Open XL C/C++ Runtime을 통해 설치되어 있는 이 패키지가 IBM i 7.6 PASE의 기본값으로는 들어있지 않기 때문에, 입수한 파일에서 전개했습니다.
PASE 표준의 libc++.a를 덮어쓰고 싶지 않으므로 별도 디렉토리에 전개하고 있습니다.
mkdir -p /tmp/ssl-extract && cd /tmp/ssl-extract
ar -X64 -x /QOpenSys/pkgs/lib/libssl.so.3
mv shr_64.o libssl.so.3
...
cargo가 기대하는 것은 libssl.a 아카이브 안의 libssl.so.3 (OpenSSL 3.x) 멤버이지만, PASE 표준의 libssl.a에는 1.0 계열까지만 들어있었습니다.
그렇기 때문에 yum으로 도입된 /QOpenSys/pkgs/lib/libssl.so.3가 3.x이므로, 이것을 libssl.a로서 재아카이브했습니다. crypto에서도 동일한 작업을 수행했습니다.
for f in rustc rustdoc cargo; do
cp /opt/freeware/lib/RustSDK/1.92/bin/$f /opt/freeware/lib/RustSDK/1.92/bin/$f.bak
sed 's|export LIBPATH=/usr/lpp/xlC/lib|export LIBPATH=/opt/freeware/lib/openxl:/usr/lpp/xlC/lib|' \
...
방금 생성한 /opt/freeware/lib/openxl/에 둔 새로운 libc++ / libssl / libcrypto를 PASE 표준보다 우선하여 읽게 하고 싶으므로, LIBPATH의 선두에 추가합니다.
$ rustc --version
rustc 1.92.0 (e74881c9b 2026-03-10) (IBM Open SDK for Rust on AIX 1.92.0.1)
$ cargo new hello && cd hello && cargo build && ./target/debug/hello
...
여기까지 해서 겨우 Rust 단독으로 작동하게 되었습니다.
여기서 pydantic-core의 Rust 빌드가 시작되어 build.rs 단계에 도달했으나, 다음과 같이 실패합니다.
error: failed to run custom build command for `anyhow v1.0.102`
Failed to clean up /.../out/probe: Not a directory (os error 20)
probe 디렉토리를 생성한다
rustc를 실행한다
fs::remove_dir_all로 정리한다
라는 흐름이지만, 이 3번의 remove_dir_all이 PASE에서는 AIX와 동작이 달라 ENOTDIR을 반환하며 실패합니다.
anyhow 하나뿐이라면 build.rs를 오버라이트 패치(overwrite patch)로 돌파할 수 있습니다.
ANYHOW=~/.cargo/registry/src/github.com-*/anyhow-1.0.102
cat > $ANYHOW/build.rs <<'EOF'
fn main() { println!("cargo:rerun-if-changed=src/nightly.rs"); }
...
하지만 pydantic-core의 의존 크레이트(dependency crate)는 수십 개에 달하며, 각각이 build.rs를 가지고 있습니다. 모든 곳에 계속 패치를 적용하는 것은 현실적이지 않기에 여기서 포기했습니다😢
Rust 단독으로는 동작하게 되었습니다. 하지만 Python SDK 계열의 pip install은 불가능했습니다. 따라서 IBM i에서 Gemini를 사용할 경우에는 REST API를 직접 호출하거나, Rust가 IBM i의 표준이 될 때까지 기다리는 것이 정답이라고 생각했습니다. 아쉽습니다