Cross Compile ARM Cortex-A9 (glibc Toolchain)
Step-by-step guide for cross-compiling inotify-tools for ARM Cortex-A9 using a glibc-based OpenWrt toolchain, including static build and troubleshooting
Critical First Step: Match the libc
Your toolchain is named: …glibc_eabi
This means it produces binaries that require glibc on the target router.
Before building anything, verify which libc the router uses.
Check libc on the router
# Which libc is installed?
ls -l /lib/libc.so* 2>/dev/null
strings /lib/libc.so* 2>/dev/null | head
What to look for
If you see:
/lib/ld-musl-...→ Router uses musluClibc references→ Router uses uClibc/lib/ld-linux.so.3or similar → Router uses glibc
If the router does not use glibc, a glibc-built binary will fail immediately.
Your options if libc mismatches
1) Use a toolchain matching the router’s libc 2) Build statically (if static libs are available) 3) Use an OpenWrt package built specifically for your firmware (often easiest)
Set Up the Toolchain
export TC=/mnt/usb/firmware/technicolor_toolchain/toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_glibc_eabi
export PATH="$TC/bin:$PATH"
export TARGET=arm-openwrt-linux-gnueabi
export CC=${TARGET}-gcc
export AR=${TARGET}-ar
export RANLIB=${TARGET}-ranlib
export STRIP=${TARGET}-strip
Sanity Check
$CC -v
${TARGET}-gcc -dumpmachine
Build inotify-tools (provides inotifywait)
mkdir -p /tmp/build-inotify && cd /tmp/build-inotify
wget -O inotify-tools.tar.gz https://github.com/inotify-tools/inotify-tools/archive/refs/tags/3.22.6.0.tar.gz
tar xf inotify-tools.tar.gz
cd inotify-tools-3.22.6.0
If your build machine has no internet access, transfer the tarball manually.
Configure for Cross Compilation
export DEST=/tmp/inotify-staging
rm -rf "$DEST"
mkdir -p "$DEST"
./autogen.sh 2>/dev/null || true
./configure \
--host="$TARGET" \
--build="$(gcc -dumpmachine)" \
--prefix=/usr
Compile and Install
make -j"$(nproc)"
make DESTDIR="$DEST" install
- Verify:
ls -l "$DEST/usr/bin/inotifywait"
file "$DEST/usr/bin/inotifywait"
- Strip for smaller size:
$STRIP --strip-all "$DEST/usr/bin/inotifywait"
Transfer to Router
From build machine:
scp "$DEST/usr/bin/inotifywait" root@ROUTER_IP:/tmp/
- On the router:
chmod +x /tmp/inotifywait
/tmp/inotifywait --help
Monitor Directory and Log
/tmp/inotifywait -m -e create,delete,modify,move /tmp/watchdir \
--format '%T %e %w%f' --timefmt '%F %T' \
>> /tmp/inotify.log
Static Build (Maximum Compatibility)
Static builds are useful if:
- glibc version mismatches
- Dynamic loader errors occur
-
First check if static libraries exist:
find "$TC" -name "libc.a" -o -name "libpthread.a" | head -
If they exist:
export CFLAGS="-Os -pipe" export LDFLAGS="-static" ./configure \ --host="$TARGET" \ --build="$(gcc -dumpmachine)" \ --prefix=/usr \ --disable-man \ --disable-nls make clean make -j"$(nproc)" make DESTDIR="$DEST" install $STRIP --strip-all "$DEST/usr/bin/inotifywait" -
Verify:
file "$DEST/usr/bin/inotifywait" ${TARGET}-readelf -d "$DEST/usr/bin/inotifywait" | head
A static binary should show no NEEDED dependencies in readelf -d.
Troubleshooting
If you get an error similiar to ./inotifywait: error while loading shared libraries: libinotifytools.so.0: cannot open shared object file: No such file or directory
1) Grab the missing library from your staging dir
On your build machine, it should be here:
```bash
ls -l /tmp/inotify-staging/usr/lib/libinotifytools.so*
lrwxrwxrwx 1 root root 24 Feb 11 17:05 /tmp/inotify-staging/usr/lib/libinotifytools.so -> libinotifytools.so.0.4.1
lrwxrwxrwx 1 root root 24 Feb 11 17:05 /tmp/inotify-staging/usr/lib/libinotifytools.so.0 -> libinotifytools.so.0.4.1
-rwxr-xr-x 1 root root 103594 Feb 11 17:05 /tmp/inotify-staging/usr/lib/libinotifytools.so.0.4.1
```
On your build machine: package a tiny runtime folder
This makes transfer easy even without SFTP
mkdir -vp /tmp/inotify-runtime/lib
cp -v /tmp/inotify-staging/usr/bin/inotifywait /tmp/inotify-runtime/
cp -va /tmp/inotify-staging/usr/lib/libinotifytools.so* /tmp/inotify-runtime/lib/
# optional: shrink
arm-openwrt-linux-gnueabi-strip --strip-all /tmp/inotify-runtime/inotifywait || true
arm-openwrt-linux-gnueabi-strip --strip-all /tmp/inotify-runtime/lib/libinotifytools.so.0.4.1 || true
# tar it
tar -C /tmp -czf /tmp/inotify-runtime.tgz inotify-runtime
ls -lh /tmp/inotify-runtime.tgz
-rw-r--r-- 1 root root 66K Feb 11 17:22 /tmp/inotify-runtime.tgz
On the router: unpack to /tmp (or USB) and run
mkdir -p /tmp/inotify
tar -C /tmp/inotify -xzf /tmp/run/mountd/sda/inotify-runtime.tgz
/tmp/inotify/inotify-runtime/inotifywait
/tmp/inotify/inotify-runtime/lib/libinotifytools.so.0 -> libinotifytools.so.0.4.1
/tmp/inotify/inotify-runtime/lib/libinotifytools.so.0.4.1
If your tarball is stored somewhere else, just adjust the path.
- You should end up with:
Set LD_LIBRARY_PATH before running
cd /tmp/inotify/inotify-runtime
export LD_LIBRARY_PATH="$PWD/lib"
./inotifywait --help
To get inotifywait to works by /usr/bin
Create /usr/bin/inotifywait wrapper script
cat > /usr/bin/inotifywait <<'EOF'
#!/bin/sh
BASE="/tmp/run/mountd/sda/inotify-runtime"
export LD_LIBRARY_PATH="$BASE/lib"
exec "$BASE/inotifywait" "$@"
EOF
chmod +x /usr/bin/inotifywait
Setup watch for /tmp directory
inotifywait -m -r \
-e create -e modify -e delete -e moved_to -e moved_from \
--format 'File: %w%f was %e' \
/tmp
- You´re done! Happy inotifying.