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