Using ODB on mobile and Embedded Systems

Source: Internet
Author: User

Source: http://wiki.codesynthesis.com/Using_ODB_on_Mobile_and_Embedded_Systems


Contents

[Hide]

  • 1
    Building SQLite and ODB runtime Libraries
  • 2
    Building the example using static libraries
  • 3
    Building the example using shared libraries
  • 4
    Minimizing runtime and generated code size

This Guide discusses a number of topics relevant to using ODB on mobile and embedded systems. specifically, it shows how to cross-compile the ODB runtime libraries in both static and shared variants. it also provides an indication of footprint as well as ways
To minimize the generated code size.

While this Guide uses
Raspberry Pi arm GNU/Linux computer as a sample target, other mobile/embedded platforms will normally require very similar steps. we will also explicitly mention a few areas that may need platform-specific changes. if you run into any problems while trying
To apply the below steps for your platform, feel free to ask for help on
ODB-Users Mailing List. For an android target, refer
Using ODB on Android.

Some mobile and embedded targets support compilation on the target itself (the so-called self-hosted development ). however, due to various constraints (RAM, CPU, connectivity, etc .), it is rarely practical to develop any real-world application on the target
Directly. As a result, a cross-compilation environment is normally used instead and in this guide we will only consider this approach.

Note also that this guide is not an introduction to developing C ++ applications for mobile/embedded systems. in particle, it assumes that you are familiar with the concept of cross-compilation and how it works for your target. before proceeding further
With this Guide, it is recommended that you install the cross-compiler for your target on your development machine, build a simple "Hello, world" C ++ application, copy it on to your target, and make sure it runs correctly, that is, there are no missing libraries,
Crashes, etc.

In this guide we will usearm-bcm2708hardfp-linux-gnueabiCross-compiler toolchain from the official

Raspberry Pi tools repository. However, other toolchains can be used as well, such as the Debian/Ubuntu arm cross-compiler package.

The most popular choice of a database for mobile/embedded systems is SQLite. So in this guide we will build the "Hello, world" example from
odb-examplesPackage for the Raspberry Pi target using SQLite as the database. this, however, is not to say that other databases (or even multiple database at once) cannot be used on mobile/embedded systems. all we will need to do is cross-compile
Or get an already pre-built client library for the database (s) We want to use.

The following list provides a high-level overview of the steps we will need to perform in order to build an ODB-based application for our mobile/Embedded Target. the comments in brackets indicate whether this step is already med on the Development Machine
Or on the target.

  1. Install the ODB compiler [development machine]
  2. Cross-compile the database (client) Library and ODB runtimes [development machine]
  3. Compile headers with the ODB compiler [development machine]
  4. Cross-compile the generated code and application code [development machine]
  5. Copy the application onto the target and run [target]

The easiest way to install the ODB compiler is to use the pre-compiled Binary Package for your development machine. For example, if your development machine is x86-64 GNU/Linux, then you will use
odb-X.Y.Z-x86_64-linux-gnuPackage. you can also build the ODB compiler from source code if you wish (note that in this case you will need to build it for your development machine, not for your mobile/Embedded Target ).

The next step is to cross-compile the SQLite database (or another database client library) and the ODB runtimes libraries. here we have two options: we can build them as static or as shared libraries. when it comes to mobile/embedded systems, static libraries
Have a number of advantages. firstly, when using static libraries, the resulting executable will only contain in ODB runtime code that is used by the application. this minimizes the executable size (both on disk and in Ram ). static libraries are also easier
Work with; they are easier to build, to link to, and they don't need to be deployed to the target. shared libraries in the mobile/Embedded context may have an advantage if more than one application is using them. as a result, we recommend that you use static
Libraries unless you have multiple applications that use ODB and even in this case it makes sense to actually check if there are any footprint savings. if you decide to build and use shared libraries, We stronugly recommend that you first try to build static
Variants to make sure that everything works in that simpler case.

Note also that it is possible to use a shared library for the database and static libraries for the ODB runtimes. this wocould make sense, for example, if SQLite came pre-installed (as a shared library) on your target because it is used by other applications.

As the first step, choose a working directory where we will build everything. Let's also create
installSub-directory in this working directory; this is the place where we will install headers, libraries, Etc ., that we are going to build (note that it's a bad idea to install them into, say,
/usr/localBecause these libraries will be built for our target, not for the development machine ).

Let's also assume that our cross-compiler toolchain and the odb compiler are also in this working directory. That is, we have
arm-bcm2708hardfp-linux-gnueabiSub-directory (cross-compiler for Raspberry Pi) and
odb-X.Y.Z-x86_64-linux-gnuOr similar sub-directory (ODB compiler). Let's also rename
odb-X.Y.Z-x86_64-linux-gnuTo justodbFor easier referencing. Note that the cross-compiler and the ODB compiler don't really have to be in our working directory. If you have them installed somewhere else, simply adjust the paths in
The instructions below.

Let's also add the cross-compiler toPATHEnvironment variable. That is, in a terminal where you will perform the compilation, do:

   export PATH=`pwd`/arm-bcm2708hardfp-linux-gnueabi/bin:$PATH   arm-bcm2708hardfp-linux-gnueabi-g++ --version

The second command verifies that the C ++ cross-compiler can now be executed directly by printing its version.

Another step that we need to perform before we can start building is to verify that the cross-compiler toolchain doesn't have broken
.laFiles, specificallylibstdc++.laAnd, if you are using a pre-built SQLite or another database (client) Library,
.laFile for that library..laFiles often end up broken because of the different directories where the toolchain was initially installed (by whomever built it) and where you unpacked it.
.laFiles will almost always end up broken if you installed your toolchain by simply unpacking
.tar.gzArchive. on the other hand, if you built the toolchain yourself (and didn't move the installation directory) or if you installed it from a package (e.g ., from Debian/UBUNTU) then
.laFiles are most likely intact and you can skip this step.

To verify that.laFiles are correct, searchlibstdc++.laIn the toolchain directory. If none is found, then you don't need to do anything. If one is found, open it in a text editor and search for
libdirVariable (usually right at the bottom). The value of this variable shocould be the path to the directory where
libstdc++.laFile resides. If it is not valid, correct it and save the file. If you are using a pre-built SQLite or another database (client) library, repeat these steps for its
.laFile.

The next section discusses building the database and the ODB runtimes as either static or shared libraries. The two sections after that show how to build and run
helloExample Using static or shared libraries, respectively. The final section in this Guide provides an indication of the resulting binary sizes as well as covers varous ways to minimize the generated code size.

[Edit]

Building SQLite and ODB runtime Libraries

Unless you already have SQLite built for your target, let's first do that. download
sqlite-autoconf-XYZ.tar.gzArchive and unpack it into the working directory:

   tar xfz sqlite-autoconf-XYZ.tar.gz   cd sqlite-autoconf-XYZ

Next we need to configure SQLite for our target. here you may need to add additional C compiler flags that are specific to your target. for instance, if you are using a generic arm toolchain (such as from Debian/UBUNTU) instead of the Raspberry Pi-specific
One, then you may need to specify the CPU version, Etc., explicitly by adding
-march=armv6 -mfpu=vfp -mfloat-abi=hardOptions toCFLAGS(And later
CXXFLAGS) Variable. You may also want to adjust the optimization level. Note also that the value of
--hostOption must match the cross-compiler tool prefix (that is
arm-bcm2708hardfp-linux-gnueabi
Inarm-bcm2708hardfp-linux-gnueabi-g++) Exactly. The basic configuration for a static SQLite library looks like this:

   ./configure CFLAGS="-Os -DSQLITE_ENABLE_UNLOCK_NOTIFY=1" --disable-shared --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

And for a shared SQLite library-like this:

   ./configure CFLAGS="-Os -DSQLITE_ENABLE_UNLOCK_NOTIFY=1" --disable-static --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

If here or belowconfigureScript terminates with an error, then you can find more detailed information about the cause of the error in
config.logFile Created by this script.

If, however, there are no errors during the configuration, then the next step is to build and install SQLite:

   make   make install

After this command you shoshould have the SQLite headers and static/Shared library in
installSub-directory of the working directory. Here and below you can also use
install-stripTarget to strip the installed libraries.

Once SQLite is ready, we can move on to building the ODB runtimes. The minimum that you will need is
libodbAndlibodb-sqlite. If you also want to use one of the profile libraries, then you can build it in the same way.

To buildlibodb, Unpack its source code into the working directory:

   tar xfz libodb-X.Y.Z.tar.gz   cd libodb-X.Y.Z

The configuration and building steps are similar to SQLite. Again, don't forget to add any extra compiler options
CXXFLAGSIf your target requires them. Static Library:

   ./configure CXXFLAGS="-Os" --disable-shared --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

Shared Library:

   ./configure CXXFLAGS="-Os" --disable-static --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

Once configuration is done:

   make   make install

To buildlibodb-sqlite, Unpack its source code into the working directory:

   tar xfz libodb-sqlite-X.Y.Z.tar.gz   cd libodb-sqlite-X.Y.Z

Then configure and build. Static Library:

   ./configure CXXFLAGS="-Os" CPPFLAGS="-I`pwd`/../install/include" LDFLAGS="-L`pwd`/../install/lib" --disable-shared --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

Shared Library:

   ./configure CXXFLAGS="-Os" CPPFLAGS="-I`pwd`/../install/include" LDFLAGS="-L`pwd`/../install/lib" --disable-static --host=arm-bcm2708hardfp-linux-gnueabi --prefix=`pwd`/../install

Once configuration is done:

   make   make install
[Edit]

Building the example using static libraries

Once the static libraries for SQLite and the odb runtimes are ready, we can build
helloExample. First, unpackodb-examplesPackage:

   tar xfz odb-examples-X.Y.Z.tar.gz   cd odb-examples-X.Y.Z/hello

While it is possible to use autotools-based build system to cross-compile the examples, in this guide we will use Modified Manual build instructions from the accompanying
READMEFile. First, we compileperson.hxxHeader with the ODB Compiler:

    ../../odb/bin/odb -d sqlite --generate-query --generate-schema person.hxx

Next we build everything with the cross-compiler:

   arm-bcm2708hardfp-linux-gnueabi-g++ -I../../install/include -Os -c person-odb.cxx   arm-bcm2708hardfp-linux-gnueabi-g++ -I../../install/include -Os -c -DDATABASE_SQLITE driver.cxx   arm-bcm2708hardfp-linux-gnueabi-g++ -L../../install/lib -o driver driver.o person-odb.o -lodb-sqlite -lodb -lsqlite3 -lpthread -ldl

The result of the last command isdriverExecutable which we can copy over on to the target and run:

   raspberrypi $ uname -a   Linux raspberrypi 3.2.27+ #3 PREEMPT Sat Dec 15 18:52:34 SAST 2012 armv6l GNU/Linux      raspberrypi $ ./driver --database /tmp/test.db   Hello, John Doe!   Hello, Jane Doe!      count  : 3   min age: 31   max age: 33
[Edit]

Building the example using shared libraries

Once the shared libraries for SQLite and the odb runtimes are ready, we can build
helloExample. First, unpackodb-examplesPackage:

   tar xfz odb-examples-X.Y.Z.tar.gz   cd odb-examples-X.Y.Z/hello

While it is possible to use autotools-based build system to cross-compile the examples, in this guide we will use Modified Manual build instructions from the accompanying
READMEFile. First, we compileperson.hxxHeader with the ODB Compiler:

    ../../odb/bin/odb -d sqlite --generate-query --generate-schema person.hxx

Next we build everything with the cross-compiler:

   arm-bcm2708hardfp-linux-gnueabi-g++ -I../../install/include -Os -c person-odb.cxx   arm-bcm2708hardfp-linux-gnueabi-g++ -I../../install/include -Os -c -DDATABASE_SQLITE driver.cxx   arm-bcm2708hardfp-linux-gnueabi-g++ -L../../install/lib -o driver driver.o person-odb.o -lodb-sqlite -lodb -lsqlite3

The result of the last command isdriverExecutable. To run it on the target, besides the executable itself, we will also need to copy over the shared libraries from
install/libSub-directory. The libraries that we will need are:
libsqlite3.so.*
,libodb-X.Y.so, Andlibodb-sqlite-X.Y.so. On the target we will also need to make sure that the dynamic linker can find them. While how exactly to achieve this depends on the target, installing them
/usr/local/libOr adding their directory toLD_LIBRARY_PATHEnvironment variable will work for Raspberry Pi or any other GNU/Linux derivative. For example, assuming that our executable and all the libraries are in the current directory
(On the target), we can run the example like this:

   raspberrypi $ uname -a   Linux raspberrypi 3.2.27+ #3 PREEMPT Sat Dec 15 18:52:34 SAST 2012 armv6l GNU/Linux      raspberrypi $ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH   raspberrypi $ ./driver --database /tmp/test.db   Hello, John Doe!   Hello, Jane Doe!      count  : 3   min age: 31   max age: 33
[Edit]

Minimizing runtime and generated code size

To give an indication of the footprint one can receive CT when using odb on mobile/embedded systems, the stripped
helloExample executable when built with static SQLite and ODB runtime libraries is 533kb. while this may seem like a lot for such a simple application, keep in mind that it should des the whole SQLite database as well as
libodbAndlibodb-sqliteRuntimes, all of which are "once-off costs", that is, they don't change with the number of persistent classes used by the application.

A more useful size breakdown can be obtained from the build that uses shared libraries (again, all stripped ):

   35348  driver   38244  libodb-2.1.so   107532 libodb-sqlite-2.1.so   504232 libsqlite3.so.0.8.6

As you can see, the driver itself, which contains the generated code for one persistent class and one view, is only 34kb. note also that the combined size of all the libraries and the executable (669kb) is about 25% greater than that of the static executable.

The ODB compiler implements fine-grained control over various features provided by the generated code. by not enabling functionality that is not needed by your application you can greatly reduce the generated code size and the resulting application footprint.
In particle, the following ODB command line flags control optional functionality provided by the generated code:

   --generate-query   --generate-prepared   --omit-unprepared   --generate-session   --generate-schema

Also, when generating database schema embedded into the C ++ code, it can be wasteful to keep that code in the main executable (and thus in the device's memory) all the time. for example, if you need to create the database schema only once when the device
Is first turned on, then it may make sense to factor the schema creation function into a separate executable. This can be achieved with
--schema-format separateOption which instructs the ODB compiler to generate the schema creation C ++ code into a separate source file.

If your application is single-threaded, then it is also possible to slightly reduce the ODB runtime sizes by disabling multi-threading support. To achieve this, pass
--disable-threadsOption toconfigureCommands.

To reduce runtime memory usage and dynamic memory allocations in persistent classes, consider using
char[N]Arrays (or C ++ 11std::array<char,N>) Instead
std::stringOr similar for representing string and binary data. For example:

   #pragma db object   class person   {     ...          char first[32];     char last[32];          #pragma db type("BLOB")     char public_key[1024];   };

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.