From 52d988128d5014002b0431f7d4f5de0ff50f92a9 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Mon, 8 Sep 2014 16:06:48 +1000 Subject: RTEMS trace linker builds trace applications. The trace linker builds the both_hello example in examples-v2. Move the various string support functions into a C++ file and stop being inlined. Make them return const std::string. Add ld support to rld-cc. Add search path support to rld-config so installed common files can be used. Fix the path bugs. Add an absolute path function to rld-path. --- rld-cc.cpp | 49 ++++++++++++++++++- rld-cc.h | 20 ++++++++ rld-config.cpp | 47 ++++++++++++++---- rld-config.h | 18 +++++-- rld-path.cpp | 62 ++++++++++++++++++++++-- rld-path.h | 25 ++++++---- rld.cpp | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- rld.h | 139 +++++++++++++++++------------------------------------ rtems-ld.cpp | 2 +- rtems-tld.cpp | 126 ++++++++++++++++++++++++++++++++++++++---------- wscript | 2 + 11 files changed, 489 insertions(+), 150 deletions(-) diff --git a/rld-cc.cpp b/rld-cc.cpp index 29eebbb..a2b1be4 100644 --- a/rld-cc.cpp +++ b/rld-cc.cpp @@ -30,7 +30,12 @@ namespace rld 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 exec_prefix; //< The CC executable prefix. + + 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. @@ -249,6 +254,25 @@ namespace rld 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_) { @@ -418,8 +442,10 @@ namespace rld /* * Use the absolute path to CC if provided. */ - if (!cc.empty ()) + if (is_cc_set ()) + { args.push_back (cc); + } else { std::string cmd = cc_name; @@ -429,6 +455,25 @@ namespace rld } } + 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) { diff --git a/rld-cc.h b/rld-cc.h index a16bd3e..6c200d2 100644 --- a/rld-cc.h +++ b/rld-cc.h @@ -120,6 +120,21 @@ namespace rld */ bool is_cc_set (); + /** + * Set LD. The exec-prefix is ignored if this is set. + */ + void set_ld (const std::string& ld); + + /** + * Get the LD. + */ + const std::string get_ld (); + + /** + * Is the LD set ? + */ + bool is_ld_set (); + /** * Set the exec-prefix. If CC is set the exec-prefix is ignored. */ @@ -177,6 +192,11 @@ namespace rld */ void make_cc_command (rld::process::arg_container& args); + /** + * Make a LD command from the set arguments. + */ + void make_ld_command (rld::process::arg_container& args); + /** * Get the standard libraries paths from the compiler. */ diff --git a/rld-config.cpp b/rld-config.cpp index ee619c8..3a372ad 100644 --- a/rld-config.cpp +++ b/rld-config.cpp @@ -56,7 +56,7 @@ namespace rld throw error ("not found", "config record: " + this->name + '/' + name); } - std::string + const std::string section::get_record_item (const std::string& rec_name) const { const record& rec = get_record (rec_name); @@ -78,14 +78,22 @@ namespace rld } } - config::config() + config::config(const std::string& search_path) { + set_search_path (search_path); } config::~config() { } + void + config::set_search_path (const std::string& search_path) + { + if (!search_path.empty ()) + rld::path::path_split (search_path, search); + } + void config::clear () { @@ -97,10 +105,34 @@ namespace rld { CSimpleIniCaseA ini (false, true, true); - if (ini.LoadFile (path.c_str ()) != SI_OK) + std::string checked_path; + + if (rld::path::check_file (path)) + { + checked_path = path; + } + else + { + bool found = false; + for (rld::path::paths::const_iterator spi = search.begin (); + spi != search.end (); + ++spi) + { + rld::path::path_join (*spi, path, checked_path); + if (rld::path::check_file (checked_path)) + { + found = true; + break; + } + } + if (!found) + throw rld::error ("Not found.", "load config: " + path); + } + + if (ini.LoadFile (checked_path.c_str ()) != SI_OK) throw rld::error (::strerror (errno), "load config: " + path); - paths_.push_back (path); + paths_.push_back (checked_path); /* * Merge the loaded configuration into our configuration. @@ -162,12 +194,7 @@ namespace rld have_includes = true; /* - * Include records are a path which we can just load. - * - * @todo Add a search path. See 'rld::files' for details. We can default - * the search path to the install $prefix of this tool and we can - * then provide a default set of function signatures for RTEMS - * APIs. + * Include records are a paths which we can load. */ for (rld::strings::const_iterator isi = is.begin (); diff --git a/rld-config.h b/rld-config.h index b8bd495..52153d2 100644 --- a/rld-config.h +++ b/rld-config.h @@ -95,7 +95,7 @@ namespace rld * Return the single item in a record. If the record is duplicated an * error is thrown. */ - std::string get_record_item (const std::string& name) const; + const std::string get_record_item (const std::string& name) const; /** * Return the list of items in a record in a strings container. @@ -122,9 +122,18 @@ namespace rld /** * Construct an empty configuration. */ - config(); + config(const std::string& search_path = ""); + + /** + * Desctruct the configuration object. + */ virtual ~config(); + /** + * Set the search path. + */ + void set_search_path (const std::string& search_path); + /** * Clear the current configuration. */ @@ -154,8 +163,9 @@ namespace rld private: - paths paths_; /**< The path's of the loaded files. */ - sections secs; /**< The sections loaded from configuration files */ + paths search; //< The paths to search for config files in. + paths paths_; //< The path's of the loaded files. + sections secs; //< The sections loaded from configuration files }; /** diff --git a/rld-path.cpp b/rld-path.cpp index 2163706..70a9c24 100644 --- a/rld-path.cpp +++ b/rld-path.cpp @@ -27,7 +27,7 @@ namespace rld { namespace path { - std::string + const std::string basename (const std::string& name) { size_t b = name.find_last_of (RLD_PATH_SEPARATOR); @@ -36,16 +36,16 @@ namespace rld return name; } - std::string + const std::string dirname (const std::string& name) { size_t b = name.find_last_of (RLD_PATH_SEPARATOR); if (b != std::string::npos) - return name.substr (0, b - 1); + return name.substr (0, b); return name; } - std::string + const std::string extension (const std::string& name) { size_t b = name.find_last_of ('.'); @@ -96,6 +96,60 @@ namespace rld } } + const std::string + path_abs (const std::string& path) + { + std::string apath; + + if (path[0] == RLD_PATH_SEPARATOR) + { + apath = path; + } + else + { + char* buf = 0; + try + { + buf = new char[32 * 1024]; + if (!::getcwd (buf, 132 * 1024)) + throw rld::error (::strerror (errno), "get current working directory"); + path_join (buf, path, apath); + } + catch (...) + { + delete [] buf; + throw; + } + } + + strings ps; + strings aps; + + rld::split (ps, apath, RLD_PATH_SEPARATOR); + + for (strings::iterator psi = ps.begin (); + psi != ps.end (); + ++psi) + { + const std::string& dir = *psi; + + if (dir.empty () || dir == ".") + { + /* do nothing */ + } + else if (dir == "..") + { + aps.pop_back (); + } + else + { + aps.push_back (dir); + } + } + + return RLD_PATH_SEPARATOR + rld::join (aps, RLD_PATH_SEPARATOR_STR); + } + bool check_file (const std::string& path) { diff --git a/rld-path.h b/rld-path.h index 0e1329a..d73c59b 100644 --- a/rld-path.h +++ b/rld-path.h @@ -45,29 +45,29 @@ namespace rld * Return the basename of the file name. * * @param name The full file name. - * @return std::string The basename of the file. + * @return const std::string The basename of the file. */ - std::string basename (const std::string& name); + const std::string basename (const std::string& name); /** * Return the dirname of the file name. * * @param name The full file name. - * @return std::string The dirname of the file. + * @return const std::string The dirname of the file. */ - std::string dirname (const std::string& name); + const std::string dirname (const std::string& name); /** * Return the extension of the file name. * * @param name The full file name. - * @return std::string The extension of the file. + * @return const std::string The extension of the file. */ - std::string extension (const std::string& name); + const std::string extension (const std::string& name); /** - * Split a path from a string with a delimiter to the path container. Add - * only the paths that exist and ignore those that do not. + * Split a path from a string with the path seperator to the path + * container. Add only the paths that exist and ignore those that do not. * * @param path The paths as a single string delimited by the path * separator. @@ -99,6 +99,15 @@ namespace rld const paths& parts, std::string& joined); + /** + * Return the absolute path given a path and using the current working + * directory. The path is flattened removing any '..' sequences. + * + * @param path The path to be return as absolute. + * @return const std::string The absolute path. + */ + const std::string path_abs (const std::string& path); + /** * Check the path is a file using a stat call. * diff --git a/rld.cpp b/rld.cpp index a239ddc..ca29297 100644 --- a/rld.cpp +++ b/rld.cpp @@ -39,6 +39,7 @@ namespace rld { static int verbose_level = 0; + static std::string progname; /** * The option container. @@ -63,7 +64,119 @@ namespace rld /** * The output passed on the command line. */ - static std::string output; + //static std::string output; + + bool + starts_with(const std::string& s1, const std::string& s2) + { + return s2.size () <= s1.size () && s1.compare (0, s2.size (), s2) == 0; + } + + const std::string + ltrim (const std::string& s) + { + std::string t = s; + t.erase (t.begin (), + std::find_if (t.begin (), t.end (), + std::not1 (std::ptr_fun < int, int > (std::isspace)))); + return t; + } + + const std::string + rtrim (const std::string& s) + { + std::string t = s; + t.erase (std::find_if (t.rbegin (), t.rend (), + std::not1 (std::ptr_fun < int, int > (std::isspace))).base(), + t.end()); + return t; + } + + const std::string + trim (const std::string& s) + { + return ltrim (rtrim (s)); + } + + const std::string + dequote (const std::string& s) + { + if (!s.empty ()) + { + char front = s[0]; + char back = s[s.length () - 1]; + if ((front == '"') || (front == '\'')) + { + if (front != back) + throw rld::error ("invalid quoting", "string: " + s); + return s.substr (1, s.length () - (1 + 1)); + } + } + return s; + } + + const std::string + find_replace(const std::string& sin, + const std::string& out, + const std::string& in) + { + std::string s = sin; + size_t pos = 0; + while ((pos = s.find (out, pos)) != std::string::npos) + { + s.replace (pos, out.length (), in); + pos += in.length (); + } + return s; + } + + const strings + split (strings& se, + const std::string& s, + char delimiter, + bool strip_quotes, + bool strip_whitespace, + bool empty) + { + std::stringstream ss(s); + std::string e; + se.clear (); + while (std::getline (ss, e, delimiter)) + { + if (strip_whitespace) + e = trim (e); + if (strip_quotes) + e = dequote (e); + if (empty || !e.empty ()) + { + se.push_back (e); + } + } + return se; + } + + const std::string + join (const strings& ss, const std::string& separator) + { + std::string s; + for (strings::const_iterator ssi = ss.begin (); + ssi != ss.end (); + ++ssi) + { + s += *ssi; + if ((ssi + 1) != ss.end ()) + s += separator; + } + return s; + } + + const std::string + tolower (const std::string& sin) + { + std::string s = sin; + std::transform (s.begin (), s.end (), s.begin (), ::tolower); + return s; + } void verbose_inc () @@ -92,6 +205,40 @@ namespace rld return rld::to_string (RTEMS_VERSION); } + void + set_progname (const std::string& progname_) + { + progname = rld::path::path_abs (progname_); + } + + const std::string + get_progname () + { + return progname; + } + + const std::string + get_program_name () + { + return rld::path::basename (progname); + } + + const std::string + get_program_path () + { + return rld::path::dirname (progname); + } + + const std::string + get_prefix () + { + std::string pp = get_program_path (); + std::cout << "PP=" << pp << std::endl; + if (rld::path::basename (pp) == "bin") + pp = rld::path::dirname (pp); + return pp; + } + void map (rld::files::cache& cache, rld::symbols::table& symbols) { diff --git a/rld.h b/rld.h index 6a42923..115b7b8 100644 --- a/rld.h +++ b/rld.h @@ -126,76 +126,34 @@ namespace rld /** * 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; - } + bool starts_with(const std::string& s1, const std::string& s2); /** * Trim from start. */ - inline std::string& ltrim (std::string &s) - { - s.erase (s.begin (), - std::find_if (s.begin (), s.end (), - std::not1 (std::ptr_fun < int, int > (std::isspace)))); - return s; - } + const std::string ltrim (const std::string& s); /** * Trim from end. */ - inline std::string& rtrim (std::string &s) - { - s.erase (std::find_if (s.rbegin (), s.rend (), - std::not1 (std::ptr_fun < int, int > (std::isspace))).base(), - s.end()); - return s; - } + const std::string rtrim (const std::string& s); /** * Trim from both ends. */ - inline std::string& trim (std::string &s) - { - return ltrim (rtrim (s)); - } + const std::string trim (const std::string& s); /** * Dequote a string. */ - inline std::string dequote (const std::string& s) - { - if (!s.empty ()) - { - char front = s[0]; - char back = s[s.length () - 1]; - if ((front == '"') || (front == '\'')) - { - if (front != back) - throw rld::error ("invalid quoting", "string: " + s); - return s.substr (1, s.length () - (1 + 1)); - } - } - return s; - } + const std::string dequote (const std::string& s); /** * Find and replace. */ - inline std::string find_replace(const std::string& sin, - const std::string& out, - const std::string& in) - { - std::string s = sin; - size_t pos = 0; - while ((pos = s.find (out, pos)) != std::string::npos) - { - s.replace (pos, out.length (), in); - pos += in.length (); - } - return s; - } + const std::string find_replace(const std::string& sin, + const std::string& out, + const std::string& in); /** * Split the string in a contain of strings based on the the @@ -203,57 +161,22 @@ namespace rld * * @todo The split should optionally honour string quoting. */ - inline strings split (strings& se, - const std::string& s, - char delimiter = ' ', - bool strip_quotes = true, - bool strip_whitespace = true, - bool empty = false) - { - std::stringstream ss(s); - std::string e; - se.clear (); - while (std::getline (ss, e, delimiter)) - { - if (strip_whitespace) - trim (e); - if (strip_quotes) - e = dequote (e); - if (empty || !e.empty ()) - { - se.push_back (e); - } - } - return se; - } + const strings split (strings& se, + const std::string& s, + char delimiter = ' ', + bool strip_quotes = true, + bool strip_whitespace = true, + bool empty = false); /** * Join the strings together with the separator. */ - inline std::string join (const strings& ss, - const std::string& separator) - { - std::string s; - for (strings::const_iterator ssi = ss.begin (); - ssi != ss.end (); - ++ssi) - { - s += *ssi; - if ((ssi != ss.begin ()) && (ssi != ss.end ())) - s += separator; - } - return s; - } + const std::string join (const strings& ss, const std::string& separator); /** * 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; - } + const std::string tolower (const std::string& sin); /** * Increment the verbose level. @@ -276,13 +199,41 @@ namespace rld */ typedef std::vector < std::string > strings; + /** + * Set the progname. + */ + void set_progname (const std::string& progname); + + /** + * Get the progname. This is an absolute path. + */ + const std::string get_progname (); + + /** + * Get the program name. + */ + const std::string get_program_name (); + + /** + * Get the program path. + */ + const std::string get_program_path (); + + /** + * Get the current install prefix. If the path to the executable has 'bin' as + * the executable's parent directory it is assumed the executable has been + * installed under a standard PREFIX. If "bin" is not found return the + * executable's absolute path. + */ + const std::string get_prefix (); + /** * Map of the symbol table. */ void map (rld::files::cache& cache, rld::symbols::table& symbols); /** - * Warn is externals in referenced object files are not used. + * Warn if externals in referenced object files are not used. */ void warn_unused_externals (rld::files::object_list& objects); } diff --git a/rtems-ld.cpp b/rtems-ld.cpp index dfa5c14..f678cde 100644 --- a/rtems-ld.cpp +++ b/rtems-ld.cpp @@ -356,7 +356,7 @@ main (int argc, char* argv[]) if (!rtems_arch_bsp.empty ()) { if (rtems_path.empty ()) - throw rld::error ("arch/bsp provide and no RTEMS path", "options"); + throw rld::error ("No RTEMS path provide with arch/bsp", "options"); rld::rtems::set_path (rtems_path); rld::rtems::set_arch_bsp (rtems_arch_bsp); } diff --git a/rtems-tld.cpp b/rtems-tld.cpp index c6d5c55..28f154d 100644 --- a/rtems-tld.cpp +++ b/rtems-tld.cpp @@ -90,7 +90,7 @@ namespace rld /** * Return the function's declaration. */ - const std::string decl () const; + const std::string decl (const std::string& prefix = "") const; }; /** @@ -193,6 +193,11 @@ namespace rld */ void generate_traces (rld::process::tempfile& c); + /** + * Get the traces. + */ + const rld::strings& get_traces () const; + /** * Dump the wrapper. */ @@ -321,9 +326,9 @@ namespace rld } const std::string - signature::decl () const + signature::decl (const std::string& prefix) const { - std::string ds = ret + ' ' + name + '('; + std::string ds = ret + ' ' + prefix + name + '('; int arg = 0; for (function_args::const_iterator ai = args.begin (); ai != args.end (); @@ -485,7 +490,6 @@ namespace rld * configuration and may contain: * * # name The name of trace being linked. - * # bsp The architecture/bsp name of the BSP. * # options A list of options as per the long command line args. * # traces The list of sections containing function lists to trace. * # functions The list of sections containing function details. @@ -503,7 +507,6 @@ namespace rld config.includes (section); name = section.get_record_item ("name"); - bsp = section.get_record_item ("bsp"); load_functions (config, section); load_traces (config, section); @@ -640,7 +643,7 @@ namespace rld const signature& sig = (*si).second; c.write_line(""); - c.write_line(sig.decl ()); + c.write_line(sig.decl ("__wrap_")); c.write_line("{"); std::string l; @@ -655,7 +658,7 @@ namespace rld l = " ret ="; } - l += " " + generator_.map_sym_prefix + sig.name + '('; + l += " __real_" + sig.name + '('; for (size_t a = 0; a < sig.args.size (); ++a) { if (a) @@ -679,6 +682,12 @@ namespace rld } } + const rld::strings& + tracer::get_traces () const + { + return traces; + } + void tracer::dump (std::ostream& out) const { @@ -710,6 +719,16 @@ namespace rld linker::load_config (const std::string& path, const std::string& trace) { + std::string sp = get_prefix (); + + rld::path::path_join (sp, "share", sp); + rld::path::path_join (sp, "rtems", sp); + rld::path::path_join (sp, "trace-linker", sp); + + if (rld::verbose () || true) + std::cout << "search path: " << sp << std::endl; + + config.set_search_path (sp); config.clear (); config.load (path); tracer_.load (config, trace); @@ -759,9 +778,38 @@ namespace rld void linker::link (rld::process::tempfile& o, - const std::string& ld_cmds) + const std::string& ld_cmd) { + rld::process::arg_container args; + + if (rld::verbose ()) + std::cout << "linking: " << o.name () << std::endl; + + std::string wrap = " -Wl,--wrap -Wl,"; + + rld::cc::make_ld_command (args); + + args.push_back (o.name ()); + + rld::process::args_append (args, ld_cmd); + rld::process::args_append (args, + wrap + rld::join (tracer_.get_traces (), wrap)); + + rld::process::tempfile out; + rld::process::tempfile err; + rld::process::status status; + + status = rld::process::execute (rld::cc::get_ld (), + args, + out.name (), + err.name ()); + if ((status.type != rld::process::status::normal) || + (status.code != 0)) + { + err.output (rld::cc::get_cc (), std::cout); + throw rld::error ("Linker error", "linking"); + } } void @@ -792,9 +840,10 @@ static struct option rld_opts[] = { { "verbose", no_argument, NULL, 'v' }, { "warn", no_argument, NULL, 'w' }, { "keep", no_argument, NULL, 'k' }, + { "compiler", required_argument, NULL, 'c' }, { "linker", required_argument, NULL, 'l' }, { "exec-prefix", required_argument, NULL, 'E' }, - { "cflags", required_argument, NULL, 'c' }, + { "cflags", required_argument, NULL, 'f' }, { "rtems", required_argument, NULL, 'r' }, { "rtems-bsp", required_argument, NULL, 'B' }, { "config", required_argument, NULL, 'C' }, @@ -807,19 +856,20 @@ usage (int exit_code) { std::cout << "rtems-trace-ld [options] objects" << std::endl << "Options and arguments:" << std::endl - << " -h : help (also --help)" << std::endl - << " -V : print linker version number and exit (also --version)" << std::endl - << " -v : verbose (trace import parts), can supply multiple times" << std::endl - << " to increase verbosity (also --verbose)" << std::endl - << " -w : generate warnings (also --warn)" << std::endl - << " -k : keep temporary files (also --keep)" << std::endl - << " -l linker : target linker is not standard (also --linker)" << std::endl - << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl - << " -c cflags : C compiler flags (also --cflags)" << std::endl - << " -r path : RTEMS path (also --rtems)" << std::endl - << " -B bsp : RTEMS arch/bsp (also --rtems-bsp)" << std::endl - << " -W wrapper : wrapper file name without ext (also --wrapper)" << std::endl - << " -C ini : user configuration INI file (also --config)" << std::endl; + << " -h : help (also --help)" << std::endl + << " -V : print linker version number and exit (also --version)" << std::endl + << " -v : verbose (trace import parts), can supply multiple times" << std::endl + << " to increase verbosity (also --verbose)" << std::endl + << " -w : generate warnings (also --warn)" << std::endl + << " -k : keep temporary files (also --keep)" << std::endl + << " -c compiler : target compiler is not standard (also --compiler)" << std::endl + << " -l linker : target linker is not standard (also --linker)" << std::endl + << " -E prefix : the RTEMS tool prefix (also --exec-prefix)" << std::endl + << " -f cflags : C compiler flags (also --cflags)" << std::endl + << " -r path : RTEMS path (also --rtems)" << std::endl + << " -B bsp : RTEMS arch/bsp (also --rtems-bsp)" << std::endl + << " -W wrappe r : wrapper file name without ext (also --wrapper)" << std::endl + << " -C ini : user configuration INI file (also --config)" << std::endl; ::exit (exit_code); } @@ -867,6 +917,7 @@ main (int argc, char* argv[]) try { rld::trace::linker linker; + std::string cc; std::string ld; std::string ld_cmd; std::string configuration; @@ -877,7 +928,7 @@ main (int argc, char* argv[]) while (true) { - int opt = ::getopt_long (argc, argv, "hvwkVl:E:c:C:r:B:W:", rld_opts, NULL); + int opt = ::getopt_long (argc, argv, "hvwkVc:l:E:f:C:r:B:W:", rld_opts, NULL); if (opt < 0) break; @@ -903,6 +954,10 @@ main (int argc, char* argv[]) rld::process::set_keep_temporary_files (); break; + case 'c': + cc = optarg; + break; + case 'l': ld = optarg; break; @@ -911,7 +966,7 @@ main (int argc, char* argv[]) rld::cc::set_exec_prefix (optarg); break; - case 'c': + case 'f': rld::cc::append_flags (optarg, rld::cc::ft_cflags); break; @@ -941,6 +996,11 @@ main (int argc, char* argv[]) } } + /* + * Set the program name. + */ + rld::set_progname (argv[0]); + argc -= optind; argv += optind; @@ -953,16 +1013,30 @@ main (int argc, char* argv[]) if (!rtems_arch_bsp.empty ()) { if (rtems_path.empty ()) - throw rld::error ("arch/bsp provide and no RTEMS path", "options"); + throw rld::error ("No RTEMS path provide with arch/bsp", "options"); rld::rtems::set_path (rtems_path); rld::rtems::set_arch_bsp (rtems_arch_bsp); } + /** + * Set the compiler and/or linker if provided. + */ + if (!cc.empty ()) + rld::cc::set_cc (cc); + if (!ld.empty ()) + rld::cc::set_ld (ld); + /* * Load the remaining command line arguments into the linker command line. */ while (argc--) - ld_cmd += ' ' + *argv++; + { + /* + * Create this value because 'ld_cmd += ' ' + *argv++' fails on clang. + */ + std::string av = *argv++; + ld_cmd += ' ' + av; + } ld_cmd = rld::trim (ld_cmd); /* diff --git a/wscript b/wscript index 7540566..400a792 100644 --- a/wscript +++ b/wscript @@ -165,6 +165,8 @@ def build(bld): cxxflags = bld.cxxflags + bld.warningflags, linkflags = bld.linkflags, use = modules) + bld.install_files('${PREFIX}/share/rtems/trace-linker', + ['rtems.ini', 'rtld-base.ini']) # # Build the symbols. -- cgit v1.2.3