1 /* d-spec.c -- Specific flags and argument handling of the D front end. 2 Copyright (C) 2006-2019 Free Software Foundation, Inc. 3 4 GCC 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 3, or (at your option) 7 any later version. 8 9 GCC 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. 13 14 You should have received a copy of the GNU General Public License 15 along with GCC; see the file COPYING3. If not see 16 <http://www.gnu.org/licenses/>. */ 17 18 #include "config.h" 19 #include "system.h" 20 #include "coretypes.h" 21 #include "opt-suggestions.h" 22 #include "gcc.h" 23 #include "tm.h" 24 #include "opts.h" 25 26 /* This bit is set if the arguments is a D source file. */ 27 #define DSOURCE (1<<1) 28 /* This bit is set if they did `-lstdc++'. */ 29 #define WITHLIBCXX (1<<2) 30 /* Skip this option. */ 31 #define SKIPOPT (1<<3) 32 33 #ifndef LIBSTDCXX 34 #define LIBSTDCXX "stdc++" 35 #endif 36 #ifndef LIBSTDCXX_PROFILE 37 #define LIBSTDCXX_PROFILE LIBSTDCXX 38 #endif 39 40 #ifndef LIBPHOBOS 41 #define LIBPHOBOS "gphobos" 42 #endif 43 #ifndef LIBPHOBOS_PROFILE 44 #define LIBPHOBOS_PROFILE LIBPHOBOS 45 #endif 46 47 #ifndef LIBDRUNTIME 48 #define LIBDRUNTIME "gdruntime" 49 #endif 50 #ifndef LIBDRUNTIME_PROFILE 51 #define LIBDRUNTIME_PROFILE LIBDRUNTIME 52 #endif 53 54 /* What do with libgphobos. */ 55 enum phobos_action 56 { 57 /* libgphobos should not be linked in. */ 58 PHOBOS_NOLINK = -1, 59 /* libgphobos should be linked in if it is needed. */ 60 PHOBOS_DEFAULT = 0, 61 /* libgphobos is needed and should be linked in. */ 62 PHOBOS_LINK, 63 /* libgphobos is needed and should be linked statically. */ 64 PHOBOS_STATIC, 65 /* libgphobos is needed and should be linked dynamically. */ 66 PHOBOS_DYNAMIC, 67 }; 68 69 static phobos_action phobos_library = PHOBOS_DEFAULT; 70 71 /* If true, use the standard D runtime library when linking with 72 standard libraries. */ 73 static bool need_phobos = true; 74 75 /* If true, do load libgphobos.spec even if not needed otherwise. */ 76 static bool need_spec = false; 77 78 void 79 lang_specific_driver (cl_decoded_option **in_decoded_options, 80 unsigned int *in_decoded_options_count, 81 int *in_added_libraries) 82 { 83 unsigned int i, j; 84 85 /* If nonzero, the user gave us the `-p' or `-pg' flag. */ 86 int saw_profile_flag = 0; 87 88 /* If true, the user gave `-g'. Used by -debuglib. */ 89 bool saw_debug_flag = false; 90 91 /* The new argument list will be contained in this. */ 92 cl_decoded_option *new_decoded_options; 93 94 /* "-lstdc++" if it appears on the command line. */ 95 const cl_decoded_option *saw_libcxx = 0; 96 97 /* Whether we need the C++ STD library. */ 98 bool need_stdcxx = false; 99 100 /* True if we saw -static. */ 101 bool static_link = false; 102 103 /* True if we should add -shared-libgcc to the command-line. */ 104 bool shared_libgcc = true; 105 106 /* What default library to use instead of phobos. */ 107 const char *defaultlib = NULL; 108 109 /* What debug library to use instead of phobos. */ 110 const char *debuglib = NULL; 111 112 /* The total number of arguments with the new stuff. */ 113 unsigned int num_args = 1; 114 115 /* "-fonly" if it appears on the command line. */ 116 const char *only_source_option = 0; 117 118 /* Whether the -o option was used. */ 119 bool saw_opt_o = false; 120 121 /* Whether the -c option was used. Also used for -E, -fsyntax-only, 122 in general anything which implies only compilation and not linking. */ 123 bool saw_opt_c = false; 124 125 /* Whether the -S option was used. */ 126 bool saw_opt_S = false; 127 128 /* The first input file with an extension of .d. */ 129 const char *first_d_file = NULL; 130 131 /* The total number of arguments with the new stuff. */ 132 unsigned int argc = *in_decoded_options_count; 133 134 /* The argument list. */ 135 cl_decoded_option *decoded_options = *in_decoded_options; 136 137 /* The number of libraries added in. */ 138 int added_libraries = *in_added_libraries; 139 140 /* An array used to flag each argument that needs a bit set for 141 DSOURCE, MATHLIB, WITHTHREAD, WITHLIBC or WITHLIBCXX. */ 142 int *args = XCNEWVEC (int, argc); 143 144 for (i = 1; i < argc; i++) 145 { 146 const char *arg = decoded_options[i].arg; 147 const int value = decoded_options[i].value; 148 149 switch (decoded_options[i].opt_index) 150 { 151 case OPT_dstartfiles: 152 need_spec = true; 153 break; 154 155 case OPT_nostdlib: 156 case OPT_nodefaultlibs: 157 phobos_library = PHOBOS_NOLINK; 158 break; 159 160 case OPT_nophoboslib: 161 need_phobos = false; 162 args[i] |= SKIPOPT; 163 break; 164 165 case OPT_fdruntime: 166 if (!value) 167 need_phobos = false; 168 break; 169 170 case OPT_defaultlib_: 171 if (defaultlib != NULL) 172 free (CONST_CAST (char *, defaultlib)); 173 if (arg != NULL) 174 { 175 need_phobos = false; 176 args[i] |= SKIPOPT; 177 defaultlib = XNEWVEC (char, strlen (arg)); 178 strcpy (CONST_CAST (char *, defaultlib), arg); 179 } 180 break; 181 182 case OPT_debuglib_: 183 if (debuglib != NULL) 184 free (CONST_CAST (char *, debuglib)); 185 if (arg != NULL) 186 { 187 need_phobos = false; 188 args[i] |= SKIPOPT; 189 debuglib = XNEWVEC (char, strlen (arg)); 190 strcpy (CONST_CAST (char *, debuglib), arg); 191 } 192 break; 193 194 case OPT_l: 195 if ((strcmp (arg, LIBSTDCXX) == 0) 196 || (strcmp (arg, LIBSTDCXX_PROFILE) == 0)) 197 { 198 args[i] |= WITHLIBCXX; 199 need_stdcxx = false; 200 } 201 /* Unrecognized libraries (e.g. -ltango) may require libphobos. */ 202 else if (phobos_library == PHOBOS_DEFAULT) 203 phobos_library = PHOBOS_LINK; 204 break; 205 206 case OPT_pg: 207 case OPT_p: 208 saw_profile_flag++; 209 break; 210 211 case OPT_g: 212 saw_debug_flag = true; 213 break; 214 215 case OPT_v: 216 /* If they only gave us `-v', don't try to link in libphobos. */ 217 if (argc == 2) 218 phobos_library = PHOBOS_NOLINK; 219 break; 220 221 case OPT_x: 222 if (phobos_library == PHOBOS_DEFAULT && (strcmp (arg, "d") == 0)) 223 phobos_library = PHOBOS_LINK; 224 break; 225 226 case OPT_Xlinker: 227 case OPT_Wl_: 228 /* Arguments that go directly to the linker might be .o files 229 or something, and so might cause libphobos to be needed. */ 230 if (phobos_library == PHOBOS_DEFAULT) 231 phobos_library = PHOBOS_LINK; 232 break; 233 234 case OPT_c: 235 case OPT_E: 236 case OPT_M: 237 case OPT_MM: 238 case OPT_fsyntax_only: 239 /* Don't specify libaries if we won't link, since that would 240 cause a warning. */ 241 saw_opt_c = true; 242 phobos_library = PHOBOS_NOLINK; 243 break; 244 245 case OPT_S: 246 saw_opt_S = true; 247 phobos_library = PHOBOS_NOLINK; 248 break; 249 250 case OPT_o: 251 saw_opt_o = true; 252 break; 253 254 case OPT_static: 255 static_link = true; 256 break; 257 258 case OPT_static_libgcc: 259 shared_libgcc = false; 260 break; 261 262 case OPT_static_libphobos: 263 if (phobos_library != PHOBOS_NOLINK) 264 phobos_library = PHOBOS_STATIC; 265 args[i] |= SKIPOPT; 266 break; 267 268 case OPT_shared_libphobos: 269 if (phobos_library != PHOBOS_NOLINK) 270 phobos_library = PHOBOS_DYNAMIC; 271 args[i] |= SKIPOPT; 272 break; 273 274 case OPT_fonly_: 275 args[i] |= SKIPOPT; 276 only_source_option = decoded_options[i].orig_option_with_args_text; 277 278 if (arg != NULL) 279 { 280 const char *suffix = strrchr (only_source_option, '.'); 281 if (suffix == NULL || strcmp (suffix, ".d") != 0) 282 only_source_option = concat (only_source_option, ".d", NULL); 283 } 284 break; 285 286 case OPT_SPECIAL_input_file: 287 { 288 if (arg[0] == '\0' || arg[1] == '\0') 289 continue; 290 291 if (phobos_library == PHOBOS_DEFAULT) 292 phobos_library = PHOBOS_LINK; 293 294 /* Record that this is a D source file. */ 295 const char *suffix = strrchr (arg, '.'); 296 if (suffix != NULL && strcmp (suffix, ".d") == 0) 297 { 298 if (first_d_file == NULL) 299 first_d_file = arg; 300 301 args[i] |= DSOURCE; 302 } 303 304 /* If this is a C++ source file, we'll need to link 305 against libstdc++ library. */ 306 if (suffix != NULL 307 && (strcmp (suffix, ".cc") == 0 308 || (strcmp (suffix, ".cpp") == 0) 309 || (strcmp (suffix, ".c++") == 0))) 310 need_stdcxx = true; 311 312 break; 313 } 314 } 315 } 316 317 /* There's no point adding -shared-libgcc if we don't have a shared 318 libgcc. */ 319 #ifndef ENABLE_SHARED_LIBGCC 320 shared_libgcc = false; 321 #endif 322 323 /* Make sure to have room for the trailing NULL argument. 324 - needstdcxx might add `-lstdcxx' 325 - libphobos adds `-Bstatic -lphobos -ldruntime -Bdynamic' 326 - only_source adds 1 more arg, also maybe add `-o'. */ 327 num_args = argc + need_stdcxx + shared_libgcc + need_phobos * 4 + 2; 328 new_decoded_options = XNEWVEC (cl_decoded_option, num_args); 329 330 i = 0; 331 j = 0; 332 333 /* Copy the 0th argument, i.e., the name of the program itself. */ 334 new_decoded_options[j++] = decoded_options[i++]; 335 336 /* NOTE: We start at 1 now, not 0. */ 337 while (i < argc) 338 { 339 if (args[i] & SKIPOPT) 340 { 341 ++i; 342 continue; 343 } 344 345 new_decoded_options[j] = decoded_options[i]; 346 347 if (!saw_libcxx && (args[i] & WITHLIBCXX)) 348 { 349 --j; 350 saw_libcxx = &decoded_options[i]; 351 } 352 353 if (args[i] & DSOURCE) 354 { 355 if (only_source_option) 356 --j; 357 } 358 359 i++; 360 j++; 361 } 362 363 if (only_source_option) 364 { 365 const char *only_source_arg = only_source_option + 7; 366 generate_option (OPT_fonly_, only_source_arg, 1, CL_DRIVER, 367 &new_decoded_options[j]); 368 j++; 369 370 generate_option_input_file (only_source_arg, 371 &new_decoded_options[j++]); 372 } 373 374 /* If no reason to link against libphobos library, then don't add it. */ 375 if (phobos_library == PHOBOS_DEFAULT) 376 phobos_library = PHOBOS_NOLINK; 377 378 /* If we didn't see a -o option, add one. This is because we need the 379 driver to pass all .d files to the D compiler. Without a -o option 380 the driver will invoke the compiler separately for each input file. */ 381 if (first_d_file != NULL && !saw_opt_o) 382 { 383 if (saw_opt_c || saw_opt_S) 384 { 385 const char *base = lbasename (first_d_file); 386 int baselen = strlen (base) - 2; 387 char *out = XNEWVEC (char, baselen + 3); 388 389 memcpy (out, base, baselen); 390 /* The driver will convert .o to some other suffix if appropriate. */ 391 out[baselen] = '.'; 392 if (saw_opt_S) 393 out[baselen + 1] = 's'; 394 else 395 out[baselen + 1] = 'o'; 396 out[baselen + 2] = '\0'; 397 generate_option (OPT_o, out, 1, CL_DRIVER, 398 &new_decoded_options[j]); 399 } 400 else 401 { 402 /* Wouldn't be necessary if the driver converted .out also. */ 403 const char *out = NULL; 404 405 #ifdef TARGET_EXECUTABLE_SUFFIX 406 if (TARGET_EXECUTABLE_SUFFIX[0] != 0) 407 out = "a" TARGET_EXECUTABLE_SUFFIX; 408 #endif 409 if (out == NULL) 410 out = "a.out"; 411 412 generate_option (OPT_o, out, 1, CL_DRIVER, 413 &new_decoded_options[j]); 414 } 415 j++; 416 } 417 418 /* Add `-lgphobos' if we haven't already done so. */ 419 if (phobos_library != PHOBOS_NOLINK && need_phobos) 420 { 421 /* Default to static linking. */ 422 if (phobos_library != PHOBOS_DYNAMIC) 423 phobos_library = PHOBOS_STATIC; 424 425 #ifdef HAVE_LD_STATIC_DYNAMIC 426 if (phobos_library == PHOBOS_DYNAMIC && static_link) 427 { 428 generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER, 429 &new_decoded_options[j]); 430 j++; 431 } 432 else if (phobos_library == PHOBOS_STATIC && !static_link) 433 { 434 generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER, 435 &new_decoded_options[j]); 436 j++; 437 } 438 #endif 439 440 generate_option (OPT_l, 441 saw_profile_flag ? LIBPHOBOS_PROFILE : LIBPHOBOS, 1, 442 CL_DRIVER, &new_decoded_options[j]); 443 added_libraries++; 444 j++; 445 generate_option (OPT_l, 446 saw_profile_flag ? LIBDRUNTIME_PROFILE : LIBDRUNTIME, 1, 447 CL_DRIVER, &new_decoded_options[j]); 448 added_libraries++; 449 j++; 450 451 #ifdef HAVE_LD_STATIC_DYNAMIC 452 if (phobos_library == PHOBOS_DYNAMIC && static_link) 453 { 454 generate_option (OPT_Wl_, LD_STATIC_OPTION, 1, CL_DRIVER, 455 &new_decoded_options[j]); 456 j++; 457 } 458 else if (phobos_library == PHOBOS_STATIC && !static_link) 459 { 460 generate_option (OPT_Wl_, LD_DYNAMIC_OPTION, 1, CL_DRIVER, 461 &new_decoded_options[j]); 462 j++; 463 } 464 #endif 465 } 466 else if (saw_debug_flag && debuglib) 467 { 468 generate_option (OPT_l, debuglib, 1, CL_DRIVER, 469 &new_decoded_options[j++]); 470 added_libraries++; 471 } 472 else if (defaultlib) 473 { 474 generate_option (OPT_l, defaultlib, 1, CL_DRIVER, 475 &new_decoded_options[j++]); 476 added_libraries++; 477 } 478 479 if (saw_libcxx) 480 new_decoded_options[j++] = *saw_libcxx; 481 else if (need_stdcxx) 482 { 483 generate_option (OPT_l, 484 (saw_profile_flag 485 ? LIBSTDCXX_PROFILE 486 : LIBSTDCXX), 487 1, CL_DRIVER, &new_decoded_options[j++]); 488 added_libraries++; 489 } 490 491 if (shared_libgcc && !static_link) 492 { 493 generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER, 494 &new_decoded_options[j++]); 495 } 496 497 *in_decoded_options_count = j; 498 *in_decoded_options = new_decoded_options; 499 *in_added_libraries = added_libraries; 500 } 501 502 /* Called before linking. Returns 0 on success and -1 on failure. */ 503 504 int 505 lang_specific_pre_link (void) 506 { 507 if ((phobos_library != PHOBOS_NOLINK && need_phobos) || need_spec) 508 do_spec ("%:include(libgphobos.spec)"); 509 510 return 0; 511 } 512 513 /* Number of extra output files that lang_specific_pre_link may generate. */ 514 515 int lang_specific_extra_outfiles = 0; /* Not used for D. */ 516 517