Why link C with crtstuff? [patch]

Sergei Ivanov svivanov@pdmi.ras.ru
Sat Apr 25 17:40:00 GMT 1998


Hello

There is a feature of egcs (and gcc 2.8.x) that I don't like.
It links everything with crtbegin[S].o/crtend[S].o which in turn
reference symbols from frame.o. 
This is not good because

1. The executable size increases (+5Kb on my i586-pc-linux-gnulibc1).
crtstuff itself is small, but frame.o is large.

2. It also goes to shared libraries. Imagine one has a library
libxxx.so and builds a program with -lxxx. The linker gets crtbegin.o
and -lxxx before -lgcc, and what is referenced by crtbegin.o is found
in libxxx.so - frame.o is there because of crtbeginS.o!
Now what if the library was built with an older version of egcs/gcc,
and things has been changed since that? Even worse, the binary now
depends on something in libxxx about which only gcc knows.
So future versions of gcc will have to include the same stuff,
with the same interface, into shared libs. Otherwise recompiling
the library will break programs depending on it.

On the other hand, crtstuff is a C++ related thing
and is not needed for pure C code (AFAIK).

So why not link it just like libstdc++, i.e. only by g++ driver?
Let good old C live in a world untouched by dirty hands of C++!

Please look at the below patch against egcs-1.0.2
(quick and a bit illogical, but works for me at least).
It enables %{x...} tests in specs and uses them in linux
startfile/endfile to get rid of crt*.o when not using c++.

E.g,  %{xc++:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}
means that crtbegin[S].o is used by g++ but not by plain gcc.
More precisely, the text under %{xLANG:...} is substituted if either
-xLANG was given to gcc or LANG is defined as the "default language"
of the driver (the patch only defines c++ for g++ but this can be 
trivially extended).
It might be good to pay attention to suffuxes of input files,
but this is not done (yet?). 

Also: {x} is deleted from linker specs (could not work anyway),
and the warning "-x has no effect" is removed.

Maybe `language_specific_driver' (which hacks the command line) can be
completely eliminated and replaced by a similar language-dependent part
of linker specs.

Does this make sense?  Or is it completely silly from the beginning?

Thanks
Sergei
 

The patch follows

diff -urpN egcs-1.0.2.vanilla/gcc/config/linux.h egcs-1.0.2/gcc/config/linux.h
--- egcs-1.0.2.vanilla/gcc/config/linux.h	Sun Feb 15 22:43:54 1998
+++ egcs-1.0.2/gcc/config/linux.h	Thu Apr 23 00:40:41 1998
@@ -70,7 +70,7 @@ Boston, MA 02111-1307, USA.  */
      %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
 		       %{!p:%{profile:gcrt1.o%s} \
 			 %{!profile:crt1.o%s}}}} \
-   crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+   crti.o%s %{xc++:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
 
 /* Provide a ENDFILE_SPEC appropriate for Linux.  Here we tack on
    the Linux magical crtend.o file (see crtstuff.c) which
@@ -80,7 +80,7 @@ Boston, MA 02111-1307, USA.  */
 
 #undef	ENDFILE_SPEC
 #define ENDFILE_SPEC \
-  "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+  "%{xc++:%{!shared:crtend.o%s} %{shared:crtendS.o%s}} crtn.o%s"
 
 /* This is for -profile to use -lc_p instead of -lc. */
 #ifndef CC1_SPEC
diff -urpN egcs-1.0.2.vanilla/gcc/cp/Make-lang.in egcs-1.0.2/gcc/cp/Make-lang.in
--- egcs-1.0.2.vanilla/gcc/cp/Make-lang.in	Sat Nov 22 00:04:09 1997
+++ egcs-1.0.2/gcc/cp/Make-lang.in	Wed Apr 22 23:21:08 1998
@@ -87,6 +87,7 @@ g++.o: $(CONFIG_H) multilib.h config.sta
 	$(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 	$(DRIVER_DEFINES) \
 	-DLANG_SPECIFIC_DRIVER \
+	-DDRIVER_LANGUAGE=\"c++\" \
   -c g++.c
 
 # Create the compiler driver for g++.
diff -urpN egcs-1.0.2.vanilla/gcc/gcc.c egcs-1.0.2/gcc/gcc.c
--- egcs-1.0.2.vanilla/gcc/gcc.c	Mon Sep  1 21:02:40 1997
+++ egcs-1.0.2/gcc/gcc.c	Thu Apr 23 13:27:49 1998
@@ -224,6 +224,12 @@ static struct obstack collect_obstack;
 
 extern char *version_string;
 
+#ifdef DRIVER_LANGUAGE
+static char *driver_language = DRIVER_LANGUAGE;
+#else
+static char *driver_language = 0;
+#endif
+
 /* Forward declaration for prototypes.  */
 struct path_prefix;
 
@@ -707,7 +713,7 @@ static int n_default_compilers
 static char *link_command_spec = "\
 %{!fsyntax-only: \
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
-			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
+			%{r} %{s} %{t} %{u*} %{z} %{Z}\
 			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
 			%{static:} %{L*} %o\
 			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
@@ -719,7 +725,7 @@ static char *link_command_spec = "\
 static char *link_command_spec = "\
 %{!fsyntax-only: \
  %{!c:%{!M:%{!MM:%{!E:%{!S:ld %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
-			%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
+			%{r} %{s} %{t} %{u*} %{z} %{Z}\
 			%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
 			%{static:} %{L*} %D %o\
 			%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
@@ -2333,7 +2339,6 @@ process_command (argc, argv)
   register int i;
   char *temp;
   char *spec_lang = 0;
-  int last_language_n_infiles;
   int have_c = 0;
   int have_o = 0;
   int lang_n_infiles = 0;
@@ -2810,7 +2815,6 @@ process_command (argc, argv)
   infiles = (struct infile *) xmalloc ((n_infiles + 1) * sizeof (struct infile));
   n_switches = 0;
   n_infiles = 0;
-  last_language_n_infiles = -1;
 
   /* This, time, copy the text of each switch and store a pointer
      to the copy in the vector of switches.
@@ -2889,19 +2893,23 @@ process_command (argc, argv)
 
 	  if (c == 'x')
 	    {
-	      if (p[1] == 0 && i + 1 == argc)
-		fatal ("argument to `-x' is missing");
 	      if (p[1] == 0)
-		spec_lang = argv[++i];
-	      else
-		spec_lang = p + 1;
-	      if (! strcmp (spec_lang, "none"))
-		/* Suppress the warning if -xnone comes after the last input
-		   file, because alternate command interfaces like g++ might
-		   find it useful to place -xnone after each input file.  */
-		spec_lang = 0;
-	      else
-		last_language_n_infiles = n_infiles;
+		{
+	          if (i + 1 == argc)
+		    fatal ("argument to `-x' is missing");
+		  /* Pretend that -x is not separated from its argument
+		     so that %{x...} in specs can work.  */
+		  p = xmalloc (strlen (argv[i+1]) + 2);
+		  p[0] = c;
+		  strcpy (p+1, argv[++i]);
+		}
+	      switches[n_switches].part1 = p;
+	      switches[n_switches].args = 0;
+	      switches[n_switches].live_cond = 0;
+	      switches[n_switches].valid = 1;
+	      n_switches++;
+
+	      spec_lang = strcmp (p+1, "none") ? 0 : p+1;
 	      continue;
 	    }
 	  switches[n_switches].part1 = p;
@@ -2975,9 +2983,6 @@ process_command (argc, argv)
 	}
     }
 
-  if (n_infiles == last_language_n_infiles && spec_lang != 0)
-    error ("Warning: `-x %s' after last input file has no effect", spec_lang);
-
   switches[n_switches].part1 = 0;
   infiles[n_infiles].name = 0;
 }
@@ -4038,6 +4043,11 @@ handle_braces (p)
 		  break;
 		}
 	    }
+	  /* -xLANG is "implicitly present" if LANG is the driver's
+	     default language.  */
+	  if (!present && filter[0]=='x' && driver_language
+	      && !strncmp (driver_language, filter+1, p-filter-1))
+	    present = 1;
 	}
 
       /* If it is as desired (present for %{s...}, absent for %{-s...})



More information about the Gcc mailing list