]>
Commit | Line | Data |
---|---|---|
e46b55d0 GK |
1 | /* Additional functions for the GCC driver on Darwin native. |
2 | Copyright (C) 2006, 2007 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 | |
2f83c7d6 | 9 | the Free Software Foundation; either version 3, or (at your option) |
e46b55d0 GK |
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 | |
2f83c7d6 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
e46b55d0 GK |
20 | |
21 | #ifndef CROSS_DIRECTORY_STRUCTURE | |
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
25 | #include "tm.h" | |
26 | #include "gcc.h" | |
27 | #include <sys/sysctl.h> | |
28 | #include "xregex.h" | |
29 | ||
30 | #ifndef SWITCH_TAKES_ARG | |
31 | #define SWITCH_TAKES_ARG(CHAR) DEFAULT_SWITCH_TAKES_ARG(CHAR) | |
32 | #endif | |
33 | ||
34 | #ifndef WORD_SWITCH_TAKES_ARG | |
35 | #define WORD_SWITCH_TAKES_ARG(STR) DEFAULT_WORD_SWITCH_TAKES_ARG (STR) | |
36 | #endif | |
37 | ||
38 | /* When running on a Darwin system and using that system's headers and | |
39 | libraries, default the -mmacosx-version-min flag to be the version | |
40 | of the system on which the compiler is running. */ | |
41 | ||
42 | void | |
43 | darwin_default_min_version (int * argc_p, char *** argv_p) | |
44 | { | |
45 | const int argc = *argc_p; | |
46 | char ** const argv = *argv_p; | |
47 | int i; | |
48 | char osversion[32]; | |
49 | size_t osversion_len = sizeof (osversion) - 1; | |
50 | static int osversion_name[2] = { CTL_KERN, KERN_OSRELEASE }; | |
51 | char * version_p; | |
52 | char * version_pend; | |
53 | int major_vers; | |
54 | char minor_vers[6]; | |
55 | static char new_flag[sizeof ("-mmacosx-version-min=10.0.0") + 6]; | |
56 | ||
57 | /* If the command-line is empty, just return. */ | |
58 | if (argc <= 1) | |
59 | return; | |
60 | /* Don't do this if the user has specified -b or -V at the start | |
61 | of the command-line. */ | |
62 | if (argv[1][0] == '-' | |
63 | && (argv[1][1] == 'V' || | |
64 | ((argv[1][1] == 'b') && (NULL != strchr(argv[1] + 2,'-'))))) | |
65 | return; | |
66 | ||
67 | /* Don't do this if the user specified -mmacosx-version-min= or | |
68 | -mno-macosx-version-min. */ | |
69 | for (i = 1; i < argc; i++) | |
70 | if (argv[i][0] == '-') | |
71 | { | |
72 | const char * const p = argv[i]; | |
73 | if (strncmp (p, "-mno-macosx-version-min", 23) == 0 | |
74 | || strncmp (p, "-mmacosx-version-min", 20) == 0) | |
75 | return; | |
76 | ||
77 | /* It doesn't count if it's an argument to a different switch. */ | |
78 | if (p[0] == '-' | |
79 | && ((SWITCH_TAKES_ARG (p[1]) > (p[2] != 0)) | |
80 | || WORD_SWITCH_TAKES_ARG (p + 1))) | |
81 | i++; | |
82 | } | |
83 | ||
84 | /* Retrieve the deployment target from the environment and insert | |
85 | it as a flag. */ | |
86 | { | |
87 | const char * macosx_deployment_target; | |
88 | macosx_deployment_target = getenv ("MACOSX_DEPLOYMENT_TARGET"); | |
89 | if (macosx_deployment_target | |
90 | /* Apparently, an empty string for MACOSX_DEPLOYMENT_TARGET means | |
91 | "use the default". Or, possibly "use 10.1". We choose | |
92 | to ignore the environment variable, as if it was never set. */ | |
93 | && macosx_deployment_target[0]) | |
94 | { | |
95 | ++*argc_p; | |
96 | *argv_p = xmalloc (sizeof (char *) * *argc_p); | |
97 | (*argv_p)[0] = argv[0]; | |
98 | (*argv_p)[1] = concat ("-mmacosx-version-min=", | |
99 | macosx_deployment_target, NULL); | |
100 | memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); | |
101 | return; | |
102 | } | |
103 | } | |
104 | ||
105 | /* Determine the version of the running OS. If we can't, warn user, | |
106 | and do nothing. */ | |
107 | if (sysctl (osversion_name, ARRAY_SIZE (osversion_name), osversion, | |
108 | &osversion_len, NULL, 0) == -1) | |
109 | { | |
110 | fprintf (stderr, "sysctl for kern.osversion failed: %s\n", | |
111 | xstrerror (errno)); | |
112 | return; | |
113 | } | |
114 | ||
115 | /* Try to parse the first two parts of the OS version number. Warn | |
116 | user and return if it doesn't make sense. */ | |
117 | if (! ISDIGIT (osversion[0])) | |
118 | goto parse_failed; | |
119 | major_vers = osversion[0] - '0'; | |
120 | version_p = osversion + 1; | |
121 | if (ISDIGIT (*version_p)) | |
122 | major_vers = major_vers * 10 + (*version_p++ - '0'); | |
123 | if (major_vers > 4 + 9) | |
124 | goto parse_failed; | |
125 | if (*version_p++ != '.') | |
126 | goto parse_failed; | |
127 | version_pend = strchr(version_p, '.'); | |
128 | if (!version_pend) | |
129 | goto parse_failed; | |
130 | if (! ISDIGIT (*version_p)) | |
131 | goto parse_failed; | |
132 | strncpy(minor_vers, version_p, version_pend - version_p); | |
133 | minor_vers[version_pend - version_p] = '\0'; | |
134 | ||
135 | /* The major kernel version number is 4 plus the second OS version | |
136 | component. */ | |
137 | if (major_vers - 4 <= 4) | |
138 | /* On 10.4 and earlier, the old linker is used which does not | |
139 | support three-component system versions. */ | |
140 | sprintf (new_flag, "-mmacosx-version-min=10.%d", major_vers - 4); | |
141 | else | |
142 | sprintf (new_flag, "-mmacosx-version-min=10.%d.%s", major_vers - 4, | |
143 | minor_vers); | |
144 | ||
145 | /* Add the new flag. */ | |
146 | ++*argc_p; | |
147 | *argv_p = xmalloc (sizeof (char *) * *argc_p); | |
148 | (*argv_p)[0] = argv[0]; | |
149 | (*argv_p)[1] = new_flag; | |
150 | memcpy (*argv_p + 2, argv + 1, (argc - 1) * sizeof (char *)); | |
151 | return; | |
152 | ||
153 | parse_failed: | |
154 | fprintf (stderr, "couldn't understand kern.osversion `%.*s'\n", | |
155 | (int) osversion_len, osversion); | |
156 | return; | |
157 | } | |
158 | ||
159 | #endif /* CROSS_DIRECTORY_STRUCTURE */ |