LinuxDevices.com Archive Index (1999-2012) | 2013-current at LinuxGizmos.com | About  

Using eCos with CMake

Nov 27, 2006 — by LinuxDevices Staff — from the LinuxDevices Archive

Foreword: This detailed, technical how-to explains how eCos developers can use CMake to simplify and streamline the chore of writing makefiles manually. It discusses both simple, single-application eCos build environments, as well as those with multiple targets, such as production and debug builds for actual and virtual hardware.


Using eCos with CMake

A CMake-based build system for embedded development with eCos

by Alexander Neundorf

Introduction

eCos is an open source, royalty-free, real-time operating system intended for deeply embedded applications. The highly configurable nature of eCos allows the operating system to be customized to precise application requirements, delivering the best possible run-time performance and an optimized hardware resource footprint.

A thriving net community has grown up around the operating system ensuring on-going technical innovation and wide platform support. eCos is not a rival to Linux in embedded space, instead it complements it ideally at the low end.

When developing an embedded application with eCos, you write an application, which links to the static eCos libraries (libtarget.a, libextras.a). These libraries provide the operating system and support libraries, and so the resulting executable is a completely self-contained application that can run on the target hardware.

eCos comes with tools to generate a Makefile for the eCos libraries. But in order to compile your own sources, link them to the eCos libraries and produce an executable for the target, you still have to write a Makefile yourself. Now in the days of graphical IDE's like XCode or MS Visual Studio on one side and autoconf/automake and friends on the other side, most people will agree: having to write Makefiles manually for non-trivial tasks sucks.

However, here comes CMake into play, a buildsystem that has been picking up a lot of steam in the last months.

CMake is a cross-platform, open-source make system that can generate Makefiles from simple descriptive script files and other sources. I have known CMake for approximately two years now, and since then I have been using it basically for everything I have to compile on any platform, be it Linux, Mac OS X, MS Windows with MSVC 6, MS Windows with cygwin, and also for cross-compiling eCos under both Linux and MS Windows. CMake reads files named CMakeLists.txt and produces either Makefiles for UNIX or cygwin, project files for KDevelop 3, MS Visual Studio, Apple XCode and others. So by writing one CMakeLists.txt you can compile your software with all these different build environments.

Here is probably the most simple CMakeLists.txt:


ADD_EXECUTABLE(helloworld hello.cpp)


And that's it. Running CMake on this file will generate a Makefile which builds helloworld(or a XCode project file if you prefer).

CMake 2.4.4 was released just a few days ago. With this new release, building eCos applications can be done very comfortably using CMake. With CMake 2.4.4 it has become easy to build single eCos applications, as well as managing big project trees consisting of multiple eCos applications, optionally each built in different configurations, and accompanying host tools.

It offers the following features:

  • builds the eCos libraries (libtarget.a, libextras.a) and your embedded application
  • optionally builds the embedded application for various targets, including different real targets and the synthetic Linux target
  • optionally builds the embedded application with different configurations, e.g. a release- and a debug-build
  • creates the executable as ELF file, as plain binary file and as srec-file
  • creates a listing file for each application, giving detailed information about the memory layout and the assembler output
  • keeps the need to manually edit files as low as possible
  • works both under Linux and MS Windows/cygwin
  • feels comfortable for developers used to IDE-based project management

How to build eCos applications using CMake

We'll start with a simple example application for the Intel XScale IQ80321 evaluation board, which is supported by eCos. It consists of the source files main.c, utils/foo.c, and utils/bar.c (and the accompanying headers). Additionally to the actual sources some more files are required, the layout is as follows:


sampleapp/ <- the main directory
|
+-CMakeLists.txt <- specifies the source files and how to build the application from them
|
+-main.c <- one of the source files, the rest is skipped here
|
+-ecos/ <- below this directory the compilation of eCos will take place
|
+-ecos.ecc <- the eCos config file
|
+-install/lib/ <- here you will find the eCos libraries, libtarget.a, libtarget.ld
|
+-install/include/ <- here you will find the eCos header files, this directory will
be part if the compiler include path


main.c and friends are the application source files, not much to say about them, you know them best. ecos/ecos.ecc is the eCos configuration file, which describes how your eCos will be built. You can edit it manually or using ecosconfig or configtool, just as you prefer. It is important that it must be named “ecos.ecc” and that it must reside in the subdirectory named “ecos/”. CMakeLists.txt is the most important file for us (in this article). This file will be read by CMake and used to create the Makefiles for your application.

Let's have a look at this file line by line:


# this is one of the most important lines
# here you list all source files of your application
# you can mix C and C++ files as you like
# you can also add the header files here, but you don't have to
# you can use relative or absolute paths as you like
SET(SRC_LIST main.c utils/foo.c utils/bar.c)

# use ADD_DEFINITIONS() to add the definitions (or switches) you like
ADD_DEFINITIONS(-O2 -fno-strict-aliasing)

# use the eCos support coming with CMake
# without this line CMake doesn't know how to build eCos applications
# all functions/macros coming from this file start with "ECOS_"
INCLUDE(UseEcos)

# add the ecos/install/include/ directory to the header search path
ECOS_ADD_INCLUDE_DIRECTORIES()

# we want to crosscompile for an Intel XScale processor
# so we have to use the arm-elf toolchain
# adjust this line depending on which toolchain you need or just
# leave it out if you want to compile for the Linux synthetic target
ECOS_USE_ARM_ELF_TOOLS()

# this is the most important line:
# tell CMake that we want to create an executable named "sampleapp"
# from the files listed in the variable SRC_LIST
ECOS_ADD_EXECUTABLE(sampleapp ${SRC_LIST} )


That's all there is to it. For more information about the CMake syntax visit e.g. www.cmake.org or have a look at the CMake man page.

So what to do next? Enter the directory sampleapp/ and run CMake:


~/src/sampleapp/ $ cmake .
-- Found ecosconfig: /opt/gnutools/bin/ecosconfig
-- ECOS_REPOSITORY is set to /usr/src/ecos/packages
-- Configuring done
-- Generating done
-- Build files have been written to: ~/src/sampleapp


Please note the dot after CMake, which tells CMake that the CMakeLists.txt file is located in the current directory. This is required, otherwise it won't work. As you see, CMake checks for the availability of ecosconfig. This succeeds if ecosconfig is in the PATH, otherwise it will stop with an error message. In this case you can either extend the system path so that it also includes the directory where ecosconfig is located or you can the ccmake tool coming with CMake and enter the path to ecosconfig there. CMake also checks that the ECOS_REPOSITORY environment variable is set correctly and gives an error message if this is not the case.

If everything is ok now there should be a Makefile in this directory, if not, something went wrong. Let's suppose everything went fine, and you have now a Makefile in sampleapp/. Before you run make, make sure that your cross compiling toolchain is also available in the PATH. If this is set up correctly, enter make. At first eCos will be built in ~/src/sampleapp/ecos/ and then the application sampleapp will be built and linked with the eCos libraries to create a complete executable.

If there were no problems, you should now find a the “sampleapp.elf” ELF file, the “sampleapp.bin” binary file and the “sampleapp.srec” file in the sampleapp/ directory.

More things you should know

Compiler options

A bunch of compiler options, which are appropriate for embedded applications, are added automatically by UseEcos.cmake:


ADD_DEFINITIONS(-D__ECOS__ -Wall -Wno-long-long -pipe -fno-builtin)
SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wstrict-prototypes")
SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual -fno-rtti
-Wctor-dtor-privacy -fno-strict-aliasing -fno-exceptions")


If you prefer other switches, you can either edit the file or remove the flags using REMOVE_DEFINITIONS().

Supported toolchains

UseEcos.cmake comes with support for three crosscompiling toolchains:

  • ECOS_USE_ARM_ELF_TOOLS()
  • ECOS_USE_PPC_EABI_TOOLS()
  • ECOS_USE_I386_ELF_TOOLS()

Have a look at UseEcos.cmake to check out whether these are suitable for you. If that's not the case edit them as appropriate for your target or add a new equivalent macro. If you want to compile for the Linux synthetic target you can use either the i386-elf toolchain or you can use the normal host toolchain.

Available Makefile targets

The generated Makefiles offer the following targets:

  • all: default target, check all dependencies and build all
  • clean: clean the application. After this the complete application will be compiled and linked again.
  • ecosclean: clean the application and the complete ecos/ subdirectory. After this the complete application and the complete eCos libraries will be compiled and linked again.
  • ecos: build eCos in the ecos/ subdirectory and link the application again
  • help: lists all available make targets
  • listing: create a listing file for the generated executable. The listing file (which will have the suffix “.lst”) contains a lot of useful information. Currently it features:
    • a listing of all symbols, sorted by address in memory space
    • a listing of all symbols, sorted by their size
    • a listing of all memory sections and their properties
    • the symbol table
    • the complete assembly listing of the generated executable, intermixed with the source code (you need to compile with the -g switch for this to work)

Additionally for every source file targets to build the respective object file, the preprocessed file and the assembler file are supported. So if you have a file main.c, you can enter

  • make main.o to compile this file to an object file
  • make main.i to preprocess this file, this is useful mainly for debugging purposes
  • make main.s to create the assembler file

Supported platforms

The build system works under MS Windows with cygwin and under Linux (tested: several versions of Slackware, SUSE, and kubuntu). Under Linux you can also use the KDevelop3 project generator of CMake, which will create Makefiles as usual and additionally project files for KDevelop3. To have CMake generate project files for KDevelop 3, you have to execute the following:


~/src/sampleapp $ cmake . -GKDevelop3
CMake Error: Error: generator : KDevelop3
Does not match the generator used previously: Unix Makefiles
Either remove the CMakeCache.txt file or choose a different binary directory.


As you see, problems may occur. If CMake was run before and generated normal Makefiles, it will complain if you try to specify a different “generator.” In this case do what CMake tells you, delete the file CMakeCache.txt and then run the command as given above again. Then it should complete without errors and will produce a project file named “Project.kdevelop”. If you would prefer a better name for the project than “Project,” this can be easily achieved, simply by adding the following line to the CMakeLists.txt:


PROJECT(sampleapp)


Then run CMake again and it will generate a project file named “sampleapp.kdevelop.” This makes the combination of eCos and KDevelop a very comfortable free software development environment for embedded real time systems.

When do you have to run CMake manually?

Usually you only have to invoke CMake explicitly as shown above only when initially creating the Makefiles (or project files). Once the Makefiles exist, they contain appropriate rules and dependencies to run CMake automatically again if required.

More information

If you need more information about CMake, here are some tips:

Using CMake to manage complex project trees

Now that you know how to build an eCos application using CMake, we'll proceed to the next level. Let's say you have a family of devices running with eCos applications. In this case you might need some more support from the build system. So we'll have a look at how to manage complex a source tree. It contains several eCos applications.

Each application will be built in a release and a debug configuration, and each application can be built for the real target and for the Linux synthetic target. Additionally there is a directory where source files used by all applications will reside. It also offers a directory where eventually required custom host applications can be compiled. With all this in place, it is possible to compile all applications (embedded and host) in all configurations with a single “make” invocation from the top level.

The directory structure for that looks like this:


bigproject/ <- the main directory
|
+-CMakeLists.txt <- list the subdirectories
|
+-firmware/ <- the root directory for all eCos applications
| |
| +-CMakeLists.txt <- include UseEcos.cmake and list the subdirectories
| |
| +-common/ <- common/ is a directory which contains sources and headers generally
| | useful for applications, this directory will be added to the include-path
| |
| +-helloworld/ <- an embedded application project directory
| |
| +-CMakeLists.txt <- list the subdirectories
| |
| +-ProjectSources.txt <- list all source files of your application in this file
| |
| +-main.cpp <- one of the source files, the other ones are skipped here
| |
| +-ecos-synth/ <- here the application will be compiled for the synth target
| | |
| | +-CMakeLists.txt <- adjust the compiler settings here
| | |
| | +-ecos/ <- below this directory the eCos compilation will take place
| | |
| | +-ecos.ecc <- this is the eCos configuration for helloworld for ecos-synth
| | |
| | +-install/lib/ <- here you will find the eCos library, libtarget.a
| | |
| | +-install/include/ <- here you will find the eCos header files, this directory will
| | also be added to the include-path
| |
| +-ecos-iq80321/ <- here comes all the stuff from above again, but now for the
| | Intel IQ80321 processor
| |
| +-ecos-ppc/ <- and now for a power pc target
|
+-host/ <- the root directory for all host tools
|
+-CMakeLists.txt <- list the subdirectories
|
+-sometool/ <- some tool you might need
|
+-cooltool/ <- and an especially cool tool


Again, let's have a look at the directory tree. As you may have noticed it is considerably more complex than in the first example.

In every subdirectory there is a CMakeLists.txt. If in the specific directory nothing is actually built but it only branches into more subdirectories, the CMakeLists.txt files in these directories are all quite simple, e.g. bigproject/CMakeLists.txt looks like this:


# this simply branches into the listed subdirectories
ADD_SUBDIRECTORY( firmware )
ADD_SUBDIRECTORY( host )


The CMakeLists.txt in bigproject/firmware/ and in bigproject/host/ are equivalent. Below the bigproject/host/ directory you can add arbitrary directories for building host tools. There you can use the “normal” CMake functions for building “normal” applications.

All the firmware source files are located below the bigproject/firmware/ directory. The bigproject/firmware/common/ directory is the place where sources shared by different applications can be put. bigproject/firmware/helloworld/ contains an eCos application comparable to the sampleapp from the beginning. Let's have a closer look at this directory.

You'll notice there are subdirectories starting with “ecos-“. These are the directories where the eCos application will be built for the different configurations and/or targets. This means when bigproject/firmware/helloworld/ is built, the helloworld application will be built for the Linux synthetic target under ecos-synth/, for a PowerPC target under ecos-ppc/ and for the XScale under ecos-iq80321/. So you can view bigproject/firmware/helloworld/ as the “home” directory of your application where you put all the application specific files, the “ecos-XXX” directories are used “only” for compiling.

This is the CMakeLists.txt in bigproject/firmware/:


INCLUDE (UseEcos)

INCLUDE_DIRECTORIES( common/ )

ADD_SUBDIRECTORY( helloworld )


Here UseEcos.cmake is included, so that the eCos-specific CMake functions are available in the CMakeLists.txt in all subdirectories below this directory. Then it branches deeper into all application subdirectories (in this case only helloworld).

This is the CMakeLists.txt in bigproject/firmware/helloworld/:


ADD_SUBDIRECTORY( ecos-iq80321 )
ADD_SUBDIRECTORY( ecos-ppc )

IF (NOT WIN32)
ADD_SUBDIRECTORY( ecos-synth )
ENDIF (NOT WIN32)


Nothing is compiled here, it just branches further into the “ecos-XXX” compile directories. Notable is the IF (WIN32), this is used to differentiate between compiling under MS Windows/cygwin and Linux. As you can see the ecos-synth/ directory is not compiled under MS Windows/cygwin, for obvious reasons.

Next to the CMakeLists.txt there is the file name ProjectSources.txt. This one is important, here you list all source files of your application.


#the following name will be used as the name for the executable
SET(ECOS_PROJECT_NAME helloworld)

#list the source files for the application
SET(PROJECT_SRCS main.cpp ${CMAKE_SOURCE_DIR}/firmware/common/shared.c)


As you can see, you can mix C and C++ files as you want, and you can use files from this directory and from other directories (e.g. the common/ directory). This file, ProjectSources.txt is used in the “ecos-XXX” compile directories, where the actual compilations take place.

Now finally, the contents of bigproject/firmware/helloworld/ecos-iq80321/CMakeLists.txt:


# give the project a name, so that the KDevelop project gets a nice name
PROJECT(helloworld-iq80321)

#include the file with the source list
INCLUDE(../ProjectSources.txt)

#compile for the XScale processor
ECOS_USE_ARM_ELF_TOOLS()

#add some compile switches
ADD_DEFINITIONS(-O2 -g)

# verbose Makefiles, so that we see the complete compile commands
SET(CMAKE_VERBOSE_MAKEFILE ON)

# we are one directory level deeper here, so the
# relative paths from the ProjectSources.txt have to be adjusted accordingly
ECOS_ADJUST_DIRECTORY(target_SRCS ${PROJECT_SRCS})

#add the eCos include directories
ECOS_ADD_INCLUDE_DIRECTORIES()

#create the eCos executable
ECOS_ADD_EXECUTABLE(${ECOS_PROJECT_NAME} ${target_SRCS})


Now this file looks quite similar to the CMakeLists.txt from the sampleapp example above. Actually there are only two differences: the INCLUDE(../ProjectSources.txt) command and the ECOS_ADJUST_DIRECTORY() call. ProjectSources.txt contains the list of source files, that's why it has to be included here. In ProjectSources.txt the source files can be listed with relative paths, e.g. “main.cpp.” The relative paths are relative to the location of ProjectSources.txt, but now this file is included one directory level deeper and so the the relative paths to the source files aren't correct, e.g. “main.cpp” doesn't exist, but “../main.cpp” would be the correct path to this file. This adjustment is done by calling the ECOS_ADJUST_DIRECTORY() macro. It adjusts all relative paths accordingly and puts the resulting list of source files into a new variable, here named target_SRCS. These target_SRCS are then used for building the eCos executable.

As in the first example, at first CMake has to be executed once:


~/src/bigproject/ $ cmake .


Or “cmake . -GKDevelop3” if you intend to use KDevelop. After that you can enter make in this directory and it will compile the complete source tree with all eCos applications in all configurations and also the host tools. Of course you can also enter make in any of the subdirectories and build only that.

So, I hope I have helped to make your eCos-experience even better, and that you'll have a lot of fun with CMake and eCos 🙂

If you have comments, problems, fixes, improvements, feel free to contact me: [email protected]. Further details on eCos and CMake are available here:


About the author: Alexander Neundorf is a longtime KDE developer who has contributed to free software development since 1997. He is known for writing the LISA LAN browser and for maintaining SMB support in KDE. He also ported kdelibs to the CMake build system earlier in 2006. Neundorf earned a degree in Computer Science in Engineering in 2002 from the Technische Universitat in Ilmenau, Germany. He currently works at Jenoptik LOS, GmbH, developing professional digital cameras and infrared cameras.


 
This article was originally published on LinuxDevices.com and has been donated to the open source community by QuinStreet Inc. Please visit LinuxToday.com for up-to-date news and articles about Linux and open source.



Comments are closed.