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
. In the
case of the OpenRISC 1000 this is target
.hor32.h
.
We need to make four changes.
We need to tell the C preprocessor to look for headers in the relocated newlib library directory.
We need to tell the linker to pick up the newlib C runtime start up file.
We need to tell the linker where to find the newlib
libraries.
We need to tell the linker to include the BSP library in the right place.
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.
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 | |
---|---|
If |
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 | |
---|---|
If |
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 | |
---|---|
If |
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.