From de4da665d3205afa239749c41513a315c3831f51 Mon Sep 17 00:00:00 2001
From: Stephen Kelly <steveire@gmail.com>
Date: Sat, 13 Apr 2013 14:46:57 +0200
Subject: Use --sysroot when cross compiling.

As CMAKE_ROOT_FIND_PATH can be a list, a new CMAKE_SYSROOT is
introduced, which is never a list.

The contents of this variable is passed to supporting compilers
as --sysroot. It is also accounted for when processing implicit
link directories reported by the compiler, and when generating
RPATH information.
---
 Modules/Compiler/GNU.cmake                     |  1 +
 Source/cmComputeLinkInformation.cxx            | 11 +++++++++--
 Source/cmDocumentVariables.cxx                 | 10 ++++++++++
 Source/cmFindCommon.cxx                        | 24 ++++++++++++++++++++----
 Source/cmLocalGenerator.cxx                    |  6 +++++-
 Source/cmMakefileExecutableTargetGenerator.cxx | 16 ++++++++++++++++
 Source/cmMakefileLibraryTargetGenerator.cxx    | 20 ++++++++++++++++++++
 Source/cmMakefileTargetGenerator.cxx           | 17 +++++++++++++++++
 Source/cmNinjaNormalTargetGenerator.cxx        | 22 +++++++++++++++++++++-
 Source/cmNinjaTargetGenerator.cxx              | 18 +++++++++++++++++-
 10 files changed, 136 insertions(+), 9 deletions(-)

diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index 504704d..e5e10c3 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -30,6 +30,7 @@ macro(__compiler_gnu lang)
   endif()
   set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
   set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
+  set(CMAKE_SYSROOT_FLAG "--sysroot=")
 
   # Older versions of gcc (< 4.5) contain a bug causing them to report a missing
   # header file as a warning if depfiles are enabled, causing check_header_file
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 02495c4..b378391 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1884,6 +1884,8 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
     }
   if(use_build_rpath || use_link_rpath)
     {
+    std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+    cmSystemTools::ConvertToUnixSlashes(rootPath);
     std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath();
     for(std::vector<std::string>::const_iterator ri = rdirs.begin();
         ri != rdirs.end(); ++ri)
@@ -1907,9 +1909,14 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
            !cmSystemTools::IsSubDirectory(ri->c_str(), topSourceDir) &&
            !cmSystemTools::IsSubDirectory(ri->c_str(), topBinaryDir))
           {
-          if(emitted.insert(*ri).second)
+          std::string d = *ri;
+          if (d.find(rootPath) == 0)
             {
-            runtimeDirs.push_back(*ri);
+            d = d.substr(rootPath.size());
+            }
+          if(emitted.insert(d).second)
+            {
+            runtimeDirs.push_back(d);
             }
           }
         }
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 689508f..4499cbd 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -561,6 +561,16 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
      "Variables That Change Behavior");
 
     cm->DefineProperty
+    ("CMAKE_SYSROOT",  cmProperty::VARIABLE,
+     "Path to pass to the compiler in the --sysroot flag.",
+     "The CMAKE_SYSROOT content is passed to the compiler in the --sysroot "
+     "flag, if supported.  The path is also stripped from the RPATH if "
+     "necessary on installation.  The CMAKE_SYSROOT is also used to prefix "
+     "paths searched by the find_* commands.",
+     false,
+     "Variables That Change Behavior");
+
+    cm->DefineProperty
     ("CMAKE_FIND_LIBRARY_PREFIXES",  cmProperty::VARIABLE,
      "Prefixes to prepend when looking for libraries.",
      "This specifies what prefixes to add to library names when "
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index b44864e..5daa47d 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -62,10 +62,15 @@ void cmFindCommon::GenerateDocumentation()
     "The CMake variable CMAKE_FIND_ROOT_PATH specifies one or more "
     "directories to be prepended to all other search directories. "
     "This effectively \"re-roots\" the entire search under given locations. "
-    "By default it is empty. It is especially useful when "
+    "By default it is empty.  "
+    "The variable CMAKE_SYSROOT can also be used to specify exactly one "
+    "directory to use as a prefix.  Setting CMAKE_SYSROOT also has other "
+    "effects.  See the documentation for that variable for more.  "
+    "These are especially useful when "
     "cross-compiling to point to the root directory of the "
     "target environment and CMake will search there too. By default at first "
-    "the directories listed in CMAKE_FIND_ROOT_PATH and then the non-rooted "
+    "the CMAKE_SYSROOT directory is searched, then the directories listed in "
+    "CMAKE_FIND_ROOT_PATH and then the non-rooted "
     "directories will be searched. "
     "The default behavior can be adjusted by setting "
     "CMAKE_FIND_ROOT_PATH_MODE_XXX.  This behavior can be manually "
@@ -187,16 +192,27 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
     {
     return;
     }
+  const char* sysroot =
+    this->Makefile->GetDefinition("CMAKE_SYSROOT");
   const char* rootPath =
     this->Makefile->GetDefinition("CMAKE_FIND_ROOT_PATH");
-  if((rootPath == 0) || (strlen(rootPath) == 0))
+  const bool noSysroot = !sysroot || !*sysroot;
+  const bool noRootPath = !rootPath || !*rootPath;
+  if(noSysroot && noRootPath)
     {
     return;
     }
 
   // Construct the list of path roots with no trailing slashes.
   std::vector<std::string> roots;
-  cmSystemTools::ExpandListArgument(rootPath, roots);
+  if (sysroot)
+    {
+    roots.push_back(sysroot);
+    }
+  if (rootPath)
+    {
+    cmSystemTools::ExpandListArgument(rootPath, roots);
+    }
   for(std::vector<std::string>::iterator ri = roots.begin();
       ri != roots.end(); ++ri)
     {
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index c2da4a9..1563860 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1425,6 +1425,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     return;
     }
 
+  std::string rootPath = this->Makefile->GetSafeDefinition("CMAKE_SYSROOT");
+
   std::vector<std::string> implicitDirs;
   // Load implicit include directories for this language.
   std::string impDirVar = "CMAKE_";
@@ -1437,7 +1439,9 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
     for(std::vector<std::string>::const_iterator i = impDirVec.begin();
         i != impDirVec.end(); ++i)
       {
-      emitted.insert(*i);
+      std::string d = rootPath + *i;
+      cmSystemTools::ConvertToUnixSlashes(d);
+      emitted.insert(d);
       if (!stripImplicitInclDirs)
         {
         implicitDirs.push_back(*i);
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index e4219a9..271183e 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -365,6 +365,22 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   vars.TargetVersionMajor = targetVersionMajor.c_str();
   vars.TargetVersionMinor = targetVersionMinor.c_str();
 
+  if (const char *rootPath =
+                    this->Makefile->GetDefinition("CMAKE_SYSROOT"))
+    {
+    if (*rootPath)
+      {
+      if (const char *sysrootFlag =
+                      this->Makefile->GetDefinition("CMAKE_SYSROOT_FLAG"))
+        {
+        flags += " ";
+        flags += sysrootFlag;
+        flags += this->LocalGenerator->EscapeForShell(rootPath);
+        flags += " ";
+        }
+      }
+    }
+
   vars.LinkLibraries = linkLibs.c_str();
   vars.Flags = flags.c_str();
   vars.LinkFlags = linkFlags.c_str();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 347f26d..36d1a5a 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -589,6 +589,26 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
                          cmLocalGenerator::SHELL);
   vars.ObjectDir = objdir.c_str();
   vars.Target = targetOutPathReal.c_str();
+
+  if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
+    {
+    if (const char *rootPath =
+                    this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"))
+      {
+      if (*rootPath)
+        {
+        if (const char *sysrootFlag =
+                        this->Makefile->GetDefinition("CMAKE_SYSROOT_FLAG"))
+          {
+          linkFlags += " ";
+          linkFlags += sysrootFlag;
+          linkFlags += this->LocalGenerator->EscapeForShell(rootPath);
+          linkFlags += " ";
+          }
+        }
+      }
+    }
+
   vars.LinkLibraries = linkLibs.c_str();
   vars.ObjectsQuoted = buildObjs.c_str();
   if (this->Target->HasSOName(this->ConfigName))
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 10b7849..f31b1a8 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -686,6 +686,23 @@ cmMakefileTargetGenerator
                             cmLocalGenerator::START_OUTPUT,
                             cmLocalGenerator::SHELL);
   vars.ObjectDir = objectDir.c_str();
+
+  if (const char *rootPath =
+                    this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"))
+    {
+    if (*rootPath)
+      {
+      if (const char *sysrootFlag =
+                      this->Makefile->GetDefinition("CMAKE_SYSROOT_FLAG"))
+        {
+        flags += " ";
+        flags += sysrootFlag;
+        flags += this->LocalGenerator->EscapeForShell(rootPath);
+        flags += " ";
+        }
+      }
+    }
+
   vars.Flags = flags.c_str();
 
   std::string definesString = "$(";
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 1bc4302..0a2a75f 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -223,7 +223,27 @@ cmNinjaNormalTargetGenerator
     vars.TargetVersionMajor = targetVersionMajor.c_str();
     vars.TargetVersionMinor = targetVersionMinor.c_str();
 
-    vars.Flags = "$FLAGS";
+
+    std::string flags = "$FLAGS";
+
+    if (const char *rootPath =
+                      this->GetMakefile()->GetSafeDefinition("CMAKE_SYSROOT"))
+      {
+      if (*rootPath)
+        {
+        if (const char *sysrootFlag =
+                    this->GetMakefile()->GetDefinition("CMAKE_SYSROOT_FLAG"))
+          {
+          flags += " ";
+          flags += sysrootFlag;
+          flags += this->GetLocalGenerator()->EscapeForShell(rootPath);
+          flags += " ";
+          }
+        }
+      }
+
+    vars.Flags = flags.c_str();
+
     vars.LinkFlags = "$LINK_FLAGS";
 
     std::string langFlags;
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index ae18a48..43b7baa 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -414,7 +414,23 @@ cmNinjaTargetGenerator
     cmSystemTools::ReplaceString(depFlagsStr, "<CMAKE_C_COMPILER>",
                        mf->GetDefinition("CMAKE_C_COMPILER"));
     flags += " " + depFlagsStr;
-  }
+
+    if (const char *rootPath =
+                      this->Makefile->GetSafeDefinition("CMAKE_SYSROOT"))
+      {
+      if (*rootPath)
+        {
+        if (const char *sysrootFlag =
+                        this->Makefile->GetDefinition("CMAKE_SYSROOT_FLAG"))
+          {
+          flags += " ";
+          flags += sysrootFlag;
+          flags += this->LocalGenerator->EscapeForShell(rootPath);
+          flags += " ";
+          }
+        }
+      }
+    }
   vars.Flags = flags.c_str();
 
 
-- 
cgit v0.12