Skip to content

Instantly share code, notes, and snippets.

@lupyuen
Last active June 1, 2023 23:32
Show Gist options
  • Save lupyuen/f59c681dde9ebac86b331f2577aa04ad to your computer and use it in GitHub Desktop.
Save lupyuen/f59c681dde9ebac86b331f2577aa04ad to your computer and use it in GitHub Desktop.
Compile Apache NuttX RTOS on Android with Termux (Incomplete)

Compile Apache NuttX RTOS on Android with Termux (Incomplete)

How to compile Apache NuttX RTOS on Android with Termux (incomplete)...

Install Termux

Install Termux from F-Droid, because the Google Play version is outdated...

Launch Termux on Android and enter...

pkg upgrade
pkg update

Install SSH Server or Dropbear

Install SSH Server, so that it's easier to enter the install commands later...

## Install SSH Server
pkg install openssh

## Set the SSH Password
passwd

## Start SSH Server. To kill SSH Server: `pkill sshd`
sshd

## Find the IP address x.x.x.x of our Android Device
ifconfig

Alternatively, install Dropbear (because SSHD didn't work for me)...

## Install Dropbear
pkg install dropbear

## Set the SSH Password
passwd

## Start Dropbear. To kill Dropbear: `pkill dropbear`
dropbear

## Find the IP address x.x.x.x of our Android Device
ifconfig

From our Desktop Computer, ssh to our Android Device...

ssh x.x.x.x -p 8022

Install NuttX Build Tools

In the SSH Session, install the NuttX Build Tools on Android Termux...

pkg install binutils clang git make \
  bison flex gettext texinfo \
  gperf automake libtool pkg-config \
  util-linux 

## Kconfig doesn't exist for Arm64 Android, need to build ourselves
pushd $TMPDIR
git clone https://bitbucket.org/nuttx/tools.git
cd tools
cd kconfig-frontends
./configure --enable-mconf --disable-nconf --disable-gconf --disable-qconf
ln -s /data/data/com.termux/files/usr/bin/aclocal /data/data/com.termux/files/usr/bin/aclocal-1.15
ln -s /data/data/com.termux/files/usr/bin/automake /data/data/com.termux/files/usr/bin/automake-1.15
make

## `make install` won't work because Android Termux uses its own PATH
cp frontends/conf/.libs/kconfig-conf /data/data/com.termux/files/usr/bin
cp frontends/mconf/.libs/kconfig-mconf /data/data/com.termux/files/usr/bin
cp frontends/kconfig /data/data/com.termux/files/usr/bin
cp utils/kconfig-tweak /data/data/com.termux/files/usr/bin
cp libs/parser/.libs/libkconfig-parser-4.11.0.so /data/data/com.termux/files/usr/lib/
popd

Assume we're building NuttX for Arm64 PinePhone.

Termux on Android is based on aarch64-linux-android-gcc, which isn't supported by the Precompiled GCC Toolchain. So we need to compile the GCC Toolchain ourselves.

Install GCC Arm64 Toolchain aarch64-none-elf-gcc from Source Code...

## Download GCC Toolchain Source Code.
## Copied from https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
cd $HOME
mkdir gcc
cd gcc
curl -O -L https://developer.arm.com/-/media/Files/downloads/gnu/12.2.rel1/srcrel/arm-gnu-toolchain-src-snapshot-12.2.rel1.tar.xz
tar xf ../arm-gnu-toolchain-src-snapshot-12.2.rel1.tar.xz

## Build MPC ourselves because the older version fails with clang
curl -O -L https://ftp.gnu.org/gnu/mpc/mpc-1.1.0.tar.gz
tar xf mpc-1.1.0.tar.gz
pushd mpc-1.1.0
./configure \
  --disable-shared \
  --enable-static \
  --prefix=$HOME/gcc \
  --with-gmp=$HOME/gcc \
  --with-mpfr=$HOME/gcc
make
make install
popd

## Build GCC Toolchain for `aarch64-none-elf`
## TODO: Change the target for your NuttX Device
## Refer to the Linaro ABE Example Manifests at https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
pushd arm-gnu-toolchain-src-snapshot-12.2.rel1
./configure \
  --target=aarch64-none-elf \
  --enable-static \
  --prefix=$HOME/gcc \
  --with-gmp=$HOME/gcc \
  --with-mpfr=$HOME/gcc \
  --disable-shared \
  --disable-nls \
  --disable-threads \
  --disable-tls \
  --enable-checking=release \
  --enable-languages=c,c++ \
  --with-newlib \
  --with-gnu-as \
  --with-gnu-ld

make
## Or `make -j 8` if your Android Device can handle it.
## Don't try `make -j`, it will crash your Android Device!

make install
popd

(Based on the Linaro ABE Example Manifest for aarch64-none-elf)

GCC Build fails with this error...

make[3]: Entering directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/build-aarch64-unknown-linux-gnu/libcpp'
test -f config.h || (rm -f stamp-h1 && make stamp-h1)
g++ -std=c++11  -I../.././libcpp -I. -I../.././libcpp/../include -I../.././libcpp/include  -g -O2       -W -Wall -Wno-narrowing -Wwrite-strings -Wmissing-format-attribute -pedantic -Wno-long-long  -fno-exceptions -fno-rtti -I../.././libcpp -I. -I../.././libcpp/../include -I../.././libcpp/include    -c -o lex.o -MT lex.o -MMD -MP -MF .deps/lex.Tpo ../.././libcpp/lex.cc
../.././libcpp/lex.cc:1289:7: warning: use of the 'likely' attribute is a C++20 extension [-Wc++20-attribute-extensions]
      ATTR_LIKELY case kind::NONE:
      ^~~~~~~~~~~
../.././libcpp/system.h:427:25: note: expanded from macro 'ATTR_LIKELY'
#  define ATTR_LIKELY [[likely]]
                      ~~^~~~~~~~
../.././libcpp/lex.cc:4241:6: error: use of undeclared identifier 'fputc_unlocked'
            fputc (NODE_NAME (token->val.node.node)[i], fp);
            ^
../.././libcpp/system.h:95:28: note: expanded from macro 'fputc'
#  define fputc(C, Stream) fputc_unlocked (C, Stream)
                           ^
../.././libcpp/lex.cc:4247:2: error: use of undeclared identifier 'fputc_unlocked'
        fputc ('"', fp);
        ^
../.././libcpp/system.h:95:28: note: expanded from macro 'fputc'
#  define fputc(C, Stream) fputc_unlocked (C, Stream)
                           ^
../.././libcpp/lex.cc:4250:2: error: use of undeclared identifier 'fputc_unlocked'
        fputc ('"', fp);
        ^
../.././libcpp/system.h:95:28: note: expanded from macro 'fputc'
#  define fputc(C, Stream) fputc_unlocked (C, Stream)
                           ^
1 warning and 3 errors generated.
make[3]: *** [Makefile:227: lex.o] Error 1
make[3]: Leaving directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/build-aarch64-unknown-linux-gnu/libcpp'
make[2]: *** [Makefile:3110: all-build-libcpp] Error 2
make[2]: Leaving directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1'
make[1]: *** [Makefile:26855: stage1-bubble] Error 2
make[1]: Leaving directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1'
make: *** [Makefile:1072: all] Error 2

Because fputc_unlocked isn't defined on Android Termux. (See this)

To fix it: Edit gcc/system.h and undefine fputc at the end of the file...

// Existing code
...
#endif /* ! GCC_SYSTEM_H */

// Add this to the end of the file
#undef fputc

And rerun make -j.

We might need to fix this warning...

gcc -c -g -O2     -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -Wno-overlength-strings -pedantic -Wno-long-long   -DHAVE_CONFIG_H -I. -I../.././fixincludes -I../include -I../.././fixincludes/../include ../.././fixincludes/fixincl.c
../.././fixincludes/fixincl.c:1255:8: warning: call to undeclared function 'fputc_unlocked'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
       fputc ('\n', out_fp);
       ^
../.././fixincludes/system.h:78:28: note: expanded from macro 'fputc'
#  define fputc(C, Stream) fputc_unlocked (C, Stream)

TODO: GCC Toolchain Build fails with another error...

make[2]: Entering directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc'
/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc/xgcc -B/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc/ -dumpspecs > tmp-specs
"/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc/xgcc": error: Android 5.0 and later only support position-independent executables (-fPIE).
make[2]: *** [Makefile:2185: specs] Error 1
make[2]: Leaving directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc'

TODO: To fix this, edit host-aarch64-unknown-linux-gnu/gcc/Makefile. Change...

NO_PIE_CFLAGS = -fno-PIE
NO_PIE_FLAG = -no-pie

To...

NO_PIE_CFLAGS = -fPIE
NO_PIE_FLAG = -fPIE

Rebuild...

pushd host-aarch64-unknown-linux-gnu/gcc
make clean
make -j 8
popd
make

Fails with this error...

checking for aarch64-none-elf-gcc... /data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc/xgcc -B/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/host-aarch64-unknown-linux-gnu/gcc/ -B/data/data/com.termux/files/home/gcc/aarch64-none-elf/bin/ -B/data/data/com.termux/files/home/gcc/aarch64-none-elf/lib/ -isystem /data/data/com.termux/files/home/gcc/aarch64-none-elf/include -isystem /data/data/com.termux/files/home/gcc/aarch64-none-elf/sys-include
checking for suffix of object files... configure: error: in `/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1/aarch64-none-elf/libgcc':
configure: error: cannot compute suffix of object files: cannot compile
See `config.log' for more details
make[1]: *** [Makefile:13954: configure-target-libgcc] Error 1
make[1]: Leaving directory '/data/data/com.termux/files/home/gcc/arm-gnu-toolchain-src-snapshot-12.2.rel1'
make: *** [Makefile:1030: all] Error 2

TODO: xgcc has been compiled successfully. How do we turn it into aarch64-none-elf-gcc?

~/.../host-aarch64-unknown-linux-gnu/gcc $ ./xgcc --help
Usage: xgcc [options] file...
Options:
  -pass-exit-codes         Exit with highest error code from a phase.
  --help                   Display this information.
  --target-help            Display target specific command line options (including assembler and linker options).
  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...].
                           Display specific types of command line options.
  (Use '-v --help' to display command line options of sub-processes).
  --version                Display compiler version information.
  -dumpspecs               Display all of the built in spec strings.
  -dumpversion             Display the version of the compiler.
  -dumpmachine             Display the compiler's target processor.
  -foffload=<targets>      Specify offloading targets.
  -print-search-dirs       Display the directories in the compiler's search path.
  -print-libgcc-file-name  Display the name of the compiler's companion library.
  -print-file-name=<lib>   Display the full path to library <lib>.
  -print-prog-name=<prog>  Display the full path to compiler component <prog>.
  -print-multiarch         Display the target's normalized GNU triplet, used as
                           a component in the library path.
  -print-multi-directory   Display the root directory for versions of libgcc.
  -print-multi-lib         Display the mapping between command line options and
                           multiple library search directories.
  -print-multi-os-directory Display the relative path to OS libraries.
  -print-sysroot           Display the target libraries directory.
  -print-sysroot-headers-suffix Display the sysroot suffix used to find headers.
  -Wa,<options>            Pass comma-separated <options> on to the assembler.
  -Wp,<options>            Pass comma-separated <options> on to the preprocessor.
  -Wl,<options>            Pass comma-separated <options> on to the linker.
  -Xassembler <arg>        Pass <arg> on to the assembler.
  -Xpreprocessor <arg>     Pass <arg> on to the preprocessor.
  -Xlinker <arg>           Pass <arg> on to the linker.
  -save-temps              Do not delete intermediate files.
  -save-temps=<arg>        Do not delete intermediate files.
  -no-canonical-prefixes   Do not canonicalize paths when building relative
                           prefixes to other gcc components.
  -pipe                    Use pipes rather than intermediate files.
  -time                    Time the execution of each subprocess.
  -specs=<file>            Override built-in specs with the contents of <file>.
  -std=<standard>          Assume that the input sources are for <standard>.
  --sysroot=<directory>    Use <directory> as the root directory for headers
                           and libraries.
  -B <directory>           Add <directory> to the compiler's search paths.
  -v                       Display the programs invoked by the compiler.
  -###                     Like -v but options quoted and commands not executed.
  -E                       Preprocess only; do not compile, assemble or link.
  -S                       Compile only; do not assemble or link.
  -c                       Compile and assemble, but do not link.
  -o <file>                Place the output into <file>.
  -pie                     Create a dynamically linked position independent
                           executable.
  -shared                  Create a shared library.
  -x <language>            Specify the language of the following input files.
                           Permissible languages include: c c++ assembler none
                           'none' means revert to the default behavior of
                           guessing the language based on the file's extension.

Options starting with -g, -f, -m, -O, -W, or --param are automatically
 passed on to the various sub-processes invoked by xgcc.  In order to pass
 other options on to these processes the -W<letter> options must be used.

For bug reporting instructions, please see:
<https://gcc.gnu.org/bugs/>.

~/.../host-aarch64-unknown-linux-gnu/gcc $ ./xgcc -dumpmachine
aarch64-none-elf

TODO: Add aarch64-none-elf-gcc to PATH. ~/.bashrc doesn't exist on Android Termux.

Download NuttX...

cd $HOME
mkdir nuttx
cd nuttx
git clone https://github.com/apache/nuttx nuttx
git clone https://github.com/apache/nuttx-apps apps

Configure NuttX...

cd nuttx
tools/configure.sh pinephone:lvgl

Build NuttX...

make

Which fails because the GCC Arm64 Toolchain aarch64-none-elf-gcc is not installed...

~/nuttx/nuttx $ make
sh: aarch64-none-elf-gcc: inaccessible or not found
ERROR: aarch64-none-elf-gcc failed: 127
       command: aarch64-none-elf-gcc -MT ./builtin_list.c.data.data.com.termux.files.home.nuttx.apps.builtin.o  -M '-fno-common' '-Wall' '-Wstrict-prototypes' '-Wshadow' '-Wundef' '-Werror' '-Os' '-fno-strict-aliasing' '-fomit-frame-pointer' '-ffunction-sections' '-fdata-sections' '-g' '-march=armv8-a' '-mtune=cortex-a53' '-isystem' '/data/data/com.termux/files/home/nuttx/nuttx/include' '-D__NuttX__' '-D__KERNEL__' '-pipe' '-I' '/data/data/com.termux/files/home/nuttx/apps/graphics/lvgl' '-I' '/data/data/com.termux/files/home/nuttx/apps/include' ./builtin_list.c
make[2]: *** [/data/data/com.termux/files/home/nuttx/apps/Application.mk:250: .depend] Error 1
make[1]: *** [Makefile:56: /data/data/com.termux/files/home/nuttx/apps/builtin_depend] Error 2
make: *** [tools/Unix.mk:594: pass2dep] Error 2

Remember give extra power to Android Termux to speed it up...

  • Termux > App Info > App Battery Usage > Unrestricted

If the GCC Toolchain fails to build, try another distro on top of Termux...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment