xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/config/darwin-driver.c (revision a6f3f22f245acb8ee3bbf6871d7dce989204fa97)
1 /* Additional functions for the GCC driver on Darwin native.
2    Copyright (C) 2006-2013 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 char *
33 darwin_find_version_from_kernel (void)
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   char * new_flag;
43 
44   /* Determine the version of the running OS.  If we can't, warn user,
45      and do nothing.  */
46   if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion,
47 	      &osversion_len, NULL, 0) == -1)
48     {
49       warning (0, "sysctl for kern.osversion failed: %m");
50       return NULL;
51     }
52 
53   /* Try to parse the first two parts of the OS version number.  Warn
54      user and return if it doesn't make sense.  */
55   if (! ISDIGIT (osversion[0]))
56     goto parse_failed;
57   major_vers = osversion[0] - '0';
58   version_p = osversion + 1;
59   if (ISDIGIT (*version_p))
60     major_vers = major_vers * 10 + (*version_p++ - '0');
61   if (*version_p++ != '.')
62     goto parse_failed;
63   version_pend = strchr(version_p, '.');
64   if (!version_pend)
65     goto parse_failed;
66   if (! ISDIGIT (*version_p))
67     goto parse_failed;
68   strncpy(minor_vers, version_p, version_pend - version_p);
69   minor_vers[version_pend - version_p] = '\0';
70 
71   /* The major kernel version number is 4 plus the second OS version
72      component.  */
73   if (major_vers - 4 <= 4)
74     /* On 10.4 and earlier, the old linker is used which does not
75        support three-component system versions.  */
76     asprintf (&new_flag, "10.%d", major_vers - 4);
77   else
78     asprintf (&new_flag, "10.%d.%s", major_vers - 4, minor_vers);
79 
80   return new_flag;
81 
82  parse_failed:
83   warning (0, "couldn%'t understand kern.osversion %q.*s",
84 	   (int) osversion_len, osversion);
85   return NULL;
86 }
87 
88 #endif
89 
90 /* When running on a Darwin system and using that system's headers and
91    libraries, default the -mmacosx-version-min flag to be the version
92    of the system on which the compiler is running.
93 
94    When building cross or native cross compilers, default to the OSX
95    version of the target (as provided by the most specific target header
96    included in tm.h).  This may be overidden by setting the flag explicitly
97    (or by the MACOSX_DEPLOYMENT_TARGET environment).  */
98 
99 static void
100 darwin_default_min_version (unsigned int *decoded_options_count,
101 			    struct cl_decoded_option **decoded_options)
102 {
103   const unsigned int argc = *decoded_options_count;
104   struct cl_decoded_option *const argv = *decoded_options;
105   unsigned int i;
106   const char *new_flag;
107 
108   /* If the command-line is empty, just return.  */
109   if (argc <= 1)
110     return;
111 
112   /* Don't do this if the user specified -mmacosx-version-min= or
113      -mno-macosx-version-min.  */
114   for (i = 1; i < argc; i++)
115     if (argv[i].opt_index == OPT_mmacosx_version_min_)
116       return;
117 
118   /* Retrieve the deployment target from the environment and insert
119      it as a flag.  */
120   {
121     const char * macosx_deployment_target;
122     macosx_deployment_target = getenv ("MACOSX_DEPLOYMENT_TARGET");
123     if (macosx_deployment_target
124 	/* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means
125 	   "use the default".  Or, possibly "use 10.1".  We choose
126 	   to ignore the environment variable, as if it was never set.  */
127 	&& macosx_deployment_target[0])
128       {
129 	++*decoded_options_count;
130 	*decoded_options = XNEWVEC (struct cl_decoded_option,
131 				    *decoded_options_count);
132 	(*decoded_options)[0] = argv[0];
133 	generate_option (OPT_mmacosx_version_min_, macosx_deployment_target,
134 			 1, CL_DRIVER, &(*decoded_options)[1]);
135 	memcpy (*decoded_options + 2, argv + 1,
136 		(argc - 1) * sizeof (struct cl_decoded_option));
137 	return;
138       }
139   }
140 
141 #ifndef CROSS_DIRECTORY_STRUCTURE
142 
143   /* Try to find the version from the kernel, if we fail - we print a message
144      and give up.  */
145   new_flag = darwin_find_version_from_kernel ();
146   if (!new_flag)
147     return;
148 
149 #else
150 
151   /* For cross-compilers, default to the target OS version. */
152   new_flag = DEF_MIN_OSX_VERSION;
153 
154 #endif /* CROSS_DIRECTORY_STRUCTURE */
155 
156   /* Add the new flag.  */
157   ++*decoded_options_count;
158   *decoded_options = XNEWVEC (struct cl_decoded_option,
159 			      *decoded_options_count);
160   (*decoded_options)[0] = argv[0];
161   generate_option (OPT_mmacosx_version_min_, new_flag,
162 		   1, CL_DRIVER, &(*decoded_options)[1]);
163   memcpy (*decoded_options + 2, argv + 1,
164 	  (argc - 1) * sizeof (struct cl_decoded_option));
165   return;
166 }
167 
168 /* Translate -filelist and -framework options in *DECODED_OPTIONS
169    (size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
170    considered to be linker inputs in the case that no other inputs are
171    specified.  Handling these options in DRIVER_SELF_SPECS does not
172    suffice because specs are too late to add linker inputs, and
173    handling them in LINK_SPEC does not suffice because the linker will
174    not be called if there are no other inputs.  When native, also
175    default the -mmacosx-version-min flag.  */
176 
177 void
178 darwin_driver_init (unsigned int *decoded_options_count,
179 		    struct cl_decoded_option **decoded_options)
180 {
181   unsigned int i;
182 
183   for (i = 1; i < *decoded_options_count; i++)
184     {
185       if ((*decoded_options)[i].errors & CL_ERR_MISSING_ARG)
186 	continue;
187       switch ((*decoded_options)[i].opt_index)
188 	{
189 #if DARWIN_X86
190 	case OPT_arch:
191 	  if (!strcmp ((*decoded_options)[i].arg, "i386"))
192 	    generate_option (OPT_m32, NULL, 1, CL_DRIVER, &(*decoded_options)[i]);
193 	  else if (!strcmp ((*decoded_options)[i].arg, "x86_64"))
194 	    generate_option (OPT_m64, NULL, 1, CL_DRIVER, &(*decoded_options)[i]);
195 	  break;
196 #endif
197 
198 	case OPT_filelist:
199 	case OPT_framework:
200 	  ++*decoded_options_count;
201 	  *decoded_options = XRESIZEVEC (struct cl_decoded_option,
202 					 *decoded_options,
203 					 *decoded_options_count);
204 	  memmove (*decoded_options + i + 2,
205 		   *decoded_options + i + 1,
206 		   ((*decoded_options_count - i - 2)
207 		    * sizeof (struct cl_decoded_option)));
208 	  generate_option (OPT_Xlinker, (*decoded_options)[i].arg, 1,
209 			   CL_DRIVER, &(*decoded_options)[i + 1]);
210 	  generate_option (OPT_Xlinker,
211 			   (*decoded_options)[i].canonical_option[0], 1,
212 			   CL_DRIVER, &(*decoded_options)[i]);
213 	  break;
214 
215 	default:
216 	  break;
217 	}
218     }
219 
220   darwin_default_min_version (decoded_options_count, decoded_options);
221 }
222