diff gcc/config/darwin-driver.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/config/darwin-driver.c	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/config/darwin-driver.c	Fri Oct 27 22:46:09 2017 +0900
@@ -1,5 +1,5 @@
 /* Additional functions for the GCC driver on Darwin native.
-   Copyright (C) 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2006-2017 Free Software Foundation, Inc.
    Contributed by Apple Computer Inc.
 
 This file is part of GCC.
@@ -19,68 +19,26 @@
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+#include "libiberty.h"
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "gcc.h"
 #include "opts.h"
+#include "diagnostic-core.h"
 
 #ifndef CROSS_DIRECTORY_STRUCTURE
 #include <sys/sysctl.h>
 #include "xregex.h"
 
-/* When running on a Darwin system and using that system's headers and
-   libraries, default the -mmacosx-version-min flag to be the version
-   of the system on which the compiler is running.  */
-
-static void
-darwin_default_min_version (unsigned int *decoded_options_count,
-			    struct cl_decoded_option **decoded_options)
+static char *
+darwin_find_version_from_kernel (void)
 {
-  const unsigned int argc = *decoded_options_count;
-  struct cl_decoded_option *const argv = *decoded_options;
-  unsigned int i;
   char osversion[32];
   size_t osversion_len = sizeof (osversion) - 1;
   static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE };
+  int major_vers;
   char * version_p;
-  char * version_pend;
-  int major_vers;
-  char minor_vers[6];
-  static char new_flag[sizeof ("10.0.0") + 6];
-
-  /* If the command-line is empty, just return.  */
-  if (argc <= 1)
-    return;
-  
-  /* Don't do this if the user specified -mmacosx-version-min= or
-     -mno-macosx-version-min.  */
-  for (i = 1; i < argc; i++)
-    if (argv[i].opt_index == OPT_mmacosx_version_min_)
-      return;
-
-  /* Retrieve the deployment target from the environment and insert
-     it as a flag.  */
-  {
-    const char * macosx_deployment_target;
-    macosx_deployment_target = getenv ("MACOSX_DEPLOYMENT_TARGET");
-    if (macosx_deployment_target
-	/* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means
-	   "use the default".  Or, possibly "use 10.1".  We choose
-	   to ignore the environment variable, as if it was never set.  */
-	&& macosx_deployment_target[0])
-      {
-	++*decoded_options_count;
-	*decoded_options = XNEWVEC (struct cl_decoded_option,
-				    *decoded_options_count);
-	(*decoded_options)[0] = argv[0];
-	generate_option (OPT_mmacosx_version_min_, macosx_deployment_target,
-			 1, CL_DRIVER, &(*decoded_options)[1]);
-	memcpy (*decoded_options + 2, argv + 1,
-		(argc - 1) * sizeof (struct cl_decoded_option));
-	return;
-      }
-  }
+  char * new_flag;
 
   /* Determine the version of the running OS.  If we can't, warn user,
      and do nothing.  */
@@ -88,7 +46,7 @@
 	      &osversion_len, NULL, 0) == -1)
     {
       warning (0, "sysctl for kern.osversion failed: %m");
-      return;
+      return NULL;
     }
 
   /* Try to parse the first two parts of the OS version number.  Warn
@@ -99,47 +57,73 @@
   version_p = osversion + 1;
   if (ISDIGIT (*version_p))
     major_vers = major_vers * 10 + (*version_p++ - '0');
-  if (major_vers > 4 + 9)
-    goto parse_failed;
   if (*version_p++ != '.')
     goto parse_failed;
-  version_pend = strchr(version_p, '.');
-  if (!version_pend)
-    goto parse_failed;
-  if (! ISDIGIT (*version_p))
-    goto parse_failed;
-  strncpy(minor_vers, version_p, version_pend - version_p);
-  minor_vers[version_pend - version_p] = '\0';
   
   /* The major kernel version number is 4 plus the second OS version
      component.  */
   if (major_vers - 4 <= 4)
     /* On 10.4 and earlier, the old linker is used which does not
-       support three-component system versions.  */
-    sprintf (new_flag, "10.%d", major_vers - 4);
+       support three-component system versions.
+       FIXME: we should not assume this - a newer linker could be used.  */
+    asprintf (&new_flag, "10.%d", major_vers - 4);
   else
-    sprintf (new_flag, "10.%d.%s", major_vers - 4,
-	     minor_vers);
+    /* Although the newer linker supports three-component system
+       versions, there's no guarantee that the minor version component
+       of the kernel and the system are the same. Apple's clang always
+       uses 0 as the minor version: do the same.  */
+    asprintf (&new_flag, "10.%d.0", major_vers - 4);
 
-  /* Add the new flag.  */
-  ++*decoded_options_count;
-  *decoded_options = XNEWVEC (struct cl_decoded_option,
-			      *decoded_options_count);
-  (*decoded_options)[0] = argv[0];
-  generate_option (OPT_mmacosx_version_min_, new_flag,
-		   1, CL_DRIVER, &(*decoded_options)[1]);
-  memcpy (*decoded_options + 2, argv + 1,
-	  (argc - 1) * sizeof (struct cl_decoded_option));
-  return;
-  
+  return new_flag;
+
  parse_failed:
   warning (0, "couldn%'t understand kern.osversion %q.*s",
 	   (int) osversion_len, osversion);
-  return;
+  return NULL;
 }
+#endif
 
+/* When running on a Darwin system and using that system's headers and
+   libraries, default the -mmacosx-version-min flag to be the version
+   of the system on which the compiler is running.  
+   
+   When building cross or native cross compilers, default to the OSX
+   version of the target (as provided by the most specific target header
+   included in tm.h).  This may be overidden by setting the flag explicitly
+   (or by the MACOSX_DEPLOYMENT_TARGET environment).  */
+
+static const char *
+darwin_default_min_version (void)
+{
+  /* Try to retrieve the deployment target from the environment.  */
+  const char *new_flag = getenv ("MACOSX_DEPLOYMENT_TARGET");
+
+  /* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means
+     "use the default".  Or, possibly "use 10.1".  We choose
+     to ignore the environment variable, as if it was never set.  */
+  if (new_flag == NULL || new_flag[0] == 0)
+#ifndef CROSS_DIRECTORY_STRUCTURE
+    /* Try to find the version from the kernel, if we fail - we print a
+       message and give up.  */
+    new_flag = darwin_find_version_from_kernel ();
+#else
+    /* For cross-compilers, default to a minimum version determined by
+       the configuration. */
+    new_flag = DEF_MIN_OSX_VERSION;
 #endif /* CROSS_DIRECTORY_STRUCTURE */
 
+  if (new_flag != NULL)
+    {
+      size_t len = strlen (new_flag);
+      if (len > 128) { /* Arbitrary limit, number should be like xx.yy.zz */
+	warning (0, "couldn%'t understand version %s\n", new_flag);
+	return NULL;
+      }
+      new_flag = xstrndup (new_flag, len);
+    }
+  return new_flag;
+}
+
 /* Translate -filelist and -framework options in *DECODED_OPTIONS
    (size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
    considered to be linker inputs in the case that no other inputs are
@@ -154,13 +138,58 @@
 		    struct cl_decoded_option **decoded_options)
 {
   unsigned int i;
+  bool seenX86 = false;
+  bool seenX86_64 = false;
+  bool seenPPC = false;
+  bool seenPPC64 = false;
+  bool seenM32 = false;
+  bool seenM64 = false;
+  bool appendM32 = false;
+  bool appendM64 = false;
+  const char *vers_string = NULL;
+  bool seen_version_min = false;
 
   for (i = 1; i < *decoded_options_count; i++)
     {
       if ((*decoded_options)[i].errors & CL_ERR_MISSING_ARG)
 	continue;
+
       switch ((*decoded_options)[i].opt_index)
 	{
+	case OPT_arch:
+	  /* Support provision of a single -arch xxxx flag as a means of
+	     specifying the sub-target/multi-lib.  Translate this into -m32/64
+	     as appropriate.  */  
+	  if (!strcmp ((*decoded_options)[i].arg, "i386"))
+	    seenX86 = true;
+	  else if (!strcmp ((*decoded_options)[i].arg, "x86_64"))
+	    seenX86_64 = true;
+	  else if (!strcmp ((*decoded_options)[i].arg, "ppc"))
+	    seenPPC = true;
+	  else if (!strcmp ((*decoded_options)[i].arg, "ppc64"))
+	    seenPPC64 = true;
+	  else
+	    error ("this compiler does not support %s",
+		   (*decoded_options)[i].arg);
+	  /* Now we've examined it, drop the -arch arg.  */
+	  if (*decoded_options_count > i) {
+	    memmove (*decoded_options + i,
+		     *decoded_options + i + 1,
+		     ((*decoded_options_count - i)
+		      * sizeof (struct cl_decoded_option)));
+	  }
+	  --i;
+	  --*decoded_options_count; 
+	  break;
+
+	case OPT_m32:
+	  seenM32 = true;
+	  break;
+
+	case OPT_m64:
+	  seenM64 = true;
+	  break;
+
 	case OPT_filelist:
 	case OPT_framework:
 	  ++*decoded_options_count;
@@ -178,12 +207,111 @@
 			   CL_DRIVER, &(*decoded_options)[i]);
 	  break;
 
+	case OPT_mmacosx_version_min_:
+	  seen_version_min = true;
+	  vers_string = xstrndup ((*decoded_options)[i].arg, 32);
+
 	default:
 	  break;
 	}
     }
 
-#ifndef CROSS_DIRECTORY_STRUCTURE
-  darwin_default_min_version (decoded_options_count, decoded_options);
+  /* Turn -arch xxxx into the appropriate -m32/-m64 flag.
+     If the User tried to specify multiple arch flags (which is possible with
+     some Darwin compilers) warn that this mode is not supported by this
+     compiler (and ignore the arch flags, which means that the default multi-
+     lib will be generated).  */
+  /* TODO: determine if these warnings would better be errors.  */
+#if DARWIN_X86
+  if (seenPPC || seenPPC64)
+    warning (0, "this compiler does not support PowerPC (arch flags ignored)");
+  if (seenX86)
+    {
+      if (seenX86_64 || seenM64)
+	warning (0, "%s conflicts with i386 (arch flags ignored)",
+	        (seenX86_64? "x86_64": "m64"));
+      else if (! seenM32) /* Add -m32 if the User didn't. */
+	appendM32 = true;
+    }
+  else if (seenX86_64)
+    {
+      if (seenX86 || seenM32)
+	warning (0, "%s conflicts with x86_64 (arch flags ignored)",
+		 (seenX86? "i386": "m32"));
+      else if (! seenM64) /* Add -m64 if the User didn't. */
+	appendM64 = true;
+    }  
+#elif DARWIN_PPC
+  if (seenX86 || seenX86_64)
+    warning (0, "this compiler does not support X86 (arch flags ignored)");
+  if (seenPPC)
+    {
+      if (seenPPC64 || seenM64)
+	warning (0, "%s conflicts with ppc (arch flags ignored)",
+		 (seenPPC64? "ppc64": "m64"));
+      else if (! seenM32) /* Add -m32 if the User didn't. */
+	appendM32 = true;
+    }
+  else if (seenPPC64)
+    {
+      if (seenPPC || seenM32)
+	warning (0, "%s conflicts with ppc64 (arch flags ignored)",
+		 (seenPPC? "ppc": "m32"));
+      else if (! seenM64) /* Add -m64 if the User didn't. */
+	appendM64 = true;
+    }
 #endif
+
+  if (appendM32 || appendM64)
+    {
+      ++*decoded_options_count;
+      *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+				     *decoded_options,
+				     *decoded_options_count);
+      generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER,
+		       &(*decoded_options)[*decoded_options_count - 1]);
+    }
+
+  /* We will need to know the OS X version we're trying to build for here
+     so that we can figure out the mechanism and source for the sysroot to
+     be used.  */
+  if (! seen_version_min && *decoded_options_count > 1)
+    {
+      /* Not set by the User, try to figure it out.  */
+      vers_string = darwin_default_min_version ();
+      if (vers_string != NULL)
+	{
+	  ++*decoded_options_count;
+	  *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+					 *decoded_options,
+					 *decoded_options_count);
+	  generate_option (OPT_mmacosx_version_min_, vers_string, 1, CL_DRIVER,
+			  &(*decoded_options)[*decoded_options_count - 1]);
+	}
+    }
+  /* Create and push the major version for assemblers that need it.  */
+  if (vers_string != NULL)
+    {
+      char *asm_major = NULL;
+      const char *first_period = strchr(vers_string, '.');
+      if (first_period != NULL)
+	{
+	  const char *second_period = strchr(first_period+1, '.');
+	  if (second_period  != NULL)
+	    asm_major = xstrndup (vers_string, second_period-vers_string);
+	  else
+	    asm_major = xstrdup (vers_string);
+        }
+      /* Else we appear to have a weird macosx version with no major number.
+         Punt on this for now.  */
+      if (asm_major != NULL)
+        {
+	  ++*decoded_options_count;
+	  *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+					 *decoded_options,
+					 *decoded_options_count);
+	  generate_option (OPT_asm_macosx_version_min_, asm_major, 1, CL_DRIVER,
+			  &(*decoded_options)[*decoded_options_count - 1]);
+        }
+    }
 }