Patchwork Go patch committed: Add -fgo-relative-import-path option

login
register
mail settings
Submitter Ian Taylor
Date Oct. 31, 2012, 12:38 a.m.
Message ID <mcrd2zzo4pr.fsf@google.com>
Download mbox | patch
Permalink /patch/195668/
State New
Headers show

Comments

Ian Taylor - Oct. 31, 2012, 12:38 a.m.
The go tool, used by many people to build Go programs, handles relative
import paths by passing a special option to the compiler.  The option is
a prefix to use for any relative import.  The go tool does this so that
programs can be built in a temporary directory and can still find
packages imported on a relative path.  The gc compiler calls this option
-D.  This patch adds the same option to gccgo, using the name
-fgo-relative-import-path.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline and 4.7 branch.

Ian


2012-10-30  Ian Lance Taylor  <iant@google.com>

	* lang.opt (-fgo-relative-import-path): New option.
	* go-lang.c (go_relative_import_path): New static variable.
	(go_langhook_init): Pass go_relative_import_path to
	go_create_gogo.
	(go_langhook_handle_option): Handle -fgo-relative-import-path.
	* go-c.h (go_create_gogo): Update declaration.
	* gccgo.texi (Invoking gccgo): Document
	-fgo-relative-import-path.

Patch

Index: gcc/go/lang.opt
===================================================================
--- gcc/go/lang.opt	(revision 192992)
+++ gcc/go/lang.opt	(working copy)
@@ -61,6 +61,10 @@  fgo-prefix=
 Go Joined RejectNegative
 -fgo-prefix=<string>	Set package-specific prefix for exported Go names
 
+fgo-relative-import-path=
+Go Joined RejectNegative
+-fgo-relative-import-path=<path> Treat a relative import as relative to path
+
 frequire-return-statement
 Go Var(go_require_return_statement) Init(1) Warning
 Functions which return values must end with return statements
Index: gcc/go/gccgo.texi
===================================================================
--- gcc/go/gccgo.texi	(revision 192992)
+++ gcc/go/gccgo.texi	(working copy)
@@ -184,6 +184,12 @@  Using either @option{-fgo-pkgpath} or @o
 the special treatment of the @code{main} package and permits that
 package to be imported like any other.
 
+@item -fgo-relative-import-path=@var{dir}
+@cindex @option{-fgo-relative-import-path}
+A relative import is an import that starts with @file{./} or
+@file{../}.  If this option is used, @command{gccgo} will use
+@var{dir} as a prefix for the relative import when searching for it.
+
 @item -frequire-return-statement
 @itemx -fno-require-return-statement
 @cindex @option{-frequire-return-statement}
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 192992)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -44,6 +44,7 @@  Gogo::Gogo(Backend* backend, Linemap* li
     pkgpath_set_(false),
     pkgpath_from_option_(false),
     prefix_from_option_(false),
+    relative_import_path_(),
     verify_types_(),
     interface_types_(),
     specific_type_functions_(),
@@ -477,7 +478,8 @@  Gogo::import_package(const std::string& 
       return;
     }
 
-  Import::Stream* stream = Import::open_package(filename, location);
+  Import::Stream* stream = Import::open_package(filename, location,
+						this->relative_import_path_);
   if (stream == NULL)
     {
       error_at(location, "import file %qs not found", filename.c_str());
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 192992)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -206,6 +206,17 @@  class Gogo
   pkgpath_from_option() const
   { return this->pkgpath_from_option_; }
 
+  // Return the relative import path as set from the command line.
+  // Returns an empty string if it was not set.
+  const std::string&
+  relative_import_path() const
+  { return this->relative_import_path_; }
+
+  // Set the relative import path from a command line option.
+  void
+  set_relative_import_path(const std::string& s)
+  {this->relative_import_path_ = s; }
+
   // Return the priority to use for the package we are compiling.
   // This is two more than the largest priority of any package we
   // import.
@@ -732,6 +743,9 @@  class Gogo
   bool pkgpath_from_option_;
   // Whether an explicit prefix was set by -fgo-prefix.
   bool prefix_from_option_;
+  // The relative import path, from the -fgo-relative-import-path
+  // option.
+  std::string relative_import_path_;
   // A list of types to verify.
   std::vector<Type*> verify_types_;
   // A list of interface types defined while parsing.
Index: gcc/go/gofrontend/go.cc
===================================================================
--- gcc/go/gofrontend/go.cc	(revision 192992)
+++ gcc/go/gofrontend/go.cc	(working copy)
@@ -21,7 +21,7 @@  static Gogo* gogo;
 GO_EXTERN_C
 void
 go_create_gogo(int int_type_size, int pointer_size, const char *pkgpath,
-	       const char *prefix)
+	       const char *prefix, const char *relative_import_path)
 {
   go_assert(::gogo == NULL);
   Linemap* linemap = go_get_linemap();
@@ -32,6 +32,9 @@  go_create_gogo(int int_type_size, int po
   else if (prefix != NULL)
     ::gogo->set_prefix(prefix);
 
+  if (relative_import_path != NULL)
+    ::gogo->set_relative_import_path(relative_import_path);
+
   // FIXME: This should be in the gcc dependent code.
   ::gogo->define_builtin_function_trees();
 }
Index: gcc/go/gofrontend/import.h
===================================================================
--- gcc/go/gofrontend/import.h	(revision 192992)
+++ gcc/go/gofrontend/import.h	(working copy)
@@ -124,8 +124,10 @@  class Import
   // Find import data.  This searches the file system for FILENAME and
   // returns a pointer to a Stream object to read the data that it
   // exports.  LOCATION is the location of the import statement.
+  // RELATIVE_IMPORT_PATH is used as a prefix for a relative import.
   static Stream*
-  open_package(const std::string& filename, Location location);
+  open_package(const std::string& filename, Location location,
+	       const std::string& relative_import_path);
 
   // Constructor.
   Import(Stream*, Location);
Index: gcc/go/gofrontend/import.cc
===================================================================
--- gcc/go/gofrontend/import.cc	(revision 192992)
+++ gcc/go/gofrontend/import.cc	(working copy)
@@ -41,6 +41,9 @@  go_add_search_path(const char* path)
 // When FILENAME is not an absolute path and does not start with ./ or
 // ../, we use the search path provided by -I and -L options.
 
+// When FILENAME does start with ./ or ../, we use
+// RELATIVE_IMPORT_PATH as a prefix.
+
 // When FILENAME does not exist, we try modifying FILENAME to find the
 // file.  We use the first of these which exists:
 //   * We append ".gox".
@@ -55,19 +58,35 @@  go_add_search_path(const char* path)
 // later in the search path.
 
 Import::Stream*
-Import::open_package(const std::string& filename, Location location)
+Import::open_package(const std::string& filename, Location location,
+		     const std::string& relative_import_path)
 {
   bool is_local;
   if (IS_ABSOLUTE_PATH(filename))
     is_local = true;
-  else if (filename[0] == '.' && IS_DIR_SEPARATOR(filename[1]))
+  else if (filename[0] == '.'
+	   && (filename[1] == '\0' || IS_DIR_SEPARATOR(filename[1])))
     is_local = true;
   else if (filename[0] == '.'
 	   && filename[1] == '.'
-	   && IS_DIR_SEPARATOR(filename[2]))
+	   && (filename[2] == '\0' || IS_DIR_SEPARATOR(filename[2])))
     is_local = true;
   else
     is_local = false;
+
+  std::string fn = filename;
+  if (is_local && !IS_ABSOLUTE_PATH(filename) && !relative_import_path.empty())
+    {
+      if (fn == ".")
+	{
+	  // A special case.
+	  fn = relative_import_path;
+	}
+      else
+	fn = relative_import_path + '/' + fn;
+      is_local = false;
+    }
+
   if (!is_local)
     {
       for (std::vector<std::string>::const_iterator p = search_path.begin();
@@ -77,14 +96,14 @@  Import::open_package(const std::string& 
 	  std::string indir = *p;
 	  if (!indir.empty() && indir[indir.size() - 1] != '/')
 	    indir += '/';
-	  indir += filename;
+	  indir += fn;
 	  Stream* s = Import::try_package_in_directory(indir, location);
 	  if (s != NULL)
 	    return s;
 	}
     }
 
-  Stream* s = Import::try_package_in_directory(filename, location);
+  Stream* s = Import::try_package_in_directory(fn, location);
   if (s != NULL)
     return s;
 
Index: gcc/go/go-lang.c
===================================================================
--- gcc/go/go-lang.c	(revision 192992)
+++ gcc/go/go-lang.c	(working copy)
@@ -85,6 +85,7 @@  struct GTY(()) language_function
 
 static const char *go_pkgpath = NULL;
 static const char *go_prefix = NULL;
+static const char *go_relative_import_path = NULL;
 
 /* Language hooks.  */
 
@@ -101,7 +102,8 @@  go_langhook_init (void)
      to, e.g., unsigned_char_type_node) but before calling
      build_common_builtin_nodes (because it calls, indirectly,
      go_type_for_size).  */
-  go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix);
+  go_create_gogo (INT_TYPE_SIZE, POINTER_SIZE, go_pkgpath, go_prefix,
+		  go_relative_import_path);
 
   build_common_builtin_nodes ();
 
@@ -240,6 +242,10 @@  go_langhook_handle_option (
       go_prefix = arg;
       break;
 
+    case OPT_fgo_relative_import_path_:
+      go_relative_import_path = arg;
+      break;
+
     default:
       /* Just return 1 to indicate that the option is valid.  */
       break;
Index: gcc/go/go-c.h
===================================================================
--- gcc/go/go-c.h	(revision 192992)
+++ gcc/go/go-c.h	(working copy)
@@ -33,7 +33,8 @@  extern int go_enable_optimize (const cha
 extern void go_add_search_path (const char*);
 
 extern void go_create_gogo (int int_type_size, int pointer_size,
-			    const char* pkgpath, const char *prefix);
+			    const char* pkgpath, const char *prefix,
+			    const char *relative_import_path);
 
 extern void go_parse_input_files (const char**, unsigned int,
 				  bool only_check_syntax,