From 5c75d3435ae8e049a3049a6eec1295f1de2694cf Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sun, 7 Sep 2014 10:47:00 +1000 Subject: rtems-tld: Add --wrapper option to aid testing. The --wrapper option lets a user control the wrapper file name and location to aid testing. Add keep support to tempfiles so specific tempfile can be set to be kept. Add unlink to the rld::path namespace. --- | Bin 0 -> 1704 bytes rld-path.cpp | 28 ++++++++++++++++- rld-path.h | 7 +++++ rld-process.cpp | 92 ++++++++++++++++++++++++++++++++++++-------------------- rld-process.h | 54 ++++++++++++++++++++++++++------- rld.h | 2 +- rtems-tld.cpp | 46 +++++++++++++++++++--------- 7 files changed, 169 insertions(+), 60 deletions(-) create mode 100644 diff --git a/ b/ new file mode 100644 index 0000000..f646398 Binary files /dev/null and b/ differ diff --git a/rld-path.cpp b/rld-path.cpp index 8e24d3a..2163706 100644 --- a/rld-path.cpp +++ b/rld-path.cpp @@ -19,6 +19,7 @@ #endif #include +#include #include @@ -83,7 +84,8 @@ namespace rld joined = base + part; } - void path_join (const std::string& base, const paths& parts, std::string& joined) + void + path_join (const std::string& base, const paths& parts, std::string& joined) { joined = base; for (paths::const_iterator pi = parts.begin (); @@ -128,5 +130,29 @@ namespace rld path.clear (); } + void + unlink (const std::string& path, bool not_present_error) + { + struct stat sb; + if (::stat (path.c_str (), &sb) >= 0) + { + if (!S_ISREG (sb.st_mode)) + throw rld::error ("Not a regular file", "unlinking: " + path); + + int r; +#if _WIN32 + r = ::remove(path.c_str ()); +#else + r = ::unlink (path.c_str ()); +#endif + if (r < 0) + throw rld::error (::strerror (errno), "unlinking: " + path); + } + else + { + if (not_present_error) + throw rld::error ("Not found", "unlinking: " + path); + } + } } } diff --git a/rld-path.h b/rld-path.h index f501fb4..0e1329a 100644 --- a/rld-path.h +++ b/rld-path.h @@ -128,6 +128,13 @@ namespace rld const std::string& name, paths& search_paths); + /** + * Unlink the file. + * + * @param path The path of the file to unlink. + */ + void unlink (const std::string& path, bool not_present_error = false); + } } diff --git a/rld-process.cpp b/rld-process.cpp index 2174cce..1f0392f 100644 --- a/rld-process.cpp +++ b/rld-process.cpp @@ -60,7 +60,7 @@ namespace rld namespace process { /** - * Keep the temporary files if true. Used to help debug a system. + * Global keep of temporary files if true. Used to help debug a system. */ bool keep_temporary_files = false; @@ -79,58 +79,54 @@ namespace rld } const std::string - temporary_files::get (const std::string& suffix) + temporary_files::get (const std::string& suffix, bool keep) { char* temp = ::make_temp_file (suffix.c_str ()); if (!temp) throw rld::error ("bad temp name", "temp-file"); - std::string name = temp; - - name = rld::find_replace (name, - RLD_PATH_SEPARATOR_STR RLD_PATH_SEPARATOR_STR, - RLD_PATH_SEPARATOR_STR); - - tempfiles.push_back (name); - + const std::string name = rld::find_replace (temp, + RLD_PATH_SEPARATOR_STR RLD_PATH_SEPARATOR_STR, + RLD_PATH_SEPARATOR_STR); + tempfile_ref ref (name, keep); + tempfiles.push_back (ref); return name; } void - temporary_files::unlink (const std::string& name) + temporary_files::unlink (const tempfile_ref& ref) { - if (!keep_temporary_files) + if (!keep_temporary_files && !ref.keep) + rld::path::unlink (ref.name); + } + + void + temporary_files::erase (const std::string& name) + { + for (tempfile_container::iterator tfi = tempfiles.begin (); + tfi != tempfiles.end (); + ++tfi) { - struct stat sb; - if ((::stat (name.c_str (), &sb) >= 0) && S_ISREG (sb.st_mode)) + if ((*tfi).name == name) { - int r; -#if _WIN32 - r = ::remove(name.c_str ()); -#else - r = ::unlink (name.c_str ()); -#endif - if (r < 0) - { - std::cerr << "error: unlinking temp file: " << name << std::endl; - ::exit (100); - } + unlink (*tfi); + tempfiles.erase (tfi); + break; } } } void - temporary_files::erase (const std::string& name) + temporary_files::keep (const std::string& name) { for (tempfile_container::iterator tfi = tempfiles.begin (); tfi != tempfiles.end (); ++tfi) { - if (*tfi == name) + if ((*tfi).name == name) { - unlink (name); - tempfiles.erase (tfi); + (*tfi).keep = true; break; } } @@ -147,12 +143,13 @@ namespace rld } } - tempfile::tempfile (const std::string& suffix) + tempfile::tempfile (const std::string& suffix, bool _keep) : suffix (suffix), + overridden (false), fd (-1), level (0) { - _name = temporaries.get (suffix); + _name = temporaries.get (suffix, _keep); } tempfile::~tempfile () @@ -164,10 +161,23 @@ namespace rld void tempfile::open (bool writable) { - if ((fd < 0) && rld::path::check_file (_name)) + if (fd < 0) { + bool ok = rld::path::check_file (_name); + int flags = writable ? O_RDWR : O_RDONLY; + + if (overridden) + { + flags |= O_CREAT | O_TRUNC; + } + else + { + if (!ok) + throw rld::error ("Not found.", "tempfile open:" + _name); + } + level = 0; - fd = ::open (_name.c_str (), writable ? O_RDWR : O_RDONLY); + fd = ::open (_name.c_str (), flags); if (fd < 0) throw rld::error (::strerror (errno), "tempfile open:" + _name); } @@ -184,6 +194,22 @@ namespace rld } } + void + tempfile::override (const std::string& name_) + { + if (fd >= 0) + throw rld::error ("Already open", "tempfile override"); + rld::path::unlink (_name); + overridden = true; + _name = name_ + suffix; + } + + void + tempfile::keep () + { + temporaries.keep (_name); + } + const std::string& tempfile::name () const { diff --git a/rld-process.h b/rld-process.h index 30033a7..6c714f2 100644 --- a/rld-process.h +++ b/rld-process.h @@ -33,6 +33,20 @@ namespace rld { namespace process { + /** + * Temporary file is a name and keep state. + */ + struct tempfile_ref + { + const std::string name; //< The name of the tempfile. + bool keep; //< If true do not delete this file. + + tempfile_ref (const std::string& name, bool keep = false) + : name (name), + keep (keep) { + } + }; + /** * Manage temporary files. We keep these so we can delete them when * we exit. @@ -43,7 +57,7 @@ namespace rld /** * Container of temporary file names. */ - typedef std::list < std::string > tempfile_container; + typedef std::list < tempfile_ref > tempfile_container; /** * Construct the temporary files. @@ -58,13 +72,19 @@ namespace rld /** * Get a new temporary file name. */ - const std::string get (const std::string& suffix = ".rldxx"); + const std::string get (const std::string& suffix = ".rldxx", + bool keep = false); /** * Remove the temporary file. */ void erase (const std::string& name); + /** + * Set the tempfile reference keep state to true. + */ + void keep (const std::string& name); + /** * Remove all temporary files. */ @@ -73,9 +93,9 @@ namespace rld private: /* - * Delete the file. + * Delete the tempfile given the reference if not keeping. */ - void unlink (const std::string& name); + void unlink (const tempfile_ref& ref); tempfile_container tempfiles; //< The temporary files. @@ -89,9 +109,9 @@ namespace rld public: /** - * Get a temporary file name. + * Get a temporary file name given a suffix. */ - tempfile (const std::string& suffix = ".rldxx"); + tempfile (const std::string& suffix = ".rldxx", bool keep = false); /** * Clean up the temporary file. @@ -108,6 +128,17 @@ namespace rld */ void close (); + /** + * Override the temp file name automatically assigned with this name. The + * suffix is appended. + */ + void override (const std::string& name); + + /** + * Set the temp file keep state to true so it is not deleted. + */ + void keep (); + /** * The name of the temp file. */ @@ -157,11 +188,12 @@ namespace rld private: - std::string _name; //< The name of the file. - const std::string suffix; //< The temp file's suffix. - int fd; //< The file descriptor - char buf[256]; //< The read buffer. - int level; //< The level of data in the buffer. + std::string _name; //< The name of the file. + const std::string suffix; //< The temp file's suffix. + bool overridden; //< The name is overridden; may no exist. + int fd; //< The file descriptor + char buf[256]; //< The read buffer. + int level; //< The level of data in the buffer. }; /** diff --git a/rld.h b/rld.h index 2c5fdd2..0a6cd9c 100644 --- a/rld.h +++ b/rld.h @@ -272,7 +272,7 @@ namespace rld const std::string version (); /** - * The RTEMS version string. + * The RTEMS version string. @todo move to rld-rtems. */ const std::string rtems_version (); diff --git a/rtems-tld.cpp b/rtems-tld.cpp index 7a5ca65..41269da 100644 --- a/rtems-tld.cpp +++ b/rtems-tld.cpp @@ -727,8 +727,10 @@ namespace rld rld::cc::make_cc_command (args); rld::cc::append_flags (rld::cc::ft_cflags, args); + args.push_back ("-O2"); + args.push_back ("-g"); args.push_back ("-c"); - args.push_back ("-o "); + args.push_back ("-o"); args.push_back (o.name ()); args.push_back (c.name ()); @@ -782,6 +784,7 @@ static struct option rld_opts[] = { { "rtems", required_argument, NULL, 'r' }, { "rtems-bsp", required_argument, NULL, 'B' }, { "config", required_argument, NULL, 'C' }, + { "wrapper", required_argument, NULL, 'W' }, { NULL, 0, NULL, 0 } }; @@ -790,17 +793,18 @@ 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 - << " -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 - << " -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 + << " -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; ::exit (exit_code); } @@ -851,11 +855,12 @@ main (int argc, char* argv[]) std::string ld_cmd; std::string configuration; std::string trace = "tracer"; + std::string wrapper; bool arch_bsp_load = false; while (true) { - int opt = ::getopt_long (argc, argv, "hvwkVE:c:C:r:B:", rld_opts, NULL); + int opt = ::getopt_long (argc, argv, "hvwkVE:c:C:r:B:W:", rld_opts, NULL); if (opt < 0) break; @@ -902,6 +907,10 @@ main (int argc, char* argv[]) configuration = optarg; break; + case 'W': + wrapper = optarg; + break; + case '?': usage (3); break; @@ -945,10 +954,19 @@ main (int argc, char* argv[]) */ try { + linker.load_config (configuration, trace); + rld::process::tempfile c (".c"); rld::process::tempfile o (".o"); - linker.load_config (configuration, trace); + if (!wrapper.empty ()) + { + c.override (wrapper); + c.keep (); + o.override (wrapper); + o.keep (); + } + linker.generate_wrapper (c); linker.compile_wrapper (c, o); -- cgit v1.2.3