http://www.aros.orgAROS-ExecTeam AROSAROS-Exec Archives

Home

English

Deutsch

Ελληυικά

Français

Italiano

Nederlands

Polski

Português

Русский

Español

Suomi

Svenska

Česky


News

Archive

Introduction

Status
Screenshots
Ports
License

Download


Documentation

Users
Installation
Using
Shell commands
Applications
FAQ
Developers
Contribute
Roadmap
Bug Tracker
Working with Subversion
Compiling
Application Development Manual
Zune Application Development Manual
System Development Manual
Debugging Manual
Reference
Specifications
UI Style Guide
Documenting
Porting
Translating
Summaries
Links

Contact

Mailing lists
IRC channels

Credits

Acknowledgements


Pictures

Developers
Developers en Masse

Sponsors

Linking

Links

SourceForge Logo

AROS Application Development Manual

Index

Warning

This guide has it's last major revision begin November 2006. Changes to the build system after this date will not be reflected in this guide.

The AROS build system

Introduction

Purpose of the AROS build system

One may wonder why AROS needs a build system. The answer is that it simplifies the building of more complex binaries and takes away a lot of the manual work otherwise needed to compile, link and copy the files. Additionally this system builds a dependency tree over a big source code tree and will build the binaries in the right order so that all dependencies are fulfilled when a certain binary is built. This system also makes the source code tree modular: you can add or remove certain directories and the build system will take up these changes (of course one always has to take care one does not delete code other parts are still depending on).

Components of the build system

AROS uses several development tools in it's build system. A short list of the most important components is:

  • GNU make: the GNU version of the make program. The task of this program is to regenerate an output file from its dependencies using a user defined program like a compiler, a text processor, etc. The main advantage over a normal list of commands is that it will check if anything has changed in the source files and save time by not redoing the command not necessary.

    Familiarity with GNU make and it's input file syntax is not strictly necessary when a developer's need is covered by the high level macros discussed further in this paragraph. If this is not the case one can use GNU's makefile syntax directly. The usage of the GNU make program won't be discussed in these pages but the GNU info pages about the make program are a good source for documentation.

  • MetaMake: A make supervisor program. It can keep an overview of all makefiles which exist in subdirectories of a certain root directory. A more in depth explanation is given below.

  • genmf: (generate makefile) A macro language for makefiles. It simplifies the writing of the makefiles by providing high level macros for easy building of binary files for AROS.

  • Several other tools will be used by the build instructions. These contain AROS and non-AROS specific tools. More explanation of these tools will be given when appropriate.

To illustrate how these tools interact which each other we will explain what happens under the hood when you compile the HelloWorld program given in the previous chapter.

If you followed the tutorial for the building the program with the build system you first added the local/helloworld directory with some source files; afterwards you called make local-helloworld in the top make directory. During the execution of this command the following steps were taken:

  • The make program calls the MetaMake program with the following command mmake AROS.local-helloworld. This instructs the MetaMake program to build the local-helloworld meta-target of the AROS project. If you build from the regular AROS source tree, AROS is the one and only project known to MetaMake.
  • The first thing MetaMake does when it is started, is go over the source tree to see if there are directories added or deleted.
  • During the scanning of the directory tree MetaMake will also see if there are mmakefiles to be (re)generated. The program allows to generate a mmakefile from a mmakefile.src file. This feature is used by AROS to implement high level macros. In the helloworld example the %build_prog macro was used. If you have followed the helloworld example you can have a look at the resulting build instructions in local/helloworld/mmakefile. MetaMake also detects it if a mmakefile.src is newer then the existing mmakefile and will regenerate it.
  • A last thing MetaMake does when scanning the source tree is collect the metamake targets from all available mmakefile files and the dependency between the metamake targets. In the helloworld example the meta-target was defined as local-helloworld by passing the argument mmake=local-helloworld to the %build_prog macro. If you look in the mmakefile you can see several lines starting with #MM; these are the lines defining the meta-targets and the dependency between them. It is not necessary to understand the exact meaning of these statements to be able to use the high level build macros provided by AROS.
  • When MetaMake has gone through the source tree and collected all the information about the meta-targets it will (try to) build the specified meta-target. In the previous step the program has built a dependency tree of the meta-targets. Before building the specified meta-target it will first build the meta-targets it depends on. In our example there is not a dependency and it will directly build the program from local/helloworld by calling the GNU make program in that directory.

Build system tutorial

In this section a description is given of the most important macros for AROS application development. The purpose is not to give an in-depth discussion but enough information to be able to perform most of the application development needs. An in-depth discussion of the build tools is given in the reference section in this manual.

Basic file syntax and setup

As was seen in the helloworld example above you use the build system by putting a mmakefile.src file in the directory containing your source files. For the AROS build system to notice your file the directory containing it has to be below the AROS main source directory (the name of this top directory is most likely AROS). So for the moment you need to get hold of the AROS source code to be able to use the build system which is discussed in another chapter. A good place to put your own source code is below the AROS/local directory as was done for the helloworld example. An AROS mmakefile has to start with the following line:

include $(TOP)/config/make.cfg

...

The start line will set the environment in the makefile for AROS compilation. It has to be included because this environment is used by the metamake macros.

After this first line most of the time one or more calls to a genmf macro will follow. Such a macro has the following syntax:

%macro param1=... param2=... ...

When the mmakefile.src file is translated into a mmakefile file the line above will be replaced with make commands defined by the macro. A macro is called by it's name followed by zero or more parameters with an optional value assigned to the parameter. The order of the parameters is not important and not all parameters defined by a macro have to get values; a default value will be used when a parameter is not provided. Some parameters may be mandatory and an error message will be generated when it is left out.

One macro call can be spread over several lines by ending a line with a backslash and continue the macro on the next line. So the example macro call could have been written also as:

%macro \
    param1=... \
    param2=... \
    ...

Normally no spaces are allowed in the values given to a parameter, if that is needed one has to enclose the list by double quotes (").

In the following chapters the most important high level commands will be discussed. Only the most important parameters for the macros will be discussed, a list and description of all parameters of a macro will be given in the reference section.

Building an AROS program

You can build a program by using the following macro in your mmakefile.src file:

%build_prog mmake=MetaTarget progname=Prog files=SourceFiles

This will build a program named Prog from the list of SourceFiles. By giving the mmake argument the MetaMake program will see that this program can be built by MetaTarget; e.g. doing make MetaTarget in the top AROS source directory will build the program. When typing this command also the dependencies will be built every time you want to recompile this module. Additionally a MetaTarget-quick meta-target will be defined that allows to build the program without that the dependencies will be rebuilt, this can save time when you are changing the source code of a program and want to rebuild it often.

The list of files SourceFiles are the name of the C input files without the .c suffix. As explained above this list has to be enclosed by double quotes if it contains more then one file.

By default the program will be put in the AROS binary tree in the same subdirectory from the top directory as the subdirectory relative where the source files are put into the source code tree. You can change this directory by specifying the targetdir=... argument. The latter argument has to contain a full path so most of the time it will start with $(AROSDIR)/ to put the program somewhere in the binary AROS tree. So if you want to put the program in the Extras directory you can do it this way:

%build_prog ... targetdir=$(AROSDIR)/Extras

As explained above the argument to a macro has to be enclosed by quotation marks if it contains more then one file. Currently the list can't be split over more then one line and often make variables are used to pass the list of files to build. The next three examples do the same only with different syntax. First the in-line list version:

%build_prog \
    mmake=myprog progname=MyProg \
    files="file1 file2 file3"

Now with using a make variable:

FILES := file1 file2 file3

%build_prog \
    mmake=myprog progname=MyProg \
    files=$(FILES)

Or with using the make line continuation:

FILES := \
    file1 \
    file2 \
    file3

%build_prog \
    mmake=myprog progname=MyProg \
    files=$(FILES)

Building an AROS library

Another type of binary often built for AROS is a shared library. First a basic skeleton will be given of how to build a library then some handy extensions are given.

Basic library skeleton

A shared library is built with the %build_module macro with a line like this:

%build_module mmake=MetaTarget modname=mylib modtype=library files=SourceFiles

This macro can build different AROS module types like devices, Zune classes, HIDDs, ... but we'll focus here on a shared library and therefor we assume that you specify the modtype=library parameter.

The mmake and the files parameter act the same as for the %build_prog macro. Additionally to the meta-target MetaTarget and MetaTarget-quick, also meta-targets MetaTarget-includes, MetaTarget-includes-quick and MetaTarget-linklib are defined. This allows to only build a subset of all the files normally generated. They will most of the time be used to specify dependencies.

For building a shared library more information is necessary then given in the %build_module macro. This information is stored in another file that by default is called mylib.conf when modname=mylib is specified. This file can contain a lot of information but we'll give here a minimal example. More information can be found in the reference section of the %build_module macro. Here is an example .conf file:

##begin config
version 1.0
##end config

##begin functionlist
void func1(LONG a, LONG b)
int func2(char *s, ULONG a)
##end functionlist

As you can see this is a file with two sections, each section starting with ##begin sectionname and ending with ##end sectionname. The section config is for providing the information needed by AROS when it wants to use the shared library about the library and for giving options to influence the type of module that will be build. In-depth discussion can be found in the reference section. The functionlist section gives a list of functions that will be included in the library and the list consist of the function prototypes. The order of the list is important because it will determine the place of the function in the lookup table. Also empty lines are important because an empty line in the functionlist will cause an empty slot in the table. Comment lines start with one '#' character and these lines will be ignored and do not give rise to an empty slot in the library's table.

If all this information is present and you then execute the command make MetaTarget the following file will be generated ($(AROSDIR) corresponds with the directory for the binary tree):

  • $(AROSDIR)/Libs/mylib.library: the module itself
  • several include files in $(AROSDIR)/Development/include with the main include file proto/mylib.h. The latter file can be included in code using the library for the function prototypes.
  • $(AROSDIR)/Development/lib/libmylib.a: a static link library that can be linked to other code and that can take care of auto-opening the library and contains stub functions. When these functions are called it will redirect to the code in the library using the lookup table in the libbase.

Using non-standard types

In the example given above standard C variable type or standard exec types were used for the arguments of the function. If you want to use your own types or types defined in other include files you will need to take extra steps. This can be done in the cdef section as shown in the next example where another include file is used:

##begin config
...
##end config

##begin cdef
#include <exec/semaphores.h>
##end cdef

##begin functionlist
...
BOOL func3(struct SignalSemaphore *sig)
##end functionlist

The lines in the cdef structures are normal C code and they will be part of the generated include files before the library's function prototypes. You could also define your own structure like this:

##begin cdef
struct MyStruct
{
    ...
};
##end cdef

##begin functionlist
...
int func4(struct MyStruct *sig)
##end functionlist

When doing it this way the structure definition will be part of the generated include files. The recommended way to do it in AROS is to do the definition in a separate header file and then include that header file. One way to do it is to define your own file named libraries/mylib.h with the following contents:

#ifndef __LIBRARIES_MYLIB_H
#define __LIBRARIES_MYLIB_H

struct MyStruct
{
    ...
};

...

#endif /* __LIBRARIES_MYLIB_H */

This file is then copied as explained in another paragraph and then simply included by the cdef section:

##begin cdef
#include <libraries/mylib.h>
##end cdef

Functions with m68k register passing

The functions put into the library vector table up to now were regular C functions. In the amiga m68k days the parameters for library functions most of the time were passed in registers and not on the stack. For backwards compatibility you can also define functions where the arguments are passed in m68k registers. When your library is compiled for m68k it will use the specified registers, on other architectures own conventions will be used by either using registers available on that CPU or using stack based argument passing. Defining a function with m68k registers has to be done by adding the registers to the line in the function list and use macros for the header of the function in the source code. The line in the functionlist looks as follows:

##begin functionlist
...
ULONG func5(ULONG a, STRPTR b) (D0,A0)
...
##end functionlist

And the function in the source code is defined as follows:

AROS_LH2(ULONG, func5,
    AROS_LHA(ULONG, a, D0),
    AROS_LHA(STRPTR, b, A0),
    struct Library *, MylibBase, 9, Mylib
)
{
      AROS_LIBFUNC_INIT

    ...

    AROS_LIBFUNC_EXIT
}

This macro has the name AROS_LHn with n the number of arguments passed to the function. The macros has the following arguments:

  • The function return type
  • The name of the function
  • The list of function arguments using the AROS_LHA(vartype, varname, register) macro. vartype is the type of the argument, varname is the name of the argument and register the m68k register to use. The register is specified as D0-D7 for numeric arguments and A0-A5 for pointer arguments (A6 and A7 are reserved for other use).
  • The library base type. When you have not defined your own libbase type as explained in this paragraph
  • The variable for the libbase, this can be used in the function for accessing the libbase
  • The number of the vector in the vector table. For libraries the first function in the functionlist has number 5, the next 6 and so on. Although this information is not necessary because the functionlist in the .conf already determines this number it still has to be given for legacy reasons.
  • The base name of the library. If this is not overridden in the config section of the .conf file it is equal to the name given to the modname parameter with the first letter capitalized.

Using an extended libbase

On AROS and other amiga-like systems every shared library has a library base. The base of a library contains the vector table and some data about the library used by the OS. It can also be extended with user defined data. This can be done by providing your own C struct for the type of the libbase. There are two config options that let you decide the type of the libbase:

##begin config
...
libbasetype struct MyLibIntBase
libbasetypeextern struct MyLibBase
...
##end config

libbasetype is the type used internal in the library code, this type also decides how much memory is allocated for the libbase. If this type is not given struct Library is taken as default. libbasetypeextern is the type by external programs using your library. If not given also here struct Library is used as the type. Both the internal and the external type have to start with a struct Library structure. If the external type is given the first part of the internal type has to be the same as the external type.

For keeping your library backwards compatible one can not change the external type of a library. You can only extend it once you have released a version of your library into the public. The internal type can be changed at will when all internal code of your library is adapted to the changes of the internal library structure.

The external type also has be exported to the users of your library. This is the same as the usage of other non-standard types. On the contrary, the internal type oftentimes is not meant to be exported to the users, for this reason a cdefprivate section can be put in the config file. This way the library initialization code has all the information about your internal type without having the internal structure publicly exported. A common convention is to declare your internal structures in mylib_intern.h and then include this in the cdefprivate section. The mylib_intern.h would then include the following code:

struct MyLibIntBase
{
    struct Library base;

    ...
};

And the config file the following section:

...
##begin cdefprivate
#include "mylib_intern.h"
##end cdefprivate
...

Using a per-opener libbase

Up to now only one libbase would be created for a library. All users who open the library get a pointer to the same library base. Sometimes one wants to have data that is different per opener of the library. This can be done by using a special option in the config section:

##begin config
...
options peropenerbase
##end config

The use of a base per opener of the library does not make much sense when not using an extended libbase. At the moment also the only way to pass the libbase to the functions of the library is by using m68k register passing. (Development is underway to also be able to get the libbase in library functions using the normal C argument passing). You could also add the libbase as an explicit argument to the function but this is not encouraged.

Note

On AROS the need for extended libbases is much less then on classic AmigaOS. On classic AmigaOS it was discouraged to use global variables in the library and to use the libbase for storing variables. On AROS global variables are handled fine so the use of an extended libbase is only needed for using a per-opener libbase.

Library initialization

Sometimes you want to perform initialization when your library is loaded or when it is opened. You can use the same mechanism as for programs through the ADD2INIT and ADD2EXIT as in the next example:

static int InitFunc(void)
{
    ...
}

static void ExitFunc(void)
{
    ...
}

ADD2INIT(InitFunc, 0);
ADD2EXIT(ExitFunc, 0);

When you add this code in one of your source files the code in InitFunc will be executed when the library is initialized and the code in ExitFunc when the library is expunged. The return value of InitFunc indicates succes or failure, when it returns a zero (== FALSE) value it indicates a failure to initialize and the library will be unloaded again and not be usable. The ExitFunc may not fail and thus has no return value.

Often one wants to initialize part of the libbase and therefor the methods discussed above are not appropriate. For libraries additional ways are available for adding initialization or clean-up code:

static int InitFunc(struct Library *lh);
ADD2INITLIB(InitFunc, 0);

static int ExpungeFunc(struct Library *lh);
ADD2EXPUNGELIB(ExpungeFunc, 0);

static int OpenFunc(struct Library *lh);
ADD2OPENLIB(OpenFunc, 0);

static void CloseFunc(struct Library *lh);
ADD2CLOSELIB(CloseFunc, 0);

The InitFunc function will be called once during initialization and the ExpungeFunc once during expunge of the module. OpenFunc and CloseFunc functions are called resp. everytime the modules is opened or closed. InitFunc, ExpungeFunc and OpenFunc return a value indicating the success of the function. If InitFunc fails the module will be expunged, if OpenFunc fails the opening of the library will fail and if ExpungeFunc fails expunging the library will be delayed. If the latter happens the next time the expunge will be tried all registered functions for expunge will be called again. This means that if more then one function is registered and the second function returns 0, the first function will be called a second time the next time AROS tries to expunge the module. If you implement an ExpungeFunc that can return a 0 you also have to be sure that other ExpungeFuncs may be called more then once.

If you look at the ADD2...LIB macros above you can also see that next to the function name there is an extra number. This number indicates the priority to call the function. InitFunc and OpenFunc with a higher number will be called after the ones with a lower number. For CloseFunc and ExpungeFunc the opposite order is used, e.g. higher numbers are called before lower numbers. The number is a signed byte, which means it has to have a value from -127 to 128. Most often this value can be kept at 0.

If a per-opener base is used a copy will be made of your libbase every time the module is opened. InitFuncs will be called before the copy so initialization of values in the libbase will be seen by all the openers. OpenFuncs are called after the copy of the libbase and changes made to libbase are thus private to the opener.

Copying include files

Often when writing a library extra includes have to be provided that can be included by the programs using your library by using #include <...> in the code. For this purpose a copy_includes macro is available. In the following line the arguments are given for the macro with the default values:

%copy_includes mmake=includes-copy includes=$(INCLUDE_FILES) path=. dir=

Here follows an explanation of the arguments and after that some examples will be given:

  • Similar to the macros earlier in this document, the mmake argument indicates the meta-target that will copy the includes. The default value is includes-copy so if the argument is not specified the includes will be copied by this meta-target.
  • includes: these are the files to be copied in the system include directory. It may be a list that contains files in subdirectories. By default $(INCLUDE_FILES) is used. This means that you can put the list of the files to copy in the INCLUDE_FILES make variable.
  • path: this argument allows you to copy the includes in a subdirectory of the system include directory. This name is added in front of the include files before they are copied so that the path is added in the include statement e.g. #include <path/...>
  • dir: this argument allows to strip a directory from the include files list before they are copied to the system include directory. This is often used to put the include files in a subdirectory called include. By then specifying the argument dir=include the include files are copied from this subdirectory but to a path in the system directory not containing the include directory.

Some examples to make this more clear:

  • Example 1: copy the *.h files from the current directory to the system include directory:

    INCLUDE_FILES := $(wildcard *.h)
    %copy_includes mmake=MyIncludes
    
  • Example 2: copy the mylib.h file to the libraries directory:

    %copy_includes mmake=MyLib-includes includes=mylib.h path=libraries
    

    The programs can then use #include <libraries/mylib.h> to access your include file.

  • Example 3: copy files from the include subdirectory to the system include directory:

    INCLUDE_FILES := $(wildcard include/*.h)
    %copy_includes mmake=MyIncludes dir=include
    

    If then a file include/myinclude.h is available the programs may not use #include <include/myinclude.h> but #include <myinclude.h> instead.

Using non-core libraries in programs or libraries

Before programs or other libraries can use another library that is not part of the core AROS libraries they have to add it to the list of libraries to use by using the uselibs argument for the %build_prog or the build_module macro. So if you want your program to use the mylib library you have to do it like this:

%build_prog ... uselibs=mylib

For a library it looks the same:

%build_module ... uselibs=mylib

Build system reference

Warning

This reference manual is out of date and things have changed considerably. Please consult config/make.tmpl in the source code tree to see the current implementation. If you want to help updating this section, please contact us.

MetaMake

Introduction

MetaMake is a version of make which allows to recursively build targets in the various directories of a project or even another project. It searches a directory tree for makefiles and all makefiles it finds for "metatargets". Then it tries to build all metatargets. You can also specify a program which converts "source" makefiles into makefiles before MetaMake will invoke make.

Syntax of the makefile

MetaMake uses normal makefile syntax but gives a special meaning to a comment line that starts with #MM. This line is used to define so called metatargets. The name of the makefile itself is defined in the MetaMake config file that is discussed in one of the following sections.

There exist three ways of defining a metatarget in a makefile:

  • This defines a metatarget with its metaprerequisites:

    #MM metatarget : metaprerequisites
    

    When a user asks to build this metatarget, first the metaprerequisites will be build as metatargets and afterwards the given metatarget.

    This form also indicates that in this makefile also a makefile target is present with the same name. This makefile target has to be defined, yet.

  • This is the same definition as in the previous paragraph, but now no normal make target is present in the makefile with the same name as the metatarget. Using this 'virtual' metatargets speeds up the build because make isn't called with this target:

    #MM- metatarget : metaprerequisites
    
  • This form defines both a metatarget and a make target with the same name. The prerequisites are no metaprerequisites:

    #MM
    metatarget : prerequisites
    

The line for the definition of a metatarget can be spread over several lines if you end every line with the \ character and start the next line with #MM.

You can define a metatarget with the same name in several files. The metaprerequisites are then collected.

If a metatarget is defined both with #MM and #MM- the #MM has priority.

How MetaMake works

MetaMake is run by calling make in the root directory of the AROS source tree.

At first MetaMake will build up a tree of all the makefiles present in a root directory and all subdirectories. At the same time it will also build a tree of all the metatargets and their dependencies.

Next it will build all the metaprerequisites needed for this metatarget and then finally the metatarget itself. Actually someone can look at it that every metaprerequisite becomes a metatarget when it needs to be build. For each of these metatargets a walk through of all the directories is done. In every makefile where the metatarget is defined by the first or third way from the previous section make is called with the name of the target as a make target.

When MetaMake calls normal make also two variables are defined. $(TOP) has the value of the root directory and $(CURDIR) the path relative to this root directory.

Metatargets which aren't a prerequisite of another target aren't build by default. If you want to build such a metatarget you have to type make metatarget in the root directory of the AROS source tree.

Autogenerated makefiles

Another feature of MetaMake is automatic generating a makefile from a source makefile. When the directory tree is scanned for all the makefiles in every directory it is checked if a makefile is present with a .src suffix added. If it is there and is newer than the makefile present in that directory a script will be called to regenerate the makefile from the source makefile. What script has to be called is defined in the configuration file.

Examples

The next few examples are taken from the AROS project.

Example 1: normal dependencies
#MM contrib-regina-module : setup linklibs includes contrib-regina-includes

This example says that in this makefile a contrib-regina-module is present that has to be build. Before building this metatarget first the metatargets setup, linklibs, ... have to be build; this ensures that the includes, linklibs etc. have to be present before this module can be build.

Example 2: metatarget consisting of submetatargets
#MM- contrib-freetype : contrib-freetype-linklib \
#MM      contrib-freetype-graph \
#MM      contrib-freetype-fonts \
#MM      contrib-freetype-demos

Here actually is said that the contrib-freetype metatarget requires building of linklib, graph, fonts and demos of freetype. If some extra work needs to be done in the makefile where this metatarget is, the definition can start with #MM and a normal make target contrib-freetype has to be present in the makefile.

Also the use of the line continuation for the metatarget definition is shown here.

Example 3: Quick building of a target
#MM workbench-utilities : includes linklibs setup-clock-catalogs
#MM
workbench-utilities-quick : workbench-utilities

When a user executes MetaMake with as argument workbench-utilities make will be called in all the directories where the metaprerequisites are present in the makefile. This can become quite annoying when debugging programs. When now the second metatarget workbench-utilities-quick is defined as shown above only that target will be build in this directory. Of course the user has then to be sure that the metatargets on which workbench-utilities depend are up-to-date.

Configuration file

The MetaMake configuration file has the path $(TOP)/mmake.config. A short explanation of its content:

[AROS]
Begins a config section for the project AROS
maketool $(HOST_MAKE) $(MKARGS) TOP=$(TOP) CURDIR=$(CURDIR) TARGET=$(TARGET)
Specifies the name of the tool to build a target. This is usually make.
defaultmakefilename mmakefile
This defines mmakefile as name for MetaMake makefiles.
genmakefilescript $(GENMF) $(TOP)/config/make.tmpl --listfile $(MMLIST)
MetaMake allows to generate makefiles with a script. The makefile will be regenerated if it doesn't exist, if the source file is newer or if the file specified with genmakefiledeps is newer. The name of the source file is generated by concatenating defaultmakefilename and ".src"
genmakefiledeps $(GENMF) $(TOP)/config/make.tmpl
If this file is newer than the makefile, the given script will be executed.
globalvarfile $(TOP)/bin/$(AROS_HOST_ARCH)-$(AROS_HOST_CPU)/gen/config/host.cfg
MetaMake will read this file and every variable in this file will be available everywhere where you can use a variable.
genglobalvarfile sh $(TOP)/configure
This defines a script to regenerate the globalvarfile.
ignoredir ...
This tells MetaMake to ignore these directories.

Genmf

Introduction

Genmf uses two files for generating a makefile. First is the macro definition file and finally the source makefile (mmakefile.src) where these macros can be used. The macros for AROS are in the file $(TOP)/config/make.tmpl.

Syntax

In general the % character is used as the special character for genmf source makefiles.

Macro definition

A macro definition has the following syntax:

%define macroname option1[=[default][\A][\M]] option2[=[default][\A][\M]] ...
...
%end

macroname is the name of the macro. option1, option2, ... are the arguments for the macro. These options can be used in the body of this template by typing %(option1). This will be replaced be the value of option1.

The argument can be followed by a default value. If no default value is specified an empty string is taken. Normally no spaces are allowed in the default value of an argument. If this is needed this can be done by surrounding the value with double quotes (").

Also two switches can be given:

\A
Is the switch to always need a value for this. When the macro is instantiated always a value needs to be assigned to this argument.
\M
Is the switch to turn on multi words. This means that all the words following this argument will be assigned to this argument. This also means that after the use of such an argument no other argument can be present because it will become part of this argument.
Macro instantiation

The instantiation of the macro is done by using the '%' character followed by the name of the macro to instantiate (without round brackets around it):

%macro_name [option1=]value [option2=]value

Two ways are possible to specify value for arguments to a macro:

value
This will assign the first value to the first argument, the second value to the second argument and so on.
option1=value
This will assign the given value to the option with the specified name.

When giving values to arguments also double quotes need to be used if someone wants to include spaces in the values of the arguments.

Macro instantiation may be used inside the body of a macro, even macros that will only be defined later on in the macro definition file.

Note

In the definition of the genmf rules sometimes MetaMake variables are used as default variables for an argument (e.g. dflags=%(cflags)). This is not really possible in the definition file but is done by using text that has the same effect.

AROS application development macros reference

High level mmakefile.src macros

AROS standard metamake targets

The following metatargets are often used as prerequisite:

  • includes: the *.h files
  • linklibs: static linker libraries

FIXME: complete

Note

These mega metamake targets were introduced in the beginning of the project. The usage of these metatargets is now considered as deprecated and should be avoided.

One should try to use more specific targets for dependencies, e.g. if a certain program uses a certain library one should specify this library as a dependency of this program not all the linklibs by using the linklibs metatarget.

Building programs

There are two macros for building programs. One macro %build_progs that will compile every input file to a separate executable and one macro %build_prog that will compile and link all the input files into one executable.

%build_progs

This macro will compile and link every input file to a separate executable and has the following definition:

%define build_progs mmake=/A files=/A \
    objdir=$(GENDIR)/$(CURDIR) targetdir=$(AROSDIR)/$(CURDIR) \
    cflags=$(CFLAGS) dflags=$(BD_CFLAGS$(BDID)) ldflags=$(LDFLAGS) \
    uselibs= usehostlibs= usestartup=yes detach=no

With the following arguments:

mmake=/A
This is the name of the metatarget that will build the programs. Also a %(mmake)-quick metatarget will be defined.
files=/A
The basenames of the C source files that will be compiled and linked to executables. For every name present in this list an executable with the same name will be generated.
objdir=$(GENDIR)/$(CURDIR)
The directory where the compiled object files will be put.
targetdir=$(AROSDIR)/$(CURDIR)
The directory where the executables will be placed.
cflags=$(CFLAGS)
The flags to add when compiling the .c files. By default the standard AROS cflags (the $(CFLAGS) make variables are taken. This also means that some flags can be added by assigning these to the USER_CFLAGS and USER_INCLUDES make variables before using this macro.
dflags=%(cflags)
The flags to add when doing the dependency check. Default is the same as the cflags.
ldflags=$(LDFLAGS)
The flags to use when linking the executables. By default the standard AROS link flags will be used.
uselibs=

A list of static libraries to add when linking the executables. This is the name of the library without the lib prefix or the .a suffix and without the -l prefix for the use in the flags for the C compiler.

By default no libraries are used when linking the executables.

usehostlibs=

A list of static libraries of the host to add when linking the executables. This is the name of the library without the lib prefix or the .a suffix and without the -l prefix for the use in the flags for the C compiler.

By default no libraries are used when linking the executables.

usestartup=yes
Use the standard startup code for the executables. By default this is yes and this is also what someone wants most of the time. Only disable this if you know what you are doing.
detach=no
Whether the executables will run detached. Defaults to no.
%build_prog

This macro will compile and link the input files to an executable and has the following definition:

%define build_prog mmake=/A progname=/A files=%(progname) asmfiles= \
    objdir=$(GENDIR)/$(CURDIR) targetdir=$(AROSDIR)/$(CURDIR) \
    cflags=$(CFLAGS) dflags=$(BD_CFLAGS$(BDID)) ldflags=$(LDFLAGS) \
    aflags=$(AFLAFS) uselibs= usehostlibs= usestartup=yes detach=no

With the following arguments:

mmake=/A
This is the name of the metatarget that will build the program. Also a %(mmake)-quick metatarget will be defined.
progname=/A
The name of the executable.
files=
The basenames of the C source files that will be compiled and linked into the executable. By default just the name of the executable is taken.
asmfiles=
The assembler files to assemble and include in the executable. By default no asm files are included in the executable.
objdir=$(GENDIR)/$(CURDIR)
The directory where the compiled object files will be put.
targetdir=$(AROSDIR)/$(CURDIR)
The directory where the executables will be placed.
cflags=$(CFLAGS)
The flags to add when compiling the .c files. By default the standard AROS cflags (the $(CFLAGS) make variable) are taken. This also means that some flags can be added by assigning these to the USER_CFLAGS and USER_INCLUDES make variables before using this macro.
dflags=%(cflags)
The flags to add when doing the dependency check. Default is the same as the cflags.
aflags=$(AFLAGS)
The flags to add when compiling the asm files. By default the standard AROS aflags (e.g. $(AFLAGS)) are taken. This also means that some flags can be added by assigning these to the SPECIAL_AFLAGS make variable before using this macro.
ldflags=$(LDFLAGS)
The flags to use when linking the executable. By default the standard AROS link flags will be used.
uselibs=

A list of static libraries to add when linking the executable. This is the name of the library without the lib prefix or the .a suffix and without the -l prefix for the use in the flags for the C compiler.

By default no libraries are used when linking the executable.

usehostlibs=

A list of static libraries of the host to add when linking the executable. This is the name of the library without the lib prefix or the .a suffix and without the -l prefix for the use in the flags for the C compiler.

By default no libraries are used when linking the executable.

usestartup=yes
Use the standard startup code for the executables. By default this is yes and this is also what someone wants most of the time. Only disable this if you know what you are doing.
detach=no
Whether the executable will run detached. Defaults to no.

Common

%define common

This adds some common stuff like a clean target to the makefile. The clean target only deletes generated makefiles.

Building catalogs

The definition of the macro is as follows:

%define build_catalogs mmake=/A name=/A subdir=/A \
  catalogs="$(basename $(wildcard *.ct))" source="../strings.h" \
  description="$(basename $(wildcard *.cd))" dir=$(AROS_CATALOGS) \
  sourcedescription="$(TOOLDIR)/C_h_orig"

With the meaning of the arguments as follows:

mmake=/A
This is the name of the metatarget that will build the catalogs. Also a %(mmake)-clean metatarget will be defined.
name=/A
This is the name of the destination catalog, without the .catalog suffix.
subdir=A
This is the destination subdir of the catalogs.
catalogs
This is the list of catalogs, without the .ct suffix (default *.ct)
source
This is the path to the generated source code file. The default value creates the file strings.h in the parent directory. Remember that generated files must not be committed to SVN.
description
This is the catalog description file (.cd) (default *.cd).
dir
This is the base destination directory (default $(AROS_CATALOGS)).
sourcedescription
This is the path to the FlexCat's source description file, without the .sd suffix.

Example:

%build_catalogs mmake=workbench-system-wanderer-tools-info-catalogs \
name=Info subdir=System/System/Wanderer/Tools

Building icons

Creates icons. The images must be in PNG or ILBM format. The icon is configured from an additional text file with the name %(iconname).info.src. You can find the documentation of this file in $(TOP)/tools/ilbmtoicon/README

The definition of the macro is as follows:

%define build_icons mmake=/A icons=/A dir=/A

With the meaning of the arguments as follows:

mmake
This is the name of the metatarget. Also a %(mmake)-clean metatarget will be defined.
icons
This is a list of icon base names (without the .info suffix).
dir
This is the destination directory.

Example:

%build_icons mmake=workbench-system-wanderer-tools-newdrawer-icons \
icons=newdrawer dir=$(AROS_WANDERER)/Tools

The definition file has the name newdrawer.info.src.

Building static linklibraries

Building link libraries is straight forward. A list of files will be compiled or assembled and collected in a link library into a specified target directory.

The definition of the macro is as follows:

%define build_linklib mmake=/A libname=/A files="$(basename $(wildcard *.c)) \
  asmfiles= cflags=$(CFLAGS) dflags=%(cflags) aflags=$(AFLAGS) \
  objdir=$(OBJDIR) libdir=$(LIBDIR)

With the meaning of the arguments as follows:

mmake=/A
This is the name of the metatarget that will build the linklib.
libname=/A
The base name of the library to generate. The file that will be generated will be called lib%(libname).a
files=$(basename $(wildcard *.c))
The C files to compile and include in the library. By default all the files ending in .c in the source directory will be used.
asmfiles=
The assembler files to assemble and include in the library. By default no asm files are included in the library.
cflags=$(CFLAGS)
The flags to use when compiling the .c files. By default the standard AROS cflags (e.g. $(CFLAGS)) are taken. This also means that some flags can be added by assigning these to the USER_CFLAGS and USER_INCLUDES make variables before using this macro.
dflags=%(cflags)
The flags to add when doing the dependency check. Default is the same as the cflags.
aflags=$(AFLAGS)
The flags to add when compiling the asm files. By default the standard AROS aflags (e.g. $(AFLAGS)) are taken. This also means that some flags can be added by assigning these to the SPECIAL_AFLAGS make variable before using this macro.
objdir=$(OBJDIR)
The directory where to generate all the intermediate files. The default value is $(OBJDIR) which in itself is by default equal to $(GENDIR)/$(CURDIR).
libdir=$(LIBDIR)
The directory to put the library in. By default the standard library directory $(LIBDIR) will be used.

Building modules

Building modules consists of two parts. First is a macro to use in mmakefile.src files. Another is a configuration file that describes the contents of the module.

The mmakefile.src macro

This is the definition header of the build_module macro:

%define build_module mmake=/A modname=/A modtype=/A            \
  conffile=%(modname).conf files="$(basename $(wildcard *.c))" \
  cflags=$(CFLAGS) dflags=%(cflags) objdir=$(OBJDIR)           \
  linklibname=%(modname) uselibs=

Here is a list of the arguments for this macro:

mmake=/A
This is the name of the metatarget that will build the module. Also a %(mmake)-quick and %(mmake)-clean metatarget will be defined.
modname=/A
This is the name of the module without the suffix.
modtype=/A
This is the type of the module and corresponds with the suffix of the module. At the moment only library, mcc, mui and mcp are supported. Support for other modules is planned in the future.
conffile=%(modname).conf
The name of the configuration file. Default is modname.conf.
files="$(basename $(wildcard *.c))"
A list of all the C source files without the .c suffix that contain the code for this module. By default all the .c files in the current directory will be taken.
cflags=$(CFLAGS)
The flags to use when compiling the .c files. By default the standard AROS cflags (e.g. $(CFLAGS)) are taken. This also means that some flags can be added by assigning these to the USER_CFLAGS and USER_INCLUDES make variables before using this macro.
dflags=%(cflags)
The flags to add when doing the dependency check. Default is the same as the cflags.
objdir=$(OBJDIR)
The directory where to generate all the intermediate files. The default value is $(OBJDIR) which in itself is by default equal to $(GENDIR)/$(CURDIR).
linklibname=%(modname)

The name to be used for the static link library that contains the library autoinit code and the stubs converting C stack calling convention to a call off the function from the library functable with the appropriate calling mechanism. These stubs are normally not needed when the AROS defines for module functions are not disabled.

There will always be a file generated with the name $(LIBDIR)/lib%(linklibname).a and by default linklibname will be the same as modname.

uselibs=

A list of static libraries to add when linking the module. This is the name of the library without the lib prefix or the .a suffix and without the -l prefix for the use in the flags for the C compiler.

By default no libraries are used when linking the module.

The module configuration file

The module configuration file is subdivided in several sections. A section is defined with the following lines:

## begin sectionname
...
## end sectionname

The interpretation of the lines between the ##begin and ##end statement is different for every section. The following sections are defined:

  • config

    The lines in this section have all the same format:

    optionname string
    

    with the string starting from the first non white space after optionname to the last non white space character on that line.

    A list of all the options available:

    basename

    Followed by the base name for this module. This will be used as a prefix for a lot of symbols. By default the modname specified in the makefile is taken with the first letter capitalized.

    libbase

    The name of the variable to the library base in. By default the basename will be taken with Base added to the end.

    libbasetype

    The type to use for the libbase for use internally for the library code. E.g. the sizeof operator applied to this type has to yield the real size of the object. Be aware that it may not be specified as a pointer. By default 'struct LibHeader' is taken.

    libbasetypeextern

    The type to use for the libbase for code using the library externally. By default 'struct Library' is taken.

    version

    The version to compile into the module. This has to be specified as major.minor. By default 0.0 will be used.

    date

    The date that this library was made. This has to have the format of DD.MM.YYYY. As a default 00.00.0000 is taken.

    libcall

    The argument passing mechanism used for the functions in this module. It can be either 'stack' or 'register'. By default 'stack' will be used.

    forcebase

    This will force the use of a certain base variable in the static link library for auto opening the module. Thus it is only valid for module that support auto opening. This option can be present more then once in the config section and then all these base will be in the link library. By default no base variable will be present in the link library.

  • cdef

    In this section all the C code has to be written that will declare all the type of the arguments of the function listed in the function. All valid C code is possible including the use of #include.

  • functionlist

    In this section are all the functions that are externally accessible by programs.

    For stack based argument passing only a list of the functions has to be given. For register based argument passing the names of the register have to be given between rounded brackets. If you have function foo with the first argument in D0 and the second argument in A0 it gives the following line in in the list:

    foo(D0,A0)
    

Compiling arch and/or CPU specific files

In the previous paragraph the method was explained how a module can be build with the AROS genmf macros. Sometimes someone wants to replace certain files in a module with an implementation only valid for a certain arch or a certain CPU.

The macro definition

Arch specific files are handled by the macro called %build_archspecific and it has the following header:

%define build_archspecific mainmmake=/A maindir=/A arch=/A files= asmfiles= \
cflags=$(CFLAGS) dflags=%(cflags) aflags=$(AFLAGS) compiler=target

And the explanation of the argument to this macro:

mainmmake=/A
The mmake of the module from which someone wants to replace files or to which to add additional files.
maindir=/A
The directory where the object files of the main module are stored. The is only the path relative to $(GENDIR). Most of the time this is the directory where the source files of the module are stored.
arch=/A
The architecture for which these files needs to be build. It can have three different forms ARCH-CPU, ARCH or CPU. For example when linux-i386 is specified these files will only be build for the linux port on i386. With ppc it will be build for all ppc processors and with linux it will be build for all linux ports.
files=
The basenames of the C source files to replace add to the module.
asmfiles=
The basenames of the asm source files to replace or add to the module.
cflags=$(CFLAGS)
The flags to add when compiling the .c files. By default the standard AROS cflags (the $(CFLAGS) make variables are taken. This also means that some flags can be added by assigning these to the USER_CFLAGS and USER_INCLUDES make variables before using this macro.
dflags=%(cflags)
The flags to add when doing the dependency check. Default is the same as the cflags.
aflags=$(AFLAGS)
The flags to add when assembling the asm files. By default the standard AROS cflags (the $(AFLAGS) make variable) are taken. This also means that some flags can be added by assigning these to the SPECIAL_AFLAGS make variable before using this macro.
compiler=target
Indicates which compiler to use during compiling C source files. Can be either target or host to use the target compiler or the host compiler. By default the target compiler is used.
Code shared by different ports

A second macro called %rule_archalias allows to create a virtual architecture. And code for that virtual architecture is shared between several architectures. Most likely this is used for code that uses an API that is shared between several architecture but not all of them.

The macro has the following header:

%define rule_archalias mainmmake=/A arch=/A alias=/A

With the following arguments

mainmmake=/A
The mmake of the module from which someone wants to replace files or to which to add additional files.
arch=/A
The arch someone wants to make alias from.
alias=/A
The arch someone wants to alias to.
Examples
  1. This is an extract from the file config/linux/exec/mmakefile.src that replaces the main init.c file from exec with a linux specialized one:

    %build_archspecific \
      mainmmake=kernel-exec maindir=rom/exec arch=linux \
      files=init compiler=host
    
  2. For the dos.library some arch specific files are grouped together in the unix arch. The following lines are present in the several mmakefiles to make this possible

    In config/linux/mmakefile.src:

    %rule_archalias mainmmake=kernel-dos arch=linux alias=unix
    

    In config/freebsd/mmakefile.src:

    %rule_archalias mainmmake=kernel-dos arch=freebsd alias=unix
    

    And finally in config/unix/dos/mmakefile.src:

    %build_archspecific \
      mainmmake=kernel-dos maindir=rom/dos \
      arch=unix \
      files=boot \
      compiler=host
    

The file $(TOP)/config/make.tmpl contains more macros. See the comments in that file for usage.

AROS portable makefile variables

The file $(TOP)/config/make.cfg is usually included in all makefiles. It contains a lot of variables which are often used in this makefiles. The most important are the absolute paths for standard directories (e.g. AROS_C) and names for tools (e.g. MMAKE, GENMF).

Platform depending definitions can be found in:

  • $(TOP)/bin/$(AROS_HOST_ARCH)-$(AROS_HOST_CPU)/gen/config/host.cfg
  • $(TOP)/bin/$(AROS_HOST_ARCH)-$(AROS_HOST_CPU)/gen/config/target.cfg

Copyright © 1995-2008, The AROS Development Team. All rights reserved.
Amiga® is a trademark of Amiga Inc. All other trademarks belong to their respective owners.