diff g23m/nds_busyb.pl @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/g23m/nds_busyb.pl	Mon Jun 01 03:24:05 2015 +0000
@@ -0,0 +1,1493 @@
+#!perl -w
+#-----------------------------------------------------------------------------
+#  Project :
+#  Modul   :  nds_busyb.pl
+#-----------------------------------------------------------------------------
+#  Copyright 2003 Texas Instruments Deutschland GmbH
+#                 All rights reserved.
+#
+#                 This file is confidential and a trade secret of Texas
+#                 Instruments Deutschland GmbH
+#                 The receipt of or possession of this file does not convey
+#                 any rights to reproduce or disclose its contents or to
+#                 manufacture, use, or sell anything it may describe, in
+#                 whole, or in part, without the specific written consent of
+#                 Texas Instruments Deutschland GmbH.
+#-----------------------------------------------------------------------------
+#  Purpose :
+#-----------------------------------------------------------------------------
+
+
+use strict;
+use File::Copy;
+use File::Find;
+use File::Spec;
+use Cwd;
+use Getopt::Long qw(:config pass_through);
+
+
+#-------------------------------------------------------------------------------
+# Variables
+#-------------------------------------------------------------------------------
+
+# misc. variables
+my $hw_variant;
+my $l1_variant;
+
+my $command;
+
+# make tool (gnumake/clearmake)
+my $make;
+
+# makefile file name
+my $makeFile;
+
+my $makeVars;
+my $condat_var_variables;
+
+# specifies whether input file format is XML (default) or make (*.mak)
+my $called_with_mak_file;
+
+# specifies whether there is a "mconst:" target in the makefile or not
+my $has_target_named_mconst;
+
+my @busyb_libs;
+my @intram_libs;
+
+my $current_dir = cwd;
+# do not only store the drive in $current_drive, but rather store the path
+# to the current dir (necessary to work directly on V:\<view>\...)
+my $current_drive = cwd;
+$current_drive =~ s|[\\/][^\\/]+$||;
+
+# path to Nice software (covering SSA, WCP, and SDVK)
+my $hw_root = $current_dir . "/../chipsetsw";
+my $hw_layer1 = $hw_root . "/layer1";
+my $hw_system = $hw_root . "/system";
+my $hw_system_config = $hw_system . "/config";
+# points to the system/deps_objs/<ABC-CONFIG> directory (initialized by
+# extract_globals_from_makefile() function)
+my $hw_system_objects;
+
+# path to GPF software
+my $gpf_root = $current_drive . "/gpf";
+# we need to honor proper upper and lower case when using clearmake!
+my $gpf_ccd = $gpf_root . "/CCD";
+
+# BuSyB cdginc output directories (necessary for step 7)
+my $cdginc_dir;
+my $cdginc_tools_dir;
+
+# BuSyB target image (.out) file name (necessary for step 9)
+my $target_image;
+
+# specifies whether output is being redirected (logged to a file) or not
+my $outerr_redirected;
+
+# specifies whether ccddata_dll.dll can be built (1) or not (0):
+# this depends on the presence of cl.exe, see also determine_cl_version() and
+# step__check_environment()
+my $generate_ccddata_dll;
+
+# Generated makefile names
+my $abc_exports;
+my $busyb_prefix;
+my $condat_lib_ip_mak;
+my $condat_var_mak;
+
+# tool definitions
+my $t_perl           = "perl";
+my $t_updtBusybInc   = "gen_abc_exports.mak";
+my $t_updtAbc        = "update_exported_makefiles.pl";
+my $t_abc            = "abc.pl";
+my $t_updtBusyb      = "system/update_makefile.mak";
+
+# command line options (do not initialize $o_make! -- see step 0 below)
+my $o_file;
+my $o_make;
+my $o_logfile = "report.txt";
+my $o_shell = 0;
+my $o_help = 0;
+
+# ABC/make pass-through options
+my $abc_opt;
+my $make_opt;
+
+# script exit value, being set by last step: step__compile_berlin_sw()
+my $exit_value;
+
+# Variables needed for the progress bar
+my $list_of_libs_available = 0 ;
+my $pid;
+
+
+
+#-------------------------------------------------------------------------------
+# Main Program
+#-------------------------------------------------------------------------------
+
+# parse command line, passing through all unknown options to make
+parse_command_line();
+
+
+# logging is enabled by default (unless $o_shell is set, done by option "-s")
+if (!$o_shell)
+{
+    # attempt to redirect STDOUT+STDERR
+    $outerr_redirected = redirect_output();
+}
+else
+{
+    # do not redirect output, it is being sent to shell
+    $outerr_redirected = 0;
+}
+
+my $build_message = "\nStarting build of " . $o_file . ",
+REDIRECT_PLACEHOLDER
+
+Build may take a while, so please be patient!\n\n";
+
+if ($outerr_redirected)
+{
+    $build_message =~ s/REDIRECT_PLACEHOLDER/output is being logged to $o_logfile,/;
+    print CONSOLE_OUT $build_message;
+}
+else
+{
+    $build_message =~ s/REDIRECT_PLACEHOLDER/output is NOT being logged!/;
+    print $build_message;
+}
+
+
+# steps 1 and 2 must always be performed
+step__check_environment (1);
+step__parse_input_file (2);
+
+# all other steps depend on the input file format, "mconst:" target in the
+# BuSyB makefile, or hybrid build system vs. unified build system
+my @build_steps;
+
+
+# determine if UnBuSy or HyBuSy is being used for compilation
+if (defined($hw_variant))
+{
+    # queue HyBuSy (hybrid build system) steps
+    # ($called_with_mak_file is being set in step__check_environment() and is
+    # already known at this point)
+    push @build_steps, \&step__update_busyb_makefile
+        unless $called_with_mak_file;
+    push @build_steps, \&step__busyb_create_directories;
+    push @build_steps, sub
+    {
+        # $has_target_named_mconst may be set as late as in
+        # step__update_busyb_makefile(), so it may not yet be known and we need
+        # to check this at run-time
+        if ($has_target_named_mconst)
+        {
+            # only process SAP/MSG docs if "mconst:" target exists in makefile
+            step__busyb_process_interfaces (@_);
+        }
+        else
+        {
+            # if not, need to decrement $step_no (first parameter of this function)
+            $_[0]--;
+        }
+    };
+    push @build_steps, sub
+    {
+        # $cdginc_tools_dir may be set as late as in
+        # step__update_busyb_makefile(), so it may not yet be known and we need
+        # to check this at run-time
+        if ($cdginc_tools_dir)
+        {
+            # only generate ccddata_dll.dll if SAP/MSG docs were processed
+            step__generate_ccddata_dll (@_);
+        }
+        else
+        {
+            # if not, need to decrement $step_no (first parameter of this function)
+            $_[0]--;
+        }
+    };
+    push @build_steps, \&step__generate_interface_for_abc
+        unless $called_with_mak_file;
+    push @build_steps, \&step__update_abc_config;
+    push @build_steps, \&step__extract_abc_variables
+        unless $called_with_mak_file;
+    push @build_steps, \&step__abc_compilation;
+    push @build_steps, \&step__busyb_compilation;
+
+}
+else
+{
+    # queue UnBuSy (unified build system) steps
+    # ($called_with_mak_file is being set in step__check_environment() and is
+    # already known at this point)
+#    push @build_steps, \&step__busyb_generate_l1_configdef_files;
+    push @build_steps, sub { step__update_busyb_makefile ($_[0], "system/unbusy_g23m.ini"); }
+        unless $called_with_mak_file;
+    push @build_steps, \&step__busyb_create_directories;
+    push @build_steps, \&step__busyb_generate_cfg_files;
+    push @build_steps, \&step__busyb_generate_header_files;
+    push @build_steps, sub
+    {
+        # $has_target_named_mconst may be set as late as in
+        # step__update_busyb_makefile(), so it may not yet be known and we need
+        # to check this at run-time
+        if ($has_target_named_mconst)
+        {
+            # only process SAP/MSG docs if "mconst:" target exists in makefile
+            step__busyb_process_interfaces (@_);
+        }
+        else
+        {
+            # if not, need to decrement $step_no (first parameter of this function)
+            $_[0]--;
+        }
+    };
+    push @build_steps, sub
+    {
+        # $cdginc_tools_dir may be set as late as in
+        # step__update_busyb_makefile(), so it may not yet be known and we need
+        # to check this at run-time
+        if ($cdginc_tools_dir)
+        {
+            # only generate ccddata_dll.dll if SAP/MSG docs were processed
+            step__generate_ccddata_dll (@_);
+        }
+        else
+        {
+            # if not, need to decrement $step_no (first parameter of this function)
+            $_[0]--;
+        }
+    };
+    push @build_steps, \&step__busyb_compilation;
+}
+
+
+# execution of queued steps, starting with step number 3
+$exit_value = 0;
+my $step_no = 3;
+foreach my $step (@build_steps)
+{
+    &{$step} ($step_no);
+    $step_no++;
+}
+
+# restore redirected STDOUT+STDERR, if necessary
+restore_redirection()
+    if $outerr_redirected;
+
+exit $exit_value;
+
+
+#-------------------------------------------------------------------------------
+# SUBROUTINES
+#-------------------------------------------------------------------------------
+
+
+#-------------------------------------------------------------------------------
+# parses the command line, sets global $o_* variables to all specified options,
+# checks which options/parameters are passed through to make or ABC
+#-------------------------------------------------------------------------------
+sub parse_command_line
+{
+    GetOptions ("file=s"=>\$o_file,
+        "log=s"=>\$o_logfile,
+        "shell"=>\$o_shell,
+        "make=s"=>\$o_make,
+        "help|?" =>\$o_help);
+
+    if ($o_help)
+    {
+        usage();
+        exit 0;
+    }
+
+    # determine ABC and make/BuSyB pass-through options from @ARGV
+    $abc_opt = "";
+    $make_opt = "";
+    foreach (@ARGV)
+    {
+        if (/^-x/)
+        {
+            # ABC pass-through option: -x...
+            #FIXME: are multiple ABC options allowed?
+            s/^-x//;
+            $abc_opt = $_;
+        }
+        else
+        {
+            # make/BuSyB pass-through option: all else
+            $make_opt .= " " . $_;
+        }
+    }
+
+    # sanity checks: due to enabled 'pass_through' and 'permute' of GetOptions(),
+    # some busyb.pl options may end up in other options parameters instead (e.g. if
+    # options which require a parameter are specified w/o any parameter: "... -m",
+    # or "... -m -l", ...)
+    foreach ($o_file, $o_logfile, $o_make)
+    {
+        # check all options which should take a parameter if they actually contain
+        # another otion and no parameter
+        if (defined($_) and /^-/)
+        {
+            print "\nERROR: Option missing mandatory parameter!\n\n";
+            usage();
+            exit 1;
+        }
+    }
+    foreach ("-f", "-l", "-m")
+    {
+        # check if the pass-through options to make contain on of the busyb.pl
+        # options
+        if ($make_opt =~ /$_/i)
+        {
+            print "\nERROR: Option missing mandatory parameter!\n\n";
+            usage();
+            exit 1;
+        }
+    }
+
+    if (!$o_file)
+    {
+        print "\nERROR: No input/configuration file specified with \"-f file\"!\n\n";
+        usage();
+        exit 1;
+    }
+    die "\nERROR: Input/configuration file \"" . $o_file . "\" not found, aborting"
+        unless -e $o_file;
+    # replace backslash with slash in filename
+    $o_file =~ s:\\:/:g;
+}
+
+
+#-------------------------------------------------------------------------------
+# print short usage notes
+#-------------------------------------------------------------------------------
+sub usage
+{
+    print "\nUSAGE:
+    perl busyb.pl -f XML-File [OPTIONS] [make_flags] [make_targets]
+
+Build TI protocol stack with BuSyB/ABC, logging all output to report.txt by
+default.
+
+OPTIONS:
+    -l LOGFILE  log to LOGFILE (default is report.txt)
+    -s          output to current shell, no logging to report.txt
+    -x\"OPT\"     pass-through options for ABC
+
+EXAMPLES:
+    perl busyb.pl -f variants/2b_gp_mf_fd_..ps.xml
+    perl busyb.pl -f variants/2b_gp_mf_fd_..ps.xml clean_aci
+    perl busyb.pl -f variants/2b_gp_mf_fd_..ps.xml -x\"ENVFILE=my_env.mak\"
+    perl busyb.pl -f variants/2b_gp_mf_fd_..ps.xml -k
+";
+}
+
+
+#-------------------------------------------------------------------------------
+# print current step to STDOUT (usually redirected to report.txt) and
+# additionally to CONSOLE_OUT
+#-------------------------------------------------------------------------------
+sub print_status
+{
+    print "\n-------------------------------------------------------------------------------";
+    print "\n$_[0]\n";
+    print "-------------------------------------------------------------------------------\n\n";
+
+    print CONSOLE_OUT "$_[0]\n"
+        if $outerr_redirected;
+}
+
+
+#-------------------------------------------------------------------------------
+# print to CONSOLE_OUT for progress bar
+#-------------------------------------------------------------------------------
+sub print_progress
+{
+    print CONSOLE_OUT "$_[0]\r"
+        if $outerr_redirected;
+
+}
+
+
+
+#-------------------------------------------------------------------------------
+# this function parses the XML file
+# it returns 0 on failure
+# it sets the following global variables
+#   $hw_variant, $l1_variant, $makeVars
+#-------------------------------------------------------------------------------
+sub parse_file {
+  my $line;
+  open (IN,"<$_[0]")
+    or die "ERROR: Can't open file \"$_[0]\" ($!), aborting";
+
+  while(defined($line = <IN>))
+  {
+    # find HW string in ConfigDef document, e.g.
+    # <property name="HW_VARIANT" value="GPRS_DSAMPLE_AMR_NW"/>
+    #                                    ^^^^^^^^^^^^^^^^^^^
+    if ($line =~ /name=\"HW_VARIANT\"\s*value=\"(.*)\"/ ) {
+      $hw_variant = $1;
+    }
+    elsif ($line =~ /name=\"(L1)\"\s*value=\"(.*)\"/ ) {
+      $l1_variant = $2;
+      $makeVars .= " $1=$2";
+    }
+    # finding all other properties in order to pass them to make
+    elsif ($line =~ /name=\"(\w+)\"\s*value=\"(.*)\"/ ) {
+      $makeVars .= " $1=$2";
+    }
+  }
+  close IN ;
+
+
+  return 1;
+}
+
+
+#-------------------------------------------------------------------------------
+# currently need to remove all L1 objects before compiling (dependency problems
+# in ABC) when the ABC config (== $hw_variant) changes (last ABC config is stored in
+# /g23m/.abc_config)
+#-------------------------------------------------------------------------------
+sub purge_abc_obj_files
+{
+    my $last_abc_config_file = $current_dir . "/.abc_config";
+    my $abc_config_changed = 1;
+
+    if (-e $last_abc_config_file)
+    {
+        open (IN, $last_abc_config_file)
+            or die "ERROR: could not open file \"" . $last_abc_config_file . "\" ($!),";
+
+        while (<IN>)
+        {
+            chomp;
+            if (/ABC config = $hw_variant$/)
+            {
+                # still using the same ABC config as the last build
+                $abc_config_changed = 0;
+                print "ABC config not changed since the last build, keeping layer 1 *.obj files.\n";
+            }
+        }
+        close IN;
+    }
+
+    if ($abc_config_changed == 1)
+    {
+        # udpate .abc_config with current ABC config ($hw_variant)
+        open (OUT, ">$last_abc_config_file")
+            or die "ERROR: could not write to file \"" . $last_abc_config_file . "\" ($!),";
+        print OUT "This file is auto-generated, do not change!\nCurrent ABC config = " . $hw_variant . "\n";
+        close OUT;
+
+        # remove L1 .obj files
+        print "Removing all *.obj files in \"" . $hw_layer1 . "\" and below
+    (currently necessary to properly re-compile when the ABC config changed)\n\n";
+        find (\&rm_file, $hw_layer1);
+    }
+}
+
+
+#-------------------------------------------------------------------------------
+# Check/Initialize some necessary env. variables:
+# - %PATH must contain gpf/bin, gpf/tools/bin, chipsetsw/system (in that order)
+# - %C_DIR must only contain slashes (no backslashes, semicolons)
+#-------------------------------------------------------------------------------
+sub init_environment
+{
+    my $current_drive_winformat = $current_drive;
+    $current_drive_winformat =~ s:/:\\:g;
+
+    # check if all necessary paths are in %PATH, add them if not (this removes
+    # the dependency on initvars.bat)
+    if (!($ENV{'PATH'} =~ m:[\\/]chipsetsw[\\/]system:))
+    {
+        # add \chipsetsw\system to %PATH (should be third)
+        $ENV{'PATH'} = "$current_drive_winformat\\chipsetsw\\system;" . $ENV{'PATH'};
+        print "%PATH   : \"$current_drive_winformat\\chipsetsw\\system\" + %PATH\n";
+    }
+
+    if (!($ENV{'PATH'} =~ m:[\\/]gpf[\\/]tools[\\/]bin:))
+    {
+        # add \gpf\tools\bin to %PATH (should be second)
+        $ENV{'PATH'} = "$current_drive_winformat\\gpf\\tools\\bin;" . $ENV{'PATH'};
+        print "%PATH   : \"$current_drive_winformat\\gpf\\tools\\bin\" + %PATH\n";
+    }
+
+    if (!($ENV{'PATH'} =~ m:[\\/]gpf[\\/]bin:))
+    {
+        # add \gpf\bin to %PATH (should be first)
+        $ENV{'PATH'} = "$current_drive_winformat\\gpf\\bin;" . $ENV{'PATH'};
+        print "%PATH   : \"$current_drive_winformat\\gpf\\bin\" + %PATH\n";
+    }
+
+    # check correct setting of environment variables for TI compiler and linker
+    # PATH_CC_1_22e=C:\tools\TMS4701x_1.22e\NT
+    die "\nERROR: environment variable %PATH_CC_1_22e must be set!\n"
+      unless exists($ENV{'PATH_CC_1_22e'});
+    $ENV{'PATH_CC_1_22e'} =~ s|\\|/|g;
+    $ENV{'PATH_CC_1_22e'} =~ s|;.*||;
+    print "%PATH_CC_1_22e  : \"" . $ENV{'PATH_CC_1_22e'} . "\"\n";
+
+
+    # PATH_LNK_1_9902=C:\tools\vislink_1.9902
+    die "\nERROR: environment variable %PATH_LNK_1_9902 must be set!\n"
+      unless exists($ENV{'PATH_LNK_1_9902'});
+    $ENV{'PATH_LNK_1_9902'} =~ s|\\|/|g;
+    $ENV{'PATH_LNK_1_9902'} =~ s|;.*||;
+    print "%PATH_LNK_1_9902  : \"" . $ENV{'PATH_LNK_1_9902'} . "\"\n";
+
+} # init_environment
+
+#-------------------------------------------------------------------------------
+# Return "<view-name> (type: <view-type>)" or "none":
+# <view-name>: CC view name/"unknown"
+# <view-type>: CC view type ("dynamic/snapshot/unknown")
+# Check view text mode, which must be 'unix' (aka 'transparent mode').
+#-------------------------------------------------------------------------------
+sub determine_view_context
+{
+    # check if using CC dynamic/snapshot view or no view at all
+    my $view_details = `cleartool lsview -long -properties -full -cview 2>&1`;
+    my $cc_view;
+
+    if ($? == 0)
+    {
+        # store view name + view type (dynamic/snapshot)
+        if ($view_details =~ /Tag:\s*(\w+)/)
+        {
+            $cc_view = $1;
+        }
+        else
+        {
+            print "\nWARNING: Could not determine current view name.\n";
+            $cc_view = "unknown";
+        }
+
+        if ($view_details =~ /Properties: (\w+)/)
+        {
+            $cc_view .= " (type: " . $1 . ")";
+        }
+        else
+        {
+            print "WARNING: Could not determine view type (dynamic/snapshot).\n";
+            $cc_view .= " (type: unknown)";
+        }
+
+        # check view text mode (_must_ be "unix", otherwise most GNU tools like
+        # gnumake don't work properly!)
+        if ($view_details =~ /Text mode: (\w+)/)
+        {
+            if ($1 ne "unix")
+            {
+                die "\nERROR: Wrong text mode (found \"$1\", should be \"unix\") of CC view $cc_view, aborting";
+            }
+        }
+    }
+    else
+    {
+        $cc_view = "none";
+    }
+    return $cc_view;
+} # determine_view_context
+
+#-------------------------------------------------------------------------------
+# Check for gnumake/clearmake availability, returns gnumake/clearmake depending
+# on view context ($dynamic_view) and user choice ($o_make)
+#-------------------------------------------------------------------------------
+sub determine_make_tool
+{
+    my $cmake;
+    my $gmake;
+    my $use_make;
+
+    # checking for clearmake/gnumake availability
+    my ($rc) = int (system("gnumake -ver > NUL 2>&1") / 256);
+    
+    if($rc == 0){
+      $gmake = "gnumake";
+    }
+
+    # choosing the "right" make (gnumake for all kind of views)
+    if (defined($gmake)) {
+      $use_make = $gmake;
+    }
+    else {
+      die "\nERROR: No appropriate gnumake tool found, aborting";
+    }
+
+    # checking for user supplied make
+    if (defined($o_make) && ($o_make =~ /clearmake/i) && defined($cmake)) {
+      die "\nERROR: Clearmake make tool no longer supported, aborting";
+    }
+    elsif (defined($o_make) && ($o_make =~ /gnumake/i) && defined($gmake)) {
+      $use_make = $gmake;
+    }
+    elsif (defined($o_make)) {
+      die "\nERROR: Specified make tool \"$o_make\" not found or not supported, aborting";
+    }
+
+    return $use_make;
+}
+
+
+#-------------------------------------------------------------------------------
+# Check which GCC variant (Cygwin/MingW) and which version is installed,
+# return GCC version and set %GCC env. variable to run this GCC variant in ABC.
+#-------------------------------------------------------------------------------
+sub determine_gcc_version
+{
+    my $gcc_ver = `gcc --version 2>&1`;
+    if ($? == 0)
+    {
+        # only keep the first line of GCC version string
+        $gcc_ver =~ s/\n.*$//s;
+
+        # Nice GCC variant: Cygwin
+        $ENV{'GCC'} = "\@gcc";
+    }
+    else
+    {
+        $gcc_ver = `cpp --version 2>&1`;
+        if ($? == 0)
+        {
+            # only keep the first line of GCC version string
+            $gcc_ver =~ s/\n.*$//s;
+
+            # Berlin GCC variant: MingW (defines WIN32 by default which is
+            # interpreted by Nice SW as 'simulation build')
+            $ENV{'GCC'} = "\@cpp -UWIN32";
+        }
+        else
+        {
+            die "\nERROR: GCC not found (gcc.exe/cpp.exe not installed or not in the path), aborting";
+        }
+    }
+
+    return $gcc_ver;
+}
+
+
+#-------------------------------------------------------------------------------
+# Check if cl.exe (shipped with MS Visual Studio/VC++) is installed in the path,
+# return version string and indicate whether ccddata_dll.dll can be built
+# ($generate_ccddata_dll = 1) or not (= 0)
+#-------------------------------------------------------------------------------
+sub determine_cl_version
+{
+    my $cl_ver = `cl.exe 2>&1`;
+    if ($? == 0)
+    {
+        # only keep the first line of version string
+        chomp $cl_ver;
+        $cl_ver =~ s/\n.*$//s;
+
+        # indicate that ccddata_dll.dll should be built
+        $generate_ccddata_dll = 1;
+    }
+    else
+    {
+        $cl_ver = "not found, unable to generate ccddata_dll.dll";
+
+        # indicate that ccddata_dll.dll should not be built
+        $generate_ccddata_dll = 0;
+    }
+
+    return $cl_ver;
+}
+
+
+#-------------------------------------------------------------------------------
+# Check if Java is installed (in the path), return version string of Java.
+#-------------------------------------------------------------------------------
+sub determine_java_version
+{
+    my $java_ver = `java -version 2>&1`;
+    if ($? == 0)
+    {
+        # only keep the first line of java version string and remove "java", if present
+        $java_ver =~ s/\n.*$//s;
+        $java_ver =~ s/\s*java\s*//;
+    }
+    else
+    {
+        die "\nERROR: Java not found (not installed or not in the path), aborting";
+    }
+
+    return $java_ver;
+}
+
+
+#-------------------------------------------------------------------------------
+# Extract some globals from a given makefile
+# 1) $cdginc_dir
+# 2) $cdginc_tools_dir
+# 3) $target_image
+# 4) $has_target_named_mconst
+# 5) @busyb_libs
+#-------------------------------------------------------------------------------
+sub extract_globals_from_makefile
+{
+    my ($makeFile) = @_;
+
+    my $grab_libs = 0;
+    my $grab_irlibs = 0;
+    my $grab_irplacements = 0;
+    my $lib_no = 0;
+
+    open (IN, $makeFile)
+        or die "ERROR: could not open file \"" . $makeFile . "\" ($!),";
+
+    while (<IN>)
+    {
+        if (/.*(__out__\/.+\/cdginc)\/mconst\.cdg/)
+        {
+            # grep cdginc directory from generated makefile
+            $cdginc_dir = $1;
+        }
+        elsif (/.*(__out__\/.+\/cdginc[^ \/]+)/)
+        {
+            # grep cdginc_tools dir from generated makefile (take anything which
+            # starts with "cdginc" but w/o blank or slash directly afterwards)
+            $cdginc_tools_dir = $1;
+        }
+        elsif (/(__out__\/.+\.out):/)
+        {
+            # grep target image (.out) name (w/ complete path) from generated
+            # makefile for step 9
+            $target_image = $1;
+
+            # start grabbing libs (from next line on)
+            $grab_libs = 1;
+        }
+        elsif ($grab_libs and /\s+(\S+)\s*([\\]*)/)
+        {
+            # disable lib-grabbing if last lib (i.e. no "\" at end of line)
+            if ($2 eq "")
+            {
+                $grab_libs = 0;
+            }
+            # skip any make variables
+            next if ($1 =~ /\$\(/);
+            # skip the linker command file (*.lcf)
+            next if ($1 =~ /.*\.lcf/);
+            # skip all libs stored in chipsetsw VOB
+            next if ($1 =~ /chipsetsw\//);
+
+            # store lib in @busyb_libs
+            push @busyb_libs, $1;
+        }
+        elsif (/__out__.+\.lcf:\s*(\w*)\s*\\/)
+        {
+            # start grabbing intram libs
+            $grab_irlibs = 1;
+        }
+        elsif ($grab_irlibs and /\s+(\S+)\s*([\\]*)/)
+        {
+            # disable lib-grabbing if last lib (i.e. "\" at end of line),
+            # start grabbing ir-placements instead
+            if ($2 eq "")
+            {
+                $grab_irlibs = 0;
+                $grab_irplacements = 1;
+            }
+
+            # skip any make variables
+            next if ($1 =~ /\$\(/);
+            # skip linker command file template
+            next if ($1 =~ /\.template/);
+
+            # store lib in @intram_libs
+            push @intram_libs, $1;
+        }
+        elsif ($grab_irplacements and /\$\(BSB_ECHO\)\s+(\(.*\))\s*>/)
+        {
+            # grab intram lib placements
+            # skip any make variables (e.g. $SSA_INT_RAM_PLACEMENT)
+            next if ($1 =~ /\$\(/);
+
+            # need to store each placement with the correct lib
+            $intram_libs[$lib_no] .= " $1";
+            $lib_no++;
+        }
+        elsif ($grab_irplacements and /make_cmd\.pl/)
+        {
+            # stop grabbing intram lib placements
+            $grab_irplacements = 0;
+        }
+        elsif (/^mconst:/)
+        {
+            $has_target_named_mconst = 1;
+        }
+        elsif (/chipsetsw\/system\/deps_objs\/(\w+)\// and !defined($hw_system_objects))
+        {
+            # grep Nice deps_objs dir (different for each ABC config)
+            $hw_system_objects = $1;
+        }
+    }
+    close IN;
+} # extract_globals_from_makefile
+
+
+sub step__check_environment
+{
+    print_status ($_[0] . ". Checking environment");
+
+    # create the makefile filename
+    my $dir = (File::Spec->splitpath($o_file))[1];  #FIXME: remove this, we don't seem to need it anymore
+    $makeFile = (File::Spec->splitpath($o_file))[2];
+    $makeFile =~ s/(.*)\..*/$1.mak/;
+
+    # generate *.abc_exports.mak filename
+    $abc_exports = $makeFile;
+    $abc_exports =~ s/\.mak$//;
+    $abc_exports = $abc_exports . ".abc_exports.mak";
+
+    # initialize necessary env. variables (%PATH, %C_DIR)
+    init_environment();
+
+    # get view name, view type (dynamic/snapshot/none), and check text mode for
+    # dynamic views (must be 'unix')
+    my $view = determine_view_context();
+    print "CC View : $view\n";
+
+    # check for clearmake & gnumake, determine if user specified make exists
+    $make = determine_make_tool ($view);
+    print "Make    : using \"$make\" for the build\n";
+
+    # check installed GCC variant (gcc.exe/cpp.exe), set %GCC env. variable for ABC
+    my $gcc_version = determine_gcc_version();
+    print "GCC     : " . $gcc_version . ", using \"" . $ENV{'GCC'} . "\" for ABC\n";
+
+    # check installed cl.exe version (part of MS Visual Studio/VC++)
+    my $cl_version = determine_cl_version();
+    print "cl.exe  : $cl_version\n";
+
+
+    # determine input file format: XML (default), or make (*.mak)
+    $called_with_mak_file = ($o_file =~ /.*\.mak/);
+    if ($called_with_mak_file)
+    {
+        print "Input   : Makefile format (will skip several steps during build)\n";
+
+        # set global variables $cdginc_dir, $target_image, and
+        # $has_target_named_mconst, which are needed to determine further steps
+        extract_globals_from_makefile ($makeFile);
+    }
+    else
+    {
+        print "Input   : XML format\n";
+
+        # extract_globals_from_makefile() is only possible after step 2, where the
+        # makefile is being created
+    }
+
+
+    # only check if Java is installed, if input is XML (i.e. we need to generate
+    # everything ourselves) _or_ if input is MAK and we have a target "mconst:"
+    my $java_version;
+    if ((not ($called_with_mak_file)) or
+        (($called_with_mak_file) and ($has_target_named_mconst)))
+    {
+        $java_version = determine_java_version();
+    }
+    else
+    {
+        $java_version = "not necessary";
+    }
+    print "Java    : " . $java_version . "\n";
+
+
+    # set environment variable %BUSYB_PREFIX, which is being used in ABCs master.mak
+    # (is necessary for supporting old Berlin build system in parallel)
+    $busyb_prefix = $makeFile;
+    $busyb_prefix =~ s/\.mak$/\./;
+    $ENV{'BUSYB_PREFIX'} = $busyb_prefix;
+    print "Prefix  : BUSYB_PREFIX=" . $busyb_prefix . "\n";
+}
+
+
+sub step__parse_input_file
+{
+    print_status ($_[0] . ". Parsing input file ($o_file)");
+
+    if (!parse_file ($o_file))
+    {
+        die "ERROR: Either HW_VARIANT or L1 property missing in file \"$o_file\", aborting";
+    }
+
+    if (defined($l1_variant))
+    {
+        print "L1: " . $l1_variant . "\n";
+    }
+    else
+    {
+        print "L1 : Not defined\n"
+    }
+    if (defined($hw_variant))
+    {
+        print "HW variant: " . $hw_variant . "\n";
+    }
+    else
+    {
+        print "HW variant : Not defined - Compiling with Unified BuSyB\n"
+    }
+
+}
+
+
+#-------------------------------------------------------------------------------
+# update BuSyB makefile, if necessary; takes an additional second parameter
+# to specify the BuSyB .ini file
+#-------------------------------------------------------------------------------
+sub step__update_busyb_makefile
+{
+    print_status ($_[0] . ". Updating BuSyB makefile ($makeFile)");
+
+    $command = "$make -f $t_updtBusyb MFILE=$makeFile XMLFILE=$o_file ABC_EXPORTS_MAKEFILE_NAME=$abc_exports";
+    if (defined ($_[1]))
+    {
+        $command .= " BUSYB_INI_FILE=$_[1]";
+    }
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Can't create makefile \"$makeFile\" ($!), aborting";
+    print "\n";
+
+    # set global variables $cdginc_dir, $target_image, and $has_target_named_mconst,
+    # which are needed to determine further steps (in case $called_with_mak_file
+    # is not true, see step__check_environment())
+    extract_globals_from_makefile ($makeFile);
+
+    # generate clearmake build option specification (<makefile>.options),
+    # regardless if using clearmake or gnumake in order to have this file
+    # available in case one first wants to use gnumake and switches later on
+    # to clearmake
+    open (BOS, ">$makeFile.options")
+        or die "ERROR: could not write to file \"" . $makeFile . ".options\" ($!),";
+    print BOS "# clearmake build option specification (BOS) file
+
+# this clearmake-specific rule causes clearmake to treat the logfile as a
+# view-private file and not as a derived object (which causes several problems
+# during the initial and subsequent builds with clearmake)
+.NO_DO_FOR_SIBLING: " . $o_logfile . "\n";
+    close BOS;
+}
+
+
+sub step__busyb_create_directories
+{
+    print_status ($_[0] . ". Creating directories ($make)");
+
+    # create all the directories using the BUSYB makefile
+
+    $command = "$make -f $makeFile MAKEDEPEND=0 allOutDirs";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Can't create directories ($!), aborting";
+    print "\n";
+}
+
+
+sub step__busyb_process_interfaces
+{
+    print_status ($_[0] . ". Processing SAP/MSG interfaces ($make)");
+
+    # process SAP/MSG documents using the BUSYB makefile
+
+    $command = "$make -f $makeFile MAKEDEPEND=0 mconst";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Can't process SAP/MSG documents ($!), aborting";
+    print "\n";
+}
+
+
+#-------------------------------------------------------------------------------
+# generate ccddata_dll.dll (requires cl.exe, see determine_cl_version() above)
+#-------------------------------------------------------------------------------
+sub step__generate_ccddata_dll
+{
+    if ($generate_ccddata_dll)
+    {
+        print_status ($_[0] . ". Generating ccddata_dll.dll ($make)");
+
+        chdir $gpf_ccd
+            or die "ERROR: Can't cd to \"$gpf_ccd\" ($!), aborting";
+
+        #FIXME: PROJECT=gprs may always be used...? Check with Henning.
+        my $out_dir = $cdginc_tools_dir;
+        $out_dir =~ s:/cdginc.+::;
+
+        $command = "$make -f ccddata.mk TARGET=win32 PROJECT=gprs \
+            GPF=$gpf_root \
+            CCDDATA_LIB=$current_dir/$out_dir/bin/ccddata_dll.dll \
+            CDGINCDIR=$current_dir/$cdginc_tools_dir \
+            OBJDIR=$current_dir/$cdginc_tools_dir";
+        print "$command\n\n";
+
+        system($command) == 0
+            or print "WARNING: Error while executing ccddata.mk ($!), continuing build.\n";
+        print "\n";
+
+        chdir $current_dir
+            or die "ERROR: Can't cd to \"$current_dir\" ($!), aborting";
+    }
+    else
+    {
+        print_status ($_[0] . ". Skipping ccddata_dll.dll generation (cl.exe not found)");
+    }
+}
+
+
+#-------------------------------------------------------------------------------
+# generate makefiles <variant>_condat_lib_ip.mak and <variant>_condat_var.mak for ABC
+#-------------------------------------------------------------------------------
+sub step__generate_interface_for_abc
+{
+    print_status ($_[0] . ". Generate interface for ABC (<variant>_condat_*.mak)");
+
+    $condat_lib_ip_mak = $busyb_prefix . "condat_lib_ip.mak";
+    $condat_var_mak = $busyb_prefix . "condat_var.mak";
+
+    print "cdginc output dir: \"" . $cdginc_dir . "\"\n\n";
+
+    # Berlin libs
+    my $berlin_libs;
+    foreach my $lib (@busyb_libs)
+    {
+        $berlin_libs .= " \$(CONDAT_BASE_DIR)/../$lib";
+    }
+
+    # Berlin intram libs + their placements
+    my $berlin_bss_libs;
+    my $berlin_const_libs;
+    foreach my $place (@intram_libs)
+    {
+        next if ($place =~ /chipsetsw\//);
+        if ($place =~ /BSS_LIBS/)
+        {
+            (my $bss = $place) =~ s/CONST_LIBS\s+\(.*\)//;
+            $bss =~ s/\(+BSS_LIBS\s+(\([^)]+\))/$1/;
+            $berlin_bss_libs .= " \$(CONDAT_BASE_DIR)/../$bss"
+                if ($bss ne "");
+        }
+        if ($place =~ /CONST_LIBS/)
+        {
+            (my $const = $place) =~ s/BSS_LIBS\s+\(\.\w+\)\s+//;
+            $const =~ s/\(+CONST_LIBS\s+(\([^)]+\))\)*/$1/;
+            $berlin_const_libs .= " \$(CONDAT_BASE_DIR)/../$const"
+                if ($const ne "");
+        }
+    }
+
+    # generate <variant>.condat_lib_ip.mak
+    print "Generating condat/" . $condat_lib_ip_mak . "\n";
+    open (CONDAT_LIB_IP, ">condat/" . $condat_lib_ip_mak)
+        or die "ERROR: could not open file \"condat/" . $condat_lib_ip_mak . "\" for writing ($!),";
+    print CONDAT_LIB_IP "# This file is auto-generated, do not change!
+ifndef CONDAT_LIB_IP_MAK # to avoid multiple condat_lib_ip.mak (import + include)
+	export CONDAT_LIB_IP_MAK := 1
+
+ifndef GPF_DIR
+	export GPF_DIR := \$(CONDAT_BASE_DIR)/../../gpf
+	export CONDAT_DIR := \$(CONDAT_BASE_DIR)
+endif
+
+    L23_NAMES := \$(NCMPMODE)\$(NMMI)\$(NPMODE)\$(NPKTIO)\$(NSRVC)\$(NSTD)\$(NTK)\$(NWAP)\$(NGAME)\$(NEMS)\$(NMMS)\$(NHZONE)\$(NUNIC)\$(NCHIMMI)\$(NETXT)\$(NPDU)\$(NPS)\$(NEM)\$(NDP)\$(NCOMPTRC)\$(NEOTD)\$(NTTY)\$(NCPHS)\$(NBT)
+
+export CONDAT_INCLUDES := \$(CONDAT_BASE_DIR)/com/include \$(CONDAT_BASE_DIR)/ms/src/l1 \$(GPF_DIR)/frame/cust_os \$(CONDAT_BASE_DIR)/com/src/comframe/configps \$(GPF_DIR)/inc
+
+export CONDAT_LIBS :=" . $berlin_libs . "
+
+export CONDAT_BSS_LIBS :=" . $berlin_bss_libs . "
+export CONDAT_CONST_LIBS :=" . $berlin_const_libs . "
+
+# extracted from " . $makeFile . "
+export ICDG=\$(CONDAT_BASE_DIR)/../" . $cdginc_dir . "
+export SRCACI=\$(CONDAT_BASE_DIR)/ms/src/aci
+export SRCACIDTIMNG=\$(CONDAT_BASE_DIR)/ms/src/aci_dti_mng
+export SRCACIA=\$(CONDAT_BASE_DIR)/ms/src/acia
+export SRCKSD=\$(CONDAT_BASE_DIR)/ms/src/ksd
+
+endif # ifndef CONDAT_LIB_IP_MAK\n";
+    close CONDAT_LIB_IP;
+
+    # generate <variant>.condat_var.mak
+    print "Generating condat/" . $condat_var_mak . "\n";
+
+    # put all feature flags in <variant>.condat_var.mak, except for
+    # L1, CHIPSET, BOARD, COPY_DOCS, BUILD_UTILITIES, CMP_MODE, MAKE_DEPENDENCIES,
+    # since these are not relevant for ABC
+    $condat_var_variables = $makeVars;
+    $condat_var_variables =~ s/ /\nexport /g;
+    $condat_var_variables =~ s/\nexport L1=/\n#export L1=/;
+    $condat_var_variables =~ s/\nexport CHIPSET=/\n#export CHIPSET=/;
+    $condat_var_variables =~ s/\nexport BOARD=/\n#export BOARD=/;
+    $condat_var_variables =~ s/\nexport COPY_DOCS=/\n#export COPY_DOCS=/;
+    $condat_var_variables =~ s/\nexport BUILD_UTILITIES=/\n#export BUILD_UTILITIES=/;
+    $condat_var_variables =~ s/\nexport CMP_MODE=/\n#export CMP_MODE=/;
+    $condat_var_variables =~ s/\nexport MAKE_DEPENDENCIES=/\n#export MAKE_DEPENDENCIES=/;
+
+    open (CONDAT_VAR, ">condat/" . $condat_var_mak)
+        or die "ERROR: could not open file \"condat/" . $condat_var_mak . "\" for writing ($!),";
+    print CONDAT_VAR "# This file is auto-generated, do not change!
+ifndef CONDAT_VAR_MAK # to avoid multiple condat_var.mak (import + include)
+	export CONDAT_VAR_MAK := 1
+
+# matching " . $o_file . ":
+# all feature flags, except for L1, CHIPSET, BOARD, COPY_DOCS, BUILD_UTILITIES, CMP_MODE, MAKE_DEPENDENCIES
+" . $condat_var_variables . "
+
+endif # ifndef CONDAT_VAR_MAK\n";
+    close CONDAT_VAR;
+} # generate_interface_for_abc
+
+
+sub step__update_abc_config
+{
+    print_status ($_[0] . ". Updating ABC config ($t_updtAbc)");
+
+    chdir $hw_system
+        or die "ERROR: Can't cd to \"$hw_system\" ($!), aborting";
+
+    $command = "$t_perl $t_updtAbc $hw_variant";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Execution of \"$t_updtAbc\" failed ($!), aborting";
+
+    chdir $current_dir
+        or die "ERROR: Can't cd to \"$current_dir\" ($!), aborting";
+}
+
+
+#-------------------------------------------------------------------------------
+# generate include makefile for SSA filenames
+#-------------------------------------------------------------------------------
+
+sub step__extract_abc_variables
+{
+    print_status ($_[0] . ". Extracting ABC variables for Berlin SW ($abc_exports)");
+
+    my $command;
+
+    $command = "$make -f $t_updtBusybInc ABC_EXPORTS_MAKEFILE_NAME=$abc_exports $makeVars";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Execution of \"" . $t_updtBusybInc . "\" failed ($!),\n";
+    print " \n";
+
+    if (! -e $abc_exports) {
+      die "ERROR: File \"$abc_exports\" has not been generated\n"
+    }
+} # extracting_abc_variables
+
+
+
+#-------------------------------------------------------------------------------
+# compiling nice sw using abc
+#-------------------------------------------------------------------------------
+sub step__abc_compilation
+{
+    print_status ($_[0] . ". Compiling Nice SW ($t_abc)");
+
+    my $command;
+
+    # remove some .obj files in the \chipsetsw VOB due to ABC dependency errors
+    # (temporary solution!)
+    ##purge_abc_obj_files();
+    print "\n";
+
+    # compile Nice software w/ ABC
+    chdir $hw_system
+        or die "ERROR: Can't cd to \"" . $hw_system . "\" ($!),";
+
+    $command = "$t_perl $t_abc $hw_variant";
+    if ($abc_opt)
+    {
+        $command .= " -x\"$abc_opt\"";
+    }
+    print "$command\n\n";
+
+    my $res = system($command);
+
+    if ($res != 0)
+    {
+        print_status ("ERROR: BUILD FAILED!");
+        exit 1;
+    }
+
+    chdir $current_dir
+        or die "ERROR: Can't cd to \"" . $current_dir . "\" ($!),";
+} # compiling_nice_sw
+
+
+
+#-------------------------------------------------------------------------------
+# finally run make w/ the generated makefile from BuSyB
+#-------------------------------------------------------------------------------
+
+sub step__busyb_compilation
+{
+    print_status ($_[0] . ". Running BuSyB makefile ($make)");
+
+    # Start progress bar display mechanism
+    start_progress_bar_display();
+
+    my $command;
+
+    $command = "$make -f $makeFile$make_opt";
+    print "$command\n\n";
+
+    if ((system($command) == 0) and (-e $target_image))
+    {
+        print_status ("Build succeeded");
+        $exit_value = 0;
+    }
+    else
+    {
+        print_status ("ERROR: BUILD FAILED!");
+        $exit_value = 1;
+    }
+    # Kill child process if it exists
+    if ($list_of_libs_available == 1) {kill 2, $pid; }
+}
+
+
+
+sub step__busyb_generate_l1_configdef_files
+{
+    print_status ($_[0] . ". Generating Layer1 ConfigDef files");
+
+    chdir ("$hw_layer1\\tools")
+        or die "ERROR: Can't cd to \"" . $hw_system . "\" ($!),";
+
+    $command = "perl -w $hw_system\\Scripts\\L1Config.pl";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Execution of \"" . $command . "\" failed ($!),";
+
+    chdir $current_dir
+        or die "ERROR: Can't cd to \"" . $current_dir . "\" ($!),";
+}
+
+
+sub step__busyb_generate_cfg_files
+{
+    print_status ($_[0] . ". Generating .cfg files ($make)");
+
+    $command = "$make -f $makeFile cfg_files";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Execution of \"" . $command . "\" failed ($!),";
+
+}
+
+
+sub step__busyb_generate_header_files
+{
+    print_status ($_[0] . ". Generating header files ($make)");
+
+    $command = "$make -f $makeFile header_files";
+    print "$command\n\n";
+
+    system($command) == 0
+        or die "ERROR: Execution of \"" . $command . "\" failed ($!),";
+
+}
+
+
+sub step__init_icl470_environment
+{
+    print_status ($_[0] . ". Init icl470 environment");
+
+    print "%TEMPORARY_FILE_DIR: \"" . $hw_system . "/deps_objs/" . $hw_system_objects . "\"\n\n";
+
+    $ENV{'TEMPORARY_FILE_DIR'} = $hw_system . "/deps_objs/" . $hw_system_objects;
+}
+
+#-------------------------------------------------------------------------------
+# this function is used by find() (File::Find) above and removes all found
+# *.obj files (NOTE: some are checked-in, so unlink() will fail)
+#-------------------------------------------------------------------------------
+sub rm_file
+{
+    unlink ($_)
+        if /.*\.obj$/;
+}
+
+
+#-------------------------------------------------------------------------------
+# redirect STDOUT+STDERR to $o_logfile, return 1 if redirection successful or
+# 0 if redirection failed
+#-------------------------------------------------------------------------------
+sub redirect_output
+{
+    my $redirected = 1;
+
+    open (CONSOLE_OUT, ">&STDOUT");
+    open (CONSOLE_ERR, ">&STDERR");
+
+    open (STDOUT, '>', $o_logfile)
+        or $redirected = 0;
+    open (STDERR, ">&STDOUT")
+        or $redirected = 0;
+
+    if ($redirected)
+    {
+        # make output unbuffered
+        select (STDERR); $| = 1;
+        select (STDOUT); $| = 1;
+
+        # install signal handler function for die()
+        $SIG{__DIE__} = \&die_handler
+            or print CONSOLE_ERR "WARNING: Could not install die() signal handler,
+console output may be corrupted when exiting with an error!\n";
+    }
+    else
+    {
+        # redirection failed: use old STDOUT+STDERR
+        restore_redirection();
+
+        print "WARNING: Could not redirect STDOUT+STDERR to " . $o_logfile . ",
+not logging output!\n";
+    }
+
+    return $redirected;
+}
+
+
+#-------------------------------------------------------------------------------
+# close logging to $o_logfile and restore old STDOUT+STDERR
+# (pointing to console)
+#-------------------------------------------------------------------------------
+sub restore_redirection
+{
+    # restore redirected STDOUT+STDERR
+    close (STDOUT);
+    close (STDERR);
+
+    open (STDOUT, ">&CONSOLE_OUT");
+    open (STDERR, ">&CONSOLE_ERR");
+}
+
+
+#-------------------------------------------------------------------------------
+# print die() error message, to also log it to $o_logfile and then restore
+# the STDOUT+STDERR redirection
+#-------------------------------------------------------------------------------
+sub die_handler
+{
+    print STDERR $_[0];
+
+    restore_redirection();
+}
+
+#-------------------------------------------------------------------------------
+# Get number of libraries that have to be generated and display a 'progress bar'
+# during the build according to the number of rebuilt libraries
+#-------------------------------------------------------------------------------
+
+sub start_progress_bar_display
+{
+    # Get libraries list
+    my @libraries = () ;
+    my %libDates ;
+    my $total_lib = 0;
+    my $line;
+
+    open (IN, "<$makeFile")
+        or die "ERROR: could not open file \"" . $makeFile . "\" ($!),";
+
+    while(defined($line = <IN>))
+    {
+        # Check if variable BSB_TARGETS_ALL exists in the makefile
+        if ( ( $line =~ /^BSB_TARGETS_ALL\s*=\s*([^\s]*)\s*(\\*)/ ) ||
+             ( ( $line =~ /\s*([^\s]*)\s*(\\*)/ ) && ( $list_of_libs_available == 1 ) ) )
+        {
+            my $cur_lib = $1 ;
+            my $end = $2 ;
+            $list_of_libs_available = 1 ;
+
+            if ( $cur_lib =~ m/\.lib$/ )
+            {
+                push( @libraries, $cur_lib ) ;
+            }
+
+            if ( $end eq "" ) {last;}
+            next ;
+        }
+    }
+    $total_lib = $#libraries + 1;
+
+    # Retrieve current time (this allows to make time dif with future generated libraries)
+    my $mytime = time;
+
+    # If the list of libraries is available, create the process which take care about the progress
+    # and start display progress
+    if ($list_of_libs_available == 1)
+    {
+        # Create the process to display the progress bar
+        defined($pid = fork)
+            or die "Cannot fork: $!";
+
+        # If child process
+        unless ($pid)
+        {
+            # Flush Output buffer
+            select CONSOLE_OUT;
+            $| = 1;
+
+            # The child process is stopped when the build is finished
+            while (1)
+            {
+                # For the algorithm, we guess that the list of libraries in the array are ordered
+                # in the same way that BuSyB compile these one. This means if the lib at index n
+                # has been rebuilt, that means 100*n/total_lib have been rebuilt (where
+                # total_libs is the number of libs that contribute to the image file)
+                my $i = 0;
+                foreach (reverse( @libraries ))
+                {
+                    my $mlib = "$_" ;
+                    if (-e $mlib) # Check if the library exist
+                    {
+                        if ( ( stat( $mlib ) )[ 10 ] > $mytime ) # Check if the file has been rebuilt
+                        {
+                            last;
+                        }
+                        else
+                        {
+                            $i++;
+                        }
+                    }
+                    else {$i++;} # If the library does not exist, we continue with the
+                                 #previous library in the array
+                }
+                my $nb_generated_libs = $total_lib - $i;
+
+                # Search for the number of files already generated
+                my $progress;
+
+                $progress = sprintf ("%.02d", (100 * $nb_generated_libs)/$total_lib);
+
+                print_progress("Progress : " . $progress . "%");
+
+                sleep 10;
+            }
+        }
+    }
+}
+