This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][LTO] "Kill" ltrans-driver(?)
On Wed, 16 Sep 2009, Diego Novillo wrote:
> On Wed, Sep 16, 2009 at 11:06, Richard Guenther <rguenther@suse.de> wrote:
>
> > Diego - any preference on the -fltrans-driver functionality? ÂI could
> > preserve the old behavior if -fltrans-driver=ltrans-driver is specified
> > and make the new behavior the default. ÂOr turn on the new behavior
> > on explicit -fltrans-driver= only (or -fno-ltrans-driver?). ÂBug 39276
> > notes existing portability issues with the ltrans-driver script.
>
> Ripping out the old behaviour is exactly what I had in mind. I don't
> want lto1 to drive the LTRANS phase, I want to give it back to xgcc to
> do the driving. Getting rid of the ltrans-driver is fine. At some
> point we will need to add the capability of launching LTRANS in
> parallel (say via distcc), but that can and should be done from the
> actual driver, not lto1.
>
> So, toss it.
Like the following. Bootstrapped and tested on x86_64-unknown-linux-gnu,
will apply after the last merge is committed.
Richard.
2009-09-17 Richard Guenther <rguenther@suse.de>
PR lto/39276
* doc/invoke.texi (-fltrans-driver): Remove.
lto/
* lto.c (lto_execute_ltrans): Perform ltrans phase manually.
* Make-lang.in: Remove ltrans-driver stuff.
* config-lang.in: Likewise.
* lang.opt (fltrans-driver): Remove.
* lto-lang.c (lto_init_options): Remove code initializing
ltrans_driver.
* ltrans-driver: Remove.
Index: gcc/lto/lto.c
===================================================================
*** gcc/lto/lto.c.orig 2009-09-17 12:00:06.000000000 +0200
--- gcc/lto/lto.c 2009-09-17 12:06:08.000000000 +0200
*************** get_filename_for_set (cgraph_node_set se
*** 843,849 ****
{
/* Since SET does not need to be processed by LTRANS, use
the original file name and mark it with a '*' prefix so that
! lto_execute_ltrans knows not to send it to ltrans_driver. */
cgraph_node_set_iterator si = csi_start (set);
struct cgraph_node *first = csi_node (si);
fname = prefix_name_with_star (first->local.lto_file_data->file_name);
--- 843,849 ----
{
/* Since SET does not need to be processed by LTRANS, use
the original file name and mark it with a '*' prefix so that
! lto_execute_ltrans knows not to not process it. */
cgraph_node_set_iterator si = csi_start (set);
struct cgraph_node *first = csi_node (si);
fname = prefix_name_with_star (first->local.lto_file_data->file_name);
*************** lto_wpa_write_files (void)
*** 945,975 ****
/* Perform local transformations (LTRANS) on the files in the NULL-terminated
FILES array. These should have been written previously by
! lto_wpa_write_files (). Transformations are performed via the
! ltrans_driver executable, which is passed a list of filenames via the
! command line. The CC and CFLAGS environment variables are set to
! appropriate values before it is executed. */
static void
lto_execute_ltrans (char *const *files)
{
struct pex_obj *pex;
! const char *env_val;
! const char *extra_cflags = " -fno-wpa -fltrans -xlto";
struct obstack env_obstack;
const char **argv;
const char **argv_ptr;
const char *errmsg;
! size_t i;
int err;
int status;
FILE *ltrans_output_list_stream = NULL;
timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
/* Initalize the arguments for the LTRANS driver. */
! for (i = 0; files[i]; ++i);
! argv = XNEWVEC (const char *, i + 2);
/* Open the LTRANS output list. */
if (ltrans_output_list)
--- 945,1006 ----
/* Perform local transformations (LTRANS) on the files in the NULL-terminated
FILES array. These should have been written previously by
! lto_wpa_write_files (). Transformations are performed via executing
! COLLECT_GCC for reach file. */
static void
lto_execute_ltrans (char *const *files)
{
struct pex_obj *pex;
! const char *collect_gcc_options, *collect_gcc;
struct obstack env_obstack;
const char **argv;
const char **argv_ptr;
const char *errmsg;
! size_t i, j;
int err;
int status;
FILE *ltrans_output_list_stream = NULL;
timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
+ /* Get the driver and options. */
+ collect_gcc = getenv ("COLLECT_GCC");
+ if (!collect_gcc)
+ fatal_error ("environment variable COLLECT_GCC must be set");
+
+ /* Set the CFLAGS environment variable. */
+ collect_gcc_options = getenv ("COLLECT_GCC_OPTIONS");
+ if (!collect_gcc_options)
+ fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
+
+ /* Count arguments. */
+ i = 0;
+ for (j = 0; collect_gcc_options[j] != '\0'; ++j)
+ if (collect_gcc_options[j] == '\'')
+ ++i;
+ if (i % 2 != 0)
+ fatal_error ("malformed COLLECT_GCC_OPTIONS");
+
/* Initalize the arguments for the LTRANS driver. */
! argv = XNEWVEC (const char *, 8 + i/2);
! argv_ptr = argv;
! *argv_ptr++ = collect_gcc;
! *argv_ptr++ = "-xlto";
! for (j = 0; collect_gcc_options[j] != '\0'; ++j)
! if (collect_gcc_options[j] == '\'')
! {
! ++j;
! i = j;
! while (collect_gcc_options[j] != '\'')
! ++j;
! obstack_init (&env_obstack);
! obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
! obstack_1grow (&env_obstack, 0);
! *argv_ptr++ = XOBFINISH (&env_obstack, char *);
! }
! *argv_ptr++ = "-fno-wpa";
! *argv_ptr++ = "-fltrans";
/* Open the LTRANS output list. */
if (ltrans_output_list)
*************** lto_execute_ltrans (char *const *files)
*** 979,986 ****
error ("opening LTRANS output list %s: %m", ltrans_output_list);
}
- argv_ptr = argv;
- *argv_ptr++ = ltrans_driver;
for (i = 0; files[i]; ++i)
{
size_t len;
--- 1010,1015 ----
*************** lto_execute_ltrans (char *const *files)
*** 1001,1083 ****
}
else
{
/* Otherwise, add FILES[I] to ltrans-driver's command line
and add the resulting file to LTRANS output list. */
- *argv_ptr++ = files[i];
/* Replace the .o suffix with a .ltrans.o suffix and write
the resulting name to the LTRANS output list. */
if (ltrans_output_list_stream)
{
! len = strlen (files[i]) - 2;
! if (fwrite (files[i], 1, len, ltrans_output_list_stream) < len
! || fwrite (".ltrans.o\n", 1, 10, ltrans_output_list_stream)
! < 10)
error ("writing to LTRANS output list %s: %m",
ltrans_output_list);
}
- }
- }
-
- *argv_ptr++ = NULL;
-
- /* Close the LTRANS output list. */
- if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
- error ("closing LTRANS output list %s: %m", ltrans_output_list);
! /* If there are any files to compile, execute the LTRANS driver. */
! if (argv[1] != NULL)
! {
! /* Set the CC environment variable. */
! env_val = getenv ("COLLECT_GCC");
! if (!env_val)
! fatal_error ("environment variable COLLECT_GCC must be set");
!
! obstack_init (&env_obstack);
! obstack_grow (&env_obstack, "CC=", sizeof ("CC=") - 1);
! obstack_grow (&env_obstack, env_val, strlen (env_val) + 1);
! putenv (XOBFINISH (&env_obstack, char *));
!
! /* Set the CFLAGS environment variable. */
! env_val = getenv ("COLLECT_GCC_OPTIONS");
! if (!env_val)
! fatal_error ("environment variable COLLECT_GCC_OPTIONS must be set");
!
! obstack_init (&env_obstack);
! obstack_grow (&env_obstack, "CFLAGS=", sizeof ("CFLAGS=") - 1);
! obstack_grow (&env_obstack, env_val, strlen (env_val));
! obstack_grow (&env_obstack, extra_cflags, strlen (extra_cflags) + 1);
! putenv (XOBFINISH (&env_obstack, char *));
!
! pex = pex_init (0, "lto1", NULL);
! if (pex == NULL)
! fatal_error ("pex_init failed: %s", xstrerror (errno));
!
! errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0],
! CONST_CAST (char **, argv), NULL, NULL, &err);
! if (errmsg)
! fatal_error ("%s: %s", errmsg, xstrerror (err));
! if (!pex_get_status (pex, 1, &status))
! fatal_error ("can't get program status: %s", xstrerror (errno));
! if (status)
! {
! if (WIFSIGNALED (status))
{
! int sig = WTERMSIG (status);
! fatal_error ("%s terminated with signal %d [%s]%s",
! argv[0], sig, strsignal (sig),
! WCOREDUMP (status) ? ", core dumped" : "");
}
- else
- fatal_error ("%s terminated with status %d", argv[0], status);
- }
! pex_free (pex);
}
timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
}
--- 1030,1098 ----
}
else
{
+ char *output_name;
+
/* Otherwise, add FILES[I] to ltrans-driver's command line
and add the resulting file to LTRANS output list. */
/* Replace the .o suffix with a .ltrans.o suffix and write
the resulting name to the LTRANS output list. */
+ obstack_init (&env_obstack);
+ obstack_grow (&env_obstack, files[i], strlen (files[i]) - 2);
+ obstack_grow (&env_obstack, ".ltrans.o", sizeof (".ltrans.o"));
+ output_name = XOBFINISH (&env_obstack, char *);
if (ltrans_output_list_stream)
{
! len = strlen (output_name);
! if (fwrite (output_name, 1, len, ltrans_output_list_stream) < len
! || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1)
error ("writing to LTRANS output list %s: %m",
ltrans_output_list);
}
! argv_ptr[0] = "-o";
! argv_ptr[1] = output_name;
! argv_ptr[2] = files[i];
! argv_ptr[3] = NULL;
!
! /* Execute the driver. */
! pex = pex_init (0, "lto1", NULL);
! if (pex == NULL)
! fatal_error ("pex_init failed: %s", xstrerror (errno));
!
! errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0],
! CONST_CAST (char **, argv), NULL, NULL, &err);
! if (errmsg)
! fatal_error ("%s: %s", errmsg, xstrerror (err));
! if (!pex_get_status (pex, 1, &status))
! fatal_error ("can't get program status: %s", xstrerror (errno));
! if (status)
{
! if (WIFSIGNALED (status))
! {
! int sig = WTERMSIG (status);
! fatal_error ("%s terminated with signal %d [%s]%s",
! argv[0], sig, strsignal (sig),
! WCOREDUMP (status) ? ", core dumped" : "");
! }
! else
! fatal_error ("%s terminated with status %d", argv[0], status);
}
! pex_free (pex);
! }
}
+ /* Close the LTRANS output list. */
+ if (ltrans_output_list_stream && fclose (ltrans_output_list_stream))
+ error ("closing LTRANS output list %s: %m", ltrans_output_list);
+
+ obstack_free (&env_obstack, NULL);
+ free (argv);
+
timevar_pop (TV_WHOPR_WPA_LTRANS_EXEC);
}
Index: gcc/doc/invoke.texi
===================================================================
*** gcc/doc/invoke.texi.orig 2009-09-14 12:21:11.000000000 +0200
--- gcc/doc/invoke.texi 2009-09-17 12:09:20.000000000 +0200
*************** Objective-C and Objective-C++ Dialects}.
*** 348,354 ****
-fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
-fivopts -fkeep-inline-functions -fkeep-static-consts @gol
-floop-block -floop-interchange -floop-strip-mine -fgraphite-identity @gol
! -floop-parallelize-all -fltrans -fltrans-driver -fltrans-output-list @gol
-fmerge-all-constants -fmerge-constants -fmodulo-sched @gol
-fmodulo-sched-allow-regmoves -fmove-loop-invariants -fmudflap @gol
-fmudflapir -fmudflapth -fno-branch-count-reg -fno-default-inline @gol
--- 348,354 ----
-fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
-fivopts -fkeep-inline-functions -fkeep-static-consts @gol
-floop-block -floop-interchange -floop-strip-mine -fgraphite-identity @gol
! -floop-parallelize-all -fltrans -fltrans-output-list @gol
-fmerge-all-constants -fmerge-constants -fmodulo-sched @gol
-fmodulo-sched-allow-regmoves -fmove-loop-invariants -fmudflap @gol
-fmudflapir -fmudflapth -fno-branch-count-reg -fno-default-inline @gol
*************** mode, which reads in summary information
*** 7102,7109 ****
a whole-program analysis based on summary information only. It generates
object files for subsequent runs of the link-time optimizer where
individual object files are optimized using both summary information from
! the WPA mode and the actual function bodies. It then initiates LTRANS by
! executing the LTRANS driver (See @option{-fltrans-driver}.).
Disabled by default. This option is only supported by the LTO frontend.
--- 7102,7109 ----
a whole-program analysis based on summary information only. It generates
object files for subsequent runs of the link-time optimizer where
individual object files are optimized using both summary information from
! the WPA mode and the actual function bodies. It then drives the LTRANS
! phase.
Disabled by default. This option is only supported by the LTO frontend.
*************** In the LTRANS mode, LTO optimizes an obj
*** 7115,7132 ****
Disabled by default. This option is only supported by the LTO frontend.
- @item -fltrans-driver=@var{driver}
- @opindex fltrans-driver
- This option specifies an executable to drive the LTO local transformation
- (LTRANS) mode. When the LTO front end runs in WPA mode (See @option{-fwpa}.),
- it writes new object files and then executes the LTRANS driver. The driver is
- passed a list of object file names, and the CC and CFLAGS environment
- variables are initialized with the compiler driver and flags used to
- initiate WPA. For each input file suffixed with .o, the driver must generate a
- corresponding output file ending in .ltrans.o.
-
- Default value points to the ltrans_driver script installed alongside lto1.
-
@item -fltrans-output-list=@var{file}
@opindex fltrans-output-list
This option specifies a file to which the names of LTRANS output files are
--- 7115,7120 ----
Index: gcc/lto/Make-lang.in
===================================================================
*** gcc/lto/Make-lang.in.orig 2009-07-27 10:57:50.000000000 +0200
--- gcc/lto/Make-lang.in 2009-09-17 12:02:09.000000000 +0200
*************** LINKER_PLUGIN_API_H = $(srcdir)/../inclu
*** 30,43 ****
LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
- LTRANS_DRIVER_EXE := ltrans-driver$(exeext)
-
# Rules
# These hooks are used by the main GCC Makefile. Consult that
# Makefile for documentation.
! lto.all.cross: $(LTO_EXE) $(LTRANS_DRIVER_EXE)
! lto.start.encap: $(LTO_EXE) $(LTRANS_DRIVER_EXE)
lto.rest.encap:
lto.tags:
lto.install-common:
--- 30,41 ----
LTO_TREE_H = lto/lto-tree.h $(LINKER_PLUGIN_API_H)
# Rules
# These hooks are used by the main GCC Makefile. Consult that
# Makefile for documentation.
! lto.all.cross: $(LTO_EXE)
! lto.start.encap: $(LTO_EXE)
lto.rest.encap:
lto.tags:
lto.install-common:
*************** lto.srcinfo:
*** 54,60 ****
lto.install-plugin:
lto.mostlyclean:
! rm -f $(LTO_OBJS) $(LTO_EXE) $(LTRANS_DRIVER_EXE)
lto.clean:
lto.distclean:
--- 52,58 ----
lto.install-plugin:
lto.mostlyclean:
! rm -f $(LTO_OBJS) $(LTO_EXE)
lto.clean:
lto.distclean:
*************** $(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIB
*** 75,83 ****
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
$(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS) -lelf
- $(LTRANS_DRIVER_EXE): $(srcdir)/lto/ltrans-driver
- cp $(srcdir)/lto/ltrans-driver $(LTRANS_DRIVER_EXE)
-
# Dependencies
lto/lto-lang.o: lto/lto-lang.c $(CONFIG_H) coretypes.h debug.h \
flags.h $(GGC_H) langhooks.h $(LANGHOOKS_DEF_H) $(SYSTEM_H) \
--- 73,78 ----
Index: gcc/lto/config-lang.in
===================================================================
*** gcc/lto/config-lang.in.orig 2009-07-07 15:37:44.000000000 +0200
--- gcc/lto/config-lang.in 2009-09-17 12:08:26.000000000 +0200
***************
*** 20,26 ****
#Boston, MA 02110-1301, USA.
language="lto"
! compilers="lto1\$(exeext) ltrans-driver\$(exeext)"
stagestuff="lto1\$(exeext)"
gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c"
--- 20,26 ----
#Boston, MA 02110-1301, USA.
language="lto"
! compilers="lto1\$(exeext)"
stagestuff="lto1\$(exeext)"
gtfiles="\$(srcdir)/lto/lto-tree.h \$(srcdir)/lto/lto-lang.c \$(srcdir)/lto/lto.c"
Index: gcc/lto/lang.opt
===================================================================
*** gcc/lto/lang.opt.orig 2009-07-07 15:37:44.000000000 +0200
--- gcc/lto/lang.opt 2009-09-17 12:01:01.000000000 +0200
*************** fltrans
*** 28,37 ****
LTO Report Var(flag_ltrans) Optimization
Run the link-time optimizer in local transformation (LTRANS) mode.
- fltrans-driver=
- LTO Joined Var(ltrans_driver)
- Specify an executable for performing local transformations on WPA output.
-
fltrans-output-list=
LTO Joined Var(ltrans_output_list)
Specify a file to which a list of files output by LTRANS is written.
--- 28,33 ----
Index: gcc/lto/lto-lang.c
===================================================================
*** gcc/lto/lto-lang.c.orig 2009-09-08 11:13:30.000000000 +0200
--- gcc/lto/lto-lang.c 2009-09-17 12:24:31.000000000 +0200
*************** static GTY(()) tree registered_builtin_f
*** 619,667 ****
/* Language hooks. */
- #define DEFAULT_LTRANS_DRIVER "ltrans-driver"
- #define DEFAULT_LTRANS_DRIVER_LEN (strlen (DEFAULT_LTRANS_DRIVER) + 1)
-
static unsigned int
lto_init_options (unsigned int argc ATTRIBUTE_UNUSED,
! const char **argv)
{
- const char *p;
- char *q;
-
- /* The following code initializes ltrans_driver to its default value.
- We don't necessarily know where we're installed, but lto1 and ltans-driver
- should be in the same directory. If argv[0] contains the full path to
- lto1, use it. Otherwise, we assume ltrans-driver is reachable via the
- PATH environment variable. */
-
- p = argv[0] + strlen (argv[0]);
- while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
- --p;
-
- if (p != argv[0])
- {
- size_t pathlen = p - argv[0];
-
- /* The string at argv[0] is a full path name. Use it to locate the
- LTRANS driver in the same directory. */
- q = XNEWVEC (char, pathlen + DEFAULT_LTRANS_DRIVER_LEN);
- ltrans_driver = q;
- strncpy (q, argv[0], p - argv[0]);
- q += pathlen;
- }
- else
- {
- q = XNEWVEC (char, DEFAULT_LTRANS_DRIVER_LEN);
- ltrans_driver = q;
- }
- strncpy (q, DEFAULT_LTRANS_DRIVER, DEFAULT_LTRANS_DRIVER_LEN);
-
/* Always operate in unit-at-time mode so that we can defer
decisions about what to output. */
flag_unit_at_a_time = 1;
-
return CL_LTO;
}
--- 619,632 ----
/* Language hooks. */
static unsigned int
lto_init_options (unsigned int argc ATTRIBUTE_UNUSED,
! const char **argv ATTRIBUTE_UNUSED)
{
/* Always operate in unit-at-time mode so that we can defer
decisions about what to output. */
flag_unit_at_a_time = 1;
return CL_LTO;
}
Index: gcc/lto/ltrans-driver
===================================================================
*** gcc/lto/ltrans-driver 2009-08-17 16:04:39.000000000 +0200
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
***************
*** 1,104 ****
- #!/bin/sh
-
- # Copyright (C) 2008 Free Software Foundation, Inc.
-
- #This file is part of GCC.
-
- #GCC is free software; you can redistribute it and/or modify it under
- #the terms of the GNU General Public License as published by the Free
- #Software Foundation; either version 2, or (at your option) any later
- #version.
-
- #GCC is distributed in the hope that it will be useful, but WITHOUT
- #ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- #FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- #for more details.
-
- #You should have received a copy of the GNU General Public License
- #along with GCC; see the file COPYING. If not, write to the Free
- #Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- #02110-1301, USA.
-
-
- # This is the default ltrans_driver for LTO. It takes a list of files
- # output during WPA mode and expects the CC and CFLAGS environment variables
- # to be set. It generates a temporary Makefile, and uses it to convert .o
- # files to .ltrans.o files.
-
- # See if CFLAGS includes -v or -save-temps to react accordingly.
- verbose=0
- save_temps=0
- for f in $CFLAGS ; do
- if [ "$f" = "'-v'" ] ; then
- verbose=1
- elif [ "$f" = "'-save-temps'" ] ; then
- save_temps=1
- fi
- done
-
- # Create a temporary directory $tmp in $TMPDIR (default /tmp).
- # Use mktemp if possible; otherwise fall back on mkdir,
- # with $RANDOM to make collisions less likely.
- : ${TMPDIR=/tmp}
- {
- tmp=`
- (umask 077 && mktemp -d "$TMPDIR/ltrans_driverXXXXXX") 2>/dev/null
- ` &&
- test -n "$tmp" && test -d "$tmp"
- } || {
- tmp=$TMPDIR/ltrans_driver$$-$RANDOM
- (umask 077 && mkdir "$tmp")
- } || exit $?
-
- # Remove the temporary directory on exit or if a SIGTERM or SIGINT is
- # received.
- if [ $save_temps -eq 0 ] ; then
- trap 'rm -rf $tmp' TERM INT EXIT
- fi
-
- # Create a temporary Makefile.
- makefile=$tmp/Makefile
- touch $makefile
-
- # We have to clear these to avoid problems with this make invocation getting
- # confused with variables set by (for example) "make -j 2 check".
- unset MAKEFLAGS
- unset MAKEINFO
- unset MAKELEVEL
-
- inputlist="$@"
- outputlist=
- for input in $inputlist
- do
- output=`dirname $input`/`basename $input .o`.ltrans.o
- outputlist="$outputlist $output"
-
- echo "$output: $input" >> $makefile
- echo " \$(CC) \$(CFLAGS) -o $output $input" >> $makefile
- echo >> $makefile
- done
-
- echo ".PHONY: all" >> $makefile
- echo "all: $outputlist" >> $makefile
-
- if [ $verbose -eq 1 ] ; then
- set -x
- fi
-
- # Use some simple heuristics to determine how much parallelism to use
- # when invoking make. Note that this probably only works reliably on
- # Linux. Also, the load may spike right after the calculation, so
- # it's not foolproof.
- awk=/usr/bin/awk
- uptime=/usr/bin/uptime
- getconf=/usr/bin/getconf
- par=1
- if [ $verbose -ne 1 -a -x $awk -a -x $uptime -a -x $getconf ] ; then
- loadavg=$($uptime | $awk '{ l = $(NF - 2); print int (strtonum (l)); }')
- nprocs=$($getconf _NPROCESSORS_ONLN)
- if [ $loadavg -lt $nprocs ] ; then
- par=$[($nprocs - $loadavg) * 2]
- fi
- fi
- ${MAKE-make} -s -f $makefile -j $par all
- exit $?
--- 0 ----