File: buildsystem.md

package info (click to toggle)
yotta 0.20.5-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,880 kB
  • sloc: python: 11,279; makefile: 32
file content (275 lines) | stat: -rw-r--r-- 11,740 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
---
layout: default
title: yotta Configuration System Reference
section: reference/buildsystem
---

# Build System Reference

yotta defines the way that software builds in order to make it easier for
separate modules to work together. It has both a simple automatic build system
that will build modules based on the source files discovered in the `source`
directory, and the capability to support building modules of any complexity
using [CMake](http://cmake.org).

## <a href="#info" name="info">#</a> Information Available To Builds

yotta makes some useful information available to the modules being compiled, which
can be embedded in the built binary or otherwise used at compile time. The
majority of this information is defined by yotta's [configuration
system](/reference/config.html), but some other information is also available.

### Information Always Available
The name of the library being built by the current module is available as
`YOTTA_MODULE_NAME`, as if it were defined:

```
#define YOTTA_MODULE_NAME modulename-unquoted
```

No header needs to be included for this definition to be available.

Use the [preprocessor stringification
trick](https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html) to get the
module name as a string, if desired. Note that this definition is **not**
currently available when compiling tests, and there are other circumstances
where using custom CMake can make it unavailable.


### Information Available in the Build Info Header
If the yotta build information header is included, then you can also access
other information. Note that this header changes with every build (as it
includes a build timestamp and unique ID), so do not include it unnecessarily.

To include the yotta build information header:

```C
#include YOTTA_BUILD_INFO_HEADER
```

This header defines the following:

```C
#define YOTTA_BUILD_YEAR   2015 // the current year, UTC
#define YOTTA_BUILD_MONTH  9    // the current month, 1-12, UTC
#define YOTTA_BUILD_DAY    16   // the current day of the month, 1-31, UTC
#define YOTTA_BUILD_HOUR   18   // UTC hour 0-23
#define YOTTA_BUILD_MINUTE 16   // UTC minute 0-59
#define YOTTA_BUILD_SECOND 47   // UTC second 0-61 (1)
#define YOTTA_BUILD_UUID   1f37f267-f31b-48c0-bfdd-2a7a5449817b // a uuid representing the build (2)
```

If yotta finds a mercurial or git repository in the module or application being
built, then the following will also be defined in this header:

```C
#define YOTTA_BUILD_VCS_ID 0123456789abcdef // git or mercurial hash, variable length up to 40 characters
#define YOTTA_BUILD_VCS_CLEAN 1             // 1 if there were no uncommitted changes, else 0
#define YOTTA_BUILD_VCS_DESCRIPTION v0.5-57-gad36348 // git describe or mercurial equivalent
```

Corresponding definitions for all of the build information are always available
in CMake without including any files.

Notes:

 * (1) Leap seconds will not currently occur in the _SECOND value, but they may do
   in future, so allow for the possibility of values up to and including 61 here.
 * (2) The build UUID changes every time that yotta build is invoked, even if the
   build would otherwise be identical.



## <a href="#automatic" name="automatic">#</a> Automatic Build System

yotta will automatically build the contents of the `source` and `test`
subdirectories of a software module. If you wan to exclude files from being
picked up by this build system then you can add them to a
[`.yotta_ignore`](/reference/ignore.html) file placed at the top of the module.

Any files in the source directory, and any of its subdirectories, will be
compiled into a single static library (for normal modules), or into the
application (for an executable module).

Any source files at the top-level of the test directory will be compiled into
separate test executables, and the (recursive) contents of any subdirectories
will each be compiled into a single test executable. You can use the
`yotta test` subcommand to build and run these tests.

Files in any other directories are normally ignored by yotta. By convention,
public header files that a module exposes are placed in a subdirectory with the
same name as the module, and then should be included as:

```C
#include "modulename/headername.h"
```


## <a href="#custom-cmake" name="custom-cmake">#</a> Using Custom CMake to Control The Build

To override yotta's default build rules for the `source` and `test`
directories, place your own CMakeLists.txt file in these directories. yotta
will also ensure that any CMakeLists.txt file in any other top-level
subdirectory of your module is included in the build. The testing with yotta
guide explains how to make yotta aware of any tests you add manually so that
`yotta test` can run them.

yotta will also respect a CMakeLists.txt file at the top-level of your module.
If this file is detected, then yotta will not automatically generate any build
rules. This is useful if you're adding yotta support to a module with an
existing build system, especially if the build system already uses CMake.

To ensure that yotta can automatically link your module to other modules, make
sure you define exactly one library with the same name as your module. A custom
build system may also define other build artifacts. In this case take care to
ensure that you name them in a way that minimizes the likelihood of name
collisions with other modules.

### <a href="#cmakelists" name="cmakelists">#</a> Places CMake Rules Can be Defined

There are various places you can define CMake rules to control the build, these
each have different effects:

 * **`./CMakeLists.txt` (in the module root)**: if you define a
   `CMakeLists.txt` file in the root of your module or executable, then yotta
   completely delegates building your module to this file.
 * **`./source/CMakeLists.txt`**: defining a `CMakeLists.txt` file in the
   source directory replaces yotta's default build rules for your library or
   executable, but yotta will still generate default rules for yout test
   directory (if any).
 * **`./source/<anything>.cmake`**: any .cmake files found in the source
   directory will be included at the *end* of the yotta-generated build rules
   for the source directory. If you want to make a very simple modification
   (such as definining a new preprocessor macro that your module needs), then
   this is the best way to do it. 
 * **`./test/CMakeLists.txt`**: defining a `CMakeLists.txt` file in the
   test directory replaces yotta's default build rules for your tests. yotta
   will build your library or executable from the contents of the source
   directory as normal.
 * **`./<anything>/CMakeLists.txt`**: Any subdirectory with a `CMakeLists.txt`
   file will be included in the build (unless it is ignored in the
   .yotta_ignore file). There aren't very many good reasons to do this.


### <a href="#cmake-examples" name="cmake-examples">#</a> Custom CMake Examples

All the following examples are using standard [CMake](http://cmake.org) syntax.
For documentation on the commands used, pleas see the [CMake
docs](https://cmake.org/documentation/).

General tips for writing CMake:

 * Always wrap expanded `"${VARIABLES}"` in quotes (or expand them inside a
   quoted string), if they are unquoted then any spaces in the expanded
   variable will cause it to be split into separate arguments

 * Where possible, avoid overriding yotta's generated CMakeLists.txt, and use
   the automatically included `.cmake` files to modify what yotta defined
   instead.

#### <a href="#generating-files" name="generating-files">#</a> Generating Files

If you have a script `./scripts/munge.py <input> <output>` that you want to run on an input file
`./resources/input.data` to generate an output C file to include in the build,
you can use a custom CMake file like this:

`./source/CMakeLists.txt`

```cmake
# construct the output path for our generated file (in the build directory, so
# that it gets removed by `yotta clean`):
set(MYMODULE_GENERATED_FILES ${CMAKE_BINARY_DIR}/generated/mymodule)

# ensure that the directory for the generated file exists:
file(MAKE_DIRECTORY "${MYMODULE_GENERATED_FILES}")

# save the paths to the script, input and output files, for convenience:
set(MYMODULE_MUNGE_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/../scripts/munge.py")
set(MYMODULE_MUNGE_INPUT  "${CMAKE_CURRENT_LIST_DIR}/../resources/input.data")
set(MYMODULE_MUNGE_OUTPUT "${MYMODULE_GENERATED_FILES}/generated.c")

# define the command to generate this file
add_custom_command(
    OUTPUT "${MYMODULE_GENERATED_FILES}/generated.c"
    DEPENDS "${MYMODULE_MUNGE_SCRIPT}"
            "${MYMODULE_MUNGE_INPUT}"
    COMMAND python "${MYMODULE_MUNGE_SCRIPT}" "${MYMODULE_MUNGE_INPUT}" "${MYMODULE_MUNGE_OUTPUT}"
    COMMENT "Munging input into generated.c"
)

# define the library for this module, using the generated file:
add_library(mymodule # your module must create a library with its own name
    sourcefile1.c
    sourcefile2.c
    "${MYMODULE_GENERATED_FILES}/generated.c"
)

# link against the module's dependencies
target_link_libraries(mymodule
    mydependency
    myotherdependency
)

```

Note that as we're replacing the yotta-generated CMakeLists for the source
directory, you need to make sure you're still linking against all of your
module's dependencies

#### <a href="#changing-flags" name="changing-flags">#</a> Changing the Compilation Flags for a module

You can use a `.cmake` file to change the link flags of an existing target
without having to redefine the automatically generated build rules. For
example, if your module is called `mymodule`, you could add this:

`./source/override_flags.cmake`:

```CMake
# add -funroll loops to the compile commands used for the sources in this
# module... loops deserve some fun too!
set_target_properties(mymodule COMPILE_FLAGS "-funroll-loops")
```

Note that here "mymodule" is the name of the static library that your module is
generating (the CMake "target" that it defines – nothing to do with the yotta
target). By convention all yotta modules produce a static library with the same
name as the module

For documentation on the other things that you can set with
set_target_properties, including preprocessor definitions, see the [CMake
docs](https://cmake.org/cmake/help/v3.0/command/set_target_properties.html).

#### <a href="#linking-external" name="linking-external">#</a> Linking an External Library

`./source/link_foo.cmake`:

```CMake
# link ./precompiled/foo.a into mymodule, in addition to its yotta
# dependencies:

target_link_libraries(mymodule "${CMAKE_CURRENT_LIST_DIR}/../precompiled/foo.a")
```


### <a href="#cmake-definitions" name="cmake-definitions">#</a> Definitions Available in CMake Lists

yotta makes all the definitions which are available to the preprocessor
available to CMake scripts (including, for example, the path to the build
information header, and the definitions derived from the config information).

In addition, several other definitions are available, including:

 * `YOTTA_CONFIG_MERGED_JSON_FILE`: This expands to the full path of a file
   where the current yotta config information has been written. If you want to
   use the config information for advanced pre-build steps (such as including
   portions of it in the executable in a parseable form), then this is the file
   you should read the config information from.


## <a href="#build-products" name="build-products">#</a> Build Products

Everything that yotta generates during the build is created within the `build`
subdirectory. Within this directory build products are further divided by the
name of the [target](tutorial/targets.html) being built. This makes it safe to
switch between building for different targets without cleaning.