aboutsummaryrefslogtreecommitdiff
path: root/gold/options.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/options.cc')
-rw-r--r--gold/options.cc132
1 files changed, 125 insertions, 7 deletions
diff --git a/gold/options.cc b/gold/options.cc
index 4df21b0..f49b9f5 100644
--- a/gold/options.cc
+++ b/gold/options.cc
@@ -20,9 +20,13 @@
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
+#include "gold.h"
+
#include <iostream>
+#include <sys/stat.h>
+#include "filenames.h"
+#include "libiberty.h"
-#include "gold.h"
#include "options.h"
namespace gold
@@ -216,6 +220,51 @@ help(int, char**, char*, gold::Command_line*)
return 0;
}
+// If the default sysroot is relocatable, try relocating it based on
+// the prefix FROM.
+
+char*
+get_relative_sysroot(const char* from)
+{
+ char* path = make_relative_prefix(gold::program_name, from,
+ TARGET_SYSTEM_ROOT);
+ if (path != NULL)
+ {
+ struct stat s;
+ if (::stat(path, &s) == 0 && S_ISDIR(s.st_mode))
+ return path;
+ free(path);
+ }
+
+ return NULL;
+}
+
+// Return the default sysroot. This is set by the --with-sysroot
+// option to configure.
+
+std::string
+get_default_sysroot()
+{
+ const char* sysroot = TARGET_SYSTEM_ROOT;
+ if (*sysroot == '\0')
+ return "";
+
+ if (TARGET_SYSTEM_ROOT_RELOCATABLE)
+ {
+ char* path = get_relative_sysroot (BINDIR);
+ if (path == NULL)
+ path = get_relative_sysroot (TOOLBINDIR);
+ if (path != NULL)
+ {
+ std::string ret = path;
+ free(path);
+ return ret;
+ }
+ }
+
+ return sysroot;
+}
+
} // End anonymous namespace.
namespace gold
@@ -285,8 +334,8 @@ options::Command_line_options::options[] =
NULL, ONE_DASH, &General_options::set_shared),
GENERAL_NOARG('\0', "static", N_("Do not link against shared libraries"),
NULL, ONE_DASH, &General_options::set_static),
- GENERAL_ARG('\0', "sysroot", N_("Currently ignored"), NULL, TWO_DASHES,
- &General_options::ignore),
+ GENERAL_ARG('\0', "sysroot", N_("Set target system root directory"),
+ N_("--sysroot DIR"), TWO_DASHES, &General_options::set_sysroot),
POSDEP_NOARG('\0', "as-needed",
N_("Only set DT_NEEDED for dynamic libs if used"),
NULL, TWO_DASHES, &Position_dependent_options::set_as_needed),
@@ -321,7 +370,8 @@ General_options::General_options()
rpath_(),
rpath_link_(),
is_shared_(false),
- is_static_(false)
+ is_static_(false),
+ sysroot_()
{
}
@@ -334,6 +384,66 @@ Position_dependent_options::Position_dependent_options()
{
}
+// Add the sysroot, if any, to the search paths.
+
+void
+General_options::add_sysroot()
+{
+ if (this->sysroot_.empty())
+ {
+ this->sysroot_ = get_default_sysroot();
+ if (this->sysroot_.empty())
+ return;
+ }
+
+ const char* sysroot = this->sysroot_.c_str();
+ char* canonical_sysroot = lrealpath(sysroot);
+
+ for (Dir_list::iterator p = this->search_path_.begin();
+ p != this->search_path_.end();
+ ++p)
+ p->add_sysroot(sysroot, canonical_sysroot);
+
+ free(canonical_sysroot);
+}
+
+// Search_directory methods.
+
+// This is called if we have a sysroot. Apply the sysroot if
+// appropriate. Record whether the directory is in the sysroot.
+
+void
+Search_directory::add_sysroot(const char* sysroot,
+ const char* canonical_sysroot)
+{
+ gold_assert(*sysroot != '\0');
+ if (this->put_in_sysroot_)
+ {
+ if (!IS_DIR_SEPARATOR(this->name_[0])
+ && !IS_DIR_SEPARATOR(sysroot[strlen(sysroot) - 1]))
+ this->name_ = '/' + this->name_;
+ this->name_ = sysroot + this->name_;
+ this->is_in_sysroot_ = true;
+ }
+ else
+ {
+ // Check whether this entry is in the sysroot. To do this
+ // correctly, we need to use canonical names. Otherwise we will
+ // get confused by the ../../.. paths that gcc tends to use.
+ char* canonical_name = lrealpath(this->name_.c_str());
+ int canonical_name_len = strlen(canonical_name);
+ int canonical_sysroot_len = strlen(canonical_sysroot);
+ if (canonical_name_len > canonical_sysroot_len
+ && IS_DIR_SEPARATOR(canonical_name[canonical_sysroot_len]))
+ {
+ canonical_name[canonical_sysroot_len] = '\0';
+ if (FILENAME_CMP(canonical_name, canonical_sysroot) == 0)
+ this->is_in_sysroot_ = true;
+ }
+ free(canonical_name);
+ }
+}
+
// Input_arguments methods.
// Add a file to the list.
@@ -414,8 +524,12 @@ Command_line::process(int argc, char** argv)
char first = opt[0];
int skiparg = 0;
char* arg = strchr(opt, '=');
+ bool argument_with_equals = arg != NULL;
if (arg != NULL)
- *arg = '\0';
+ {
+ *arg = '\0';
+ ++arg;
+ }
else if (i + 1 < argc)
{
arg = argv[i + 1];
@@ -438,6 +552,8 @@ Command_line::process(int argc, char** argv)
{
if (!options[j].takes_argument())
{
+ if (argument_with_equals)
+ this->usage(_("unexpected argument"), argv[i]);
arg = NULL;
skiparg = 0;
}
@@ -517,8 +633,10 @@ Command_line::process(int argc, char** argv)
}
// FIXME: We should only do this when configured in native mode.
- this->options_.add_to_search_path("/lib");
- this->options_.add_to_search_path("/usr/lib");
+ this->options_.add_to_search_path_with_sysroot("/lib");
+ this->options_.add_to_search_path_with_sysroot("/usr/lib");
+
+ this->options_.add_sysroot();
}
// Apply a command line option.