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