Notes on cross-compiling applications under DD-WRT
Recently, my Wi-Fi router stopped working and after some thought, I ordered Asus RT-N16. I wanted to finally get acquainted with alternative firmware. The characteristics of this router have already been described on Habré. So, DD-WRT is installed (v2.24), samba is wound up, a system flash drive is plugged into the first usb port, and an external hard drive is inserted into the second. And then I became interested: can I run my programs on this router? I have not found a guide to building programs for the router on the network and I hope to fill in the gap with this article. Here is a step-by-step guide describing the small problems encountered along the way.
As a test program, I wanted to run Easysync, which I wrote about recently. I repeat that this is an open program for synchronizing files in the style of dropbox. The program is written using Qt 4, and Unison is used as a synchronization engine. So this article describes how to compile Qt, Unison, Easysync for MIPS architecture and talks about running Easysync on your home router.
The routers use processors unusual for the average user. Home users are accustomed to the x86 architecture, Intel and AMD processors. The Asus RT-N16 uses the Broadcom BCM4718 processor with MIPS architecture. The resources on the router itself may not be enough to build the program and therefore, usually the programs are compiled on a big brother (for example, a familiar desktop computer), but for the desired architecture. This process is called cross-compilation.
That's it, now we have a synchronization server on our home router. If you can connect to the router from outside, then synchronization will work from anywhere.
As a test program, I wanted to run Easysync, which I wrote about recently. I repeat that this is an open program for synchronizing files in the style of dropbox. The program is written using Qt 4, and Unison is used as a synchronization engine. So this article describes how to compile Qt, Unison, Easysync for MIPS architecture and talks about running Easysync on your home router.
Mistress on a note.
The routers use processors unusual for the average user. Home users are accustomed to the x86 architecture, Intel and AMD processors. The Asus RT-N16 uses the Broadcom BCM4718 processor with MIPS architecture. The resources on the router itself may not be enough to build the program and therefore, usually the programs are compiled on a big brother (for example, a familiar desktop computer), but for the desired architecture. This process is called cross-compilation.
Instruments.
- We will need a working Linux computer on board. I used Ubuntu;
- Compilers (gcc, g ++);
- Standard C, C ++ libraries;
- Utilities in the form of GNU make, TAR, GZIP, GIT and so on;). In the case of Ubuntu, most are already installed.
Steps
- The first thing we need is to understand how the programs for DD-WRT are assembled. A page on their wiki is up to date. Of particular interest is the Instructions section . There is a link to the toolchain (hereinafter referred to as the toolchain), which is used to build DD-WRT from source. The toolchain in this case is the Uclibc library already compiled for the desired architecture , as well as the compiler. So tulcheyn swinging with DD-WRT website. It is not written there, but everything is built under the x86_64 architecture. Therefore, if you typing the command uname -m in the terminalIf you don’t see anything with a value of 64 (x86_64 or amd64), then you will have to install a new version of Linux. An alternative method is to build the toolchain yourself, but I preferred to install the system I need. After waiting for the download to complete (and this is 716 MB today), we proceed to the next step.
- We open the archive, it contains folders with toolchains for different architectures. We need toolchain-mipsel_gcc4.1.2. I unpacked this folder in / home / fralik /. Why exactly toolchain-mipsel_gcc4.1.2? Mipsel, because I saw that optware is installed from mipsel packages on the router, which means that the byte order is used from lowest to highest (little-endian). The remaining folders containing mipsel in the name, in my opinion, are used to build the DD-WRT kernel components.
- Add the toolchain to the path:
- PATH = $ PATH: ~ / toolchain-mipsel_gcc4.1.2 / bin /
- cd ~
- mipsel-linux-gcc --version
You should see GCC version information. - To verify that everything works, you can use two helloworld programs. helloworld-cc:
- #include
- #include
- int main () {
- printf ("Hello world! \ n");
- return 0;
- }
We collect and verify using the file command:mipsel-linux-gcc helloworld-cc -o helloworld-c
file helloworld-c
Must see:helloworld-c: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
You can run helloworld-c on the router and test the functionality even in reality. Now helloworld-cpp.cpp:#define NEED_PRINTF 1
#include
int main () {
std :: cout << "Hellow world!" << std :: endl;
return 0;
}
In terminal:mipsel-linux-g ++ helloworld-cpp.cpp -o helloworld-cpp
Pay attention to the first line! Without it, the program will not build and an error will be generated:/home/fralik/toolchain-mipsel_gcc4.1.2/bin/../lib/gcc/mipsel-linux-uclibc/4.1.2/../../../../include/c++/4.1.2/ cstdio: 126: error: ':: printf' has not been declared
We collect, verify that everything works on the router. - #include
- It is time to build Qt. Download Qt libraries for embedded Linux . I unpacked the archive in my home directory as well.
- We go in the terminal to the folder with Qt. You need to pay attention to the mkspecs / qws folder. It stores Make files for different architectures. For example, mkspecs / qws / linux-mips-g ++ / qmake.conf .
Copy the linux-mips-g ++ folder to linux-mipsel-g ++ :cp -R mkspecs / qws / linux-mips-g ++ / mkspecs / qws / linux-mipsel-g ++
- Edit the file mkspecs / qws / linux-mipsesl-g ++ / qmake.conf so that it uses the mipsel-linux- * commands instead of mips-linux- *. As flags I use
-mel -march = mips32r2
- Next, proceed to the Qt configuration. But first, install libxext-dev, otherwise we get an error:
Basic XLib functionality test failed!
sudo apt-get install libxext-dev
./configure -no-cups -release -shared -no-qt3support -no-phonon -no-audio-backend -no-javascript-jit -no-webkit -qt-sql-lite - no-script -no-scripttools -opensource -no-gui -no-nis -no-opengl -nomake examples -nomake demos
Must see:Qt is now configured for building. Just run 'make'. Once everything is built, you must run 'make install'. Qt will be installed into /usr/local/Trolltech/Qt-4.7.2
Run the configurator again:./configure -no-cups -release -shared -no-qt3support -no-phonon -no-audio-backend -no-javascript-jit -no-webkit -qt-sql-sqlite -no-script -no-scripttools - platform linux-g ++ - 64 -xplatform qws / linux-mipsel-g ++ -opensource -no-gui -no-nis -embedded mips -little-endian -no-opengl -nomake examples -nomake demos
The first time we configured Qt for the current architecture, the second for MIPS. In the second command, the xplatform argument just points to the folder that we created in step 6. I removed support for unnecessary things: no-qt3support, no-phonon, no-audio-backend, -nomake example, etc.
As a result, we see the following message:Qt is now configured for building. Just run 'make'. Once everything is built, you must run 'make install'. Qt will be installed into /usr/local/Trolltech/QtEmbedded-4.7.2-mips
- Run make . You can go for a smoke or brew tea. =)
At this step, I have another problem:.obj / release-shared-emb-mips / qrect.o: In function `QRectF :: toAlignedRect () const ': qrect.cpp :(. text + 0x1468): undefined reference to `ceilf ' qrect.cpp :(. text + 0x1488): undefined reference to `ceilf '
The fact is that the ceilf function is not enabled by default in the uclibc library . You can, of course, rebuild the library and add this function there, but we still use the DD-WRT toolchain, which means that the router also has a library without the ceilf function . At this step, I danced with a tambourine for a long time, trying to turn the ceilf challenge into ceil . But Qt was unshakable. I had to take on a scalpel, especially considering that I would not need the QRect class . Open the file ~ / qt-everywhere-opensource-src-4.7.2 / src / corelib / tools / qrect.cpp , find line 2379. Change to:int xmax = int ((float) ((int) xp + w));
that is, we replace the callqCeil (xp + y)
on the(float) ((int) xp + y)
We perform a similar operation on line 2381, as well as on line 640 of the file ~ / qt-everywhere-opensource-src-4.7.2 / src / corelib / tools / qtimeline.cpp
We call make again, this time the process should complete successfully. - We carry out
sudo make install
We check that now we have the Qt library under MIPS (despite Qt's assurances that the installation will occur in the /usr/local/Trolltech/QtEmbedded-4.7.2-mips folder , everything was installed in / usr / local / Trolltech / Qt -4.7.2 ):file /usr/local/Trolltech/Qt-4.7.2/lib/libQtCore.so.4.7.2
/usr/local/Trolltech/Qt-4.7.2/lib/libQtCore.so.4.7.2: ELF 32-bit LSB shared object, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
- We pass to assembly of Easysync.
# Go to some directory, for example,
cd ~
git clone git: //github.com/fralik/Easysync.git
cd Easysync / server
/usr/local/Trolltech/Qt-4.7.2/bin/qmake easysync-server .pro
make
# check:
file build / easysync-server - Now we need Unison. Despite its usefulness, it is not in optware. We will collect it directly on the router. We go to the router via ssh or telnet.
ipkg-opt install buildroot ocaml
mkdir / mnt / unison
cd / mnt / unison
wget http: // www.seas.upenn.edu /~bcpierce/unison//download/releases/stable/unison-2.40.61.tar.gz
tar xvfz unison-2.40.61.tar.gz ocaml
mkProjectInfo.ml> Makefile.ProjectInfo
# Before collecting unison, you need to make a symbolic link from libncurses to libcurses
ln -s /opt/lib/libncurses.so.5.7 / opt / lib /libcurses.so.5.7
ln -s /opt/lib/libcurses.so.5.7 /opt/lib/libcurses.so.5
ln -s /opt/lib/libcurses.so.5 /opt/lib/libcurses.so
make NATIVE = false UISTYLE = text
./unison -version
cp ./unison / opt / bin / unison
Here the key point is ocaml mkProjectInfo.ml> Makefile.ProjectInfo . Without this, it will not be possible. - Now we need to run everything that we have collected. Let's say the address of the router is 192.168.2.1 and the / mnt directory is available for us to write
scp /usr/local/Trolltech/Qt-4.7.2/lib/libQtCore.so.4.7.2 root@192.168.2.1: / opt / lib
scp /usr/local/Trolltech/Qt-4.7.2/lib/libQtNetwork .so.4.7.2 root@192.168.2.1: / opt / lib
scp /usr/local/Trolltech/Qt-4.7.2/lib/libQtSql.so.4.7.2 root@192.168.2.1: / opt / lib /
cd
# We pack Easysync-server in one file, so that it is easier to transfer to the router:
./build_package_dd-wrt.sh
scp dd-wrt_bundle.tar.gz root@192.168.2.1: / mnt - We go to the router, in the / mnt folder , unpack easysync-server-mipsel32.tar.gz
tar xvfz easysync-server_mipsel.tar.gz
ln -s /opt/lib/libQtCore.so.4.7.2 /opt/lib/libQtCore.so.4.7
ln -s /opt/lib/libQtCore.so.4.7 / opt / lib / libQtCore.so.4
ln -s /opt/lib/libQtCore.so.4 /opt/lib/libQtCore.so
ln -s /opt/lib/libQtSql.so.4.7.2 / opt / lib / libQtSql. so.4.7
ln -s /opt/lib/libQtSql.so.4.7 /opt/lib/libQtSql.so.4
ln -s /opt/lib/libQtSql.so.4 /opt/lib/libQtSql.so
ln -s /opt/lib/libQtNetwork.so.4.7.2 /opt/lib/libQtNetwork.so.4.7
ln -s /opt/lib/libQtNetwork.so.4.7 /opt/lib/libQtNetwork.so.4
ln -s / opt /lib/libQtNetwork.so.4 /opt/lib/libQtNetwork.so
- Further, it makes sense to check the operation of the unison without Easysync (you can refer to the documentation of the unison itself as well as to the Easysync install-files ). After setting up the unison, return to the router, edit the config.ini.sample file and run:
./setup_dd-wrt.sh
That's it, now we have a synchronization server on our home router. If you can connect to the router from outside, then synchronization will work from anywhere.
Brief squeeze
- You can build programs for DD-WRT using the toolchain from their website. For C ++ programs, you must use #define NEED_PRINTF .
- Despite the lack of unison in the assembly of optware, it can be assembled on a router. You can, in principle, do cross-compilation, but I did not understand this.
- Qt is almost without problems going under MIPS: +1 to the cross-platform of your programs.
- Easysync is now on home routers! It is worth noting that after a reboot, the service will not start automatically. Most likely, it will not even be marked as installed (because the installation flag is stored in / tmp ). It can re-establish the command / opt / bin / easysync-server -i or run without installation team /opt/etc/init.d/easysync-server start
for those interested Easysync'om, but does not want to build it from source , an already compiled version is available .Update 05/30/2016
Nabytovych user suggests that some links are out of date. Updated links to toolchain and Qt.