| <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" | 
 | "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" | 
 | [<!ENTITY % poky SYSTEM "../poky.ent"> %poky; ] > | 
 |  | 
 | <chapter id='sdk-working-projects'> | 
 |  | 
 |     <title>Using the SDK Toolchain Directly</title> | 
 |  | 
 |     <para> | 
 |         You can use the SDK toolchain directly with Makefile, | 
 |         Autotools, and <trademark class='trade'>Eclipse</trademark>-based | 
 |         projects. | 
 |         This chapter covers the first two, while the | 
 |         "<link linkend='sdk-eclipse-project'>Developing Applications Using <trademark class='trade'>Eclipse</trademark></link>" | 
 |         Chapter covers the latter. | 
 |     </para> | 
 |  | 
 |     <section id='autotools-based-projects'> | 
 |         <title>Autotools-Based Projects</title> | 
 |  | 
 |         <para> | 
 |             Once you have a suitable | 
 |             <ulink url='&YOCTO_DOCS_REF_URL;#cross-development-toolchain'>cross-development toolchain</ulink> | 
 |             installed, it is very easy to develop a project using the | 
 |             <ulink url='https://en.wikipedia.org/wiki/GNU_Build_System'>GNU Autotools-based</ulink> | 
 |             workflow, which is outside of the | 
 |             <ulink url='&YOCTO_DOCS_REF_URL;#build-system-term'>OpenEmbedded build system</ulink>. | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             The following figure presents a simple Autotools workflow. | 
 |             <imagedata fileref="figures/sdk-autotools-flow.png" width="7in" height="8in" align="center" /> | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             Follow these steps to create a simple Autotools-based | 
 |             "Hello World" project: | 
 |             <note> | 
 |                 For more information on the GNU Autotools workflow, | 
 |                 see the same example on the | 
 |                 <ulink url='https://developer.gnome.org/anjuta-build-tutorial/stable/create-autotools.html.en'>GNOME Developer</ulink> | 
 |                 site. | 
 |             </note> | 
 |             <orderedlist> | 
 |                 <listitem><para> | 
 |                     <emphasis>Create a Working Directory and Populate It:</emphasis> | 
 |                     Create a clean directory for your project and then make | 
 |                     that directory your working location. | 
 |                     <literallayout class='monospaced'> | 
 |      $ mkdir $HOME/helloworld | 
 |      $ cd $HOME/helloworld | 
 |                     </literallayout> | 
 |                     After setting up the directory, populate it with files | 
 |                     needed for the flow. | 
 |                     You need a project source file, a file to help with | 
 |                     configuration, and a file to help create the Makefile, | 
 |                     and a README file: | 
 |                     <filename>hello.c</filename>, | 
 |                     <filename>configure.ac</filename>, | 
 |                     <filename>Makefile.am</filename>, and | 
 |                     <filename>README</filename>, respectively.</para> | 
 |  | 
 |                     <para> Use the following command to create an empty README | 
 |                     file, which is required by GNU Coding Standards: | 
 |                     <literallayout class='monospaced'> | 
 |      $ touch README | 
 |                     </literallayout> | 
 |                     Create the remaining three files as follows: | 
 |                     <itemizedlist> | 
 |                         <listitem><para> | 
 |                             <emphasis><filename>hello.c</filename>:</emphasis> | 
 |                             <literallayout class='monospaced'> | 
 |      #include <stdio.h> | 
 |  | 
 |      main() | 
 |         { | 
 |            printf("Hello World!\n"); | 
 |         } | 
 |                             </literallayout> | 
 |                             </para></listitem> | 
 |                         <listitem><para> | 
 |                             <emphasis><filename>configure.ac</filename>:</emphasis> | 
 |                             <literallayout class='monospaced'> | 
 |      AC_INIT(hello,0.1) | 
 |      AM_INIT_AUTOMAKE([foreign]) | 
 |      AC_PROG_CC | 
 |      AC_CONFIG_FILES(Makefile) | 
 |      AC_OUTPUT | 
 |                             </literallayout> | 
 |                             </para></listitem> | 
 |                         <listitem><para> | 
 |                             <emphasis><filename>Makefile.am</filename>:</emphasis> | 
 |                             <literallayout class='monospaced'> | 
 |      bin_PROGRAMS = hello | 
 |      hello_SOURCES = hello.c | 
 |                             </literallayout> | 
 |                             </para></listitem> | 
 |                     </itemizedlist> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Source the Cross-Toolchain | 
 |                     Environment Setup File:</emphasis> | 
 |                     As described earlier in the manual, installing the | 
 |                     cross-toolchain creates a cross-toolchain | 
 |                     environment setup script in the directory that the SDK | 
 |                     was installed. | 
 |                     Before you can use the tools to develop your project, | 
 |                     you must source this setup script. | 
 |                     The script begins with the string "environment-setup" | 
 |                     and contains the machine architecture, which is | 
 |                     followed by the string "poky-linux". | 
 |                     For this example, the command sources a script from the | 
 |                     default SDK installation directory that uses the | 
 |                     32-bit Intel x86 Architecture and the | 
 |                     &DISTRO_NAME; Yocto Project release: | 
 |                     <literallayout class='monospaced'> | 
 |      $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux | 
 |                     </literallayout> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Create the <filename>configure</filename> Script:</emphasis> | 
 |                     Use the <filename>autoreconf</filename> command to | 
 |                     generate the <filename>configure</filename> script. | 
 |                     <literallayout class='monospaced'> | 
 |      $ autoreconf | 
 |                     </literallayout> | 
 |                     The <filename>autoreconf</filename> tool takes care | 
 |                     of running the other Autotools such as | 
 |                     <filename>aclocal</filename>, | 
 |                     <filename>autoconf</filename>, and | 
 |                     <filename>automake</filename>. | 
 |                     <note> | 
 |                         If you get errors from | 
 |                         <filename>configure.ac</filename>, which | 
 |                         <filename>autoreconf</filename> runs, that indicate | 
 |                         missing files, you can use the "-i" option, which | 
 |                         ensures missing auxiliary files are copied to the build | 
 |                         host. | 
 |                     </note> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Cross-Compile the Project:</emphasis> | 
 |                     This command compiles the project using the | 
 |                     cross-compiler. | 
 |                     The | 
 |                     <ulink url='&YOCTO_DOCS_REF_URL;#var-CONFIGURE_FLAGS'><filename>CONFIGURE_FLAGS</filename></ulink> | 
 |                     environment variable provides the minimal arguments for | 
 |                     GNU configure: | 
 |                     <literallayout class='monospaced'> | 
 |      $ ./configure ${CONFIGURE_FLAGS} | 
 |                     </literallayout> | 
 |                     For an Autotools-based project, you can use the | 
 |                     cross-toolchain by just passing the appropriate host | 
 |                     option to <filename>configure.sh</filename>. | 
 |                     The host option you use is derived from the name of the | 
 |                     environment setup script found in the directory in which | 
 |                     you installed the cross-toolchain. | 
 |                     For example, the host option for an ARM-based target that | 
 |                     uses the GNU EABI is | 
 |                     <filename>armv5te-poky-linux-gnueabi</filename>. | 
 |                     You will notice that the name of the script is | 
 |                     <filename>environment-setup-armv5te-poky-linux-gnueabi</filename>. | 
 |                     Thus, the following command works to update your project | 
 |                     and rebuild it using the appropriate cross-toolchain tools: | 
 |                     <literallayout class='monospaced'> | 
 |      $ ./configure --host=armv5te-poky-linux-gnueabi --with-libtool-sysroot=<replaceable>sysroot_dir</replaceable> | 
 |                     </literallayout> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Make and Install the Project:</emphasis> | 
 |                     These two commands generate and install the project | 
 |                     into the destination directory: | 
 |                     <literallayout class='monospaced'> | 
 |      $ make | 
 |      $ make install DESTDIR=./tmp | 
 |                     </literallayout> | 
 |                     <note> | 
 |                         To learn about environment variables established | 
 |                         when you run the cross-toolchain environment setup | 
 |                         script and how they are used or overridden when | 
 |                         the Makefile, see the | 
 |                         "<link linkend='makefile-based-projects'>Makefile-Based Projects</link>" | 
 |                         section. | 
 |                     </note> | 
 |                     This next command is a simple way to verify the | 
 |                     installation of your project. | 
 |                     Running the command prints the architecture on which | 
 |                     the binary file can run. | 
 |                     This architecture should be the same architecture that | 
 |                     the installed cross-toolchain supports. | 
 |                     <literallayout class='monospaced'> | 
 |      $ file ./tmp/usr/local/bin/hello | 
 |                     </literallayout> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Execute Your Project:</emphasis> | 
 |                     To execute the project, you would need to run it on your | 
 |                     target hardware. | 
 |                     If your target hardware happens to be your build host, | 
 |                     you could run the project as follows: | 
 |                     <literallayout class='monospaced'> | 
 |      $ ./tmp/usr/local/bin/hello | 
 |                     </literallayout> | 
 |                     As expected, the project displays the "Hello World!" | 
 |                     message. | 
 |                     </para></listitem> | 
 |             </orderedlist> | 
 |         </para> | 
 |     </section> | 
 |  | 
 |     <section id='makefile-based-projects'> | 
 |         <title>Makefile-Based Projects</title> | 
 |  | 
 |         <para> | 
 |             Simple Makefile-based projects use and interact with the | 
 |             cross-toolchain environment variables established when you run | 
 |             the cross-toolchain environment setup script. | 
 |             The environment variables are subject to general | 
 |             <filename>make</filename> rules. | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             This section presents a simple Makefile development flow and | 
 |             provides an example that lets you see how you can use | 
 |             cross-toolchain environment variables and Makefile variables | 
 |             during development. | 
 |             <imagedata fileref="figures/sdk-makefile-flow.png" width="6in" height="7in" align="center" /> | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             The main point of this section is to explain the following three | 
 |             cases regarding variable behavior: | 
 |             <itemizedlist> | 
 |                 <listitem><para> | 
 |                     <emphasis>Case 1 - No Variables Set in the | 
 |                     <filename>Makefile</filename> Map to Equivalent | 
 |                     Environment Variables Set in the SDK Setup Script:</emphasis> | 
 |                     Because matching variables are not specifically set in the | 
 |                     <filename>Makefile</filename>, the variables retain their | 
 |                     values based on the environment setup script. | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Case 2 - Variables Are Set in the Makefile that | 
 |                     Map to Equivalent Environment Variables from the SDK | 
 |                     Setup Script:</emphasis> | 
 |                     Specifically setting matching variables in the | 
 |                     <filename>Makefile</filename> during the build results in | 
 |                     the environment settings of the variables being | 
 |                     overwritten. | 
 |                     In this case, the variables you set in the | 
 |                     <filename>Makefile</filename> are used. | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Case 3 - Variables Are Set Using the Command Line | 
 |                     that Map to Equivalent Environment Variables from the | 
 |                     SDK Setup Script:</emphasis> | 
 |                     Executing the <filename>Makefile</filename> from the | 
 |                     command line results in the environment variables being | 
 |                     overwritten. | 
 |                     In this case, the command-line content is used. | 
 |                     </para></listitem> | 
 |             </itemizedlist> | 
 |             <note> | 
 |                 Regardless of how you set your variables, if you use | 
 |                 the "-e" option with <filename>make</filename>, the | 
 |                 variables from the SDK setup script take precedence: | 
 |                 <literallayout class='monospaced'> | 
 |      $ make -e <replaceable>target</replaceable> | 
 |                 </literallayout> | 
 |             </note> | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             The remainder of this section presents a simple Makefile example | 
 |             that demonstrates these variable behaviors. | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             In a new shell environment variables are not established for the | 
 |             SDK until you run the setup script. | 
 |             For example, the following commands show a null value for the | 
 |             compiler variable (i.e. | 
 |             <ulink url='&YOCTO_DOCS_REF_URL;#var-CC'><filename>CC</filename></ulink>). | 
 |             <literallayout class='monospaced'> | 
 |      $ echo ${CC} | 
 |  | 
 |      $ | 
 |             </literallayout> | 
 |             Running the SDK setup script for a 64-bit build host and an | 
 |             i586-tuned target architecture for a | 
 |             <filename>core-image-sato</filename> image using the current | 
 |             &DISTRO; Yocto Project release and then echoing that variable | 
 |             shows the value established through the script: | 
 |             <literallayout class='monospaced'> | 
 |      $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux | 
 |      $ echo ${CC} | 
 |      i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux | 
 |             </literallayout> | 
 |         </para> | 
 |  | 
 |         <para> | 
 |             To illustrate variable use, work through this simple "Hello World!" | 
 |             example: | 
 |             <orderedlist> | 
 |                 <listitem><para> | 
 |                     <emphasis>Create a Working Directory and Populate It:</emphasis> | 
 |                     Create a clean directory for your project and then make | 
 |                     that directory your working location. | 
 |                     <literallayout class='monospaced'> | 
 |      $ mkdir $HOME/helloworld | 
 |      $ cd $HOME/helloworld | 
 |                     </literallayout> | 
 |                     After setting up the directory, populate it with files | 
 |                     needed for the flow. | 
 |                     You need a <filename>main.c</filename> file from which you | 
 |                     call your function, a <filename>module.h</filename> file | 
 |                     to contain headers, and a <filename>module.c</filename> | 
 |                     that defines your function. | 
 |                     </para> | 
 |  | 
 |                     <para>Create the three files as follows: | 
 |                         <itemizedlist> | 
 |                             <listitem><para> | 
 |                                 <emphasis><filename>main.c</filename>:</emphasis> | 
 |                                 <literallayout class='monospaced'> | 
 |      #include "module.h" | 
 |      void sample_func(); | 
 |      int main() | 
 |      { | 
 |      	sample_func(); | 
 |      	return 0; | 
 |      } | 
 |                                 </literallayout> | 
 |                                 </para></listitem> | 
 |                             <listitem><para> | 
 |                                 <emphasis><filename>module.h</filename>:</emphasis> | 
 |                                 <literallayout class='monospaced'> | 
 |      #include <stdio.h> | 
 |      void sample_func(); | 
 |                                 </literallayout> | 
 |                                 </para></listitem> | 
 |                             <listitem><para> | 
 |                                 <emphasis><filename>module.c</filename>:</emphasis> | 
 |                                 <literallayout class='monospaced'> | 
 |      #include "module.h" | 
 |      void sample_func() | 
 |      { | 
 | 	     printf("Hello World!"); | 
 | 	     printf("\n"); | 
 |      } | 
 |                                 </literallayout> | 
 |                                 </para></listitem> | 
 |                         </itemizedlist> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Source the Cross-Toolchain Environment Setup File:</emphasis> | 
 |                     As described earlier in the manual, installing the | 
 |                     cross-toolchain creates a cross-toolchain environment setup | 
 |                     script in the directory that the SDK was installed. | 
 |                     Before you can use the tools to develop your project, | 
 |                     you must source this setup script. | 
 |                     The script begins with the string "environment-setup" | 
 |                     and contains the machine architecture, which is | 
 |                     followed by the string "poky-linux". | 
 |                     For this example, the command sources a script from the | 
 |                     default SDK installation directory that uses the | 
 |                     32-bit Intel x86 Architecture and the | 
 |                     &DISTRO_NAME; Yocto Project release: | 
 |                     <literallayout class='monospaced'> | 
 |      $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux | 
 |                     </literallayout> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Create the <filename>Makefile</filename>:</emphasis> | 
 |                     For this example, the Makefile contains two lines that | 
 |                     can be used to set the <filename>CC</filename> variable. | 
 |                     One line is identical to the value that is set when you | 
 |                     run the SDK environment setup script, and the other line | 
 |                     sets <filename>CC</filename> to "gcc", the default GNU | 
 |                     compiler on the build host: | 
 |                     <literallayout class='monospaced'> | 
 |      # CC=i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux | 
 |      # CC="gcc" | 
 |      all: main.o module.o | 
 |      	 ${CC} main.o module.o -o target_bin | 
 |      main.o: main.c module.h | 
 | 	     ${CC} -I . -c main.c | 
 |      module.o: module.c module.h | 
 | 	     ${CC} -I . -c module.c | 
 |      clean: | 
 | 	     rm -rf *.o | 
 | 	     rm target_bin | 
 |                     </literallayout> | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Make the Project:</emphasis> | 
 |                     Use the <filename>make</filename> command to create the | 
 |                     binary output file. | 
 |                     Because variables are commented out in the Makefile, | 
 |                     the value used for <filename>CC</filename> is the value | 
 |                     set when the SDK environment setup file was run: | 
 |                     <literallayout class='monospaced'> | 
 |      $ make | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin | 
 |                     </literallayout> | 
 |                     From the results of the previous command, you can see that | 
 |                     the compiler used was the compiler established through | 
 |                     the <filename>CC</filename> variable defined in the | 
 |                     setup script.</para> | 
 |  | 
 |                     <para>You can override the <filename>CC</filename> | 
 |                     environment variable with the same variable as set from | 
 |                     the Makefile by uncommenting the line in the Makefile | 
 |                     and running <filename>make</filename> again. | 
 |                     <literallayout class='monospaced'> | 
 |      $ make clean | 
 |      rm -rf *.o | 
 |      rm target_bin | 
 |      # | 
 |      # Edit the Makefile by uncommenting the line that sets CC to "gcc" | 
 |      # | 
 |      $ make | 
 |      gcc -I . -c main.c | 
 |      gcc -I . -c module.c | 
 |      gcc main.o module.o -o target_bin | 
 |                     </literallayout> | 
 |                     As shown in the previous example, the cross-toolchain | 
 |                     compiler is not used. | 
 |                     Rather, the default compiler is used.</para> | 
 |  | 
 |                     <para>This next case shows how to override a variable | 
 |                     by providing the variable as part of the command line. | 
 |                     Go into the Makefile and re-insert the comment character | 
 |                     so that running <filename>make</filename> uses | 
 |                     the established SDK compiler. | 
 |                     However, when you run <filename>make</filename>, use a | 
 |                     command-line argument to set <filename>CC</filename> | 
 |                     to "gcc": | 
 |                     <literallayout class='monospaced'> | 
 |      $ make clean | 
 |      rm -rf *.o | 
 |      rm target_bin | 
 |      # | 
 |      # Edit the Makefile to comment out the line setting CC to "gcc" | 
 |      # | 
 |      $ make | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin | 
 |      $ make clean | 
 |      rm -rf *.o | 
 |      rm target_bin | 
 |      $ make CC="gcc" | 
 |      gcc -I . -c main.c | 
 |      gcc -I . -c module.c | 
 |      gcc main.o module.o -o target_bin | 
 |                     </literallayout> | 
 |                     In the previous case, the command-line argument overrides | 
 |                     the SDK environment variable.</para> | 
 |  | 
 |                     <para>In this last case, edit Makefile again to use the | 
 |                     "gcc" compiler but then use the "-e" option on the | 
 |                     <filename>make</filename> command line: | 
 |                     <literallayout class='monospaced'> | 
 |      $ make clean | 
 |      rm -rf *.o | 
 |      rm target_bin | 
 |      # | 
 |      # Edit the Makefile to use "gcc" | 
 |      # | 
 |      $ make | 
 |      gcc -I . -c main.c | 
 |      gcc -I . -c module.c | 
 |      gcc main.o module.o -o target_bin | 
 |      $ make clean | 
 |      rm -rf *.o | 
 |      rm target_bin | 
 |      $ make -e | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c | 
 |      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin | 
 |                     </literallayout> | 
 |                     In the previous case, the "-e" option forces | 
 |                     <filename>make</filename> to use the SDK environment | 
 |                     variables regardless of the values in the Makefile. | 
 |                     </para></listitem> | 
 |                 <listitem><para> | 
 |                     <emphasis>Execute Your Project:</emphasis> | 
 |                     To execute the project (i.e. | 
 |                     <filename>target_bin</filename>), use the following | 
 |                     command: | 
 |                     <literallayout class='monospaced'> | 
 |      $ ./target_bin | 
 |      Hello World! | 
 |                     </literallayout> | 
 |                     <note> | 
 |                         If you used the cross-toolchain compiler to build | 
 |                         <filename>target_bin</filename> and your build host | 
 |                         differs in architecture from that of the target | 
 |                         machine, you need to run your project on the target | 
 |                         device. | 
 |                     </note> | 
 |                     As expected, the project displays the "Hello World!" | 
 |                     message. | 
 |                     </para></listitem> | 
 |             </orderedlist> | 
 |         </para> | 
 |     </section> | 
 | </chapter> | 
 | <!-- | 
 | vim: expandtab tw=80 ts=4 | 
 | --> |