From 4f7bb2dfed857ab44e87bf015d756cfc0be1b86f Mon Sep 17 00:00:00 2001 From: Peng Fan Date: Sat, 24 Aug 2013 18:10:54 +0800 Subject: RA format support for rtems-ld 1. Automatically place object files in archive files into a ra file, using new option --runtime-lib 2. Add a new option --one-file to decide whether the collected object files should be merged into the rap file or not. Signed-off-by: Peng Fan --- rld-outputter.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++- rld-outputter.h | 8 +++- rtems-ld.cpp | 45 ++++++++++++++++++++++- 3 files changed, 157 insertions(+), 4 deletions(-) diff --git a/rld-outputter.cpp b/rld-outputter.cpp index 8c6c37c..87e74f0 100644 --- a/rld-outputter.cpp +++ b/rld-outputter.cpp @@ -35,6 +35,11 @@ #include #include +#include +#include +#include +#include "rld-process.h" + namespace rld { namespace outputter @@ -185,6 +190,96 @@ namespace rld arch.create (objects); } + void + archivera (const std::string& name, + const files::object_list& dependents, + files::cache& cache, + bool ra_exist) + { + files::object_list dep_copy (dependents); + files::object_list objects; + + if (rld::verbose () >= RLD_VERBOSE_INFO) + std::cout << "outputter:archivera: " << name + << ", dependents: " << dependents.size () << std::endl; + + objects.clear (); + + files::object_list::iterator oli; + for (oli = dep_copy.begin (); oli != dep_copy.end (); ++oli) + { + files::object& object = *(*oli); + + if (object.get_archive ()) + { + objects.push_back (&object); + } + } + + bool exist = false; + files::object_list objects_tmp; + files::objects& objs = cache.get_objects (); + objects_tmp.clear (); + for (files::objects::iterator obi = objs.begin (); + obi != objs.end (); + ++obi) + { + files::object* obj = (*obi).second; + exist = false; + + /** + * Replace the elf object file in ra file with elf object file + * in collected object files, if exist. + */ + for (oli = objects.begin (); oli != objects.end (); ++oli) + { + files::object& object = *(*oli); + if (obj->name ().oname () == object.name ().oname ()) + { + exist = true; + break; + } + } + if (!exist) + objects_tmp.push_back (obj); + } + + objects.merge (objects_tmp); + objects.unique (); + + if (objects.size ()) + { + if (ra_exist) + { + std::string new_name = "rld_XXXXXX"; + struct stat sb; + files::archive arch (new_name); + arch.create (objects); + + if ((::stat (name.c_str (), &sb) >= 0) && S_ISREG (sb.st_mode)) + { + if (::unlink (name.c_str ()) < 0) + std::cerr << "error: unlinking temp file: " << name << std::endl; + } + if (::link (new_name.c_str (), name.c_str ()) < 0) + { + std::cerr << "error: linking temp file: " << name << std::endl; + } + if ((::stat (new_name.c_str (), &sb) >= 0) && S_ISREG (sb.st_mode)) + { + if (::unlink (new_name.c_str ()) < 0) + std::cerr << "error: unlinking temp file: " << new_name << std::endl; + } + } + else + { + /* Create */ + files::archive arch (name); + arch.create (objects); + } + } + } + void script (const std::string& name, const std::string& entry, @@ -297,13 +392,21 @@ namespace rld app.close (); } + bool in_archive (files::object* object) + { + if (object->get_archive ()) + return true; + return false; + } + void application (const std::string& name, const std::string& entry, const std::string& exit, const files::object_list& dependents, const files::cache& cache, - const symbols::table& symbols) + const symbols::table& symbols, + bool one_file) { if (rld::verbose () >= RLD_VERBOSE_INFO) std::cout << "outputter:application: " << name << std::endl; @@ -312,6 +415,9 @@ namespace rld files::object_list objects; files::image app (name); + if (!one_file) + dep_copy.remove_if (in_archive); + cache.get_objects (objects); objects.merge (dep_copy); objects.unique (); diff --git a/rld-outputter.h b/rld-outputter.h index 0957c04..8b052e6 100644 --- a/rld-outputter.h +++ b/rld-outputter.h @@ -62,6 +62,11 @@ namespace rld const files::object_list& dependents, const files::cache& cache); + void archivera (const std::string& name, + const files::object_list& dependents, + files::cache& cache, + bool ra_exist); + /** * Output the object file list as a script. * @@ -110,7 +115,8 @@ namespace rld const std::string& exit, const files::object_list& dependents, const files::cache& cache, - const symbols::table& symbols); + const symbols::table& symbols, + bool one_file); } } diff --git a/rtems-ld.cpp b/rtems-ld.cpp index 34a1ee5..6216f04 100644 --- a/rtems-ld.cpp +++ b/rtems-ld.cpp @@ -72,6 +72,8 @@ static struct option rld_opts[] = { { "mcpu", required_argument, NULL, 'c' }, { "rap-strip", no_argument, NULL, 'S' }, { "rpath", required_argument, NULL, 'R' }, + { "runtime-lib", required_argument, NULL, 'P' }, + { "one-file", no_argument, NULL, 's' }, { NULL, 0, NULL, 0 } }; @@ -114,6 +116,8 @@ usage (int exit_code) << " -c cpu : machine architecture's CPU (also --mcpu)" << std::endl << " -S : do not include file details (also --rap-strip)" << std::endl << " -R : include file paths (also --rpath)" << std::endl + << " -P : place objects from archives (also --runtime-lib)" << std::endl + << " -s : Include archive elf object files (also --one-file)" << std::endl << " -Wl,opts : link compatible flags, ignored" << std::endl << "Output Formats:" << std::endl << " rap - RTEMS application (LZ77, single image)" << std::endl @@ -168,6 +172,7 @@ main (int argc, char* argv[]) { rld::files::cache cache; rld::files::cache base; + rld::files::cache cachera; rld::files::paths libpaths; rld::files::paths libs; rld::files::paths objects; @@ -180,6 +185,7 @@ main (int argc, char* argv[]) std::string entry = "rtems"; std::string exit; std::string output = "a.out"; + std::string outra; std::string base_name; std::string cc_name; std::string output_type = "rap"; @@ -187,12 +193,13 @@ main (int argc, char* argv[]) bool exec_prefix_set = false; bool map = false; bool warnings = false; + bool one_file = false; libpaths.push_back ("."); while (true) { - int opt = ::getopt_long (argc, argv, "hvwVMnb:E:o:O:L:l:a:c:e:d:u:C:W:R", rld_opts, NULL); + int opt = ::getopt_long (argc, argv, "hvwVMnb:E:o:O:L:l:a:c:e:d:u:C:W:R:P", rld_opts, NULL); if (opt < 0) break; @@ -233,6 +240,18 @@ main (int argc, char* argv[]) libs.push_back (optarg); break; + case 'P': + if (!outra.empty ()) + std::cerr << "warning: output ra alreay set" << std::endl; + outra = "lib"; + outra += optarg; + outra += ".ra"; + break; + + case 's': + one_file = true; + break; + case 'L': if ((optarg[::strlen (optarg) - 1] == '/') || (optarg[::strlen (optarg) - 1] == '\\')) @@ -450,8 +469,30 @@ main (int argc, char* argv[]) rld::outputter::elf_application (output, entry, exit, dependents, cache); else if (output_type == "rap") + { rld::outputter::application (output, entry, exit, - dependents, cache, symbols); + dependents, cache, symbols, + one_file); + if (!outra.empty ()) + { + rld::files::paths ra_libs; + bool ra_exist = false; + + /** + * If exist, search it, else create a new one. + */ + if ((ra_exist = ::access (outra.c_str (), 0)) == 0) + { + ra_libs.push_back (outra); + cachera.open (); + cachera.add_libraries (ra_libs); + cachera.archives_begin (); + } + + rld::outputter::archivera (outra, dependents, cachera, + !ra_exist); + } + } else throw rld::error ("invalid output type", "output"); -- cgit v1.2.3