-
-
Notifications
You must be signed in to change notification settings - Fork 182
Using GCC for native compilation
- General Information
- Installing GCC on Entware
- Installing a build configuration system
- Installing development headers
- Environment variables
- Example compilation process
- External links
The gcc package is a beta release in the OpenWrt package repository, and it is treated likewise in Entware, primarily intended for advanced users who understand how to work around its limitations. Specifically, the GCC package in the Entware repositories only supports dynamic linking; static linking is not supported, there are no static libraries.
It is faster and much more reliable to cross-compile binaries on a GNU/Linux computer or virtual machine of a different architecture (x86_64, for instance), and a basic primer for doing so is provided here in our Wiki.
There are some notable restrictions in what can be successfully compiled and how when using GCC on Entware, and a majority are described in the following sections.
Tip
As always, before attempting to install packages in Entware using opkg, first
use the opkg update command to ensure that you're getting the latest
versions available.
A barebones install of the GCC compiler can be performed using these commands.
It will install the gcc package as well as well as any of its dependencies
(binutils, libc, libpthread, librt, libssp, and libstdcpp) that
aren't already present on the system.
opkg install gccIn addition to installing the gcc packages plus its dependencies (as shown
above), users are strongly encouraged to also install the binutils, busybox,
gawk, ldd, make, sed and tar packages before a successful compilation
can be reasonably expected for even the simplest software.
opkg install binutils busybox gawk ldd make sed tarWhile the above commands will prepare your Entware environment to perform basic
compilation of software written in C/C++ from source code, it is still lacking
some crucial utilities that most modern software projects rely on to configure
the build process appropriately for the environment it will take place on. Some
basic utilities that are often integral to the build process include the
coreutils-install, diffutils, ldconfig, patch and pkg-config packages,
which can be installed with the command below.
opkg install coreutils-install diffutils ldconfig patch pkg-config --force-overwriteThere are also several build configuration systems with widespread adoption, of which it is highly likely that you will require at least one. Once you identify the one in use by the project you're seeking to compile, the following command snippets can help you install the required packages for each.
opkg install automake libintl-full libtool-binopkg install cmake icu libopensslopkg install bash git python3-pip python3-setuptools
python3 -m pip install -U wheel
cd /opt/tmp && git clone https://github.com/ninja-build/ninja.git && cd ./ninja
git checkout release
CONFIG_SHELL=/opt/bin/bash python3 ./configure.py --bootstrap
install -Dm0755 -t /opt/bin ./ninja
cd /opt/tmp && rm -Rf /opt/tmp/ninja
python3 -m pip install -U mesonImportant
While nearly all packages in the Entware repositories are distributed without development files, a select few whose build process automatically generates architecture-dependent headers do get packaged with those headers included. Currently, those packages are:
gcc • libncurses-dev •
libxml2-dev • python3-dev • ruby-dev
• zlib-dev
If you have any of those packages installed and /opt/include is deleted or
its contents are corrupted, errors when compiling software natively (i.e. on
the device your Entware environment runs on), the issue is likely to be that
files belonging to one of the above are no longer accessible. If this happens
to you, copy/paste the following command into your Entware terminal and
execute it to forcibly reinstall every package on the list that's found in the
output of opkg list-installed to a pristine state.
for pkg in gcc libncurses-dev libxml2-dev python3-dev ruby-dev zlib-dev; do
opkg list-installed | grep -qsw "^${pkg}" && opkg --force-overwrite --force-reinstall install "${pkg}"
doneThere are no *-dev or *-devel packages in Entware (as it comes from
OpenWrt), unlike the majority of Linux distributions in use today. Those
packages typically install the headers, static libraries and other development
files that are required to successfully build and link other software that
depends on those packages. In order to keep the number of packages in each of
the Entware repositories manageable, each time new versions of packages are
built, rather than those files being packaged into individual -dev packages, a
single compressed tarball of all the headers and development files from the
entirety of packages is produced and uploaded to the repository.
Note
If you use these include files, configure scripts generated by Autotools that you run to prepare to compile something may report to you that you have software projects installed that you in fact do not. The reason for this is that the include archive has the development header files for almost all of the packages in Entware, and no way to selectively install only those files for the packages currently on your system. Thus, a project relying on libxml2 may tell you that it found libxml2 and complete its build configuration successfully, only to fail during compilation with a "File not found:…" error. What happened is that the configuration script found the libxml2 headers in the include directory and simply assumed you also had the library they belong to, which you didn't. The customary solution to that is to determine which Entware package(s) the missing files are associated with, and install them, then run the configure script again.
Tip
If the reverse is true and you find that the build system is unable to locate
a library or other package that you are certain is present on your system
along with its headers, the issue may be the lack of a .pc file for it in
/opt/lib/pkgconfig. You can often overcome this by visiting the source code
repository for that library/package and finding out what the expected name and
contents are of the .pc files it installs, then download them with the correct
name into /opt/lib/pkgconfig or using a text editor to create them in that
directory by hand.
There is a different tar.gz archive for each of the architectures in the Entware repository. You can expand the section below to find the link to the archive for your device's architecture in order to download it directly to your computer and examine the contents. This would be a prudent step for someone who, for instance, didn't expect to need the files for more than just a single compilation and was familiar enough with the process to know which files/directories they needed, preferring not to clutter their Entware filesystem with the full contents of the archive.
Links to header archives for all Entware-supported architectures
| Architecture | Kernel Ver. | Archive Link |
|---|---|---|
| aarch64 | 3.10 | https://bin.entware.net/aarch64-k3.10/include/include.tar.gz |
| mipssf | 3.4 | https://bin.entware.net/mipssf-k3.4/include/include.tar.gz |
| mipselsf | 3.4 | https://bin.entware.net/mipselsf-k3.4/include/include.tar.gz |
| armv7sf | 3.2 | https://bin.entware.net/armv7sf-k3.2/include/include.tar.gz |
| x64 | 3.2 | https://bin.entware.net/x64-k3.2/include/include.tar.gz |
For those interested in adding all of the development files available for their architecture to their Entware partition, the following one-liner shell command can determine the correct architecture link from the table above, download the archive and expand its contents in the proper location, using just the busybox tools present in every Entware setup.
Important
This currently requires over 300 MiB of available storage on your Entware filesystem and is prone to increasing in size over time, as new packages are added to Entware and the existing ones become more complex.
/opt/bin/busybox wget -qO- "$(/opt/bin/busybox sed -Ene \
's%^src/gz[[:space:]]entware[[:space:]]https?([[:graph:]]+)%http\1/include/include.tar.gz%p' \
/opt/etc/opkg.conf)" | /opt/bin/busybox tar x -vzC /opt/includeBinaries compiled in Entware must use rpath=/opt/lib and a non-standard
dynamic linker. The gcc package installs the /opt/bin/gcc_env.sh script that
will set sane default values for the CFLAGS and LDFLAGS environment variables
which are crucial for building binaries, but don't be surprised if they require
further customization to achieve a successful build. If the source code you're
attempting to build is written in C++ and not C, you may also have to define the
CPPFLAGS and/or CXXFLAGS variables. For armv7sf, this might look like:
List of the dynamic linker path and GNU C Library (`glibc`) version for all Entware-supported architectures
| Architecture | Kernel Ver. | Dynamic Linker | GNU C Library Version |
|---|---|---|---|
| aarch64 | 3.10 | /opt/lib/ld-linux-aarch64.so.1 |
2.27 |
| mipssf | 3.4 | /opt/lib/ld.so.1 |
2.27 |
| mipselsf | 3.4 | /opt/lib/ld.so.1 |
2.27 |
| armv7sf | 3.2 | /opt/lib/ld-linux.so.3 |
2.27 |
| x64 | 3.2 | /opt/lib/ld-linux-x86-64.so.2 |
2.27 |
/opt/lib/ld-linux.so.3 |
|||
/opt/lib/ld-linux.so.3 |
|||
/opt/lib/ld-linux.so.2 |
export LDFLAGS="-Wl,-rpath=/opt/lib -Wl,--dynamic-linker=/opt/lib/ld-linux.so.3 -L/opt/lib"
export CFLAGS="-O2 -pipe -march=armv7-a -mtune=cortex-a9 -fno-caller-saves -mfloat-abi=soft"
export CPPFLAGS="${CFLAGS} -I/opt/include"
export CXXFLAGS="${CFLAGS} ${LDFLAGS}"To setup environment variables for GCC execute
source /opt/bin/gcc_env.shAlternatively, use the flags from /opt/bin/gcc_env.sh manually when building
binaries, such as the following invocation for the GNU C Compiler:
source /opt/bin/gcc_env.sh && gcc "${CFLAGS}" "${LDFLAGS}" helloworld.c -o helloworldOr this one for the GNU C++ Compiler:
source /opt/bin/gcc_env.sh && g++ "${CFLAGS}" -I/opt/include "${LDFLAGS}" \
helloworld.c -o helloworldNote
Environment variables are applied automatically in the latest gcc package. Always attempt to build with the environment you have upon starting the shell first before making changes.
If you find yourself forced to attempt to "finesse" the compilation flags to achieve a working build of something, a good place to start is always the compiler's default target for your particular architecture. You can print them to the console in their entirety with this single command:
gcc -march=native -v -Q --help=targetTip
On rare occasions, there can be some utility in comparing the
compiler/precompiler defines with the project's header files. You can print
the defines to the terminal using echo | gcc -dM -E - -march=native.
Let's use GCC to build the GNU Screen
binary. The project documentation informs us that screen depends on
libncursesw and that it uses GNU Autotools to configure new builds, so install
those first, then download and extract the source code archive. Inside you're
likely to find specific tips on building the project written by the
developer(s), often in one or more files named README, INSTALL or broken
down by platform under a doc/ directory. These can be read comfortably in the
terminal using the command: ${PAGER:-/opt/bin/less} [filename] (if that
produces an error, install a pager program like less, more or most using
opkg).
The following sequence of commands demonstrates a pain-free progression from first downloading the source code tarball, verifying its integrity and extracting its contents, setting the build configuration, then finally compiling the code. It's almost never this easy.
Important
You should always pass the prefix flag to an Autotools configure script, as in
sh ./configure --prefix=/opt, and it is not at all uncommon to need to do
likewise to any other options the project exposes that involve file paths (e.g.
--sysconfdir, --sharedstatedir, --runstatedir, etc. You can see a list
containing them all using the command sh ./configure --help.) and pointing
them to a location analogous to their default but inside the /opt directory,
where you have full permissions to read, write and execute files.
Not all steps will apply to all projects; common sense must always prevail. This is an attempt to illustrate the use of "best practices" for the task in general, not a set of hard and fast rules that need to take place for a successful result.
-
Confirm that you have all the packages you need installed, for the build system and any dependencies the project needs
opkg install gcc libc libgcc autoconf automake m4 make libtool-bin pkg-config libncursesw libncurses-dev terminfo gnupg2 ldconfig ldd
-
Create a new empty directory to contain everything and make it the working directory
mkdir /opt/tmp/source && cd /opt/tmp/source
-
Download the source code archive file (tarball) you're interested in
wget http://ftp.gnu.org/gnu/screen/screen-4.8.0.tar.gz
-
If it's signed for authenticity, download the signature too
wget http://ftp.gnu.org/gnu/screen/screen-4.8.0.tar.gz.sig
-
Download the public key of the signer, either by downloading a keyring file like below or with the key ID published on the download page
wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
or
gpg --keyserver hkps://keys.openpgp.org/ --recv-keys [KEY_ID]
-
Use GnuPG to verify the signature against the public key/keyring file
gpg --verify --keyring ./gnu-keyring.gpg ./screen-4.8.0.tar.gz.sig
or
gpg --verify ./screen-4.8.0.tar.gz.sig
-
-
Uncompress the archive file
/opt/bin/busybox tar xvzf ./screen-4.8.0.tar.gz
-
Make the newly-expanded source code folder the working directory
cd ./screen-4.8.0 -
Verify that all the Autotools files are present and up-to-date
autoreconf -vfi
-
Run the
configurescript, making sure you at least set the --prefix flag (a list of all available options can be printed withsh ./configure --help)sh ./configure --prefix=/opt --sharedstatedir=/opt/var/lib --with-socket-dir=/opt/tmp/screens --with-sys-screenrc=/opt/etc/screenrc
It is critically important to use --prefix=/opt if the package creates
executables or shared libraries, or for any project you intend to install using
the make install command, instead of moving/copying the files yourself in the
shell. It's also a good practice to carefully review the list of available
configuration options to discover if any are used to define the default paths
for the program's working files. These will almost always need to be supplied
along with the prefix to the configuration script rather than using the
defaults, as was done in the example above (note that the final two option flags
above are specific to building GNU Screen and not applicable to most Autotools
builds, though the first two are). Since Entware itself lives in a
non-standard path and is most often running on embedded devices whose root
filesystems are read-only, causing software that's built expecting to write
information there to crash or otherwise behave unpredictably.
Now invoke GNU make to execute the configured build, using as many cores as your
device's CPU has, and (optionally) turn on verbose output by adding V=1 to
help troubleshoot any errors that arise:
make -j$(nproc) V=1If the process completes without error, you will find the screen binary in the
working directory. To examine the shared objects it was linked to, do:
$ ldd ./screen
libncursesw.so.6 => /opt/lib/libncursesw.so.6 (0x4011a000)
libcrypt.so.1 => /opt/lib/libcrypt.so.1 (0x4017f000)
libgcc_s.so.1 => /opt/lib/libgcc_s.so.1 (0x4009f000)
libc.so.6 => /opt/lib/libc.so.6 (0x401be000)
libdl.so.2 => /opt/lib/libdl.so.2 (0x402f9000)
/opt/lib/ld-linux.so.3 (0x400e7000)This binary appears to be exactly as we'd hoped. Specifically, what you want to see is:
- It only uses shared objects from
/opt/libor (rarely) elsewhere under/opt, and - The correct dynamic linker,
/opt/lib/ld-linux.so.3was used (you can confirm this against the table of dynamic linkers above).
You can run the newly-compiled binary in the build tree to ensure it functions as expected prior to installing it:
LD_LIBRARY_PATH="$(pwd)${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH:-/opt/lib}}" ./screenIf you're satisfied with what you saw, you can complete the process by
installing it alongside the files from your Entware packages, but first do a dry
run using make --dry-run install and check to see that all of the target paths
look well-formed. If so, you can install the fruits of your labors and retreat
out of the build directory and delete it (assuming you have no further use for
the contents).
# Actually execute the install commands printed in the dry run
make install
# Some projects that build shared libraries require that the list of shared
# objects be refreshed manually after installation, and will print a message
# roughly to that effect among the install command output. If you see one, then:
ldconfig -v
# Return to the parent directory and list its contents to be sure you're not
# deleting anything important
cd .. && ls -lFAhkp --group-directories-first
# Delete your downloads from earlier
rm -iv screen-4.8.0.tar.gz* gnu-keyring.gpg
# Likewise, delete the extracted contents of the source code archive
rm -Rfv ./screen-4.8.0/- Android
- ASUS stock firmware (ASUSWRT)
- ASUSTOR NAS
- Asuswrt-Merlin
- DD-WRT
- FreshTomato (TomatoUSB)
- Oleg's firmware
- Padavan firmware
- QNAP NAS
- Remarkable tablet
- Synology NAS
- TerraMaster NAS
- Zyxel NAS326 / NAS542
- aria2
- asciinema
- cron
- deluge
- dnscrypt-proxy
- Let's Encrypt (ACME)
- ownCloud
- pyload
- rtmpdump
- rtorrent
- SANE
- tmux
- transmission

