static const char *compare_debug_dump_opt_spec_function (int, const char **);
static const char *compare_debug_self_opt_spec_function (int, const char **);
static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
+static const char *pass_through_libs_spec_func (int, const char **);
\f
/* The Specs Language
-plugin %(linker_plugin_file) \
-plugin-opt=%(lto_wrapper) \
-plugin-opt=-fresolution=%u.res \
- %{static|static-libgcc:-plugin-opt=-pass-through=%(lto_libgcc)} \
- %{static:-plugin-opt=-pass-through=-lc} \
+ %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
} \
%{flto*:%<fcompare-debug*} \
%{flto*} %l " LINK_PIE_SPEC \
static const char *linker_plugin_file_spec = "";
static const char *lto_wrapper_spec = "";
static const char *lto_gcc_spec = "";
-static const char *lto_libgcc_spec = "";
static const char *link_command_spec = LINK_COMMAND_SPEC;
static const char *link_libgcc_spec = LINK_LIBGCC_SPEC;
static const char *startfile_prefix_spec = STARTFILE_PREFIX_SPEC;
INIT_STATIC_SPEC ("linker_plugin_file", &linker_plugin_file_spec),
INIT_STATIC_SPEC ("lto_wrapper", <o_wrapper_spec),
INIT_STATIC_SPEC ("lto_gcc", <o_gcc_spec),
- INIT_STATIC_SPEC ("lto_libgcc", <o_libgcc_spec),
INIT_STATIC_SPEC ("link_libgcc", &link_libgcc_spec),
INIT_STATIC_SPEC ("md_exec_prefix", &md_exec_prefix),
INIT_STATIC_SPEC ("md_startfile_prefix", &md_startfile_prefix),
{ "compare-debug-dump-opt", compare_debug_dump_opt_spec_function },
{ "compare-debug-self-opt", compare_debug_self_opt_spec_function },
{ "compare-debug-auxbase-opt", compare_debug_auxbase_opt_spec_function },
+ { "pass-through-libs", pass_through_libs_spec_func },
#ifdef EXTRA_SPEC_FUNCTIONS
EXTRA_SPEC_FUNCTIONS
#endif
int num_linker_inputs = 0;
char *explicit_link_files;
char *specs_file;
+ char *lto_wrapper_file;
const char *p;
struct user_specs *uptr;
char **old_argv = argv;
/* Set up to remember the pathname of the lto wrapper. */
- lto_wrapper_spec = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
- if (lto_wrapper_spec)
+ lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+ if (lto_wrapper_file)
{
+ lto_wrapper_spec = lto_wrapper_file;
obstack_init (&collect_obstack);
obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
sizeof ("COLLECT_LTO_WRAPPER=") - 1);
false);
if (!linker_plugin_file_spec)
fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
-
- lto_libgcc_spec = find_a_file (&startfile_prefixes, "libgcc.a",
- R_OK, true);
- if (!lto_libgcc_spec)
- fatal_error ("could not find libgcc.a");
}
lto_gcc_spec = argv[0];
return name;
}
+
+/* %:pass-through-libs spec function. Finds all -l options and input
+ file names in the lib spec passed to it, and makes a list of them
+ prepended with the plugin option to cause them to be passed through
+ to the final link after all the new object files have been added. */
+
+const char *
+pass_through_libs_spec_func (int argc, const char **argv)
+{
+ char *prepended = xstrdup (" ");
+ int n;
+ /* Shlemiel the painter's algorithm. Innately horrible, but at least
+ we know that there will never be more than a handful of strings to
+ concat, and it's only once per run, so it's not worth optimising. */
+ for (n = 0; n < argc; n++)
+ {
+ char *old = prepended;
+ /* Anything that isn't an option is a full path to an output
+ file; pass it through if it ends in '.a'. Among options,
+ pass only -l. */
+ if (argv[n][0] == '-' && argv[n][1] == 'l')
+ {
+ const char *lopt = argv[n] + 2;
+ /* Handle both joined and non-joined -l options. If for any
+ reason there's a trailing -l with no joined or following
+ arg just discard it. */
+ if (!*lopt && ++n >= argc)
+ break;
+ else if (!*lopt)
+ lopt = argv[n];
+ prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
+ lopt, " ", NULL);
+ }
+ else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
+ {
+ prepended = concat (prepended, "-plugin-opt=-pass-through=",
+ argv[n], " ", NULL);
+ }
+ if (prepended != old)
+ free (old);
+ }
+ return prepended;
+}