diff options
Diffstat (limited to 'linkers/rld-cc.cpp')
-rw-r--r-- | linkers/rld-cc.cpp | 608 |
1 files changed, 0 insertions, 608 deletions
diff --git a/linkers/rld-cc.cpp b/linkers/rld-cc.cpp deleted file mode 100644 index a2b1be4..0000000 --- a/linkers/rld-cc.cpp +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Copyright (c) 2011-2014, Chris Johns <chrisj@rtems.org> - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include <string.h> - -#include <fstream> - -#include <rld.h> -#include <rld-cc.h> -#include <rld-process.h> -#include <rld-rtems.h> - -namespace rld -{ - namespace cc - { - static std::string cc; //< The CC executable as absolute path. - static bool cc_set; //< True when the CC has been set. - static std::string cc_name = "gcc"; //< The CC name, ie gcc, clang. - - static std::string ld; //< The LD executable as absolute path. - static bool ld_set; //< True when the LD has been set. - static std::string ld_name = "gcc"; //< The LD name, ie gcc, clang. - - static std::string exec_prefix; //< The CC/LD executable prefix. - - static std::string cppflags; //< The CPP flags. - static std::string cflags; //< The CC flags. - static std::string cxxflags; //< The CXX flags. - static std::string ldflags; //< The LD flags. - - static std::string warning_cflags; //< The warning flags in cflags. - static std::string include_cflags; //< The include flags in cflags. - static std::string machine_cflags; //< The machine flags in cflags. - static std::string spec_cflags; //< The spec flags in cflags. - - static std::string install_path; //< The CC reported install path. - static std::string programs_path; //< The CC reported programs path. - static std::string libraries_path; //< The CC reported libraries path. - - /** - * The list of standard libraries. - */ - #define RPS RLD_PATHSTR_SEPARATOR_STR - static const char* std_lib_c = "libgcc.a" RPS "libssp.a" RPS "libc.a"; - static const char* std_lib_cplusplus = "libstdc++.a"; - - const std::string - strip_cflags (const std::string& flags) - { - std::string oflags; - rld::strings flags_; - rld::split (flags_, flags); - - for (rld::strings::iterator si = flags_.begin (); - si != flags_.end (); - ++si) - { - if (!rld::starts_with ((*si), "-O") && !rld::starts_with ((*si), "-g")) - oflags += ' ' + *si; - } - - return rld::trim (oflags); - } - - const std::string - filter_flags (const std::string& flags, - const std::string& , - const std::string& , - flag_type type, - std::string& warnings, - std::string& includes, - std::string& machines, - std::string& specs) - { - /* - * Defintion of flags to be filtered. - */ - enum flag_group - { - fg_warning, - fg_include, - fg_machine, - fg_specs - }; - struct flag_def - { - flag_group group; ///< The group this flag belong to. - const char* opt; ///< Option start. - int count; ///< Number of arguments with the option. - bool path; ///< Is this a path ? - int out; ///< If the flag type is set drop the opt.. - }; - const flag_def flag_defs[] = - { - { fg_warning, "-W", 1, false, ft_cppflags | ft_cflags | ft_ldflags }, - { fg_include, "-I", 2, true, 0 }, - { fg_include, "-isystem", 2, true, 0 }, - { fg_include, "-sysroot", 2, true, 0 }, - { fg_machine, "-O", 1, false, 0 }, - { fg_machine, "-m", 1, false, 0 }, - { fg_machine, "-f", 1, false, 0 }, - { fg_specs, "-q", 1, false, 0 }, - { fg_specs, "-B", 2, true, 0 }, - { fg_specs, "--specs", 2, false, 0 } - }; - const int flag_def_size = sizeof (flag_defs) / sizeof (flag_def); - - std::string oflags; - rld::strings flags_; - - rld::split (flags_, strip_cflags (flags)); - - warnings.clear (); - includes.clear (); - machines.clear (); - specs.clear (); - - for (rld::strings::iterator si = flags_.begin (); - si != flags_.end (); - ++si) - { - std::string opts; - std::string& opt = *(si); - bool in = true; - - for (int fd = 0; fd < flag_def_size; ++fd) - { - if (rld::starts_with (opt, flag_defs[fd].opt)) - { - int opt_count = flag_defs[fd].count; - if (opt_count > 1) - { - /* - * See if the flag is just the option. If is not take one less - * because the option's argument is joined to the option. - */ - if (opt != flag_defs[fd].opt) - { - opt_count -= 1; - /* - * @todo Path processing here. Not sure what it is needed for. - */ - } - } - opts += ' ' + opt; - while (opt_count > 1) - { - ++si; - /* - * @todo Path processing here. Not sure what it is needed for. - */ - opts += ' ' + (*si); - --opt_count; - } - switch (flag_defs[fd].group) - { - case fg_warning: - warnings += ' ' + opts; - break; - case fg_include: - includes += ' ' + opts; - break; - case fg_machine: - machines += ' ' + opts; - break; - case fg_specs: - specs += ' ' + opts; - break; - default: - throw rld::error ("Invalid group", "flag group"); - } - if ((flag_defs[fd].out & type) != 0) - in = false; - break; - } - } - - if (in) - oflags += ' ' + opts; - } - - rld::trim (warnings); - rld::trim (includes); - rld::trim (machines); - rld::trim (specs); - - return rld::trim (oflags); - } - - const std::string - filter_flags (const std::string& flags, - const std::string& arch, - const std::string& path, - flag_type type) - { - if (type != ft_cflags) - { - std::string warnings; - std::string includes; - std::string machines; - std::string specs; - return filter_flags (flags, - arch, - path, - type, - warnings, - includes, - machines, - specs); - } - else - { - return filter_flags (flags, - arch, - path, - type, - warning_cflags, - include_cflags, - machine_cflags, - spec_cflags); - } - } - - void - set_cc (const std::string& cc_) - { - cc = cc_; - cc_set = true; - } - - const std::string - get_cc () - { - return cc; - } - - bool - is_cc_set () - { - return cc_set; - } - - void - set_ld (const std::string& ld_) - { - ld = ld_; - ld_set = true; - } - - const std::string - get_ld () - { - return ld; - } - - bool - is_ld_set () - { - return ld_set; - } - - void - set_exec_prefix (const std::string& exec_prefix_) - { - exec_prefix = exec_prefix_; - } - - const std::string - get_exec_prefix () - { - return exec_prefix; - } - - bool is_exec_prefix_set () - { - return !exec_prefix.empty (); - } - - void - set_flags (const std::string& flags, - const std::string& arch, - const std::string& path, - flag_type type) - { - std::string* oflags; - switch (type) - { - case ft_cppflags: - oflags = &cppflags; - break; - case ft_cflags: - oflags = &cflags; - break; - case ft_cxxflags: - oflags = &cxxflags; - break; - case ft_ldflags: - oflags = &ldflags; - break; - default: - throw rld::error ("Invalid flag type", "CC set flags"); - } - (*oflags) = filter_flags (flags, arch, path, type); - } - - void - set_flags (const std::string& flags, flag_type type) - { - std::string arch; - std::string path; - set_flags (flags, arch, path, type); - } - - void - append_flags (const std::string& flags, - const std::string& arch, - const std::string& path, - flag_type type) - { - std::string* oflags; - switch (type) - { - case ft_cppflags: - oflags = &cppflags; - break; - case ft_cflags: - oflags = &cflags; - break; - case ft_cxxflags: - oflags = &cxxflags; - break; - case ft_ldflags: - oflags = &ldflags; - break; - default: - throw rld::error ("Invalid flag type", "CC set flags"); - } - if (oflags->empty ()) - *oflags += filter_flags (flags, arch, path, type); - else - *oflags += ' ' + filter_flags (flags, arch, path, type); - } - - void - append_flags (const std::string& flags, flag_type type) - { - std::string arch; - std::string path; - append_flags (flags, arch, path, type); - } - - const std::string - get_flags (flag_type type) - { - std::string* flags; - switch (type) - { - case ft_cppflags: - flags = &cppflags; - break; - case ft_cflags: - flags = &cflags; - break; - case ft_cxxflags: - flags = &cxxflags; - break; - case ft_ldflags: - flags = &ldflags; - break; - default: - throw rld::error ("Invalid flag type", "CC get flags"); - } - return *flags; - } - - const std::string - get_flags (flag_group group) - { - std::string* flags; - switch (group) - { - case fg_warning_flags: - flags = &warning_cflags; - break; - case fg_include_flags: - flags = &include_cflags; - break; - case fg_machine_flags: - flags = &machine_cflags; - break; - case fg_spec_flags: - flags = &spec_cflags; - break; - default: - throw rld::error ("Invalid flag group", "CC get flags"); - } - return *flags; - } - - void - append_flags (flag_type type, rld::process::arg_container& args) - { - const std::string* flags = 0; - switch (type) - { - case ft_cppflags: - flags = &cppflags; - break; - case ft_cflags: - flags = &cflags; - break; - case ft_cxxflags: - flags = &cxxflags; - break; - case ft_ldflags: - flags = &ldflags; - break; - default: - throw rld::error ("Invalid flag type", "CC append flags"); - } - if (!flags->empty ()) - rld::process::args_append (args, *flags); - } - - void - make_cc_command (rld::process::arg_container& args) - { - /* - * Use the absolute path to CC if provided. - */ - if (is_cc_set ()) - { - args.push_back (cc); - } - else - { - std::string cmd = cc_name; - if (!exec_prefix.empty ()) - cmd = exec_prefix + "-rtems" + rld::rtems::version () + '-' + cmd; - args.push_back (cmd); - } - } - - void - make_ld_command (rld::process::arg_container& args) - { - /* - * Use the absolute path to LD if provided. - */ - if (is_ld_set ()) - { - args.push_back (get_ld ()); - } - else - { - std::string cmd = ld_name; - if (!exec_prefix.empty ()) - cmd = exec_prefix + "-rtems" + rld::rtems::version () + '-' + cmd; - args.push_back (cmd); - } - } - - static bool - match_and_trim (const char* prefix, std::string& line, std::string& result) - { - std::string::size_type pos = ::strlen (prefix); - if (line.substr (0, pos) == prefix) - { - if (line[pos] == '=') - ++pos; - result = line.substr (pos, line.size () - pos - 1); - return true; - } - return false; - } - - static void - search_dirs () - { - rld::process::arg_container args; - - make_cc_command (args); - append_flags (ft_cppflags, args); - append_flags (ft_cflags, args); - args.push_back ("-print-search-dirs"); - - rld::process::tempfile out; - rld::process::tempfile err; - rld::process::status status; - - status = rld::process::execute (cc_name, args, out.name (), err.name ()); - - if ((status.type == rld::process::status::normal) && - (status.code == 0)) - { - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - out.output (cc_name, std::cout, true); - out.open (); - while (true) - { - std::string line; - out.read_line (line); - if (line.size () == 0) - break; - if (match_and_trim ("install: ", line, install_path)) - continue; - if (match_and_trim ("programs: ", line, programs_path)) - continue; - if (match_and_trim ("libraries: ", line, libraries_path)) - continue; - } - out.close (); - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - { - std::cout << "cc::install: " << install_path << std::endl - << "cc::programs: " << programs_path << std::endl - << "cc::libraries: " << libraries_path << std::endl; - } - } - else - { - err.output (cc_name, std::cout); - } - } - - void - get_library_path (std::string& name, std::string& path) - { - rld::process::arg_container args; - - make_cc_command (args); - append_flags (ft_cppflags, args); - append_flags (ft_cflags, args); - args.push_back ("-print-file-name=" + name); - - rld::process::tempfile out; - rld::process::tempfile err; - rld::process::status status; - - status = rld::process::execute (cc_name, args, out.name (), err.name ()); - - if ((status.type == rld::process::status::normal) && - (status.code == 0)) - { - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - out.output ("cc", std::cout, true); - out.open (); - out.read (path); - out.close (); - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - std::cout << "cc::libpath: " << name << " -> " << path << std::endl; - } - else - { - err.output ("cc", std::cout); - } - } - - void - get_standard_libpaths (rld::path::paths& libpaths) - { - search_dirs (); - rld::split (libpaths, libraries_path, RLD_PATHSTR_SEPARATOR); - } - - void - get_standard_libs (rld::path::paths& libs, - rld::path::paths& libpaths, - bool cplusplus) - { - strings libnames; - - rld::split (libnames, std_lib_c, RLD_PATHSTR_SEPARATOR); - if (cplusplus) - rld::path::path_split (std_lib_cplusplus, libnames); - - for (strings::iterator lni = libnames.begin (); - lni != libnames.end (); - ++lni) - { - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "cc::stdlib: " << *lni << std::endl; - - std::string path; - - rld::path::find_file (path, *lni, libpaths); - if (path.empty ()) - throw rld::error ("Library not found: " + *lni, "getting standard libs"); - - libs.push_back (path); - } - } - } -} |