# Crossdevelopment for bare-metal targets using gcc

## Preface

If you already do gcc based crossdevelopment, then you probably will not find anything new on this page. If you are familiar with gcc et al as native tools, then you will find most of the material trivial, although there are a few important differences between native and crossdevelopment. If you are relatively new to doing things the unix command line way, then read on.
What you find here is how to do crosscompilation to a bare target (i.e. reset starts executing your code and not some automagically created entry point). Although it was written for ARM7TDMI based development, most of what you find here is the same for other architectures. This is what you will find on this page:

- Interworking
- Compiling and assembling
  - gcc options for C code
  - gcc options for assembly
- Linking
  - Linker options
  - The mapfile
  - The result file
  - The linker script file
  - Object files
  - Libraries
- Generating a hexfile
- Putting it all together

## Interworking

The ARM7TDMI core can operate in two modes. One is ARM and the other is THUMB. ARM instructions are 32 bits wide. THUMB instructions are 16 bits wide, except long jumps, which remain 32 bits (actually, they are synthetised from two consecutive 16-bit instructions). Apart from the long jumps the THUMB instruction set is a proper subset of the ARM set, it simply contains the most often used ARM instructions, encoded in 16 bits. That 16 bits gets extended to a full 32-bit ARM instruction and that's what gets into the CPU's execution unit.
Naturally, the instructions being half as wide increases your code density. However, you loose a lot of useful stuff that the ARM mode has. Thus, as a rule of thumb (no pun intended), THUMB code is about 2/3 of the size of the equivalent ARM code and runs about 2/3 of the speed of the ARM code. These figures vary significantly depending on what you do, so the numbers above are only informative; your actual experience might be rather different.
The processor can switch between the two modes on the fly using a special jump instruction. That sounds pretty cool, because you can compile the bits that can make use of the extra features of the ARM set for ARM and the more mundane things for THUMB and have the best of both worlds.
Indeed that is the case, but you need to tell the compiler that you want to do that, because it has to generate the special mode switch code snipets whenever you call an ARM function from THUMB code or vice versa. That is called interworking.
If you have very little code space and you do not want to use ARM functions at all, then you can also tell the compiler that you do not use interworking. In that case the compiler will know that it doesn't have to care about it and will not generate those little code snipets that would otherwise ensure that a function can be called from any mode and guarantee that it returns to the caller in the correct mode. That will save you some codespace (not much, actually, but if things get really tight, every word counts).

## Compiling and assembling

### gcc options for C code

In general, when you compile a single C file into an object file the gcc command line looks something like this:
`gcc options -c -o filename.o filename.c`
In case of crosscompiling usually you have `arm-eabi-gcc` or similar instead of simply `gcc`, of course. There are hundreds of options you can pass to gcc. Most of them do not concern you, but there are a few that you have to deal with.

- -std=gnu99
  This option tells the compiler what C standard to follow. The gnu99 means C99 (the latest C standard), with GNU extensions. The extensions that gcc offers are rather good, it's worth to enable them.

- -I <path>
  Tells the compiler that it should look for include files in the directory specified by `<path>`. You can issue as many of these as you wish. You do not have to specify the path for the include files that come with gcc (`stdarg.h, stddef.h, float.h` and a few others) because the compiler knows that. On the other hand, you have to use this switch to tell the compiler about the location of the headers for this library. If you installed the library at the default location, you should say
  `-I /usr/local/armlib/include`.

- -g
  Tells the compiler to put debug info into the object files. Use it if you have some debugger, like gdb through the JTAG interface. If you have no debugger for your target, you can omit it. It has no effect on your final code but the size of the object files increases significantly with debug symbols enabled.

- -Os
  -O2
  -O0
  Tell the compiler to optimise for size (-Os) or speed (-O2). The third option, `-O0`, tells the compiler to turn all optimisation off. It is useful for debugging, because the optimiser transforms your code in ways which may cause your variables or even functions to disappear. If you turn optimisation off, everything works exactly as you've written it. Note that your code size, stack usage and execution time will increase greatly with `-O0`.

- -pipe
  Tells the compiler to use pipes instead of files to send the intermediate assembly output to the assembler. It has no effect on the generated code but it makes compilation a tiny bit faster.

- -MD
  Tells the compiler to generate a file that contains a dependency list for the result of the compilation. The dependency list is in a format that `make` understands. That is, you can generate the dependencies for your makefile automatically. The dependency file is located at and called the same as the output file except that it has the extension of ".d" instead of ".o".

- -ffreestanding
  Tells the compiler that you write code for a target where there's no operating system. The compiler does not expect main() to have the usual arguments and it does not generate any code to interact with the operating system.

- -fno-common
  Tells the compiler not to use common sections. If you don't know what they are, just use the switch. If you know what they are, you will also know when not to use the switch.

- -Wall -Wextra -Werror -Wundef -Wmissing-declarations
  -Wshadow -Wwrite-strings -Wmissing-field-initializers
  Tells the compiler to be a jerk. It will warn for everything that is even slightly dubious and will turn every warning into an error. No sloppy programming is allowed. You can write code that bombs, but in your code you have to tell the compiler that that's really what you want to do. I use those and suggest that you do too, because gcc is quite clever in finding iffy things and typos that result in valid C code but one that does something very different from your original intentions. When you have to explicitely specify that you want to bend the rules, it forces you to know what you are doing, or at least to think about it one more time. Note that you could also specify `-pedantic` but then you can not use anonymous structures and unions. These are very useful constructs and often save a lot of typing. However, if you do not want to use them and strict C standard compliance is important, then specify the `-pedantic` switch as well.

- -mcpu=arm7tdmi
  Tells the compiler to compile for an ARM7TDMI core. You can use the `-mcpu=arm7tdmi-s` switch, if you want. The `-s` suffix indicates that it is a synthesisable (soft) core. There are some differences between the two core versions, but the instruction set and instruction execution times are identical. From the compiler's point of view the two cores are the same.

- -mthumb
  -mno-thumb
  Tell the compiler to compile for the THUMB or the ARM instruction set, respectively.

- -mthumb-interwork
  -mno-thumb-interwork
  Tell the compiler to use interworking (so that ARM and THUMB functions can call each other) or not, respectively. Note that if you do not enable interworking, your sources must all be compiled to THUMB or to ARM, you can not mix these. Also, you must use the relevant non-interworking library. If you specify interworking, then you can mix and match THUMB and ARM functions in your code. In addition, you can use either ARM or THUMB libraries (or a mixture of them), but you have to use the interworking library versions. Interworking comes at a price of a little speed and code space so if you are memory constrained, you probably want to turn interworking off, compile for THUMB and optimise for size. If you are CPU constrained, then turn interworking off, compile for the ARM and optimise for speed. In any other case interworking is a Good Thing and you should enable it, because it empowers you to get the best of both worlds.

- -fno-inline-small-functions -fno-unroll-loops
  Tell the compiler not to inline small functions (unless you explicitely declare them inline) and not to unroll loops. These switches are relevant only if you optimise for size and you are tight on memory. In all other cases you should not use them. In particular, the inlining small functions is a tricky issue, see Automatic inlining of small functions on the The pros and cons of using gcc page for details.

- -fno-strict-aliasing
  Disables optimisations in the compiler that might break your code when you get a pointer to a type, cast it to be a pointer to an other type and dereference it. If you don't do that, then you can omit this switch.

- -fwrapv
  Tells the compiler to assume that basic arithmetics have a 2's complement wrap-around behaviour when an overflow occurs. You should use this switch if you have any place in your code where you rely on the wrap-around behaviour. Without the switch the compiler treats integer arithmetic operators as if they would never overflow. For example, the compiler assumes that x+1 is always larger than x. Therefore, if you want to test for your counter overflowing by checking that after the increment it became smaller than it was, your code will not work, as the compiler will remove your test and substitute it with an assumed 'false'. If you specify this switch, it will generate code to test the result, or, if it is simpler, it can test before the increment whether using 2's complement rules the addition would overflow or not.

- -fno-delete-null-pointer-checks
  See NULL pointer for an explanation.

- -fshort-wchar
  If you use wide characters, this switch tells the compiler to use 16-bit wide characters (i.e. you can encode only the Basic Multilingual Plane from the Unicode set). If you do not specify this switch or specify it in the negative, the wide character type will be 32 bits wide.

- -fno-zero-initialized-in-bss
  You may or may not need this switch. See Initialised variables for details.

- -c
  Tells the compiler to translate the source to object file but not to invoke the linker.

- -o <filename>
  Tells the compiler to write the compilation result to the given file.

### gcc options for assembly

We will use gcc to assemble the source. If you pass a source file that has the filename extension of ".s", then gcc treats it as assembly source and passes it to the assembler. I you use the filename extension ".S", note the capital 'S', then gcc will run the source through the C preprocessor before handling it to the assembler. That way you can share `#define`-s between assembly and C source.
If you use gcc as your assembler, the command line is the same as in case of a C compilation but only a subset of the C compiler options listed should be used. Namely:

- -std=gnu99 -g -pipe -MD -ffreestanding -fno-common
  -I <path>
  -pedantic -Wall -Wextra -Werror
  -mcpu=arm7tdmi -m(no-)thumb -m(no-)thumb-interwork

The specifying of the C standard might seem superfluous, but don't forget that gcc might have to run your assembly through the C preprocessor and the switch makes sense there.

## Linking

Assuming that you let gcc to run the linker for you, your linker command line should look something like this:
`gcc options -T <linker script file> -Wl,-Map,<mapfile> -o <result> <object files> <libraries> -lgcc`

### Linker options

The following is the list of the options you should specify for linking:

- -g -Werror -mcpu=arm7tdmi
  They are the same as with C or assembly.

- -m(no-)thumb
  Although all object files are already compiled for ARM or THUMB mode, there is one item for which the mode is not yet determined: `libgcc.a`, the compiler support library. This switch tells the linker whether it should use the ARM or the THUMB version of that library.

- -m(no-)thumb-interwork
  Tells the linker to process interworking or not. Since it is possible that from an object compiled for ARM there is a call to a function defined in an object compiled for THUMB (or the other way around), the linker has to resolve those by inserting little code snippets that switch mode as needed. If you specify interworking, the linker checks that all your files are interwork compatible and will resolve the inter-mode calls.

- -Wl,--warn-common,--fatal-warnings
  Note that this is a single option, with no spaces in it!
  This option tells gcc to pass the two options with double dashes to the linker as they are. The first one tells the linker to warn about common sections. Like with the `-fno-common` C compiler option, if you don't know what the common section is, just use the switch, if you do know, they you will know when not to use it.
  The second option is equivalent to the `-Werror` compiler switch.

- -nostdlib
  Tells the linker not to try to link any of the standard libraries or start-up files. Since your system is a bare-metal system, there are no standard libraries to link against, except the gcc support library, which you have to specify as the last item on the command line..

- -static -static-libgcc
  These switches tell the linker not to attempt to look for shared libraries and use a static version of the gcc support library, namely `libgcc.a`.

- -L path
  Tells the linker to look for libraries in the directory specified by `path`. You can use as many of these as you wish. The directories will be searched in the same order as you specified them. You don't have to tell the linker about the location of `libgcc.a` but you have to tell about the libraries in this package. If you installed them in the default location, you will have to specify
  `-L /usr/local/armlib/lib`

### The mapfile

If you specify the `-Wl,-Map,<mapfile>` switch (note that there are no spaces in it!), the linker will generate a mapfile that contains the locations of all global symbols. It can come useful, especially if you have no symbolic debugger for your target.

### The result file

You specify the filename where the final, linked objectfile will go. It will have all addresses resolved and finalised. If you specified the `-g` option, it will also contain all debug information that you will need to use with gdb.

### The linker script file

Under normal circumstances the linker has built-in knowledge about the system it links for. Therefore, allocation of memory regions happens automatically. With your bare-metal embedded system you are the only one who knows what is mapped where, how much RAM/FLASH you have, how you want to organise memory and so on. Therefore, you have to tell it to the linker. So you write a linker script file. Here is a short introduction, but for further details you should consult the linker's info page.
The linker script file is a textfile, that has some resemblance to C in that it uses { and } as block delimiters, you can use C block comments and that you can write expressions. The similarities end there, though. The first item in your linker control file is the specification of the format of the output file. It looks like this:

    OUTPUT_FORMAT(elf32-littlearm)

It means that the format is ELF, 32 bit address space, little endian byte order for both headers and content and that it is for the ARM architecture. Note that you have to specify ELF even if you use EABI.
The next step is to define your memory regions. As an example, I will use an NXP chip. In the NXP LPC2xxx microcontrollers the FLASH starts at 0 and the built-in RAM starts at 0x40000000. Let's assume that we have 128K FLASH and 32K RAM. You can give arbitrary names for memory regions. I will call the FLASH 'rom' and the RAM 'ram'. Here it is:

    MEMORY
    {
       rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x20000
       ram (rwx) : ORIGIN = 0x40000000, LENGTH = 0x08000
    }

The `(rx)` and `(rwx)` mean that the FLASH is readable and executable and the RAM is read, write, execute. It doesn't matter much, because there's no operating system to enforce the rules, but it is neat to specify it.
The next, and most important part of the linker control file is the section placement. The general format is:

    SECTIONS
    {
       section1_definition
       section2_definition
       ...
       sectionN_definition
    }

A section definition can be very complex. Here only the bare minimum is explained. For an in-depth understanding, you need to consult the info page of `ld`.
A section definition has a skeleton like this:

      section_name address (type) : attributes
      {
         section1_command
         section2_command
         ...
         sectionN_command
      } > region

The various items are the following:

- `section_name`
  This is a symbolic name for the section, such as `.text` or `.data`. You can use any identifier you wish, but customarily the executable code is in `.text`, initialise data goes to `.data` and uninitialised data resides in `.bss`.

- `address`
  The address where the section starts. If you do not specify it, then it is taken as just after the previous section (or 0 for the first section). You can use the usual decimal, hex or octal numbers or an expression containing constants and symbols that are already resolved.

- `(type)`
  There are a few types defined, but we will use only one. If you want a section to be allocated but not loaded (i.e. not stored in the result file), then you can specify `(NOLOAD)`. This applies to the `.bss` section, for example.

- `attributes`
  There are couple attributes of which we will use only one. The `AT ( exression )` attribute tells the linker that it should place the content of the section at the address specified by the expression. Note that symbols within the section will still have the value relative to the address of the section, it's just that when the linker is done and it writes the output file, the content of this section will be at the specified location in the output. You can use this feature to put the initialiser for the `.data` segment just after the code. The expression can contain all sorts of things, but for us only two operators are important:
  - `ADDR ( section_name )`
    It is the start address of the section named between the parenthesis.
  - `SIZEOF ( section_name )`
    It is the size of the section named between the parenthesis.

- `> region`
  Tells the linker which memory region you intend the section to go.

The remaining item is `section_command`. There are a few possibilities here. The most important one tells the linker what sections of the object (and library) files to put into the section. It has the general format of

       file_name(section section ... section)

The file_name is the name of the object file that you want to extract the section(s) from. There are all sorts of complicated possibilities there, but for our minimalistic purposes the wildchar filename of '*' is sufficient, since we want to process all files. The section names between the parenthesis are the names of the sections that you want to pull from the object files. Again, there are all sorts of complicated possibilities with which you can control your linking at a very fine-grained level, but we just simply want to lump identical sections together. So, to collect all code (which gcc puts into the `.text` segment) from all object files you would write this:

       *(.text)

Alas, that's not enough. Sometimes gcc has to generate extra code and it puts extensions to the section name that identifies what that little fragment is all about. So you will find sections called `.text.something` and not just simply `.text`. Fortunately, the wildcards work with section names as well, so you just modify your section specification to:

       *(.text*)

Now you have to deal with the possibility that a segment is prefixed. For example, you can tell the ARM library to prefix each segment with the name of the library, so the text segment in the math library would be `.libm.text`. To also cater for that you can use the idiom

        *(*.text*)

The compiler can generate all sorts of sections, but if you are compiling straight C code, you can expect the following:

- `.text` Contains the actual code
- `.rodata` Read-only data
- `.data` Initialised data
- `.bss` Uninitialised data

Furthermore, the linker can generate two more segment names, used to resolve interworking issues:

- `.glue_something`
- `.v4_bx`

They should go to the code segment.
When you collect things that go into one section you can do it two ways. Take the section that goes to the FLASH for example. You want all the code to go there plus all the constant data to be there. As the linker processes the object files, it can either put the `.text` and `.rodata` sections ane after the other as they come, or it can collect all `.text` sections first and all `.rodata` sections next. It is up to you which one you prefer. If you specify more than one section between the parenthesis, then you will get the sections you listed intermingled in the output:

       *(*.text* *.rodata*)

If you want all code collected first, followed by all data, then you write two input section commands:

       *(*.text*)
       *(*.rodata*)

The other `section_command` that you want to use is the assignment. If you want to clear the uninitialised data segment and initialise the initialised one at boot, you have to know where these sections start and how large they are. Furthermore, you need to know where to find the initialisers. The linker allows you to define symbols that can be referred to from C code. The general format is

       symbol = expression ;

There are all sorts of expression possibilities, but we will use only two here. The period, '.' means the current location. That is, if you write:

       *(*.text*)
       boundary = . ;
       *(*.rodata*)

then the linker will define the symbol 'boundary' and it will be the address where the code finishes and the read-only data starts in your FALSH.
The other expression you often use is in the format of

       symbol = ALIGN( 8 ) ;

This also assigns the current location to the symbol, but it aligns the current location to the next 8-byte boundary before doing that. So, if you want to know where the `.bss` segment starts and ends and in the same time you want the section to finish on a double-word boundary (you need 8-byte alignment because of EABI's requirements regarding to `long long` and `double`) you'd write:

      _bss_beg = .;
      *(*.bss*)
      _bss_end = ALIGN( 8 );

It's very important to realise that these symbols are addresses, not data values. So how can you tell the C compiler that you refer to an object but the name implies an address and not a value stored in memory? Simple. You decleare the object as an array. The name if the array is actually the address of the first element of the array. So if you want to clear your `.bss` specified with the above section commands, you could write:

    extern char _bss_beg[];
    extern char _bss_end[];

        memset( _bss_beg, 0, _bss_end - _bss_beg );

So now we can put the complete linker script together:

    /*
    * Output format
    */

    OUTPUT_FORMAT(elf32-littlearm)

    /*
    * Memory regions
    */

    MEMORY
    {
       rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x20000
       ram (rwx) : ORIGIN = 0x40000000, LENGTH = 0x08000
    }

    /*
    * Section definitions
    */

    SECTIONS
    {
       /* The stuff that we want to go into the FLASH */

       .text 0x0 :
       {
          /* The vector table must be the first. It was placed into the
             section called ".vectors". Get that, followed by the the
             actual code in .text and read-only data in .rodata.
             Don't forget the glue code either. */

          *(.vectors)
          *(*.text*)
          *(*.rodata*)
          *(*.glue*)
          *(*.v4_bx)

          /* Align and make note of the end of the section */

          _text_end = ALIGN( 8 );

          /* This section goes to the FLASH */

       } > rom

       /* The initialised data segment starts at where the RAM starts.
          However, we want the actual initialisers to go just after the
          code and read-only data. So the data section lives in the RAM
          but the initialisers are stored in the FLASH. */

       .data 0x40000000 : AT( _text_end )
       {
          _data_beg = . ;
          *(*.data*)
          _data_end = ALIGN( 8 );

       } > ram

       /* The uninitialised data is just after the initialised one in the RAM.
          It does not have to be loaded. If there would be common sections, they
          should also come here, but we don't use them. */

       .bss (NOLOAD) :
       {
          _bss_beg = . ;
          *(*.bss*)
          _bss_end = ALIGN( 8 );

       } > ram
    }

with that then you can clear your `.bss` and initialise your `.data` like this (note that your stack at the moment of the execution of this program fragment must not be in the `.bss`!):

    extern char _code_end[];
    extern char _data_beg[], _data_end[];
    extern char _bss_beg[], _bss_end[];

        memset( _bss_beg, 0, _bss_end - _bss_beg );
        memcpy( _data_beg, _code_end, data_end - data_beg );

### Object files

You just simply list all the object files in your code. They will be parsed by the linker in the order you specify them.

### Libraries

You list the libraries you want to link against. The format is

- `-lname_stem`

for each library you want to scan for undefined symbols. The linker will put `lib`in front of the `name_stem` and will put a `.a` suffix after it. Thus, if you want to link against `libfoo.a`, you write `-lfoo` and the linker supplies the rest. The linker will look for `libfoo.a` in all the directories you listed with the `-L` command line switch. If you want, you can also specify the full pathname of a library, in which case you can not omit the 'lib' and the '.a':
`-l~/mylibs/libmagic.a`
The libraries are searched for undefined symbols in the order you specify them, so if multiple libraries define the same symbol, the library order is important. That way a library specified earlier can overload symbols defined in a library specified later.

## Generating a hexfile

Usually the tools that can burn the FLASH in your micro expect a hexfile, a file that contains the binary image in ASCII format (as hexadecimal numbers). Two common formats are in use, they are called Motorola S-record and Intel hex. The former comes from Motorola and is called S-record because every line in it starts with the character 'S'. The latter is from Intel. Since in that format every line starts with the ':' character and 'Intel colon-record' doesn't sound really appealing, it was simply called 'hex'.
The binutils package installed a handy utility called `objcopy`. That program can read an object file in one format and write it in an other. It can do all sorts of other things as well, but you don't need them to create a hexfile. The command to generate Motorola S-record from the linking result is:
`arm-eabi-objcopy -O srec linker_output_file s-record_file`
Similarly, if you want Intel hex format, the command to use is:
`arm-eabi-objcopy -O ihex linker_output_file intel-hex_file`
In some cases you want to get the raw binary image itself, for example if you want to process it and calculate some checksum on it. You can use `objcopy` to obtain that as well:
`arm-eabi-objcopy -O binary linker_output_file raw_binary_file`
All of these commands will strip all debug info from the file, the only thing remaining in the output is the actual binary image that you should burn into the FLASH.

## Putting it all together

From the above you can create a makefile to build your project. Let's assume that you put the linker control file into `mystuff.ld` and you want to create a Motorola S-record file called `mystuff.hex` at the end. You have `reset.S` containing the reset vectors and the boot code and `main.c` containing your actual application code. You want to use the C library and the gcc runtime replecement routines from this library, that you installed at the default `/usr/local/armlib` location. We also assume that you use EABI and thus the tool prefix is `arm-eabi-`.

    # Project files

    FILES = reset.S main.c

    # Libraries we use

    LIBS = c gccs

    # Tool prefix.

    TOOLPFX = arm-eabi-

    # The tools. We use gcc as assembler and linker as well

    CC = $(TOOLPFX)gcc
    AS = $(CC)
    LD = $(CC)
    OC = $(TOOLPFX)objcopy

    # Location of the ARM library

    LIBDIR = /usr/local/armlib

    # C, assembler and link flags.
    # We compile for THUMB and enable interworking, optimise for size

    CFLAGS = -g -std=gnu99 -pipe -MD -c -ffreestanding -Os \
             -I $(LIBDIR)/include -I . \
             -mcpu=arm7tdmi-s -mthumb -mthumb-interwork \
             -fno-delete-null-pointer-checks -fno-trapping-math -fno-math-errno \
             -fwrapv -fno-strict-aliasing -fno-inline-small-functions \
             -fno-unroll-loops -fno-common \
             -Wall -Wextra -Werror -Wundef -Wmissing-declarations -Wshadow \
             -Wwrite-strings -Wmissing-field-initializers

    AFLAGS = -g -std=gnu99 -pipe -MD -c \
             -I $(LIBDIR)/include -I . \
             -mcpu=arm7tdmi-s -mthumb -mthumb-interwork \
             -Wall -Wextra -Werror

    LFLAGS = -g -mcpu=arm7tdmi-s -mthumb -mthumb-interwork -nostdlib \
             -static -static-libgcc -Wl,--warn-common,--fatal-warnings \
             -L $(LIBDIR)/lib

    # The object files

    OBJS = $(patsubst %,%.o,$(basename $(FILES)))

    # The default target

    mystuff.hex: mystuff.abs
    	$(OC) -O srec $< $@

    # The clean-up target

    clean:
    	rm -f *.o *.d mystuff.abs mystuff.map mystuff.hex

    # How to link the absolute file

    mystuff.abs: $(OBJS) mystuff.ld
    	$(LD) $(LFLAGS) -T mystuff.ld -Wl,-Map,mystuff.map \
    	      -o $@ $(OBJS) $(patsubst %,-l %-tis,$(LIBS)) -l gcc

    # Rules to compile and assemble files

    %.o: %.c
    	$(CC) $(CFLAGS) -o $@ $<

    %.o: %.S
    	$(AS) $(AFLAGS) -o $@ $<

    # Load the automatically generated dependencies, if they exist

    -include $(patsubst %,%.d,$(basename $(FILES))