1.. SPDX-License-Identifier: CC-BY-SA-2.0-UK
2
3********************************
4Using the SDK Toolchain Directly
5********************************
6
7You can use the SDK toolchain directly with Makefile and Autotools-based
8projects.
9
10Autotools-Based Projects
11========================
12
13Once you have a suitable :ref:`sdk-manual/intro:the cross-development toolchain`
14installed, it is very easy to develop a project using the :wikipedia:`GNU
15Autotools-based <GNU_Build_System>` workflow, which is outside of the
16:term:`OpenEmbedded Build System`.
17
18The following figure presents a simple Autotools workflow.
19
20.. image:: figures/sdk-autotools-flow.png
21   :align: center
22   :width: 70%
23
24Follow these steps to create a simple Autotools-based "Hello World"
25project:
26
27.. note::
28
29   For more information on the GNU Autotools workflow, see the same
30   example on the
31   GNOME Developer
32   site.
33
34#. *Create a Working Directory and Populate It:* Create a clean
35   directory for your project and then make that directory your working
36   location::
37
38      $ mkdir $HOME/helloworld
39      $ cd $HOME/helloworld
40
41   After setting up the directory, populate it with files needed for the flow.
42   You need a project source file, a file to help with configuration,
43   and a file to help create the Makefile, and a README file:
44   ``hello.c``, ``configure.ac``, ``Makefile.am``, and ``README``,
45   respectively.
46
47   Use the following command to create an empty README file, which is
48   required by GNU Coding Standards::
49
50      $ touch README
51
52   Create the remaining
53   three files as follows:
54
55   -  ``hello.c``::
56
57         #include <stdio.h>
58
59         main()
60             {
61                 printf("Hello World!\n");
62             }
63
64   -  ``configure.ac``::
65
66         AC_INIT(hello,0.1)
67         AM_INIT_AUTOMAKE([foreign])
68         AC_PROG_CC
69         AC_CONFIG_FILES(Makefile)
70         AC_OUTPUT
71
72   -  ``Makefile.am``::
73
74         bin_PROGRAMS = hello
75         hello_SOURCES = hello.c
76
77#. *Source the Cross-Toolchain Environment Setup File:* As described
78   earlier in the manual, installing the cross-toolchain creates a
79   cross-toolchain environment setup script in the directory that the
80   SDK was installed. Before you can use the tools to develop your
81   project, you must source this setup script. The script begins with
82   the string "environment-setup" and contains the machine architecture,
83   which is followed by the string "poky-linux". For this example, the
84   command sources a script from the default SDK installation directory
85   that uses the 32-bit Intel x86 Architecture and the &DISTRO; Yocto
86   Project release::
87
88      $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux
89
90   Another example is sourcing the environment setup directly in a Yocto
91   build::
92
93      $ source tmp/deploy/images/qemux86-64/environment-setup-core2-64-poky-linux
94
95#. *Create the configure Script:* Use the ``autoreconf`` command to
96   generate the ``configure`` script::
97
98      $ autoreconf
99
100   The ``autoreconf``
101   tool takes care of running the other Autotools such as ``aclocal``,
102   ``autoconf``, and ``automake``.
103
104   .. note::
105
106      If you get errors from ``configure.ac``, which ``autoreconf``
107      runs, that indicate missing files, you can use the "-i" option,
108      which ensures missing auxiliary files are copied to the build
109      host.
110
111#. *Cross-Compile the Project:* This command compiles the project using
112   the cross-compiler. The
113   :term:`CONFIGURE_FLAGS`
114   environment variable provides the minimal arguments for GNU
115   configure::
116
117      $ ./configure ${CONFIGURE_FLAGS}
118
119   For an Autotools-based
120   project, you can use the cross-toolchain by just passing the
121   appropriate host option to ``configure.sh``. The host option you use
122   is derived from the name of the environment setup script found in the
123   directory in which you installed the cross-toolchain. For example,
124   the host option for an ARM-based target that uses the GNU EABI is
125   ``armv5te-poky-linux-gnueabi``. You will notice that the name of the
126   script is ``environment-setup-armv5te-poky-linux-gnueabi``. Thus, the
127   following command works to update your project and rebuild it using
128   the appropriate cross-toolchain tools::
129
130     $ ./configure --host=armv5te-poky-linux-gnueabi --with-libtool-sysroot=sysroot_dir
131
132#. *Make and Install the Project:* These two commands generate and
133   install the project into the destination directory::
134
135      $ make
136      $ make install DESTDIR=./tmp
137
138   .. note::
139
140      To learn about environment variables established when you run the
141      cross-toolchain environment setup script and how they are used or
142      overridden by the Makefile, see the
143      :ref:`sdk-manual/working-projects:makefile-based projects` section.
144
145   This next command is a simple way to verify the installation of your
146   project. Running the command prints the architecture on which the
147   binary file can run. This architecture should be the same
148   architecture that the installed cross-toolchain supports::
149
150      $ file ./tmp/usr/local/bin/hello
151
152#. *Execute Your Project:* To execute the project, you would need to run
153   it on your target hardware. If your target hardware happens to be
154   your build host, you could run the project as follows::
155
156      $ ./tmp/usr/local/bin/hello
157
158   As expected, the project displays the "Hello World!" message.
159
160Makefile-Based Projects
161=======================
162
163Simple Makefile-based projects use and interact with the cross-toolchain
164environment variables established when you run the cross-toolchain
165environment setup script. The environment variables are subject to
166general ``make`` rules.
167
168This section presents a simple Makefile development flow and provides an
169example that lets you see how you can use cross-toolchain environment
170variables and Makefile variables during development.
171
172.. image:: figures/sdk-makefile-flow.png
173   :align: center
174   :width: 70%
175
176The main point of this section is to explain the following three cases
177regarding variable behavior:
178
179-  *Case 1 --- No Variables Set in the Makefile Map to Equivalent
180   Environment Variables Set in the SDK Setup Script:* Because matching
181   variables are not specifically set in the ``Makefile``, the variables
182   retain their values based on the environment setup script.
183
184-  *Case 2 --- Variables Are Set in the Makefile that Map to Equivalent
185   Environment Variables from the SDK Setup Script:* Specifically
186   setting matching variables in the ``Makefile`` during the build
187   results in the environment settings of the variables being
188   overwritten. In this case, the variables you set in the ``Makefile``
189   are used.
190
191-  *Case 3 --- Variables Are Set Using the Command Line that Map to
192   Equivalent Environment Variables from the SDK Setup Script:*
193   Executing the ``Makefile`` from the command line results in the
194   environment variables being overwritten. In this case, the
195   command-line content is used.
196
197.. note::
198
199   Regardless of how you set your variables, if you use the "-e" option
200   with ``make``, the variables from the SDK setup script take precedence::
201
202      $ make -e target
203
204
205The remainder of this section presents a simple Makefile example that
206demonstrates these variable behaviors.
207
208In a new shell environment variables are not established for the SDK
209until you run the setup script. For example, the following commands show
210a null value for the compiler variable (i.e.
211:term:`CC`)::
212
213   $ echo ${CC}
214
215   $
216
217Running the
218SDK setup script for a 64-bit build host and an i586-tuned target
219architecture for a ``core-image-sato`` image using the current &DISTRO;
220Yocto Project release and then echoing that variable shows the value
221established through the script::
222
223   $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux
224   $ echo ${CC}
225   i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/&DISTRO;/sysroots/i586-poky-linux
226
227To illustrate variable use, work through this simple "Hello World!"
228example:
229
230#. *Create a Working Directory and Populate It:* Create a clean
231   directory for your project and then make that directory your working
232   location::
233
234      $ mkdir $HOME/helloworld
235      $ cd $HOME/helloworld
236
237   After
238   setting up the directory, populate it with files needed for the flow.
239   You need a ``main.c`` file from which you call your function, a
240   ``module.h`` file to contain headers, and a ``module.c`` that defines
241   your function.
242
243   Create the three files as follows:
244
245   -  ``main.c``::
246
247         #include "module.h"
248         void sample_func();
249         int main()
250         {
251             sample_func();
252             return 0;
253         }
254
255   -  ``module.h``::
256
257         #include <stdio.h>
258         void sample_func();
259
260   -  ``module.c``::
261
262         #include "module.h"
263         void sample_func()
264         {
265             printf("Hello World!");
266             printf("\n");
267         }
268
269#. *Source the Cross-Toolchain Environment Setup File:* As described
270   earlier in the manual, installing the cross-toolchain creates a
271   cross-toolchain environment setup script in the directory that the
272   SDK was installed. Before you can use the tools to develop your
273   project, you must source this setup script. The script begins with
274   the string "environment-setup" and contains the machine architecture,
275   which is followed by the string "poky-linux". For this example, the
276   command sources a script from the default SDK installation directory
277   that uses the 32-bit Intel x86 Architecture and the &DISTRO_NAME; Yocto
278   Project release::
279
280      $ source /opt/poky/&DISTRO;/environment-setup-i586-poky-linux
281
282   Another example is sourcing the environment setup directly in a Yocto
283   build::
284
285      $ source tmp/deploy/images/qemux86-64/environment-setup-core2-64-poky-linux
286
287#. *Create the Makefile:* For this example, the Makefile contains
288   two lines that can be used to set the :term:`CC` variable. One line is
289   identical to the value that is set when you run the SDK environment
290   setup script, and the other line sets :term:`CC` to "gcc", the default
291   GNU compiler on the build host::
292
293      # CC=i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux
294      # CC="gcc"
295      all: main.o module.o
296        ${CC} main.o module.o -o target_bin
297      main.o: main.c module.h
298        ${CC} -I . -c main.c
299      module.o: module.c module.h
300        ${CC} -I . -c module.c
301      clean:
302        rm -rf *.o
303        rm target_bin
304
305#. *Make the Project:* Use the ``make`` command to create the binary
306   output file. Because variables are commented out in the Makefile, the
307   value used for :term:`CC` is the value set when the SDK environment setup
308   file was run::
309
310      $ make
311      i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c
312      i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c
313      i586-poky-linux-gcc -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin
314
315   From the results of the previous command, you can see that
316   the compiler used was the compiler established through the :term:`CC`
317   variable defined in the setup script.
318
319   You can override the :term:`CC` environment variable with the same
320   variable as set from the Makefile by uncommenting the line in the
321   Makefile and running ``make`` again::
322
323      $ make clean
324      rm -rf *.o
325      rm target_bin
326      #
327      # Edit the Makefile by uncommenting the line that sets CC to "gcc"
328      #
329      $ make
330      gcc -I . -c main.c
331      gcc -I . -c module.c
332      gcc main.o module.o -o target_bin
333
334   As shown in the previous example, the
335   cross-toolchain compiler is not used. Rather, the default compiler is
336   used.
337
338   This next case shows how to override a variable by providing the
339   variable as part of the command line. Go into the Makefile and
340   re-insert the comment character so that running ``make`` uses the
341   established SDK compiler. However, when you run ``make``, use a
342   command-line argument to set :term:`CC` to "gcc"::
343
344      $ make clean
345      rm -rf *.o
346      rm target_bin
347      #
348      # Edit the Makefile to comment out the line setting CC to "gcc"
349      #
350      $ make
351      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c
352      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c
353      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin
354      $ make clean
355      rm -rf *.o
356      rm target_bin
357      $ make CC="gcc"
358      gcc -I . -c main.c
359      gcc -I . -c module.c
360      gcc main.o module.o -o target_bin
361
362   In the previous case, the command-line argument overrides the SDK
363   environment variable.
364
365   In this last case, edit Makefile again to use the "gcc" compiler but
366   then use the "-e" option on the ``make`` command line::
367
368      $ make clean
369      rm -rf *.o
370      rm target_bin
371      #
372      # Edit the Makefile to use "gcc"
373      #
374      $ make
375      gcc -I . -c main.c
376      gcc -I . -c module.c
377      gcc main.o module.o -o target_bin
378      $ make clean
379      rm -rf *.o
380      rm target_bin
381      $ make -e
382      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c main.c
383      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux -I . -c module.c
384      i586-poky-linux-gcc  -m32 -march=i586 --sysroot=/opt/poky/2.5/sysroots/i586-poky-linux main.o module.o -o target_bin
385
386   In the previous case, the "-e" option forces ``make`` to
387   use the SDK environment variables regardless of the values in the
388   Makefile.
389
390#. *Execute Your Project:* To execute the project (i.e. ``target_bin``),
391   use the following command::
392
393      $ ./target_bin
394      Hello World!
395
396   .. note::
397
398      If you used the cross-toolchain compiler to build
399      target_bin
400      and your build host differs in architecture from that of the
401      target machine, you need to run your project on the target device.
402
403   As expected, the project displays the "Hello World!" message.
404