]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/darwin-driver.c
Darwin, Driver - Improve processing of macosx-version-min=
[thirdparty/gcc.git] / gcc / config / darwin-driver.c
CommitLineData
a9540fb6 1/* Additional functions for the GCC driver on Darwin native.
fbd26352 2 Copyright (C) 2006-2019 Free Software Foundation, Inc.
a9540fb6 3 Contributed by Apple Computer Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
038d1e19 9the Free Software Foundation; either version 3, or (at your option)
a9540fb6 10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
038d1e19 18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
a9540fb6 20
a9540fb6 21#include "config.h"
fb296c25 22#include "libiberty.h"
a9540fb6 23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
e62df35b 26#include "opts.h"
35ece5a6 27#include "diagnostic-core.h"
2c2747c3 28
228d982b 29/* Validate a version string (either given on the command line or, perhaps
30 as MACOSX_DEPLOYMENT_TARGET).
31
32 The specs %version-compare() function doesn't accept leading '0' on
33 numbers so strip them out. Do sanity checking here too.
34
35 Return:
36 * original string means it was OK and we didn't want to change it.
37 * new string means it was OK but we rewrote it to avoid possible format
38 problems.
39 * NULL means we didn't like what we saw.
40*/
41
42static const char *
43validate_macosx_version_min (const char *version_str)
44{
45 size_t version_len;
46 unsigned long major, minor, tiny = 0;
47 char *end;
48 const char *old_version = version_str;
49 bool need_rewrite = false;
50
51 version_len = strlen (version_str);
52 if (version_len < 4) /* The minimum would be 10.x */
53 return NULL;
54
55 /* Version string must consist of digits and periods only. */
56 if (strspn (version_str, "0123456789.") != version_len)
57 return NULL;
58
59 if (!ISDIGIT (version_str[0]) || !ISDIGIT (version_str[version_len - 1]))
60 return NULL;
61
62 if (version_str[0] == '0')
63 need_rewrite = true;
64
65 major = strtoul (version_str, &end, 10);
66 version_str = end + ((*end == '.') ? 1 : 0);
67
68 if (major != 10) /* So far .. all MacOS 10 ... */
69 return NULL;
70
71 /* Version string components must be present and numeric. */
72 if (!ISDIGIT (version_str[0]))
73 return NULL;
74
75 /* If we have one or more leading zeros on a component, then rewrite the
76 version string. */
77 if (version_str[0] == '0' && version_str[1] != '\0'
78 && version_str[1] != '.')
79 need_rewrite = true;
80
81 minor = strtoul (version_str, &end, 10);
82 version_str = end + ((*end == '.') ? 1 : 0);
83 if (minor > 99)
84 return NULL;
85
86 /* If 'tiny' is present it must be numeric. */
87 if (*end != '\0' && !ISDIGIT (version_str[0]))
88 return NULL;
89
90 /* If we have one or more leading zeros on a component, then rewrite the
91 version string. */
92 if (*end != '\0' && version_str[0] == '0'
93 && version_str[1] != '\0')
94 need_rewrite = true;
95
96 tiny = strtoul (version_str, &end, 10);
97 if (tiny > 99)
98 return NULL;
99
100 /* Version string must contain no more than three tokens. */
101 if (*end != '\0')
102 return NULL;
103
104 if (need_rewrite)
105 {
106 char *new_version;
107 asprintf (&new_version, "10.%lu.%lu", minor, tiny);
108 return new_version;
109 }
110
111 return old_version;
112}
113
2c2747c3 114#ifndef CROSS_DIRECTORY_STRUCTURE
a9540fb6 115#include <sys/sysctl.h>
116#include "xregex.h"
117
88df51ff 118static char *
119darwin_find_version_from_kernel (void)
05171267 120{
121 char osversion[32];
122 size_t osversion_len = sizeof (osversion) - 1;
123 static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE };
124 int major_vers;
05171267 125 char * version_p;
88df51ff 126 char * new_flag;
05171267 127
128 /* Determine the version of the running OS. If we can't, warn user,
129 and do nothing. */
130 if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion,
131 &osversion_len, NULL, 0) == -1)
132 {
133 warning (0, "sysctl for kern.osversion failed: %m");
88df51ff 134 return NULL;
05171267 135 }
136
137 /* Try to parse the first two parts of the OS version number. Warn
138 user and return if it doesn't make sense. */
139 if (! ISDIGIT (osversion[0]))
140 goto parse_failed;
141 major_vers = osversion[0] - '0';
142 version_p = osversion + 1;
143 if (ISDIGIT (*version_p))
144 major_vers = major_vers * 10 + (*version_p++ - '0');
05171267 145 if (*version_p++ != '.')
146 goto parse_failed;
05171267 147
148 /* The major kernel version number is 4 plus the second OS version
149 component. */
150 if (major_vers - 4 <= 4)
151 /* On 10.4 and earlier, the old linker is used which does not
aaa50706 152 support three-component system versions.
153 FIXME: we should not assume this - a newer linker could be used. */
88df51ff 154 asprintf (&new_flag, "10.%d", major_vers - 4);
05171267 155 else
8b917ced 156 /* Although the newer linker supports three-component system
157 versions, there's no guarantee that the minor version component
158 of the kernel and the system are the same. Apple's clang always
159 uses 0 as the minor version: do the same. */
160 asprintf (&new_flag, "10.%d.0", major_vers - 4);
05171267 161
88df51ff 162 return new_flag;
05171267 163
164 parse_failed:
165 warning (0, "couldn%'t understand kern.osversion %q.*s",
166 (int) osversion_len, osversion);
88df51ff 167 return NULL;
05171267 168}
05171267 169#endif
170
a9540fb6 171/* When running on a Darwin system and using that system's headers and
172 libraries, default the -mmacosx-version-min flag to be the version
05171267 173 of the system on which the compiler is running.
174
175 When building cross or native cross compilers, default to the OSX
176 version of the target (as provided by the most specific target header
177 included in tm.h). This may be overidden by setting the flag explicitly
178 (or by the MACOSX_DEPLOYMENT_TARGET environment). */
a9540fb6 179
fb296c25 180static const char *
181darwin_default_min_version (void)
a9540fb6 182{
fb296c25 183 /* Try to retrieve the deployment target from the environment. */
184 const char *new_flag = getenv ("MACOSX_DEPLOYMENT_TARGET");
a9540fb6 185
fb296c25 186 /* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means
187 "use the default". Or, possibly "use 10.1". We choose
188 to ignore the environment variable, as if it was never set. */
189 if (new_flag == NULL || new_flag[0] == 0)
05171267 190#ifndef CROSS_DIRECTORY_STRUCTURE
fb296c25 191 /* Try to find the version from the kernel, if we fail - we print a
192 message and give up. */
193 new_flag = darwin_find_version_from_kernel ();
05171267 194#else
fb296c25 195 /* For cross-compilers, default to a minimum version determined by
196 the configuration. */
197 new_flag = DEF_MIN_OSX_VERSION;
05171267 198#endif /* CROSS_DIRECTORY_STRUCTURE */
a9540fb6 199
fb296c25 200 if (new_flag != NULL)
201 {
228d982b 202 const char *checked = validate_macosx_version_min (new_flag);
203 if (checked == NULL)
204 {
205 warning (0, "couldn%'t understand version %s\n", new_flag);
206 return NULL;
207 }
208 new_flag = xstrndup (checked, strlen (checked));
fb296c25 209 }
210 return new_flag;
a9540fb6 211}
212
2c2747c3 213/* Translate -filelist and -framework options in *DECODED_OPTIONS
214 (size *DECODED_OPTIONS_COUNT) to use -Xlinker so that they are
215 considered to be linker inputs in the case that no other inputs are
216 specified. Handling these options in DRIVER_SELF_SPECS does not
217 suffice because specs are too late to add linker inputs, and
218 handling them in LINK_SPEC does not suffice because the linker will
219 not be called if there are no other inputs. When native, also
220 default the -mmacosx-version-min flag. */
221
222void
223darwin_driver_init (unsigned int *decoded_options_count,
224 struct cl_decoded_option **decoded_options)
225{
226 unsigned int i;
bc362791 227 bool seenX86 = false;
228 bool seenX86_64 = false;
229 bool seenPPC = false;
230 bool seenPPC64 = false;
231 bool seenM32 = false;
232 bool seenM64 = false;
233 bool appendM32 = false;
234 bool appendM64 = false;
fb296c25 235 const char *vers_string = NULL;
236 bool seen_version_min = false;
2c2747c3 237
238 for (i = 1; i < *decoded_options_count; i++)
239 {
240 if ((*decoded_options)[i].errors & CL_ERR_MISSING_ARG)
241 continue;
bc362791 242
2c2747c3 243 switch ((*decoded_options)[i].opt_index)
244 {
22db0e0c 245 case OPT_arch:
bc362791 246 /* Support provision of a single -arch xxxx flag as a means of
247 specifying the sub-target/multi-lib. Translate this into -m32/64
248 as appropriate. */
22db0e0c 249 if (!strcmp ((*decoded_options)[i].arg, "i386"))
bc362791 250 seenX86 = true;
22db0e0c 251 else if (!strcmp ((*decoded_options)[i].arg, "x86_64"))
bc362791 252 seenX86_64 = true;
253 else if (!strcmp ((*decoded_options)[i].arg, "ppc"))
254 seenPPC = true;
255 else if (!strcmp ((*decoded_options)[i].arg, "ppc64"))
256 seenPPC64 = true;
257 else
258 error ("this compiler does not support %s",
259 (*decoded_options)[i].arg);
260 /* Now we've examined it, drop the -arch arg. */
261 if (*decoded_options_count > i) {
262 memmove (*decoded_options + i,
263 *decoded_options + i + 1,
264 ((*decoded_options_count - i)
265 * sizeof (struct cl_decoded_option)));
266 }
267 --i;
268 --*decoded_options_count;
269 break;
270
271 case OPT_m32:
272 seenM32 = true;
273 break;
274
275 case OPT_m64:
276 seenM64 = true;
22db0e0c 277 break;
22db0e0c 278
2c2747c3 279 case OPT_filelist:
280 case OPT_framework:
281 ++*decoded_options_count;
282 *decoded_options = XRESIZEVEC (struct cl_decoded_option,
283 *decoded_options,
284 *decoded_options_count);
285 memmove (*decoded_options + i + 2,
286 *decoded_options + i + 1,
287 ((*decoded_options_count - i - 2)
288 * sizeof (struct cl_decoded_option)));
289 generate_option (OPT_Xlinker, (*decoded_options)[i].arg, 1,
290 CL_DRIVER, &(*decoded_options)[i + 1]);
291 generate_option (OPT_Xlinker,
292 (*decoded_options)[i].canonical_option[0], 1,
293 CL_DRIVER, &(*decoded_options)[i]);
294 break;
295
fb296c25 296 case OPT_mmacosx_version_min_:
297 seen_version_min = true;
228d982b 298 vers_string =
299 validate_macosx_version_min ((*decoded_options)[i].arg);
300 if (vers_string == NULL)
301 warning (0, "%qs is not valid for %<mmacosx-version-min%>\n",
302 (*decoded_options)[i].arg);
303 else if (vers_string == (*decoded_options)[i].arg)
304 vers_string = xstrndup ((*decoded_options)[i].arg, 32);
305 /* Now we've examined it, and verified/re-written, put it to
306 one side and append later. */
307 if (*decoded_options_count > i) {
308 memmove (*decoded_options + i,
309 *decoded_options + i + 1,
310 ((*decoded_options_count - i)
311 * sizeof (struct cl_decoded_option)));
312 }
313 --i;
314 --*decoded_options_count;
315 break;
fb296c25 316
2c2747c3 317 default:
318 break;
319 }
320 }
321
bc362791 322 /* Turn -arch xxxx into the appropriate -m32/-m64 flag.
323 If the User tried to specify multiple arch flags (which is possible with
324 some Darwin compilers) warn that this mode is not supported by this
325 compiler (and ignore the arch flags, which means that the default multi-
326 lib will be generated). */
327 /* TODO: determine if these warnings would better be errors. */
328#if DARWIN_X86
329 if (seenPPC || seenPPC64)
330 warning (0, "this compiler does not support PowerPC (arch flags ignored)");
331 if (seenX86)
332 {
333 if (seenX86_64 || seenM64)
334 warning (0, "%s conflicts with i386 (arch flags ignored)",
335 (seenX86_64? "x86_64": "m64"));
336 else if (! seenM32) /* Add -m32 if the User didn't. */
337 appendM32 = true;
338 }
339 else if (seenX86_64)
340 {
341 if (seenX86 || seenM32)
342 warning (0, "%s conflicts with x86_64 (arch flags ignored)",
343 (seenX86? "i386": "m32"));
344 else if (! seenM64) /* Add -m64 if the User didn't. */
345 appendM64 = true;
346 }
347#elif DARWIN_PPC
348 if (seenX86 || seenX86_64)
349 warning (0, "this compiler does not support X86 (arch flags ignored)");
350 if (seenPPC)
351 {
352 if (seenPPC64 || seenM64)
353 warning (0, "%s conflicts with ppc (arch flags ignored)",
354 (seenPPC64? "ppc64": "m64"));
355 else if (! seenM32) /* Add -m32 if the User didn't. */
356 appendM32 = true;
357 }
358 else if (seenPPC64)
359 {
360 if (seenPPC || seenM32)
361 warning (0, "%s conflicts with ppc64 (arch flags ignored)",
362 (seenPPC? "ppc": "m32"));
363 else if (! seenM64) /* Add -m64 if the User didn't. */
364 appendM64 = true;
365 }
366#endif
367
368 if (appendM32 || appendM64)
369 {
370 ++*decoded_options_count;
371 *decoded_options = XRESIZEVEC (struct cl_decoded_option,
372 *decoded_options,
373 *decoded_options_count);
374 generate_option (appendM32 ? OPT_m32 : OPT_m64, NULL, 1, CL_DRIVER,
375 &(*decoded_options)[*decoded_options_count - 1]);
376 }
377
fb296c25 378 /* We will need to know the OS X version we're trying to build for here
379 so that we can figure out the mechanism and source for the sysroot to
380 be used. */
381 if (! seen_version_min && *decoded_options_count > 1)
228d982b 382 /* Not set by the User, try to figure it out. */
383 vers_string = darwin_default_min_version ();
384
385 /* Create and push a cleaned up version, plus the major version for
386 assemblers and other cases that need it. */
aaa50706 387 if (vers_string != NULL)
388 {
228d982b 389 ++*decoded_options_count;
390 *decoded_options = XRESIZEVEC (struct cl_decoded_option,
391 *decoded_options,
392 *decoded_options_count);
393 generate_option (OPT_mmacosx_version_min_, vers_string, 1, CL_DRIVER,
394 &(*decoded_options)[*decoded_options_count - 1]);
395
aaa50706 396 char *asm_major = NULL;
5972cd58 397 const char *first_period = strchr(vers_string, '.');
aaa50706 398 if (first_period != NULL)
399 {
5972cd58 400 const char *second_period = strchr(first_period+1, '.');
aaa50706 401 if (second_period != NULL)
402 asm_major = xstrndup (vers_string, second_period-vers_string);
403 else
404 asm_major = xstrdup (vers_string);
405 }
406 /* Else we appear to have a weird macosx version with no major number.
407 Punt on this for now. */
408 if (asm_major != NULL)
409 {
410 ++*decoded_options_count;
411 *decoded_options = XRESIZEVEC (struct cl_decoded_option,
412 *decoded_options,
413 *decoded_options_count);
414 generate_option (OPT_asm_macosx_version_min_, asm_major, 1, CL_DRIVER,
415 &(*decoded_options)[*decoded_options_count - 1]);
416 }
417 }
2c2747c3 418}