From 5679661069a8b9acaec26d61c8da797f0726506b Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Fri, 5 Sep 2014 18:16:40 +1000 Subject: Add support for RTEMS BSP or user supplied CFLAGS. Remove march/mcpu. Added support to read an RTEMS BSP pkgconfig file and ste the CC flags. --- rld-cc.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rld-cc.h | 65 +++++++++++++++++++++ rld-path.cpp | 34 ++++++----- rld-path.h | 22 +++++-- rld-rtems.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++ rld-rtems.h | 82 ++++++++++++++++++++++++++ rld.h | 20 ++++++- 7 files changed, 529 insertions(+), 21 deletions(-) create mode 100644 rld-rtems.cpp create mode 100644 rld-rtems.h diff --git a/rld-cc.cpp b/rld-cc.cpp index 56dc6ad..f69b7c9 100644 --- a/rld-cc.cpp +++ b/rld-cc.cpp @@ -33,6 +33,10 @@ namespace rld std::string cflags; std::string cxxflags; std::string ldflags; + std::string warning_cflags; + std::string include_cflags; + std::string machine_cflags; + std::string spec_cflags; std::string install_path; std::string programs_path; std::string libraries_path; @@ -89,6 +93,183 @@ namespace rld args.push_back (ldflags); } + 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); + } + } + static bool match_and_trim (const char* prefix, std::string& line, std::string& result) { diff --git a/rld-cc.h b/rld-cc.h index db1163e..f5365c4 100644 --- a/rld-cc.h +++ b/rld-cc.h @@ -34,6 +34,17 @@ namespace rld { namespace cc { + /* + * Defintion of flags to be filtered. + */ + enum flag_type + { + ft_cppflags = 1 << 0, + ft_cflags = 1 << 1, + ft_cxxflags = 1 << 2, + ft_ldflags = 1 << 3 + }; + extern std::string cc; //< The CC executable as absolute path. extern std::string cc_name; //< The CC name, ie gcc, clang. extern std::string exec_prefix; //< The CC executable prefix. @@ -43,6 +54,11 @@ namespace rld extern std::string cxxflags; //< The CXX flags. extern std::string ldflags; //< The LD flags. + extern std::string warning_cflags; //< The warning flags in cflags. + extern std::string include_cflags; //< The include flags in cflags. + extern std::string machine_cflags; //< The machine flags in cflags. + extern std::string spec_cflags; //< The spec flags in cflags. + extern std::string install_path; //< The CC reported install path. extern std::string programs_path; //< The CC reported programs path. extern std::string libraries_path; //< The CC reported libraries path. @@ -72,6 +88,55 @@ namespace rld */ void add_ldflags (rld::process::arg_container& args); + /** + * Strip the flags of -O and -g options. + * + * @param flags The flags a space delimited list to strip. + * @return const std::string The stripped flags. + */ + const std::string strip_cflags (const std::string& flags); + + /** + * Filter the flags. Provide the type of flags being passed, the flags as a + * space separated list, the architure, and a path. Provide strings + * containers for the different flag groups so they can be sorted and + * returned. + * + * @param flags The flags a space delimited list to strip. + * @param arch The architecure per the OS specific name. + * @param path A path to adjust based on the architecture. + * @param type The type of flags being passed. + * @param warnings Return warning flags in this string. + * @param includes Return include flags in this string. + * @param machines Return machine flags in this string. + * @param specs Return spec flags in this string. + * @return const std::string The filtered flags. + */ + const std::string filter_flags (const std::string& flags, + const std::string& arch, + const std::string& path, + flag_type type, + std::string& warnings, + std::string& includes, + std::string& machines, + std::string& specs); + + /** + * Filter the cflags and update the warnings, includes, machines and specs + * if the type of flags is cflags. Provide the cflags as a space separated + * list, the architure, and a path. + * + * @param flags The flags a space delimited list to strip. + * @param arch The architecure per the OS specific name. + * @param path A path to adjust based on the architecture. + * @param type The type of flags being passed. + * @return const std::string The filtered flags. + */ + const std::string filter_flags (const std::string& flags, + const std::string& arch, + const std::string& path, + flag_type type); + /** * Get the standard libraries paths from the compiler. */ diff --git a/rld-path.cpp b/rld-path.cpp index 50eb992..51288ce 100644 --- a/rld-path.cpp +++ b/rld-path.cpp @@ -18,14 +18,7 @@ #include "config.h" #endif -#include - -#include -#include -#include -#include #include -#include #include @@ -78,16 +71,27 @@ namespace rld } void - path_join (const std::string& path_, const std::string& file_, std::string& joined) + path_join (const std::string& base, const std::string& part, std::string& joined) { - if ((path_[path_.size () - 1] != RLD_PATH_SEPARATOR) && - (file_[0] != RLD_PATH_SEPARATOR)) - joined = path_ + RLD_PATH_SEPARATOR + file_; - else if ((path_[path_.size () - 1] == RLD_PATH_SEPARATOR) && - (file_[0] == RLD_PATH_SEPARATOR)) - joined = path_ + &file_[1]; + if ((base[base.size () - 1] != RLD_PATH_SEPARATOR) && + (part[0] != RLD_PATH_SEPARATOR)) + joined = base + RLD_PATH_SEPARATOR + part; + else if ((base[base.size () - 1] == RLD_PATH_SEPARATOR) && + (part[0] == RLD_PATH_SEPARATOR)) + joined = base + &part[1]; else - joined = path_ + file_; + joined = base + part; + } + + void path_join (const std::string& base, const paths& parts, std::string& joined) + { + joined = base; + for (paths::const_iterator pi = parts.begin (); + pi != parts.end (); + ++pi) + { + path_join (joined, *pi, joined); + } } bool diff --git a/rld-path.h b/rld-path.h index d9bb991..f501fb4 100644 --- a/rld-path.h +++ b/rld-path.h @@ -77,14 +77,26 @@ namespace rld paths& paths); /** - * Make a path by joining the parts with required separator. + * Make a path by joining the base and part with required separator. * - * @param path_ The path component to be joined. - * @param file_ The file name to add to the path. + * @param base The path component to be joined. + * @param part The file name to add to the path. * @param joined The joined path and file name with a path separator. */ - void path_join (const std::string& path_, - const std::string& file_, + void path_join (const std::string& base, + const std::string& part, + std::string& joined); + + /** + * Make a path by joining the parts with the base and the required + * separator. + * + * @param base The path component to be joined. + * @param parts The files to add to the path. + * @param joined The joined path and file name with a path separator. + */ + void path_join (const std::string& base, + const paths& parts, std::string& joined); /** diff --git a/rld-rtems.cpp b/rld-rtems.cpp new file mode 100644 index 0000000..b332aa4 --- /dev/null +++ b/rld-rtems.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2011-2014, Chris Johns + * + * 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 +#include + +#include + +namespace rld +{ + namespace rtems + { + std::string version = "4.11"; + std::string path; + bool installed; + std::string arch_bsp; + + const std::string + arch (const std::string& ab) + { + std::string::size_type slash = ab.find_first_of ('/'); + if (slash == std::string::npos) + throw rld::error ("Invalid BSP name", ab); + return ab.substr (0, slash); + std::string bsp = ab.substr (slash + 1); + } + + const std::string + bsp (const std::string& ab) + { + std::string::size_type slash = ab.find_first_of ('/'); + if (slash == std::string::npos) + throw rld::error ("Invalid BSP name", ab); + return ab.substr (slash + 1); + } + + const std::string + rtems_bsp (const std::string& ab) + { + const std::string a = arch (ab); + const std::string b = bsp (ab); + return a + "-rtems" + version + '-' + b; + } + + void + load_cc () + { + path::paths parts; + std::string rtems_pkgconfig; + std::string bsp; + + if (path.empty ()) + throw rld::error ("Not set; see -r", "RTEMS path"); + + bsp = rtems_bsp (arch_bsp); + + parts.push_back ("lib"); + parts.push_back ("pkgconfig"); + + rld::path::path_join (path, parts, rtems_pkgconfig); + + if (!path::check_directory (rtems_pkgconfig)) + throw rld::error ("Invalid RTEMS path", path); + + rld::path::path_join (rtems_pkgconfig, bsp + ".pc", rtems_pkgconfig); + + if (!path::check_file (rtems_pkgconfig)) + throw rld::error ("RTEMS BSP not found", arch_bsp); + + if (rld::verbose () >= RLD_VERBOSE_INFO) + std::cout << " rtems: " << arch_bsp << ": " + << rtems_pkgconfig << std::endl; + + pkgconfig::package pkg (rtems_pkgconfig); + + std::string flags; + + if (pkg.get ("CPPFLAGS", flags)) + { + rld::cc::cppflags = rld::cc::filter_flags (flags, + arch_bsp, + path, + rld::cc::ft_cppflags); + if (rld::verbose () >= RLD_VERBOSE_INFO) + std::cout << " rtems: " << arch_bsp + << ": CPPFLAGS=" << rld::cc::cppflags << std::endl; + } + + if (pkg.get ("CFLAGS", flags)) + { + rld::cc::cflags = rld::cc::filter_flags (flags, + arch_bsp, + path, + rld::cc::ft_cflags); + if (rld::verbose () >= RLD_VERBOSE_INFO) + { + std::cout << " rtems: " << arch_bsp + << ": CFLAGS=" << rld::cc::cflags << std::endl; + std::cout << " rtems: " << arch_bsp + << ": WARNINGS=" << rld::cc::warning_cflags << std::endl; + std::cout << " rtems: " << arch_bsp + << ": INCLUDES=" << rld::cc::include_cflags << std::endl; + std::cout << " rtems: " << arch_bsp + << ": MACHINES=" << rld::cc::machine_cflags << std::endl; + std::cout << " rtems: " << arch_bsp + << ": SPECS=" << rld::cc::spec_cflags << std::endl; + } + } + + if (pkg.get ("CXXFLAGS", flags)) + { + rld::cc::cxxflags = rld::cc::filter_flags (flags, + arch_bsp, + path, + rld::cc::ft_cxxflags); + if (rld::verbose () >= RLD_VERBOSE_INFO) + std::cout << " rtems: " << arch_bsp + << ": CXXFLAGS=" << rld::cc::cxxflags << std::endl; + } + + if (pkg.get ("LDFLAGS", flags)) + { + rld::cc::ldflags = rld::cc::filter_flags (flags, + arch_bsp, + path, + rld::cc::ft_ldflags); + if (rld::verbose () >= RLD_VERBOSE_INFO) + std::cout << " rtems: " << arch_bsp + << ": LDFLAGS=" << rld::cc::ldflags << std::endl; + } + } + } +} diff --git a/rld-rtems.h b/rld-rtems.h new file mode 100644 index 0000000..97dc67e --- /dev/null +++ b/rld-rtems.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011-2014, Chris Johns + * + * 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. + */ +/** + * @file + * + * @ingroup rtems-ld + * + * @brief Support to manage RTEMS. + * + */ + +#if !defined (_RLD_RTEMS_H_) +#define _RLD_RTEMS_H_ + +#include + +namespace rld +{ + namespace rtems + { + /** + * The RTEMS default version. + */ + extern std::string version; + + /** + * The path to RTEMS. + */ + extern std::string path; + + /** + * Is the RTEMS installed. + */ + extern bool installed; + + /** + * The BSP name. + */ + extern std::string arch_bsp; + + /** + * Return the architecture given an arch/bsp string. + */ + const std::string arch (const std::string& ab); + + /** + * Return the bsp given an arch/bsp string. + */ + const std::string bsp (const std::string& ab); + + /** + * Return the RTEMS bsp string given an arch/bsp string. + */ + const std::string rtems_bsp (const std::string& ab); + + /** + * Load the configuration. Set the various values via the command or a + * configuration file then check the configuration. + */ + void load_cc (); + + /** + * Process the BSP name updating the various CC flags. + */ + void set_cc (void); + } +} + +#endif diff --git a/rld.h b/rld.h index 1f5e60b..efe3f46 100644 --- a/rld.h +++ b/rld.h @@ -121,6 +121,14 @@ namespace rld */ typedef std::vector < std::string > strings; + /** + * Does a string start with another string ? + */ + inline bool starts_with(const std::string& s1, const std::string& s2) + { + return s2.size () <= s1.size () && s1.compare (0, s2.size (), s2) == 0; + } + /** * Trim from start. */ @@ -195,7 +203,7 @@ namespace rld */ inline strings& split (strings& se, const std::string& s, - char delimiter, + char delimiter = ' ', bool strip_quotes = true, bool strip_whitespace = true, bool empty = false) @@ -235,6 +243,16 @@ namespace rld return s; } + /** + * Convert a string to lower case. + */ + inline std::string tolower (const std::string& sin) + { + std::string s = sin; + std::transform (s.begin (), s.end (), s.begin (), ::tolower); + return s; + } + /** * Increment the verbose level. */ -- cgit v1.2.3