Services and Modeling for Embedded Software Development
Embecosm divider strip
Prev  Next

7.2.2.  Updating Spec Definitions

GCC calls a number of subsidiary programs (the compiler itself, the assembler, the linker etc). The arguments to these are built up from the parametrized strings, known as Spec strings.

This application note cannot describe the huge range of possible parameters. However we will use one example to show what is possible. The changes are all made to the definitions of the strings in target.h. In the case of the OpenRISC 1000  this is or32.h.

We need to make four changes.

  1. We need to tell the C preprocessor to look for headers in the relocated newlib library directory.

  2. We need to tell the linker to pick up the newlib C runtime start up file.

  3. We need to tell the linker where to find the newlib libraries.

  4. We need to tell the linker to include the BSP library in the right place.

The Target Specific Installation Directory

All of these changes will require knowing the location of the target specific installation directory. Unfortunately there is no Spec parameter giving this. However we can construct it from two definitions available when compiling GCC. STANDARD_EXEC_PREFIX is the directory where the GCC executables will be found. Two directories up from that will be the main prefix directory. The target machine is specified in DEFAULT_TARGET_MACHINE. So concatenating the three strings yields the target specific directory.

STANDARD_EXEC_PREFIX "/../../" DEFAULT_TARGET_MACHINE
	    

The newlib headers are in the subdirectory newlib-include and the C runtime start up and libraries in newlib.

We define a new string, TARGET_PREFIX based on the concatenation.

#define CONC_DIR(dir1, dir2) dir1 "/../../" dir2
#define TARGET_PREFIX CONC_DIR (STANDARD_EXEC_PREFIX, DEFAULT_TARGET_MACHINE)
	    

Defined constants cannot be used directly in Spec strings, but we can make them available by defining the macro EXTRA_SPECS.

#define EXTRA_SPECS                                   \
  { "target_prefix", TARGET_PREFIX }
	    

The Spec string target_prefix is now available to be used in other Spec strings.

Specifying the header directory.

Additional arguments to the C preprocessor are defined in CPP_SPEC. The newlib header directory should we searched after any user specified header directories (from -I arguments) and after the GCC system headers. So it is specified using the -idirafter option.

#undef CPP_SPEC
#define CPP_SPEC "%{mor32-newlib*:-idirafter %(target_prefix)/newlib-include}"
	    

This specifies that any option beginning -mor32-newlib should be replaced by the string -idirafter followed by the newlib-incldue subdirectory of the target_prefix directory.

So so for example, if we build the OpenRISC 1000  GCC with --prefix=/opt/or32-elf-new, we would have STANDARD_EXEC_PREFIX set to /opt/or32-elf-new/lib/gcc and DEFAULT_TARGET_MACHINE set to or32-elf. The Spec variable target_prefix would therefore be /opt/or32-elf-new/lib/gcc/../../or32-elf and thus the C preprocessor would have the following added to its option list.

-idirafter /opt/or32-elf-new/lib/gcc/../../or32-elf/newlib-include"
	    

This substitution only occurs when -mor32-newlib or -mor32-newlib-uart is specified, which is exactly the behavior desired.

[Note]Note

If newlib is not relocated as described in Section 7.1, then the headers will be in a standard location, which GCC will search anyway, so there is no need to define CPP_SPEC.

Specifying the C Start up File

crt0.o should be the first object file or library specified to the linker. This is covered by STARTFILE_SPEC.

This string already has a partial definition, to look for crt0.o in a standard place, and to include the crtinit.o file from a standard place.

#undef STARTFILE_SPEC
#define STARTFILE_SPEC "%{!shared:crt0%s crtinit.o%s}"
	    

So long as -shared is not specified as an option, this looks for crt0.o and crtinit.o in standard directories and substitutes them on the command line (the suffix %s indicates that the preceding file should be searched for in standard directories, and its name expanded to include the directory name).

This needs changing to indicate that if -mor32-newlib or -mor32-newlib-uart is specified, then crt0.o should be taken from the newlib directory.

#define STARTFILE_SPEC \
    "%{!shared:%{mor32-newlib*:%(target_prefix)/newlib/crt0.o} \
     %{!mor32-newlib*:crt0.o%s} crtinit.o%s}"
	    

Note that we must also include the case that when neither of the newlib options is specified, then crt0.o will be searched for in standard directories.

[Note]Note

If newlib is not relocated as described in Section 7.1, then crt0.o will be in a standard location, which GCC will search anyway, so there is no need to modify STARTFILE_SPEC.

Specifying the Newlib library location

We need to tell the linker where to look for newlib libraries. This is achieved in a similar manner to the search for the headers, but using the -L option and LINK_SPEC.

#undef LINK_SPEC
#define LINK_SPEC "%{mor32-newlib*:-L%(target_prefix)/newlib}"
	    
[Note]Note

If newlib is not relocated as described in Section 7.1, then the newlib libraries will be in a standard location searched by GCC, so there is no need to specify LINK_SPEC.

Adding a BSP to the link line.

The libraries searched by GCC are by default specified to be -lgcc -lc -lgcc, with variants if profiling is being used. When a BSP is used, it must be searched after libc, but that can leave references unresolved, so libc must be searched again afterward.

The sequence of libraries to be searched between the two searches of libgcc is given in LIB_SPEC. It already has a definition.

#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}
	    

This specifies a variant library when profiling is in place. newlib does not offer profiling support, but it does have a debugging version of the library (libg).

#undef LIB_SPEC 
#define LIB_SPEC "%{!mor32-newlib*:%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}} \
                  %{mor32-newlib:%{!g:-lc -lor32 -lc}                     \
                                 %{g:-lg -lor32 -lg}}                     \
                  %{mor32-newlib-uart:%{!g:-lc -lor32uart -lc}            \
                                 %{g:-lg -lor32uart -lg}}"
	    

This ensures that the correct BSP library will be used, according the the option selected, and that if -g is specified on the command line, the debugging version of the C library (libg) will be used instead.

Even if the newlib is not relocated as described in Section 7.1, then this Spec change is required in order to ensure the correct libraries are picked up.

Embecosm divider strip