| 1 | 709 | jeremybenn | /* Additional functions for the GCC driver on Darwin native.
 | 
      
         | 2 |  |  |    Copyright (C) 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
 | 
      
         | 3 |  |  |    Contributed by Apple Computer Inc.
 | 
      
         | 4 |  |  |  
 | 
      
         | 5 |  |  | This file is part of GCC.
 | 
      
         | 6 |  |  |  
 | 
      
         | 7 |  |  | GCC is free software; you can redistribute it and/or modify
 | 
      
         | 8 |  |  | it under the terms of the GNU General Public License as published by
 | 
      
         | 9 |  |  | the Free Software Foundation; either version 3, or (at your option)
 | 
      
         | 10 |  |  | any later version.
 | 
      
         | 11 |  |  |  
 | 
      
         | 12 |  |  | GCC is distributed in the hope that it will be useful,
 | 
      
         | 13 |  |  | but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
      
         | 14 |  |  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
      
         | 15 |  |  | GNU General Public License for more details.
 | 
      
         | 16 |  |  |  
 | 
      
         | 17 |  |  | You should have received a copy of the GNU General Public License
 | 
      
         | 18 |  |  | along with GCC; see the file COPYING3.  If not see
 | 
      
         | 19 |  |  | <http://www.gnu.org/licenses/>.  */
 | 
      
         | 20 |  |  |  
 | 
      
         | 21 |  |  | #include "config.h"
 | 
      
         | 22 |  |  | #include "system.h"
 | 
      
         | 23 |  |  | #include "coretypes.h"
 | 
      
         | 24 |  |  | #include "tm.h"
 | 
      
         | 25 |  |  | #include "gcc.h"
 | 
      
         | 26 |  |  | #include "opts.h"
 | 
      
         | 27 |  |  |  
 | 
      
         | 28 |  |  | #ifndef CROSS_DIRECTORY_STRUCTURE
 | 
      
         | 29 |  |  | #include <sys/sysctl.h>
 | 
      
         | 30 |  |  | #include "xregex.h"
 | 
      
         | 31 |  |  |  
 | 
      
         | 32 |  |  | static bool
 | 
      
         | 33 |  |  | darwin_find_version_from_kernel (char *new_flag)
 | 
      
         | 34 |  |  | {
 | 
      
         | 35 |  |  |   char osversion[32];
 | 
      
         | 36 |  |  |   size_t osversion_len = sizeof (osversion) - 1;
 | 
      
         | 37 |  |  |   static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE };
 | 
      
         | 38 |  |  |   int major_vers;
 | 
      
         | 39 |  |  |   char minor_vers[6];
 | 
      
         | 40 |  |  |   char * version_p;
 | 
      
         | 41 |  |  |   char * version_pend;
 | 
      
         | 42 |  |  |  
 | 
      
         | 43 |  |  |   /* Determine the version of the running OS.  If we can't, warn user,
 | 
      
         | 44 |  |  |      and do nothing.  */
 | 
      
         | 45 |  |  |   if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion,
 | 
      
         | 46 |  |  |               &osversion_len, NULL, 0) == -1)
 | 
      
         | 47 |  |  |     {
 | 
      
         | 48 |  |  |       warning (0, "sysctl for kern.osversion failed: %m");
 | 
      
         | 49 |  |  |       return false;
 | 
      
         | 50 |  |  |     }
 | 
      
         | 51 |  |  |  
 | 
      
         | 52 |  |  |   /* Try to parse the first two parts of the OS version number.  Warn
 | 
      
         | 53 |  |  |      user and return if it doesn't make sense.  */
 | 
      
         | 54 |  |  |   if (! ISDIGIT (osversion[0]))
 | 
      
         | 55 |  |  |     goto parse_failed;
 | 
      
         | 56 |  |  |   major_vers = osversion[0] - '0';
 | 
      
         | 57 |  |  |   version_p = osversion + 1;
 | 
      
         | 58 |  |  |   if (ISDIGIT (*version_p))
 | 
      
         | 59 |  |  |     major_vers = major_vers * 10 + (*version_p++ - '0');
 | 
      
         | 60 |  |  |   if (major_vers > 4 + 9)
 | 
      
         | 61 |  |  |     goto parse_failed;
 | 
      
         | 62 |  |  |   if (*version_p++ != '.')
 | 
      
         | 63 |  |  |     goto parse_failed;
 | 
      
         | 64 |  |  |   version_pend = strchr(version_p, '.');
 | 
      
         | 65 |  |  |   if (!version_pend)
 | 
      
         | 66 |  |  |     goto parse_failed;
 | 
      
         | 67 |  |  |   if (! ISDIGIT (*version_p))
 | 
      
         | 68 |  |  |     goto parse_failed;
 | 
      
         | 69 |  |  |   strncpy(minor_vers, version_p, version_pend - version_p);
 | 
      
         | 70 |  |  |   minor_vers[version_pend - version_p] = '\0';
 | 
      
         | 71 |  |  |  
 | 
      
         | 72 |  |  |   /* The major kernel version number is 4 plus the second OS version
 | 
      
         | 73 |  |  |      component.  */
 | 
      
         | 74 |  |  |   if (major_vers - 4 <= 4)
 | 
      
         | 75 |  |  |     /* On 10.4 and earlier, the old linker is used which does not
 | 
      
         | 76 |  |  |        support three-component system versions.  */
 | 
      
         | 77 |  |  |     sprintf (new_flag, "10.%d", major_vers - 4);
 | 
      
         | 78 |  |  |   else
 | 
      
         | 79 |  |  |     sprintf (new_flag, "10.%d.%s", major_vers - 4,
 | 
      
         | 80 |  |  |              minor_vers);
 | 
      
         | 81 |  |  |  
 | 
      
         | 82 |  |  |   return true;
 | 
      
         | 83 |  |  |  
 | 
      
         | 84 |  |  |  parse_failed:
 | 
      
         | 85 |  |  |   warning (0, "couldn%'t understand kern.osversion %q.*s",
 | 
      
         | 86 |  |  |            (int) osversion_len, osversion);
 | 
      
         | 87 |  |  |   return false;
 | 
      
         | 88 |  |  | }
 | 
      
         | 89 |  |  |  
 | 
      
         | 90 |  |  | #endif
 | 
      
         | 91 |  |  |  
 | 
      
         | 92 |  |  | /* When running on a Darwin system and using that system's headers and
 | 
      
         | 93 |  |  |    libraries, default the -mmacosx-version-min flag to be the version
 | 
      
         | 94 |  |  |    of the system on which the compiler is running.
 | 
      
         | 95 |  |  |  
 | 
      
         | 96 |  |  |    When building cross or native cross compilers, default to the OSX
 | 
      
         | 97 |  |  |    version of the target (as provided by the most specific target header
 | 
      
         | 98 |  |  |    included in tm.h).  This may be overidden by setting the flag explicitly
 | 
      
         | 99 |  |  |    (or by the MACOSX_DEPLOYMENT_TARGET environment).  */
 | 
      
         | 100 |  |  |  
 | 
      
         | 101 |  |  | static void
 | 
      
         | 102 |  |  | darwin_default_min_version (unsigned int *decoded_options_count,
 | 
      
         | 103 |  |  |                             struct cl_decoded_option **decoded_options)
 | 
      
         | 104 |  |  | {
 | 
      
         | 105 |  |  |   const unsigned int argc = *decoded_options_count;
 | 
      
         | 106 |  |  |   struct cl_decoded_option *const argv = *decoded_options;
 | 
      
         | 107 |  |  |   unsigned int i;
 | 
      
         | 108 |  |  |   static char new_flag[sizeof ("10.0.0") + 6];
 | 
      
         | 109 |  |  |  
 | 
      
         | 110 |  |  |   /* If the command-line is empty, just return.  */
 | 
      
         | 111 |  |  |   if (argc <= 1)
 | 
      
         | 112 |  |  |     return;
 | 
      
         | 113 |  |  |  
 | 
      
         | 114 |  |  |   /* Don't do this if the user specified -mmacosx-version-min= or
 | 
      
         | 115 |  |  |      -mno-macosx-version-min.  */
 | 
      
         | 116 |  |  |   for (i = 1; i < argc; i++)
 | 
      
         | 117 |  |  |     if (argv[i].opt_index == OPT_mmacosx_version_min_)
 | 
      
         | 118 |  |  |       return;
 | 
      
         | 119 |  |  |  
 | 
      
         | 120 |  |  |   /* Retrieve the deployment target from the environment and insert
 | 
      
         | 121 |  |  |      it as a flag.  */
 | 
      
         | 122 |  |  |   {
 | 
      
         | 123 |  |  |     const char * macosx_deployment_target;
 | 
      
         | 124 |  |  |     macosx_deployment_target = getenv ("MACOSX_DEPLOYMENT_TARGET");
 | 
      
         | 125 |  |  |     if (macosx_deployment_target
 | 
      
         | 126 |  |  |         /* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means
 | 
      
         | 127 |  |  |            "use the default".  Or, possibly "use 10.1".  We choose
 | 
      
         | 128 |  |  |            to ignore the environment variable, as if it was never set.  */
 | 
      
         | 129 |  |  |         && macosx_deployment_target[0])
 | 
      
         | 130 |  |  |       {
 | 
      
         | 131 |  |  |         ++*decoded_options_count;
 | 
      
         | 132 |  |  |         *decoded_options = XNEWVEC (struct cl_decoded_option,
 | 
      
         | 133 |  |  |                                     *decoded_options_count);
 | 
      
         | 134 |  |  |         (*decoded_options)[0] = argv[0];
 | 
      
         | 135 |  |  |         generate_option (OPT_mmacosx_version_min_, macosx_deployment_target,
 | 
      
         | 136 |  |  |                          1, CL_DRIVER, &(*decoded_options)[1]);
 | 
      
         | 137 |  |  |         memcpy (*decoded_options + 2, argv + 1,
 | 
      
         | 138 |  |  |                 (argc - 1) * sizeof (struct cl_decoded_option));
 | 
      
         | 139 |  |  |         return;
 | 
      
         | 140 |  |  |       }
 | 
      
         | 141 |  |  |   }
 | 
      
         | 142 |  |  |  
 | 
      
         | 143 |  |  | #ifndef CROSS_DIRECTORY_STRUCTURE
 | 
      
         | 144 |  |  |  
 | 
      
         | 145 |  |  |  /* Try to find the version from the kernel, if we fail - we print a message
 | 
      
         | 146 |  |  |     and give up.  */
 | 
      
         | 147 |  |  |  if (!darwin_find_version_from_kernel (new_flag))
 | 
      
         | 148 |  |  |    return;
 | 
      
         | 149 |  |  |  
 | 
      
         | 150 |  |  | #else
 | 
      
         | 151 |  |  |  
 | 
      
         | 152 |  |  |  /* For cross-compilers, default to the target OS version. */
 | 
      
         | 153 |  |  |  
 | 
      
         | 154 |  |  |  strncpy (new_flag, DEF_MIN_OSX_VERSION, sizeof (new_flag));
 | 
      
         | 155 |  |  |  
 | 
      
         | 156 |  |  | #endif /* CROSS_DIRECTORY_STRUCTURE */
 | 
      
         | 157 |  |  |  
 | 
      
         | 158 |  |  |   /* Add the new flag.  */
 | 
      
         | 159 |  |  |   ++*decoded_options_count;
 | 
      
         | 160 |  |  |   *decoded_options = XNEWVEC (struct cl_decoded_option,
 | 
      
         | 161 |  |  |                               *decoded_options_count);
 | 
      
         | 162 |  |  |   (*decoded_options)[0] = argv[0];
 | 
      
         | 163 |  |  |   generate_option (OPT_mmacosx_version_min_, new_flag,
 | 
      
         | 164 |  |  |                    1, CL_DRIVER, &(*decoded_options)[1]);
 | 
      
         | 165 |  |  |   memcpy (*decoded_options + 2, argv + 1,
 | 
      
         | 166 |  |  |           (argc - 1) * sizeof (struct cl_decoded_option));
 | 
      
         | 167 |  |  |   return;
 | 
      
         | 168 |  |  |  
 | 
      
         | 169 |  |  | }
 | 
      
         | 170 |  |  |  
 | 
      
         | 171 |  |  | /* Translate -filelist and -framework options in *DECODED_OPTIONS
 | 
      
         | 172 |  |  |    (size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
 | 
      
         | 173 |  |  |    considered to be linker inputs in the case that no other inputs are
 | 
      
         | 174 |  |  |    specified.  Handling these options in DRIVER_SELF_SPECS does not
 | 
      
         | 175 |  |  |    suffice because specs are too late to add linker inputs, and
 | 
      
         | 176 |  |  |    handling them in LINK_SPEC does not suffice because the linker will
 | 
      
         | 177 |  |  |    not be called if there are no other inputs.  When native, also
 | 
      
         | 178 |  |  |    default the -mmacosx-version-min flag.  */
 | 
      
         | 179 |  |  |  
 | 
      
         | 180 |  |  | void
 | 
      
         | 181 |  |  | darwin_driver_init (unsigned int *decoded_options_count,
 | 
      
         | 182 |  |  |                     struct cl_decoded_option **decoded_options)
 | 
      
         | 183 |  |  | {
 | 
      
         | 184 |  |  |   unsigned int i;
 | 
      
         | 185 |  |  |  
 | 
      
         | 186 |  |  |   for (i = 1; i < *decoded_options_count; i++)
 | 
      
         | 187 |  |  |     {
 | 
      
         | 188 |  |  |       if ((*decoded_options)[i].errors & CL_ERR_MISSING_ARG)
 | 
      
         | 189 |  |  |         continue;
 | 
      
         | 190 |  |  |       switch ((*decoded_options)[i].opt_index)
 | 
      
         | 191 |  |  |         {
 | 
      
         | 192 |  |  | #if DARWIN_X86
 | 
      
         | 193 |  |  |         case OPT_arch:
 | 
      
         | 194 |  |  |           if (!strcmp ((*decoded_options)[i].arg, "i386"))
 | 
      
         | 195 |  |  |             generate_option (OPT_m32, NULL, 1, CL_DRIVER, &(*decoded_options)[i]);
 | 
      
         | 196 |  |  |           else if (!strcmp ((*decoded_options)[i].arg, "x86_64"))
 | 
      
         | 197 |  |  |             generate_option (OPT_m64, NULL, 1, CL_DRIVER, &(*decoded_options)[i]);
 | 
      
         | 198 |  |  |           break;
 | 
      
         | 199 |  |  | #endif
 | 
      
         | 200 |  |  |  
 | 
      
         | 201 |  |  |         case OPT_filelist:
 | 
      
         | 202 |  |  |         case OPT_framework:
 | 
      
         | 203 |  |  |           ++*decoded_options_count;
 | 
      
         | 204 |  |  |           *decoded_options = XRESIZEVEC (struct cl_decoded_option,
 | 
      
         | 205 |  |  |                                          *decoded_options,
 | 
      
         | 206 |  |  |                                          *decoded_options_count);
 | 
      
         | 207 |  |  |           memmove (*decoded_options + i + 2,
 | 
      
         | 208 |  |  |                    *decoded_options + i + 1,
 | 
      
         | 209 |  |  |                    ((*decoded_options_count - i - 2)
 | 
      
         | 210 |  |  |                     * sizeof (struct cl_decoded_option)));
 | 
      
         | 211 |  |  |           generate_option (OPT_Xlinker, (*decoded_options)[i].arg, 1,
 | 
      
         | 212 |  |  |                            CL_DRIVER, &(*decoded_options)[i + 1]);
 | 
      
         | 213 |  |  |           generate_option (OPT_Xlinker,
 | 
      
         | 214 |  |  |                            (*decoded_options)[i].canonical_option[0], 1,
 | 
      
         | 215 |  |  |                            CL_DRIVER, &(*decoded_options)[i]);
 | 
      
         | 216 |  |  |           break;
 | 
      
         | 217 |  |  |  
 | 
      
         | 218 |  |  |         default:
 | 
      
         | 219 |  |  |           break;
 | 
      
         | 220 |  |  |         }
 | 
      
         | 221 |  |  |     }
 | 
      
         | 222 |  |  |  
 | 
      
         | 223 |  |  |   darwin_default_min_version (decoded_options_count, decoded_options);
 | 
      
         | 224 |  |  | }
 |