This is an unapproved draft. It is currently in progress and under review.

7.1 Introduction

rce modules and binary objects for host systems are compiled and linked with the gnu compiler and binutils collections. The build tool is gmake.

This chapter covers:

The reader is assumed to be familiar with the tools in the gnu collection.

7.2 General compilation and linking requirements

While naturally the build system automates much of the compilation and linking process, developers must manage build dependencies manually, setting up makefiles such that modules and objects "lower" on the dependency graph are built before those "higher" on the graph.

rce modules

The rce uses elf (Embedded and Linking Format) as the native object code format for its module objects.

Modules can be built up at compile/link time from traditional static (".a") libraries and/or shared object (".so") libraries prepared using the rce repository make system. Modules can also contain static code (".a") from host system or third-party libraries, but such libraries must be (re)compiled with options required by the dynamic linker. See Section 7.9.

The dynamic linker fails if presented with duplicate symbol names. A given symbol can be used in more than one module, but only if those modules are never loaded together.

Host objects

TBW.

7.3 Makefile and build product hierarchy

Source code in the rce repository is organized using a two-level structure in which projects contain one or more packages. Packages contain code and makefiles for the construction of one or more constituents.

As discussed in Chapter Y, the pkgcreate.py script automates the creation of project and package directories and generic "blank" makefiles.

A set of repository-level makefiles allows gmake to be invoked at the top level to build all packages and projects locally, or build a full release of rce software. A set of makefile templates is used to clone new projects and packages. See Figure 4.

Building all projects at once is the exception. Typically, development iterations involve building and re-building individual packages and constituents. Figure 5 depicts the makefiles relevant to package and constituent builds.

Makefile search path

Under construction
Note: How "export library symbols...just like symbols in module sources."
Inter-package and inter-project dependencies
Must be handled manually
If A depends on B, build B first
Order of projects in projects.mk
Order of packages in packages.mk
Library search order
When linking each library is searched once
In lists of libraries put the lower-level libs first
The search order will be the reverse of that listed

Build product hierarchy

TBW.

7.4 Global make variables

Under construction

The repository-level makefiles define a set of global make variables that can be useful to cite in package- and constituent-level makefiles, and which set compiler options for various targets.

These reflect the platform information make variables derived from $(tgt_arch)
make variable compiler option
tgt_os == "linux" -Dtgt_os_linux
tgt_cpu_family == "ppc" -Dtgt_cpu_family_ppc
tgt_opt == "" -Dtgt_opt_
tgt_opt == "dbg" -Dtgt_opt_dbg
tgt_board == "" -Dtgt_board_
tgt_board == "rce405" -Dtgt_board_rce405

Other variables record the location of intermediate and final build products. See Figure 6.
Build directories for rce module code:

modobjdir
modlibdir
moddir

Build directories for host (non-module) code:

objdir
libdir
bindir

7.5 Constituent makefiles

This section describes the most common make rules and option flags for building constituents.

Constituent make rules for rce modules

The minimal constituent.mk file for building an rce module is shown below.

ifeq ($(tgt_os),rtems)

modnames := hellomod

majorv_hellomod := 1
minorv_hellomod := 2
branch_hellomod := prod

modsrcs_hellomod := hellomod.cc

endif

The following rules are required.

Rule

Description

Example

modnames

Human-friendly module name.
Forms parts of the module
soname recorded in XXX section.

modnames := transport

modsrcs_<modname>

List source files from which the module is to be built, separated by space(s).

modsrcs_transport := main.cc open.cc

majorv_<modname>

Module major version number.
Forms parts of the module
soname.

majorv_transport := 1

minorv_<modname>

Module minor version number.
Forms parts of the module
soname.

minorv_transport := 2

branch_<modname>

Module branch identifier.
Forms parts of the module
soname.

branch_transport := test

The following optional rules define dependencies and identify include directories to be searched.

Rule

Description

Example

modsneeded_<modname>

Used to record any indirect dependencies the client module may have on other modules at run time, which the dynamic linker cannot infer.
Specify the project and soname of the required module(s). Wildcards are not allowed; the dynamic linker will insist on the specified module. Compatibility requirements can be relaxed by including an rce_isCompatible function in the client module, per Chapter X.

modsneeded_transport := \
rceusr/output.2.1.prod \
rce/core.1.1.test

Is core under rce project?

modincs_<modname>

Header file include directories for headers inside the RCE release tree.

modincs_transport := \
rce/ethernet\
rce/fci

modsinc_<modname>

Header file include directories for headers outside the RCE release tree.
Full system pathname required.

modsinc_transport :\
/usr/include/net

The following optional rules govern how static and shared object libraries appropriate for linking into an rce module at build time are themselves built and/or located for linking to the target module by gnu ld.

Rule

Description

Example

modlibs_<modname>

Names of "internal" static or shared object libraries in the repository /build/../modlib sub-tree; these libraries are to be linked into the target module at build time (as opposed to dynamically linked at run time). See Figure 6.
Identify the project, followed by the library object, omitting "lib" prefix and ".a" or ".so" suffixes.

modlibs_transport := rce/enet

modslib_<modname>

Names of "external" system or third-party static libraries to be linked into the target module at build time (as opposed to dynamically linked at run time).
Specify the full system path and end with the library object name, omitting "lib" prefix and ".a" suffix.

modslib_packet := \
/opt/lib/hdr

modlibnames

Name of an "internal" library to build; the resulting library is suitable for linking into a module at build time.
Name the library, omitting "lib" prefix and any suffix.

modlibnames := foo

libsrcs_<modlibname>

Source files to use in building an "internal" library.

libsrcs_foo := alpha.cc beta.cc

libincs_<modlibname>

Header file include directories for headers inside the RCE release tree.

libincs_foo := rce/fci

libsinc_<modlibname>

Header file include directories for headers outside the RCE release tree.
Full system pathname required.

libsinc_foo := /usr/lib/net

The following example constituents.mk file illustrates the use of these optional make rules in building an rce module, george.1.0.example, which is composed of its own compiled sources as well as two internal libraries in the fci and enet projects (libcontainer and libutil) and an external library (libmodcommon). Make instructions for the libcontainer library are included in the george makefile, and the two are built as part of the same sequence.

ifeq ($(tgt_os),rtems)

modnames := george
modsrcs_george := src/abel.cc src/baker.cc
majorv_george := 1
minorv_george := 0
branch_george := example

modsneeded_george := \
    proj1/fred.1.2.prod \
    proj2/mary.2.0.devel

modincs_george := proj1/pkg1 proj2/pkg2
modsinc_george := /group/util /usr/include/bits

modlibs_george := fci/container enet/util
modslib_george := /opt/lib/modcommon

modlibnames := container
libsrcs_foo := alpha.cc beta.cc gamma.cc
libincs_foo := proj1/pkg1
libsinc_foo := /usr/include

endif

Constituent make rules for host objects

TBW.

7.6 Packages and project makefiles

Under construction

This section describes the most common make rules and option flags for packages.mk and project.mk. See Chapter Z for definitions of all options.

Use application-specific files
projects.mk at top level
packages.mk for projects

7.7 Make examples

gmake is invoked as follows:

gmake [<pathspec>.]<targetspec>[.<action>]

Where:

  • <pathspec> is an optional argument available at the top (release) level, allowing the build to be limited to a particular project or package. See Section 7.8.1.
  • <targetspec> is a required argument defining the platform and optimization level for the build. See Section 7.8.2.
  • <action> is an optional gmake build action. See Section 7.8.3.

Build all projects and packages

When executed from the top of the release tree, gmake builds all release products for a specified target.

In the following example, gmake is used to build the complete set of linux products (objects, libraries, modules, executables) for the PPC and 386 platforms.

// change directory to top of release tree
prompt> gmake ppc-linux	
prompt> gmake i386-linux

Build individual projects or packages

TBW.

// change directory to top of release tree
prompt> gmake rce.shell.ppc-rtems-rce405

// change directory to rce
prompt> gmake shell.ppc-rtems-rce405

Compile sources for a single project and use a make rule to build libraries only

TBW.

// change directory to top of release tree
prompt> gmake rceapp.console.ppc-rtems-rce405.obj

7.8 Make invocation options

Path specification

gmake can be invoked at the release, project, or package level.

At the release level, use the path specification to limit the build to a particular project or package.

prompt> gmake rce.ppc-rtems-rce405
prompt> gmake rceapp.console.ppc-rtems-rce405

The latter is equivalent to:

prompt> cd rceapp/console
prompt> gmake ppc-rtems-rce405

Target specification

The target specification consists of up to four elements, separated by a dash. Valid specifications are defined in release/make/sw/flags.mk.

Element

Description

family

Target processor family.
Can be one of: 'i386', 'sparc', 'ppc'

OS

Target operating system.
Can be one of: 'linux', 'solaris', 'rtems'

board

Can be one of: 'rce405', 'ml405'.
Note: This element is only valid for OS 'rtems'

optimization

Compiler optimization level.
Can be one or more of: "opt", "dbg"

The set of valid target specifications is as follows.

ppc-linux
ppc-rtems-rce405
ppc-rtems-ml405
i386-linux
x86_64-linux
sparc-solaris

Make actions

Steve: If an action is not specified, then what is built?

Make action

Description

all

Build 'bin' and user-defined

dir

Create build directories, but do not build.

obj

Compile sources

lib

Build libraries from object files

bin

Build libraries, executables and modules

clean

Remove all built products

cleanall

Same as 'clean', but removes some tmp directories as well

print

List what is built and where it goes

7.9 Compiler options for rce modules

The following compiler options are invoked via /make/sw/flags.mk. They are presented here for reference.
-shared
The linker will expect each module to have a "dynamic section" and a hash table for those symbols with global visibility.
-fno-pic
Although pic saves on relocations (one per function instead of one per function call) it requires the dynamic linker to know the special relocation types needed for the Global Offset Table and the Procedure Linkage Table. The latter is especially tricky to get right. It's simpler to use non-pic and just deal with the regular relocations.
The other usual reason to use pic (that most of the code can be mapped into multiple address spaces at the same time) doesn't apply here since rtems only offers one global address space.
-nostdlib
We supply our own module _init (rce_modinit) and module _fini (rce_modfinish) code. Another reason not to use the standard _init/_fini code is that their source code was compiled with -fpic.
-nostdlib also prevents searching of the standard C++ libraries. Instead we'll want to search the symbol table of the RTEMS+newlib executable either at the time the module is produced or at run time.
-fvisiblity=hidden
A shared object actually has two symbol tables, the normal one and a special "dynamic" table. The latter is the one that is searched in order to resolve inter-object references. In the past pretty much every non-static symbol from every object code file used to make the shared object went into the dynamic table. Since GCC 4.0 the compiler recognizes the -visibility option which controls the default visibility of symbols. Using -fvisibility=hidden makes "hidden" the default. Hidden symbols don't go into the dynamic symbol table so one can dramatically reduce its size. To make sure that the symbols associated with a variable, function or class do make it into the dynamic symbol table you need to mark it with _attribute_ ((visibility ("default"))):

#define EXPORT __attribute__((visibility ("default")))
int EXPORT counter;
int EXPORT foo(int i) { ... };
class EXPORT bar { ... };

-fvisibility=hidden also hides out-of-line code generated for inline functions and other compiler-generated code.
-mlongcall
By default GCC will compile function calls into branch instructions which use 26-bit PC-relative offsets. In general this won't be adequate for inter-module calls so the compiler must be instructed to make all function calls "long" calls. These use full 32-bit addresses at the cost of some speed.

Compiler options required for rebuilding system or third-party libraries

TBW.

ifeq ($(tgt_cpu_family)-$(tgt_os),ppc-rtems)

AS  := powerpc-rtems-as
CPP := powerpc-rtems-cpp
CC  := powerpc-rtems-gcc
CXX := powerpc-rtems-g++
LD  := powerpc-rtems-ld
LX  := powerpc-rtems-g++

ifeq ($(tgt_board),rce405)
RTEMSDIR := $(RELEASE_DIR)/build/rtems/target/powerpc-rtems/rce405/lib
endif

ifeq ($(tgt_board),ml405)
RTEMSDIR := $(RELEASE_DIR)/build/rtems/target/powerpc-rtems/ml405/lib
endif

LDTOOLSD := $(RELEASE_DIR)/rce/ldtools
LIBEXTNS := a
DEPFLAGS := -B$(RTEMSDIR) -MM
DEFINES  += -Dppc405
CPPFLAGS :=
CFLAGS   := -B$(RTEMSDIR) -specs bsp_specs -qrtems -mcpu=403 -Wall
CXXFLAGS := $(CFLAGS)
CASFLAGS := -x assembler-with-cpp -P $(CFLAGS)
LDFLAGS  := -r
LXFLAGS  := -B$(RTEMSDIR) -specs $(LDTOOLSD)/dynamic_specs \
            -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/dynamic.ld \
            -mcpu=403
MANAGERS := timer sem msg event signal part region dpmem io rtmon ext mp

MDEFINES  := $(DEFINES)
             -DEXPORT='__attribute__((visibility("default")))'
MCFLAGS   := -B$(RTEMSDIR) -specs $(LDTOOLSD)/module_specs \
             -qrtems -Wall -fvisibility=hidden -mlongcall
             -fno-pic -mcpu=403
MCXXFLAGS := $(MCFLAGS)
MCASFLAGS := -x assembler-with-cpp -P $(MCFLAGS)
MLDFLAGS  := -r
MLXFLAGS  := -B$(RTEMSDIR) -specs $(LDTOOLSD)/module_specs \
             -qrtems -qnolinkcmds -Wl,-T$(LDTOOLSD)/module.ld-mcpu=403 \
             -shared -nostdlib

7.10 gnu linker options for rce modules

The following gnu ld options are invoked via /make/sw/flags.mk. They are presented here for reference.

Static linking must be done by calling ld explicitly, rather than relying on g++ to do it implicitly. The latter uses the linker option --eh-frame-hdr which causes ld to abort with an error about a "non-representable section" in the output.

-shared and -nostdlib
as for g++.
-z combreloc
Makes sure that all relocation table entries go into a single contiguous sub-region of the shared object, even if by mischance they end up in more than one output section. This option also causes the linker to sort the entries so that those reference the same symbol occur together. This allows the dynamic linker to use a one-entry symbol lookup cache.
-T scriptname
Use the custom linker script.
-Map filename
to make a link map.
-soname modulename.major.minor.branch
to set the soname field to the module's name with version numbers and development branch appended.
-o modulename.major.minor.branch.so
Module filename.
-fhash-style=sysv
to suppress generation of a GNU-style hash table.

Each module that the one being constructed depends on should be named on the linker command line so that each of their sonames will be recorded in a DT_NEEDED entry in the elf dynamic section. This defines a minimum set of compatbility requirements; compatibility requirements can be expanded by implementing an rce_isCompatible function, as described in Chapter Y.

Steve: Can set rce core comaptibility here? Is this optional, only for cases where the dependency is not direct? Won't dynalink try to resolve?

  • No labels