1 /* GDC -- D front-end for GCC
2 Copyright (C) 2004 David Friedman
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /* Much taken from g++spec.c */
21 TODO: Remove C++ stuff from lang_specific_driver
26 #include "coretypes.h"
31 /* This bit is set if we saw a `-xfoo' language specification. */
32 #define LANGSPEC (1<<1)
33 /* This bit is set if they did `-lm' or `-lmath'. */
34 #define MATHLIB (1<<2)
35 /* This bit is set if they did `-lc'. */
36 #define WITHLIBC (1<<3)
37 /* This bit is set if the arguments is a D source file. */
38 #define D_SOURCE_FILE (1<<4)
39 /* This bit is set when the argument should not be passed to gcc or the backend */
40 #define REMOVE_ARG (1<<6)
43 #define MATH_LIBRARY "-lm"
45 #ifndef MATH_LIBRARY_PROFILE
46 #define MATH_LIBRARY_PROFILE "-lm"
50 #define LIBPHOBOS "-lgphobos"
52 #ifndef LIBPHOBOS_PROFILE
53 #define LIBPHOBOS_PROFILE "-lgphobos"
56 static char** all_d_sources
= NULL
;
57 static unsigned n_all_d_sources
= 0;
58 static char * output_directory_option
= NULL
;
59 static int output_parents_option
= 0;
60 static char * only_source_option
= NULL
;
62 extern int need_pthreads
;
65 lang_specific_driver (int *in_argc
, const char *const **in_argv
,
66 int *in_added_libraries
)
71 /* If nonzero, the user gave us the `-p' or `-pg' flag. */
72 int saw_profile_flag
= 0;
74 /* If nonzero, the user gave us the `-v' flag. */
75 int saw_verbose_flag
= 0;
77 /* This is a tristate:
78 -1 means we should not link in libstdc++
79 0 means we should link in libstdc++ if it is needed
80 1 means libstdc++ is needed and should be linked in. */
83 /* If nonzero, use the standard D runtime library when linking with
87 /* The number of arguments being added to what's in argv, other than
88 libraries. We use this to track the number of times we've inserted
92 /* Used to track options that take arguments, so we don't go wrapping
93 those with -xc++/-xnone. */
94 const char *quote
= NULL
;
96 /* The new argument list will be contained in this. */
99 /* Nonzero if we saw a `-xfoo' language specification on the
100 command line. Used to avoid adding our own -xc++ if the user
101 already gave a language for the file. */
102 int saw_speclang
= 0;
104 /* "-lm" or "-lmath" if it appears on the command line. */
105 const char *saw_math
= 0;
107 /* "-lc" if it appears on the command line. */
108 const char *saw_libc
= 0;
110 /* An array used to flag each argument that needs a bit set for
111 LANGSPEC, MATHLIB, or WITHLIBC. */
114 /* By default, we throw on the math library if we have one. */
115 int need_math
= (MATH_LIBRARY
[0] != '\0');
117 /* True if we should add -shared-libgcc to the command-line. */
118 int shared_libgcc
= 1;
120 /* The total number of arguments with the new stuff. */
123 /* The argument list. */
124 const char *const *argv
;
126 /* The number of libraries added in. */
129 /* The total number of arguments with the new stuff. */
132 /* If we add libraries, should we read $(libdir)/phobos-threadlib and add that */
133 int add_thread_lib
= 1;
137 added_libraries
= *in_added_libraries
;
139 args
= xcalloc (argc
, sizeof (int));
141 /* Keep track of all source files */
144 for (i
= 1; i
< argc
; i
++)
146 /* If the previous option took an argument, we swallow it here. */
153 /* We don't do this anymore, since we don't get them with minus
155 if (argv
[i
][0] == '\0' || argv
[i
][1] == '\0')
158 if (argv
[i
][0] == '-')
160 if (strcmp (argv
[i
], "-nostdlib") == 0
161 || strcmp (argv
[i
], "-nodefaultlibs") == 0)
165 else if (strcmp (argv
[i
], "-nophoboslib") == 0)
167 added
= 1; // force argument rebuild
169 args
[i
] |= REMOVE_ARG
;
171 else if (strcmp (argv
[i
], "-lm") == 0
172 || strcmp (argv
[i
], "-lmath") == 0
173 || strcmp (argv
[i
], MATH_LIBRARY
) == 0
179 else if (strcmp (argv
[i
], "-lc") == 0)
181 else if (strcmp (argv
[i
], "-pg") == 0 || strcmp (argv
[i
], "-p") == 0)
183 else if (strcmp (argv
[i
], "-v") == 0)
184 saw_verbose_flag
= 1;
185 else if (strncmp (argv
[i
], "-x", 2) == 0)
190 if (argv
[i
][2] != '\0')
192 else if (argv
[i
+1] != NULL
)
194 else /* Error condition, message will be printed later. */
196 if (strcmp (arg
, "c++") == 0
197 || strcmp (arg
, "c++-cpp-output") == 0)
202 else if (((argv
[i
][2] == '\0'
203 && strchr ("bBVDUoeTuIYmLiA", argv
[i
][1]) != NULL
)
204 || strcmp (argv
[i
], "-Xlinker") == 0
205 || strcmp (argv
[i
], "-Tdata") == 0))
207 else if ((argv
[i
][2] == '\0'
208 && strchr ("cSEM", argv
[i
][1]) != NULL
)
209 || strcmp (argv
[i
], "-MM") == 0
210 || strcmp (argv
[i
], "-fsyntax-only") == 0)
212 /* Don't specify libraries if we won't link, since that would
216 else if (strcmp (argv
[i
], "-static-libgcc") == 0
217 || strcmp (argv
[i
], "-static") == 0)
219 else if (strncmp (argv
[i
], "-fonly=", 7) == 0)
223 args
[i
] |= REMOVE_ARG
;
224 only_source_option
= argv
[i
]; //%%TODO: copy/const
226 len
= strlen(only_source_option
);
227 if (len
<= 2 || only_source_option
[len
-1] != 'd' ||
228 only_source_option
[len
-2] != '.') {
229 only_source_option
= concat(only_source_option
, ".d", NULL
);
231 only_source_option
= xstrdup(only_source_option
);
234 else if (strncmp (argv
[i
], "-fod=", 5) == 0)
236 args
[i
] |= REMOVE_ARG
;
237 output_directory_option
= xstrdup(argv
[i
] + 5);
238 fprintf(stderr
, "** outputdir = '%s'\n", output_directory_option
);
240 else if (strcmp (argv
[i
], "-fop") == 0)
242 args
[i
] |= REMOVE_ARG
;
243 output_parents_option
= 1;
244 fprintf(stderr
, "** output parents\n");
246 else if (DEFAULT_WORD_SWITCH_TAKES_ARG (&argv
[i
][1]))
249 /* Pass other options through. */
262 len
= strlen (argv
[i
]);
264 && (argv
[i
][len
- 1] == 'd')
265 && (argv
[i
][len
- 2] == '.'))
268 args
[i
] |= D_SOURCE_FILE
;
271 /* If we don't know that this is a header file, we might
272 need to be linking in the libraries. */
275 if ((len
<= 2 || strcmp (argv
[i
] + (len
- 2), ".H") != 0)
276 && (len
<= 2 || strcmp (argv
[i
] + (len
- 2), ".h") != 0)
277 && (len
<= 3 || strcmp (argv
[i
] + (len
- 3), ".hh") != 0))
284 fatal ("argument to `%s' missing\n", quote
);
286 if (only_source_option
) {
287 all_d_sources
= (char **) xmalloc (n_all_d_sources
* sizeof(char *));
288 n_all_d_sources
= 0; /* will be incremented again below */
291 /* If we know we don't have to do anything, bail now. */
292 if (! added
&& library
<= 0 && ! only_source_option
)
298 /* There's no point adding -shared-libgcc if we don't have a shared
300 #ifndef ENABLE_SHARED_LIBGCC
304 /* Make sure to have room for the trailing NULL argument. */
305 /* There is one extra argument added here for the runtime
306 library: -lgphobos. The -pthread argument is added by
307 setting need_pthreads. */
308 num_args
= argc
+ added
+ need_math
+ shared_libgcc
+ (library
> 0 ? 1 : 0) + 1;
309 arglist
= xmalloc (num_args
* sizeof (char *));
314 /* Copy the 0th argument, i.e., the name of the program itself. */
315 arglist
[i
++] = argv
[j
++];
317 /* NOTE: We start at 1 now, not 0. */
320 if ( args
[i
] & REMOVE_ARG
)
326 arglist
[j
] = argv
[i
];
328 /* Make sure -lstdc++ is before the math library, since libstdc++
329 itself uses those math routines. */
330 if (!saw_math
&& (args
[i
] & MATHLIB
) && library
> 0)
336 if (!saw_libc
&& (args
[i
] & WITHLIBC
) && library
> 0)
342 if (args
[i
] & D_SOURCE_FILE
)
345 all_d_sources
[n_all_d_sources
++] = xstrdup(arglist
[j
]);
346 if ( only_source_option
)
357 if (only_source_option
)
359 arglist
[j
++] = only_source_option
;
360 arglist
[j
++] = only_source_option
+ 7;
363 /* Add `-lstdc++' if we haven't already done so. */
364 if (library
> 0 && phobos
)
366 arglist
[j
++] = saw_profile_flag
? LIBPHOBOS_PROFILE
: LIBPHOBOS
;
371 arglist
[j
++] = saw_math
;
372 else if (library
> 0 && need_math
)
374 arglist
[j
++] = saw_profile_flag
? MATH_LIBRARY_PROFILE
: MATH_LIBRARY
;
378 arglist
[j
++] = saw_libc
;
380 arglist
[j
++] = "-shared-libgcc";
386 *in_added_libraries
= added_libraries
;
389 /* Called before linking. Returns 0 on success and -1 on failure. */
390 int lang_specific_pre_link (void) /* Not used for D. */
397 d_all_sources_spec_function (int argc
, const char ** argv
)
399 unsigned result_len
= 0;
402 if (only_source_option
) {
405 for (i
= 0; i
< n_all_d_sources
; i
++)
406 result_len
+= strlen(all_d_sources
[i
]);
407 result_len
+= n_all_d_sources
+ 1; /* once space to separate each file and terminating null
408 ... really n_all_d_sources - 1 + 1, but ignores n=0 case */
409 result
= (char *) xmalloc(result_len
);
411 for (i
= 0; i
< n_all_d_sources
; i
++) {
414 strcat(result
, all_d_sources
[i
]);
424 d_output_prefix_spec_function (int argc
, const char ** argv
)
427 fprintf(stderr
, "** d_output_prefix_spec_function(%s)\n", argv
[0]);
429 return ""; /* %% should abort */
430 if (output_directory_option
)
431 result
= concat(output_directory_option
, "/", NULL
);
432 if (output_parents_option
) {
435 /* Append the whole input filename and search backwards for
436 the directory separator. */
437 result
= concat(result
, argv
[0], NULL
);
438 p
= result
+ strlen(result
) - 1;
439 while (p
>= result
) {
440 if (IS_DIR_SEPARATOR(*p
)) {
446 fprintf(stderr
, "** -> '%s'\n", result
);
451 /* Number of extra output files that lang_specific_pre_link may generate. */
452 int lang_specific_extra_outfiles
= 0; /* Not used for D. */
454 /* Table of language-specific spec functions. */
455 const struct spec_function lang_specific_spec_functions
[] =
457 { "d-all-sources", d_all_sources_spec_function
},
458 { "d-output-prefix", d_output_prefix_spec_function
},