From: Nathan Froyd <froydnj@codesourcery.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH] pass @-files to collect2 and beyond, take 2
Date: Tue, 17 Apr 2007 20:15:00 -0000 [thread overview]
Message-ID: <20070417200340.GM9017@sparrowhawk.codesourcery.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 2333 bytes --]
The attached patch adds special handling to the gcc driver and collect2
to pass @-file arguments to collect2 and subprocesses, respectively,
when they are passed @-file arguments. The motivation behind this is to
avoid argv limits on some systems and/or large compiles.
From the previous discussion[1], the patch now consists of three parts:
1. gcc/configure.gc now defines HAVE_GNU_LD if the user specified
--with-gnu-ld or if the system's ld was found by inspection to be
GNU ld. This was done so that gcc/collect2 would only pass @-files
around when they could be understood by their subprocesses. These
bits are in 'have-gnu-ld.patch'.
2. A new function, 'writeargv', was added to libiberty to commonize
writing an argv--with proper quoting--into an @-file. These bits are
in 'writeargv.patch'.
3. The appropriate bits were added to gcc/{gcc,collect2}.c to pass
@-files if they were invoked with @-files and HAVE_GNU_LD is
defined. These bits are in 'at-file.patch'.
Bootstrapped and regtested on x86_64-unknown-linux-gnu with no
regressions. Tested with an @-file containing multiple files (including
some with names containing characters that needed to be quoted, such as
' ') and '-v' to ensure that collect2 received an @-file properly and
that collect2 passed an @-file to ld.
OK to commit?
-Nathan
[1] http://gcc.gnu.org/ml/gcc-patches/2007-04/msg00829.html
include/
2007-04-17 Nathan Froyd <froydnj@codesourcery.com>
* libiberty.h (writeargv): Declare.
libiberty/
2007-04-17 Nathan Froyd <froydnj@codesourcery.com>
* argv.c (writeargv): New function.
gcc/
2007-04-17 Nathan Froyd <froydnj@codesourcery.com>
* configure.ac: Add define for HAVE_GNU_LD.
* configure: Regenerate.
* config.in: Regenerate.
gcc/
2007-04-17 Nathan Froyd <froydnj@codesourcery.com>
* gcc.c (at_file_supplied): New variable.
(main): Set it if we expanded argv.
(do_spec_1): Pass an @-file to the linker if we were called with
an @-file argument and HAVE_GNU_LD.
* collect2.c (at_file_supplied): New variable.
(response_file): New variable.
(collect_exit): Unlink response_file if necessary.
(handler): Likewise.
(do_wait): Likewise.
(main): Set at_file_supplied if we expanded argv.
(collect_execute): PAss an @-file to subprocesses if we were called
with an @-file argument.
[-- Attachment #2: at-file.patch --]
[-- Type: text/plain, Size: 6355 bytes --]
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c (revision 123923)
+++ gcc/gcc.c (working copy)
@@ -127,6 +127,9 @@ static const char dir_separator_str[] =
/* Flag set by cppspec.c to 1. */
int is_cpp_driver;
+/* Flag set to non-zero if an @file argument has been supplied to gcc. */
+static bool at_file_supplied;
+
/* Flag saying to pass the greatest exit code returned by a sub-process
to the calling program. */
static int pass_exit_codes;
@@ -5006,9 +5009,52 @@ do_spec_1 (const char *spec, int inswitc
int max = n_infiles;
max += lang_specific_extra_outfiles;
- for (i = 0; i < max; i++)
- if (outfiles[i])
- store_arg (outfiles[i], 0, 0);
+#ifdef HAVE_GNU_LD
+ if (at_file_supplied)
+ {
+ /* We are going to expand `%o' to `@FILE', where FILE
+ is a newly-created temporary filename. The filenames
+ that would usually be expanded in place of %o will be
+ written to the temporary file. */
+
+ char *temp_file = make_temp_file ("");
+ char *at_argument;
+ char **argv;
+ int n_files, j, status;
+
+ at_argument = concat ("@", temp_file, NULL);
+ store_arg (at_argument, 0, 0);
+
+ /* Convert OUTFILES into a form suitable for writeargv. */
+
+ /* Determine how many are non-NULL. */
+ for (n_files = 0, i = 0; i < max; i++)
+ n_files += outfiles[i] != NULL;
+
+ argv = alloca (sizeof (char *) * (n_files + 1));
+
+ /* Copy the strings over. */
+ for (i = 0, j = 0; i < max; i++)
+ if (outfiles[i])
+ {
+ argv[j] = (char *) outfiles[i];
+ j++;
+ }
+ argv[j] = NULL;
+
+ status = writeargv (argv, temp_file);
+
+ if (status)
+ fatal ("could not write temporary response file %s",
+ temp_file);
+
+ record_temp_file (temp_file, 1, 1);
+ }
+ else
+#endif
+ for (i = 0; i < max; i++)
+ if (outfiles[i])
+ store_arg (outfiles[i], 0, 0);
break;
}
@@ -6090,6 +6136,7 @@ main (int argc, char **argv)
char *specs_file;
const char *p;
struct user_specs *uptr;
+ char **old_argv = argv;
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
@@ -6100,6 +6147,10 @@ main (int argc, char **argv)
expandargv (&argc, &argv);
+ /* Determine if any expansions were made. */
+ if (argv != old_argv)
+ at_file_supplied = true;
+
prune_options (&argc, &argv);
#ifdef GCC_DRIVER_HOST_INITIALIZATION
Index: gcc/collect2.c
===================================================================
--- gcc/collect2.c (revision 123923)
+++ gcc/collect2.c (working copy)
@@ -1,7 +1,7 @@
/* Collect static initialization info into data structures that can be
traversed by C++ initialization and finalization routines.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
Contributed by Chris Smith (csmith@convex.com).
Heavily modified by Michael Meissner (meissner@cygnus.com),
Per Bothner (bothner@cygnus.com), and John Gilmore (gnu@cygnus.com).
@@ -202,6 +202,9 @@ static struct head exports; /* list of
#endif
static struct head frame_tables; /* list of frame unwind info tables */
+static bool at_file_supplied; /* Whether to use @file arguments */
+static char *response_file; /* Name of any current response file */
+
struct obstack temporary_obstack;
char * temporary_firstobj;
@@ -302,6 +305,9 @@ collect_exit (int status)
if (status != 0 && output_file != 0 && output_file[0])
maybe_unlink (output_file);
+ if (response_file)
+ maybe_unlink (response_file);
+
exit (status);
}
@@ -393,6 +399,9 @@ handler (int signo)
maybe_unlink (export_file);
#endif
+ if (response_file)
+ maybe_unlink (response_file);
+
signal (signo, SIG_DFL);
raise (signo);
}
@@ -793,7 +802,15 @@ main (int argc, char **argv)
char **object_lst;
const char **object;
int first_file;
- int num_c_args = argc+9;
+ int num_c_args;
+ char **old_argv;
+
+ old_argv = argv;
+ expandargv (&argc, &argv);
+ if (argv != old_argv)
+ at_file_supplied = 1;
+
+ num_c_args = argc + 9;
no_demangle = !! getenv ("COLLECT_NO_DEMANGLE");
@@ -1513,6 +1530,12 @@ do_wait (const char *prog, struct pex_ob
error ("%s returned %d exit status", prog, ret);
collect_exit (ret);
}
+
+ if (response_file)
+ {
+ unlink (response_file);
+ response_file = NULL;
+ }
}
\f
@@ -1525,6 +1548,38 @@ collect_execute (const char *prog, char
struct pex_obj *pex;
const char *errmsg;
int err;
+ char *response_arg = NULL;
+ char *response_argv[3] ATTRIBUTE_UNUSED;
+
+#ifdef HAVE_GNU_LD
+ /* If using @file arguments, create a temporary file and put the
+ contents of argv into it. Then change argv to an array corresponding
+ to a single argument @FILE, where FILE is the temporary filename. */
+
+ if (at_file_supplied && argv[0] != NULL)
+ {
+ char **current_argv = argv + 1;
+ char *argv0 = argv[0];
+ int status;
+
+ /* Note: we assume argv contains at least one element; this is
+ checked above. */
+
+ response_file = make_temp_file ("");
+
+ status = writeargv (current_argv, response_file);
+
+ if (status)
+ fatal ("could not create response file %s", response_file);
+
+ response_arg = concat ("@", response_file, NULL);
+ response_argv[0] = argv0;
+ response_argv[1] = response_arg;
+ response_argv[2] = NULL;
+
+ argv = response_argv;
+ }
+#endif
if (vflag || debug)
{
@@ -1568,6 +1623,9 @@ collect_execute (const char *prog, char
fatal (errmsg);
}
+ if (response_arg)
+ free (response_arg);
+
return pex;
}
[-- Attachment #3: writeargv.patch --]
[-- Type: text/plain, Size: 2019 bytes --]
Index: include/libiberty.h
===================================================================
--- include/libiberty.h (revision 123791)
+++ include/libiberty.h (working copy)
@@ -86,6 +86,10 @@ extern char **dupargv (char **) ATTRIBUT
extern void expandargv PARAMS ((int *, char ***));
+/* Write argv to an @-file, inserting necessary quoting. */
+
+extern int writeargv PARAMS ((char **, const char *));
+
/* Return the last component of a path name. Note that we can't use a
prototype here because the parameter is declared inconsistently
across different systems, sometimes as "char *" and sometimes as
Index: libiberty/argv.c
===================================================================
--- libiberty/argv.c (revision 123791)
+++ libiberty/argv.c (working copy)
@@ -290,6 +290,63 @@ char **buildargv (const char *input)
/*
+@deftypefn Extension int writeargv (const char **@var{argv}, char *@{file})
+
+Write each member of ARGV, handling all necessary quoting, to the file
+named by FILE, separated by whitespace. Return 0 on success, non-zero
+if an error occurred.
+
+@end deftypefn
+
+*/
+
+int
+writeargv (char **argv, const char *file)
+{
+ FILE *f;
+ int status = 0;
+
+ f = fopen (file, "w");
+
+ if (!f)
+ return 1;
+
+ while (*argv != NULL)
+ {
+ int ret;
+ const char *arg = *argv;
+
+ while (*arg != EOS)
+ {
+ char c = *arg;
+
+ if (ISSPACE(c) || c == '\\' || c == '\'' || c == '"')
+ if (EOF == fputc ('\\', f))
+ {
+ status = 1;
+ goto done;
+ }
+
+ if (EOF == fputc (c, f))
+ {
+ status = 1;
+ goto done;
+ }
+ arg++;
+ }
+
+ fputc ('\n', f);
+ argv++;
+ }
+
+ done:
+ fclose (f);
+
+ return status;
+}
+
+/*
+
@deftypefn Extension void expandargv (int *@var{argcp}, char ***@var{argvp})
The @var{argcp} and @code{argvp} arguments are pointers to the usual
[-- Attachment #4: have-gnu-ld.patch --]
[-- Type: text/plain, Size: 950 bytes --]
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac (revision 123923)
+++ gcc/configure.ac (working copy)
@@ -206,6 +206,12 @@ if test x"${DEFAULT_LINKER+set}" = x"set
[Define to enable the use of a default linker.])
fi
+if test x"$gnu_ld_flag" = x"yes"; then
+ echo gnu ld flag $gnu_ld_flag >&5
+ AC_DEFINE(HAVE_GNU_LD, 1,
+ [Define if using GNU ld.])
+fi
+
AC_MSG_CHECKING([whether a default linker was specified])
if test x"${DEFAULT_LINKER+set}" = x"set"; then
if test x"$gnu_ld_flag" = x"no"; then
Index: gcc/config.in
===================================================================
--- gcc/config.in (revision 123923)
+++ gcc/config.in (working copy)
@@ -869,6 +869,12 @@
#endif
+/* Define if using GNU ld. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GNU_LD
+#endif
+
+
/* Define if you have the iconv() function. */
#ifndef USED_FOR_TARGET
#undef HAVE_ICONV
next reply other threads:[~2007-04-17 20:03 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-17 20:15 Nathan Froyd [this message]
2007-04-23 20:31 ` Mark Mitchell
2007-04-24 19:21 ` DJ Delorie
2007-04-27 17:56 ` Nathan Froyd
2007-05-01 22:04 ` Andrew Pinski
2007-05-04 19:35 ` Nathan Froyd
2007-05-05 22:19 ` Mark Mitchell
2007-05-07 18:43 ` DJ Delorie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070417200340.GM9017@sparrowhawk.codesourcery.com \
--to=froydnj@codesourcery.com \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).