cross-compilingomniorb

How to cross-compile omniORB 4 (on x86_64 for ARM with omniORB 4.1.6)


omniORB 4 uses an Autoconf configure script to support configuration of the build system. Many configure scripts support cross-compiling with the use of the --host and --build flags. Unfortunately, omniORB explicitly states in their README.unix file that cross compiling is not supported.

The Autoconf build does not currently work for cross compiling.

Here's what happens when you do try to use the --host and --build Autoconf flags:

Environment:

Note: I use three dots (...) to omit parts of file paths or unimportant output.

$ pwd
.../omniORB-4.1.6
$ mkdir build
$ cd build
$ ../configure --build=x86_64-linux-gnu --host=arm-linux-gnueabihf
...
$ make
...
omniidl: ERROR!

omniidl: Could not open IDL compiler module _omniidlmodule.so
omniidl: Please make sure it is in directory .../omniORB-4.1.6/build/lib
omniidl: (or set the PYTHONPATH environment variable)

omniidl: (The error was '.../omniORB-4.1.6/build/lib/_omniidlmodule.so: wrong ELF class: ELFCLASS32')
...

I believe the important message there to be wrong ELF class: ELFCLASS32. I inspected this shared object library with file.

$ file lib/_omniidlmodule.so.4.1
lib/_omniidlmodule.so.4.1: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, ...

So it appears the build system builds this shared object module for use by omniidl during the omniORB build. The issue is that it is built for ARM, and cannot be used on the host system.

How can I cross-compile omniORB given the lack of support from their build system?


Solution

  • I came to my solution with the help of an instructional post on the website of a company called Tango Controls. While their instructions may be enough for some, they were not adequate for me. The first problem was that it did not consider the need to include/link against libraries (e.g. Python) built for the host system. The second problem is that it does not address installation properly - when you follow their instructions you will end up installing some executables and libraries built for the build system.

    System Terminology (as defined by Autoconf):

    Here are the steps I took to cross-compile omniORB:

    1. Create and enter a build directory
    $ pwd
    .../omniORB-4.1.6
    $ mkdir build
    $ cd build
    
    1. Set up your environment

      • PATH set to include the cross-compilation tools
      • CPPFLAGS set to include the ARM sysroot/include folder -I.../sysroot/include
      • LDFLAGS set to include the ARM sysroot/lib folder -L.../sysroot/lib
    2. Configure

    Set your own --prefix as necessary and modify CC and CXX for your setup. You may also need to change the --build and --host settings.

    $ ../configure --build=x86_64-linux-gnu --host=arm-linux-gnueabihf --prefix=.../sysroot \
        CC=.../bin/arm-linux-gnueabihf-gcc \
        CXX=.../bin/arm-linux-gnueabihf-g++
    ...
    

    Note: I use three dots (...) to omit parts of file paths or unimportant output.

    1. Remove the include and library paths from beforeauto.mk for the x86_64 tool build
    $ sed -i 's#CPPFLAGS = -I.*include \$(DIR_CPPFLAGS) \$(IMPORT_CPPFLAGS)#CPPFLAGS = $(DIR_CPPFLAGS) $(IMPORT_CPPFLAGS)#' mk/beforeauto.mk
    $ sed -i 's#CLINKOPTIONS    = -L.*lib \$(CDEBUGFLAGS) \$(COPTIONS)#CLINKOPTIONS    = $(CDEBUGFLAGS) $(COPTIONS)#' mk/beforeauto.mk
    $ sed -i 's#CXXLINKOPTIONS  = -L.*lib \$(CXXDEBUGFLAGS) \$(CXXOPTIONS)#CXXLINKOPTIONS  = $(CXXDEBUGFLAGS) $(CXXOPTIONS)#' mk/beforeauto.mk
    

    These sed commands are generalized, but you may still need to modify them for your own setup.

    1. Make tools for the build system

    These tools are used during the compilation of omniORB, so they need to be compiled for the build system. We force make to use the build system compilers with the CC and CXX variables. These may need modification depending on the name of your build system compilers. Ensure these compilers are on your PATH.

    $ make CC=gcc -C src/tool/omniidl/cxx/cccp
    ...
    $ make CXX=g++ -C src/tool/omniidl/cxx
    ...
    $ make CC=gcc -C src/tool/omkdepend
    ...
    
    1. Patch build system - might not be necessary

    The instructions from the Tango post say to add the stdc++ lib to some of the make commands with the -l flag. The below sed commands may be used for this patch.

    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/omniMapper/dir.mk
    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/omniNames/dir.mk
    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/utils/catior/dir.mk
    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/utils/convertior/dir.mk
    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/utils/genior/dir.mk
    $ sed -i 's/@(libs="$(CORBA_LIB_NODYN)"; $(CXXExecutable))/@(libs="$(CORBA_LIB_NODYN) -lstdc++"; $(CXXExecutable))/' ../src/appl/utils/nameclt/dir.mk
    

    I have not yet determined if this patch is necessary for all systems and software versions. For my own setup, the build succeeds with or without this patch. I will update this answer if I learn more about this patch.

    1. Put the include and library paths back in beforeauto.mk for the ARM omniORB build

    You will need to put in your own paths in place of ....

    $ sed -i 's#CPPFLAGS = \$(DIR_CPPFLAGS) \$(IMPORT_CPPFLAGS)#CPPFLAGS = -I.../sysroot/include $(DIR_CPPFLAGS) $(IMPORT_CPPFLAGS)#' mk/beforeauto.mk
    $ sed -i 's#CLINKOPTIONS    = \$(CDEBUGFLAGS) \$(COPTIONS)#CLINKOPTIONS    = -L.../sysroot/lib $(CDEBUGFLAGS) $(COPTIONS)#' mk/beforeauto.mk
    $ sed -i 's#CXXLINKOPTIONS  = \$(CXXDEBUGFLAGS) \$(CXXOPTIONS)#CXXLINKOPTIONS  = -L.../sysroot/lib $(CXXDEBUGFLAGS) $(CXXOPTIONS)#' mk/beforeauto.mk
    
    1. Cross-compile omniORB
    $ make
    ...
    
    1. Cross-compile the tools we originally built for the build system
    $ make -C src/tool/omniidl/cxx/cccp clean
    ...
    $ make -C src/tool/omniidl/cxx clean
    ...
    $ make -C src/tool/omkdepend clean
    ...
    $ make -C src/tool/omniidl/cxx/cccp
    ...
    $ make -C src/tool/omniidl/cxx
    ...
    $ make -C src/tool/omkdepend
    ...
    
    1. Install everything
    $ make install
    ...
    

    We're done! You should now be able to inspect the installed binaries with the file command and see that they are built for ARM.