Eagle Mode
About
Videos
Screenshots
Documentation
Change Log
License
System Requirements
Install and Start
General User Guide
emFileMan User Guide
emFileMan Customization
Advanced Configuration
C++ API Tutorial
C++ API Reference
Make System
Download
Project Philosophy
Future Plans
Forum
Contact
Hosted at:
Get Eagle Mode at SourceForge.net. Fast, secure and Free Open Source software downloads

 

 

Copyright © 2008-2024 Oliver Hamann. All rights reserved.

All trademarks are the property of their respective owners.

Eagle Mode -
Make System

Copyright © 2010-2011,2018,2020-2021 Oliver Hamann. Homepage: http://eaglemode.sourceforge.net/

Contents

1 Introduction
2 Maker scripts
      2.1 General requirements for a maker script
      2.2 Example
      2.3 GetDependencies function
      2.4 IsEssential function
      2.5 GetFileHandlingRules function
      2.6 GetExtraBuildOptions function
      2.7 Build function
3 unicc
      3.1 Examples
      3.2 Calling Conventions
      3.3 Compilers

1 Introduction

Eagle Mode is compiled, linked and installed with an own make system written in Perl. It is a replacement for classic makefiles, and it features auto-dependencies, multiple (sub-)projects, easy extension, optional continuation on non-fatal errors, easy portability, and special file handling rules. The latter allows to define patterns for marking project files for installation, clean-up, execution-attribute-setting, backup, and private use. The make system is well-tested and has also been used for some other projects than Eagle Mode.

The make system consists of three layers:

  • The upper-most layer is the make.pl program in the top-directory of the project. It it called by the user and has options for doing all the necessary things. Type "perl make.pl --help" to read the help text. Unfortunately, make.pl still lacks a certain configuration interface. This means that you would have to edit it directly if you want to use the make system for another project than Eagle Mode.
  • The middle layer consists of so-called "maker scripts" in the subdirectory makers. There is one maker script for each "project" (i.e. sub-project of Eagle Mode). They can be seen as the makefiles.
  • The bottom layer is made of unicc, which is a unified high-level interface to C/C++ compilers. It has a command line similar to compilers, but it features auto-dependencies and compilation to object files and linkage with one call. This means, unicc can do what simple classic makefiles often do.

The following chapters are describing the maker scripts and unicc in detail.

2 Maker scripts

2.1 General requirements for a maker script

As already said, the maker scripts can be seen as makefiles for the (sub-)projects. Each maker script must follow these rules:
  • The script file must lie in the directory $EM_DIR/makers (replace $EM_DIR by the source directory of Eagle Mode).
  • The script file name must end with ".maker.pm", otherwise it will not be found by make.pl.
  • The script must be written in the Perl programming language.
  • The script must define a package with the same name as the file name without ending. We call it the (sub-)project name.
  • Within that package, the script must define a set of functions as described blow.
  • At execution, the current directory is always set to the top-level directory, there where make.pl is. All paths are relative to that point.
PITFALL WARNING: If you copy and edit a maker script, please do not forget to set the package name to the same name as the file name (without .maker.pm), otherwise you will get very strange error messages.

2.2 Example

Here comes a simple sample maker script for a dynamic library project named "example" which depends on emCore. It uses unicc for compilation and linkage. Its path would have to be $EM_DIR/makers/examples.maker.pm.

package example;

use strict;
use warnings;

sub GetDependencies
{
        return ('emCore');
}

sub IsEssential
{
        return 0;
}

sub GetFileHandlingRules
{
        return ();
}

sub GetExtraBuildOptions
{
        return ();
}

sub Build
{
        shift;
        my %options=@_;

        system(
                @{$options{'unicc_call'}},
                "--math",
                "--rtti",
                "--exceptions",
                "--bin-dir"       , "bin",
                "--lib-dir"       , "lib",
                "--obj-dir"       , "obj",
                "--inc-search-dir", "include",
                "--link"          , "emCore",
                "--type"          , "dynlib",
                "--name"          , "example",
                "src/example/example.cpp"
        )==0 or return 0;

        return 1;
}

2.3 GetDependencies function

This function returns an array of project names. Those projects are always built before.

In addition to the dependencies defined by this function, every project implicitly depends on a special project which is named "defaults".

2.4 IsEssential function

Returns 0 or 1:

0 means that the project is not so essential and that the user may want to ignore a failure with building the project.

1 means that the project is so essential, that the overall building shall always be stopped on a failure with building the project.

2.5 GetFileHandlingRules function

Returns an array of file handling rules. These rules are used to decide whether a file should be deleted by the clean command, whether it should be copied by the install command, and whether it should have execution permission then.

For most files, the rules from the defaults project are already correct. But other projects can give some additional rules for their individual files.

Each rule is a string of the form:

<op><flag>[<op><flag>[<op><flag>...]]:<pattern>
With:
<op> is either a + for setting the flag, or a - for removing the flag.

<flag> is the name of the flag. Possible names are:
   clean  - The file has to be deleted by the clean command.
   install - The file has to be installed by the install command.
   exec  - The file is an executable.
   private - The file must not be released in addition to files which have the clean flag set (developer's private stuff).
   nobackup - The file must not be backed up in addition to files which have the clean flag set (developer's private stuff).

<pattern> is a pattern for matching the file path. It's a Perl regular expression.

The flag operations of a rule are applied to all files whose file paths match the pattern. Hereby the path is relative to the current directory (the top-level directory), and the path elements are separated by slashes, even on Windows.

If there are contrary rules, the later one counts. The project dependencies are respected.

Be careful when writing the regular expressions. One error could mean that the clean command deletes some or all of the source files. Please study all existing rules before making new ones. Make backups before testing.

2.6 GetExtraBuildOptions function

The make.pl program defines some user options for the build command. Each project may define additional options though this function. It returns an array of references where each reference refers an array of three strings: The name of the option, the default value, and a description.

2.7 Build function

This function performs compilation, linkage and maybe other things for building the project. Output files which are up to date should not be re-generated (this is usually solved by using unicc). The beginning of the function body should look like:
shift;
my %options=@_;
Thereby the hashes variable %options contains all the options. Hash index is the option name, hash value is the option value. Following options are defined by default:
compiler
Name of compiler and linker to be used.

cpus
Number of CPUs to be used, or "auto".

debug
Whether to produce debug information. Must be "yes" or "no".

unicc
Relative path to the unicc directory.

unicc_call
Reference to an array which contains the first arguments for calling unicc.pl. It's like:
[ 'perl', catfile($options{'unicc'},'unicc.pl'),
  '--compiler', $options{'compiler'},
  '--cpus', $options{'cpus'},
  $options{'debug'} eq 'yes' ? ('--debug') : () ]

utils
Relative path to the utils directory.

projects
This should not be used by the maker scripts.

continue
This should not be used by the maker scripts.
In addition, there are all the extra options defined through GetExtraBuildOptions from all the projects.

The Build function has to return 1 on success. On failure, it may either return 0 or call the die function.

3 unicc

unicc is a unified high-level interface to C/C++ compilers. It takes a couple of source files, compiles them to object files, and links these in order to create an executable, a static library or a dynamic library. Each operation is performed only if the output file is not existing, or if it is not newer than the input files. Therefore, include file dependencies are checked recursively, but only if found via an explicit given include path (option --inc-search-dir). This normally means that standard include files are not checked.

unicc is written in Perl, and it can be found in: $EM_DIR/makers/unicc

3.1 Examples

Here is a simple example for building a program using the GNU compiler:
$EM_DIR/makers/unicc/unicc.pl --compiler gnu hello.c --name hello
And here comes a more complex example:
$EM_DIR/makers/unicc/unicc.pl --compiler wat src/hello.c src/world.c \
--obj-dir obj --lib-search-dir lib --inc-search-dir include \
--bin-dir bin --debug --type wexe --name helloworld

3.2 Calling Conventions

This chapter describes the arguments and options for calling unicc.pl. They can be given in any order.
src-file
Path name of a source file including the file name ending which must be ".c", ".cpp", ".cc" or ".cxx". On Windows, ".rc" files are also supported. This argument can be given multiple times.

--compiler name
Name of the compiler. See the Compilers chapter more below for all possible names. The default is gnu.

--cpus count
Number of CPUs to be used. More precisely, it is the maximum number of source files to be compiled in parallel. The default is "auto", which means to detect the number of available cpus cores.

--type type
Set the type of the output file. Possible types are:
cexe - console executable (this is the default)
wexe - windowed executable (different against cexe on Windows only)
lib - static library
dynlib - dynamic library

--name name
Set the name of the output file without ending, and, if it's a library, without the UNIX "lib" in front (Default: "unnamed").

--obj-dir dir
Target directory for object files and other temporary files (default: ".").

--bin-dir dir
Target directory for the executable (default: "."). Ignored if type is not cexe or wexe.

--lib-dir dir
Target directory for the library, if type is lib or dynlib (default: "."). In addition, this option acts like --lib-search-dir.

--lib-search-dir dir
A directory where to search for libraries to be linked. This option can be given multiple times.

--runtime-lib-search-dir dir
A directory where to search for shared libraries at runtime ("rpath"). This option can be given multiple times.

--inc-search-dir dir
A directory where to search for include files. This option can be given multiple times.

--link name
Name of a library to be linked. The name must be without file name ending and without the UNIX "lib" in front (e.g. say "X11" instead of "libX11.a"). This argument can be given multiple times. The order may be important (high-level first).

--math
Link with the standard math library.

--rtti
Enable Run Time Type Information.

--exceptions
Enable C++ exceptions.

--debug
Create debug information in the output.

--def name[=value]
Define a preprocessor variable. This option can be given multiple times.

3.3 Compilers

Here is a list of all possible values for the compiler option:
bor
Use the Borland C/C++ compiler on Windows. This is quite outdated and it never worked.

clang
Use the Clang C/C++ compiler. This should work.

gnu
Use the GNU C/C++ compiler (gcc). This is the default and it has been successfully tested with many gcc versions. Minimum should be something like version 4.9. Cygwin and MinGW are also supported.

int
Use the Intel C/C++ compiler (icc) on Linux. This is quite outdated and certainly not working anymore.

mic
Use the Microsoft C/C++ compiler on Windows. Tested with Visual Studio 2019 - not all plugins working.

sun
Use the Sun C/C++ compiler on Linux. This is quite outdated and certainly not working anymore.

wat
Use the Watcom or Open Watcom C/C++ compiler on Windows. This is quite outdated and certainly not working anymore.