Getting started with Embedded Linux: Part Twelve -- Application development

October 20, 2015

mike_eager-October 20, 2015

We are continuing our series on how to get started using Embedded Linux. The previous installments can be found on the Open Mike blog and are listed at the end of this article.

Let's take a look at software development for an Embedded Linux system, our Raspberry Pi. We are first going to write the traditional “Hello World” program and compile it on the RPi, then we will do the same on the development host, using the cross-development tools we installed to build the Linux kernel.

Compiling on the target
Log in to your RPi system, either on the system console, or like I do, using ssh in a window on my development system. Create a directory named “projects” under your home directory and cd into it. Now we can use an editor (vi or nano) to create the source file named “hello.c”:

#include 

int main (void)
{
  printf ("Hello World!\n");
  return 0;
}

We can compile this using the following command:

$ gcc -o hello hello.c

This says to run gcc, the GNU C Compiler, to create an executable program named “hello” using the source file named “hello.c”. If everything is OK, you will get a prompt. Like many other Linux commands, if there are no errors, gcc doesn't say anything.

We can run this command from the command line and it will generate the expected output.

$ ./hello 
Hello World!

You need to specify a full or partial path to the “hello” program. In this case, we enter “./” to say that the program can be found in the current directory. If you don't specify a full or partial path, the bash command shell will search the directories listed in the $PATH environment variable for the program. In this case, bash will say “command not found”.

This seems simple, but there's quite a bit going on under the covers. If you add the “-v” option to the gcc command it will list all of the steps that it takes to compile, assemble, and link the program. GCC knows where to find the “stdio.h” include file as well the library which includes the “printf” function and others needed to create an executable program. If you want to see the directories which gcc will search for include files, run this command:

$ cpp -Wp,-v /dev/null

You will see that among others, gcc will search /usr/include where it will find stdio.h. The libraries which are searched can be listed by running gcc with the -print-search-dirs option.

Compiling on the host
Let's do the same on our development system. Create a projects directory and create the “hello.c” source file. (Alternately, you can use scp to copy the file from the RPi to your development system.)

Make sure that you have the PATH environment variable set to include the Raspberry Pi toolchain directory which we used previously, “~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x86/bin”. Once we have done this, we can compile our source file using the cross compiler:

$ arm-linux-gnueabihf-gcc -o hello hello.c

(If your fingers get tired of typing the long name of the gcc compiler, you can create a shorter alias by entering the command “alias arm-gcc arm-linux-gnueabihf-gcc”)

We can copy the executable to the /tmp directory on the RPi system by using “scp hello pi@rpi:/tmp”. On the RPi system, we can run “/tmp/hello” and get the same results that we had with the version compiled natively.

If you list the directories that arm-gcc will search to find the include files or libraries, you will see that directories under the tool chain directory are listed, not the development system's directories. This is important; we want to use include files and libraries for the ARM system, not those used on the x86 host. We need to make sure that these two environments, the native development environment and the cross development environment, are in sync. When they fall out of sync, perhaps by using a cross-compiler built for a different version of the target libraries, or perhaps after updating the target libraries without a corresponding update of the cross development libraries, odd things can happen. Programs may not execute on the target, or there may be errors when they are run, or debugging may be confused.

In the next installment, we'll cover building more substantial programs on the development host and how to debug them on the target.

 

Loading comments...