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.

    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


    1. 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.
    2. 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.
    3. Add the toolchain to the path:
      1. PATH = $ PATH: ~ / toolchain-mipsel_gcc4.1.2 / bin /
      2. cd ~
      3. mipsel-linux-gcc --version

      You should see GCC version information.
    4. To verify that everything works, you can use two helloworld programs. helloworld-cc:
      1. #include 
      2. #include 
      3.  
      4. int main () {
      5.     printf ("Hello world! \ n");
      6.     return 0;
      7. }

      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.
    5. It is time to build Qt. Download Qt libraries for embedded Linux . I unpacked the archive in my home directory as well.
    6. 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 ++
    7. 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
    8. 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
      
    9. 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 call
      qCeil (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.
    10. 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
    11. 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
    12. 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.
    13. 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
    14. 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
       
    15. 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


    1. You can build programs for DD-WRT using the toolchain from their website. For C ++ programs, you must use #define NEED_PRINTF .
    2. 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.
    3. Qt is almost without problems going under MIPS: +1 to the cross-platform of your programs.
    4. 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.

    Also popular now: