1
0
Эх сурвалжийг харах

ENH: all tests are passing for XCode

Bill Hoffman 20 жил өмнө
parent
commit
785b0dc012

+ 5 - 2
Source/CMakeLists.txt

@@ -708,7 +708,10 @@ IF(BUILD_TESTING)
       )
       )
   ENDIF (CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS)
   ENDIF (CTEST_TEST_CTEST AND CMAKE_RUN_LONG_TESTS)
 
 
-  IF(UNIX AND CMAKE_RUN_LONG_TESTS)
+  IF("${CMAKE_GENERATOR}" MATCHES XCode)
+    SET(CMAKE_SKIP_BOOTSTRAP_TEST 1)
+  ENDIF("${CMAKE_GENERATOR}" MATCHES XCode)
+  IF(UNIX AND CMAKE_RUN_LONG_TESTS AND NOT CMAKE_SKIP_BOOTSTRAP_TEST)
     ADD_TEST(BootstrapTest ${CMAKE_CTEST_COMMAND}
     ADD_TEST(BootstrapTest ${CMAKE_CTEST_COMMAND}
       --build-and-test
       --build-and-test
       ${CMake_SOURCE_DIR}
       ${CMake_SOURCE_DIR}
@@ -717,7 +720,7 @@ IF(BUILD_TESTING)
       --build-noclean
       --build-noclean
       --build-makeprogram ${CMake_SOURCE_DIR}/bootstrap
       --build-makeprogram ${CMake_SOURCE_DIR}/bootstrap
       --test-command ${CMake_BINARY_DIR}/Tests/BootstrapTest/Bootstrap.cmk/cmake)
       --test-command ${CMake_BINARY_DIR}/Tests/BootstrapTest/Bootstrap.cmk/cmake)
-  ENDIF(UNIX AND CMAKE_RUN_LONG_TESTS)
+  ENDIF(UNIX AND CMAKE_RUN_LONG_TESTS AND NOT CMAKE_SKIP_BOOTSTRAP_TEST)
 
 
   IF(CMAKE_GENERATOR MATCHES "Makefiles")
   IF(CMAKE_GENERATOR MATCHES "Makefiles")
     # see if we can find a fortran compiler on the machine
     # see if we can find a fortran compiler on the machine

+ 33 - 17
Source/cmFileCommand.cxx

@@ -580,27 +580,43 @@ bool cmFileCommand::HandleInstallCommand(
           }
           }
         switch( itype )
         switch( itype )
           {
           {
-        case cmTarget::MODULE_LIBRARY:
-        case cmTarget::SHARED_LIBRARY:
-        case cmTarget::EXECUTABLE:
-        case cmTarget::INSTALL_PROGRAMS:
-
-          if ( !cmSystemTools::SetPermissions(destfile.c_str(), 
+          case cmTarget::STATIC_LIBRARY:
+#if defined(__APPLE_CC__)
+            {
+            std::string ranlib = "ranlib ";
+            ranlib += destfile;
+            if(!cmSystemTools::RunSingleCommand(ranlib.c_str()))
+              {
+              std::string err = "ranlib failed: ";
+              err += ranlib;
+              this->SetError(err.c_str());
+              }
+            }
+#endif
+            break;
+            
+          case cmTarget::MODULE_LIBRARY:
+          case cmTarget::SHARED_LIBRARY:
+          case cmTarget::EXECUTABLE:
+          case cmTarget::INSTALL_PROGRAMS:
+            
+            if ( !cmSystemTools::SetPermissions(destfile.c_str(), 
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
-              S_IREAD | S_IWRITE | S_IEXEC
+                                                S_IREAD | S_IWRITE | S_IEXEC
 #elif defined( __BORLANDC__ )
 #elif defined( __BORLANDC__ )
-              S_IRUSR | S_IWUSR | S_IXUSR
+                                                S_IRUSR | S_IWUSR | S_IXUSR
 #else
 #else
-              S_IRUSR | S_IWUSR | S_IXUSR | 
-              S_IRGRP | S_IXGRP | 
-              S_IROTH | S_IXOTH 
+                                                S_IRUSR | S_IWUSR | S_IXUSR | 
+                                                S_IRGRP | S_IXGRP | 
+                                                S_IROTH | S_IXOTH 
 #endif
 #endif
-          ) )
-            {
-            cmOStringStream err;
-            err << "Problem setting permissions on file: " << destfile.c_str();
-            perror(err.str().c_str());
-            }
+                   ) )
+              {
+              cmOStringStream err;
+              err << "Problem setting permissions on file: " 
+                  << destfile.c_str();
+              perror(err.str().c_str());
+              }
           }
           }
         smanifest_files += ";";
         smanifest_files += ";";
         smanifest_files += destfile.substr(destDirLength);
         smanifest_files += destfile.substr(destDirLength);

+ 213 - 91
Source/cmGlobalXCodeGenerator.cxx

@@ -58,6 +58,8 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator()
   m_RootObject = 0;
   m_RootObject = 0;
   m_MainGroupChildren = 0;
   m_MainGroupChildren = 0;
   m_SourcesGroupChildren = 0;
   m_SourcesGroupChildren = 0;
+  m_CurrentMakefile = 0;
+  m_CurrentLocalGenerator = 0;
   m_ExternalGroupChildren = 0;
   m_ExternalGroupChildren = 0;
 }
 }
 
 
@@ -99,11 +101,6 @@ int cmGlobalXCodeGenerator::TryCompile(const char *,
    */
    */
   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
   cmSystemTools::ChangeDirectory(bindir);
   cmSystemTools::ChangeDirectory(bindir);
-//  Usage: xcodebuild [-project <projectname>] [-activetarget] 
-//         [-alltargets] [-target <targetname>]... [-activebuildstyle] 
-//         [-buildstyle <buildstylename>] [-optionalbuildstyle <buildstylename>] 
-//         [<buildsetting>=<value>]... [<buildaction>]...
-//         xcodebuild [-list]
 
 
   makeCommand += " -project ";
   makeCommand += " -project ";
   makeCommand += projectName;
   makeCommand += projectName;
@@ -134,7 +131,7 @@ int cmGlobalXCodeGenerator::TryCompile(const char *,
   return retVal;
   return retVal;
 }
 }
 
 
-
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::ConfigureOutputPaths()
 void cmGlobalXCodeGenerator::ConfigureOutputPaths()
 {
 {
   // Format the library and executable output paths.
   // Format the library and executable output paths.
@@ -188,66 +185,98 @@ cmLocalGenerator *cmGlobalXCodeGenerator::CreateLocalGenerator()
 void cmGlobalXCodeGenerator::Generate()
 void cmGlobalXCodeGenerator::Generate()
 {
 {
   this->cmGlobalGenerator::Generate();
   this->cmGlobalGenerator::Generate();
-  std::vector<std::string> srcs;
   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
   std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
   for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
   for(it = m_ProjectMap.begin(); it!= m_ProjectMap.end(); ++it)
-    {
+    { 
     cmLocalGenerator* root = it->second[0];
     cmLocalGenerator* root = it->second[0];
-    cmMakefile* mf = root->GetMakefile();
-    // add a ALL_BUILD target to the first makefile of each project
-    mf->AddUtilityCommand("ALL_BUILD", "echo", 
-                        "\"Build all projects\"",false,srcs);
-    cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
+    m_CurrentMakefile = root->GetMakefile();
+    m_OutputDir = m_CurrentMakefile->GetHomeOutputDirectory();
+    m_OutputDir = cmSystemTools::CollapseFullPath(m_OutputDir.c_str());
+    m_CurrentLocalGenerator = root;
+    // add ALL_BUILD, INSTALL, etc
+    this->AddExtraTargets(root, it->second);
+    // now create the project
+    this->OutputXCodeProject(root, it->second);
+    }
+}
 
 
-    std::string dir = root->ConvertToRelativeOutputPath(
-      mf->GetCurrentOutputDirectory());
-    m_CurrentXCodeHackMakefile = dir;
-    m_CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
-    std::string makecommand = "make -C ";
-    makecommand += dir;
-    makecommand += " -f ";
-    makecommand += m_CurrentXCodeHackMakefile;
-    mf->AddUtilityCommand("XCODE_DEPEND_HELPER", makecommand.c_str(), 
+//----------------------------------------------------------------------------
+void 
+cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root, 
+                                        std::vector<cmLocalGenerator*>& gens)
+{
+  std::vector<std::string> srcs; // dummy list 
+  cmMakefile* mf = root->GetMakefile();
+  // Add ALL_BUILD
+  mf->AddUtilityCommand("ALL_BUILD", "echo", 
+                        "\"Build all projects\"",false,srcs);
+  cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
+  // ADD install
+  std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND");
+  mf->AddUtilityCommand("install", cmake_command.c_str(),
+                        "-P cmake_install.cmake",false,srcs);
+  // Add RUN_TESTS target if testing has been enabled
+  std::string fname;
+  fname = mf->GetStartOutputDirectory();
+  fname += "/";
+  fname += "DartTestfile.txt";
+  if (cmSystemTools::FileExists(fname.c_str()))
+    {
+    std::string ctest_command = 
+      mf->GetRequiredDefinition("CMAKE_CTEST_COMMAND");
+    mf->AddUtilityCommand("RUN_TESTS", ctest_command.c_str(), "",false,srcs);
+    }
+  // Add install 
+  mf->AddUtilityCommand("install", cmake_command.c_str(),
+                        "-P cmake_install.cmake", false, srcs);
+  // Add XCODE depend helper 
+  std::string dir = this->ConvertToRelativeOutputPath(
+    mf->GetCurrentOutputDirectory());
+  m_CurrentXCodeHackMakefile = dir;
+  m_CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
+  std::string makecommand = "make -C ";
+  makecommand += dir;
+  makecommand += " -f ";
+  makecommand += m_CurrentXCodeHackMakefile;
+  mf->AddUtilityCommand("XCODE_DEPEND_HELPER", makecommand.c_str(), 
                         "",
                         "",
                         false,srcs);
                         false,srcs);
-    cmTarget* xcodedephack = mf->FindTarget("XCODE_DEPEND_HELPER");
-    // now make the allbuild depend on all the non-utility targets
-    // in the project
-    for(std::vector<cmLocalGenerator*>::iterator i = it->second.begin();
-        i != it->second.end(); ++i)
+  // now make the allbuild depend on all the non-utility targets
+  // in the project
+  for(std::vector<cmLocalGenerator*>::iterator i = gens.begin();
+      i != gens.end(); ++i)
+    {
+    cmLocalGenerator* lg = *i; 
+    if(this->IsExcluded(root, *i))
+      {
+      continue;
+      }
+    cmTargets& tgts = lg->GetMakefile()->GetTargets();
+    for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
       {
       {
-      cmLocalGenerator* lg = *i; 
-      if(this->IsExcluded(root, *i))
+      cmTarget& target = l->second;
+      // make all exe, shared libs and modules depend
+      // on the XCODE_DEPEND_HELPER target
+      if((target.GetType() == cmTarget::EXECUTABLE ||
+          target.GetType() == cmTarget::SHARED_LIBRARY ||
+          target.GetType() == cmTarget::MODULE_LIBRARY))
         {
         {
-        continue;
+        target.AddUtility("XCODE_DEPEND_HELPER");
         }
         }
-      cmTargets& tgts = lg->GetMakefile()->GetTargets();
-      for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
+      
+      if(target.IsInAll())
         {
         {
-        cmTarget& target = l->second;
-        // make all exe, shared libs and modules depend
-        // on the XCODE_DEPEND_HELPER target
-        if((target.GetType() == cmTarget::EXECUTABLE ||
-            target.GetType() == cmTarget::SHARED_LIBRARY ||
-            target.GetType() == cmTarget::MODULE_LIBRARY))
-          {
-          target.AddUtility(xcodedephack->GetName());
-          }
-        
-        if(target.IsInAll())
-          {
-          allbuild->AddUtility(target.GetName());
-          }
+        allbuild->AddUtility(target.GetName());
         }
         }
       }
       }
-    // now create the project
-    this->OutputXCodeProject(it->second[0], it->second);
     }
     }
 }
 }
 
 
+
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::ClearXCodeObjects()
 void cmGlobalXCodeGenerator::ClearXCodeObjects()
 {
 {
+  m_TargetDoneSet.clear();
   for(unsigned int i = 0; i < m_XCodeObjects.size(); ++i)
   for(unsigned int i = 0; i < m_XCodeObjects.size(); ++i)
     {
     {
     delete m_XCodeObjects[i];
     delete m_XCodeObjects[i];
@@ -273,6 +302,7 @@ cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
   return obj;
   return obj;
 }
 }
 
 
+//----------------------------------------------------------------------------
 cmXCodeObject*
 cmXCodeObject*
 cmGlobalXCodeGenerator::CreateString(const char* s)
 cmGlobalXCodeGenerator::CreateString(const char* s)
 {
 {
@@ -280,6 +310,8 @@ cmGlobalXCodeGenerator::CreateString(const char* s)
   obj->SetString(s);
   obj->SetString(s);
   return obj;
   return obj;
 }
 }
+
+//----------------------------------------------------------------------------
 cmXCodeObject* cmGlobalXCodeGenerator::CreateObjectReference(cmXCodeObject* ref)
 cmXCodeObject* cmGlobalXCodeGenerator::CreateObjectReference(cmXCodeObject* ref)
 {
 {
   cmXCodeObject* obj = this->CreateObject(cmXCodeObject::OBJECT_REF);
   cmXCodeObject* obj = this->CreateObject(cmXCodeObject::OBJECT_REF);
@@ -287,6 +319,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateObjectReference(cmXCodeObject* ref)
   return obj;
   return obj;
 }
 }
 
 
+//----------------------------------------------------------------------------
 cmXCodeObject* 
 cmXCodeObject* 
 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, 
 cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg, 
                                               cmSourceFile* sf)
                                               cmSourceFile* sf)
@@ -307,17 +340,21 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
   const char* lang = 
   const char* lang = 
     this->GetLanguageFromExtension(sf->GetSourceExtension().c_str());
     this->GetLanguageFromExtension(sf->GetSourceExtension().c_str());
   std::string sourcecode = "sourcecode";
   std::string sourcecode = "sourcecode";
-  if(!lang)
+  if(sf->GetSourceExtension() == "o")
     {
     {
-    std::string ext = ".";
-    ext = sf->GetSourceExtension();
-    sourcecode += ext;
-    sourcecode += ext;
+    sourcecode = "compiled.mach-o.objfile";
     }
     }
   else if(sf->GetSourceExtension() == "mm")
   else if(sf->GetSourceExtension() == "mm")
     {
     {
     sourcecode += ".cpp.objcpp";
     sourcecode += ".cpp.objcpp";
     }
     }
+  else if(!lang)
+    {
+    std::string ext = ".";
+    ext = sf->GetSourceExtension();
+    sourcecode += ext;
+    sourcecode += ext;
+    }
   else if(strcmp(lang, "C") == 0)
   else if(strcmp(lang, "C") == 0)
     {
     {
     sourcecode += ".c.c";
     sourcecode += ".c.c";
@@ -329,13 +366,38 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
 
 
   fileRef->AddAttribute("lastKnownFileType", 
   fileRef->AddAttribute("lastKnownFileType", 
                         this->CreateString(sourcecode.c_str()));
                         this->CreateString(sourcecode.c_str()));
-  fileRef->AddAttribute("path", this->CreateString(
-    lg->ConvertToRelativeOutputPath(sf->GetFullPath().c_str()).c_str()));
+  std::string path = 
+    this->ConvertToRelativeOutputPath(sf->GetFullPath().c_str());
+  fileRef->AddAttribute("path", this->CreateString(path.c_str()));
   fileRef->AddAttribute("refType", this->CreateString("4"));
   fileRef->AddAttribute("refType", this->CreateString("4"));
-  fileRef->AddAttribute("sourceTree", this->CreateString("<absolute>"));
+  if(path.size() > 1 && path[0] == '.' && path[1] == '.')
+    {
+    fileRef->AddAttribute("sourceTree", this->CreateString("<group>"));
+    }
+  else
+    {
+    fileRef->AddAttribute("sourceTree", this->CreateString("<absolute>"));
+    }
   return buildFile;
   return buildFile;
 }
 }
 
 
+//----------------------------------------------------------------------------
+bool cmGlobalXCodeGenerator::SpecialTargetEmitted(std::string const& tname)
+{
+  if(tname == "ALL_BUILD" || tname == "XCODE_DEPEND_HELPER" ||
+     tname == "install" || tname == "RUN_TESTS")
+    {
+    if(m_TargetDoneSet.find(tname) != m_TargetDoneSet.end())
+      {
+      return true;
+      }
+    m_TargetDoneSet.insert(tname);
+    return false;
+    }
+  return false;
+}
+
+  
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void 
 void 
 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
 cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
@@ -348,23 +410,10 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
   for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
   for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); l++)
     { 
     { 
     cmTarget& cmtarget = l->second;
     cmTarget& cmtarget = l->second;
-    // make sure ALL_BUILD is only done once
-    if(l->first == "ALL_BUILD")
-      {
-      if(m_DoneAllBuild)
-        {
-        continue;
-        }
-      m_DoneAllBuild = true;
-      }
-    // make sure ALL_BUILD is only done once
-    if(l->first == "XCODE_DEPEND_HELPER")
+    // make sure ALL_BUILD, INSTALL, etc are only done once
+    if(this->SpecialTargetEmitted(l->first.c_str()))
       {
       {
-      if(m_DoneXCodeHack)
-        {
-        continue;
-        }
-      m_DoneXCodeHack = true;
+      continue;
       }
       }
     if(cmtarget.GetType() == cmTarget::UTILITY ||
     if(cmtarget.GetType() == cmTarget::UTILITY ||
        cmtarget.GetType() == cmTarget::INSTALL_FILES ||
        cmtarget.GetType() == cmTarget::INSTALL_FILES ||
@@ -388,10 +437,22 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
                                    this->CreateString("0"));
                                    this->CreateString("0"));
     std::vector<cmSourceFile*> &classes = l->second.GetSourceFiles();
     std::vector<cmSourceFile*> &classes = l->second.GetSourceFiles();
     // add all the sources
     // add all the sources
+    std::vector<cmXCodeObject*> externalObjFiles;
     for(std::vector<cmSourceFile*>::iterator i = classes.begin(); 
     for(std::vector<cmSourceFile*>::iterator i = classes.begin(); 
         i != classes.end(); ++i)
         i != classes.end(); ++i)
       {
       {
-      buildFiles->AddObject(this->CreateXCodeSourceFile(gen, *i));
+      cmXCodeObject* xsf = this->CreateXCodeSourceFile(gen, *i);
+      cmXCodeObject* fr = xsf->GetObject("fileRef");
+      cmXCodeObject* filetype = 
+        fr->GetObject()->GetObject("lastKnownFileType");
+      if(strcmp(filetype->GetString(), "\"compiled.mach-o.objfile\"") == 0)
+        {
+        externalObjFiles.push_back(xsf);
+        }
+      else
+        {
+        buildFiles->AddObject(xsf);
+        }
       }
       }
     // create header build phase
     // create header build phase
     cmXCodeObject* headerBuildPhase = 
     cmXCodeObject* headerBuildPhase = 
@@ -410,6 +471,11 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
                                       this->CreateString("2147483647"));
                                       this->CreateString("2147483647"));
     buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
     buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
     frameworkBuildPhase->AddAttribute("files", buildFiles);
     frameworkBuildPhase->AddAttribute("files", buildFiles);
+    for(std::vector<cmXCodeObject*>::iterator i =  externalObjFiles.begin();
+        i != externalObjFiles.end(); ++i)
+      {
+      buildFiles->AddObject(*i);
+      }
     frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
     frameworkBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", 
                                       this->CreateString("0"));
                                       this->CreateString("0"));
     cmXCodeObject* buildPhases = 
     cmXCodeObject* buildPhases = 
@@ -421,6 +487,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
     }
     }
 }
 }
 
 
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
 void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
                                                   cmXCodeObject*
                                                   cmXCodeObject*
                                                   sourceBuildPhase,
                                                   sourceBuildPhase,
@@ -553,6 +620,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
     }
     }
 }
 }
 
 
+//----------------------------------------------------------------------------
 void 
 void 
 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
 cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
                                                 cmTarget& target,
                                                 cmTarget& target,
@@ -587,8 +655,8 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
       {
       {
       if(cc.GetOutput().size())
       if(cc.GetOutput().size())
         {
         {
-        makefileStream << "\\\n\t" << m_CurrentLocalGenerator
-          ->ConvertToRelativeOutputPath(cc.GetOutput().c_str());
+        makefileStream << "\\\n\t"  << this->
+          ConvertToRelativeOutputPath(cc.GetOutput().c_str());
         }
         }
       else
       else
         {
         {
@@ -611,7 +679,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
         cc.GetComment() << "\n";
         cc.GetComment() << "\n";
       if(cc.GetOutput().size())
       if(cc.GetOutput().size())
         {
         {
-        makefileStream << m_CurrentLocalGenerator
+        makefileStream << this
           ->ConvertToRelativeOutputPath(cc.GetOutput().c_str()) << ": ";
           ->ConvertToRelativeOutputPath(cc.GetOutput().c_str()) << ": ";
         }
         }
       else
       else
@@ -639,7 +707,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
       }
       }
     }
     }
   
   
-  std::string dir = cmSystemTools::ConvertToOutputPath(
+  std::string dir = this->ConvertToRelativeOutputPath(
     m_CurrentMakefile->GetCurrentOutputDirectory());
     m_CurrentMakefile->GetCurrentOutputDirectory());
   std::string makecmd = "make -C ";
   std::string makecmd = "make -C ";
   makecmd += dir;
   makecmd += dir;
@@ -649,6 +717,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
 }
 }
 
 
 
 
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
 void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
                                                  cmXCodeObject* buildSettings,
                                                  cmXCodeObject* buildSettings,
                                                  std::string& fileType,
                                                  std::string& fileType,
@@ -794,7 +863,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
         l != linkdirs.end(); ++l)
         l != linkdirs.end(); ++l)
       {
       {
       std::string libpath = 
       std::string libpath = 
-        m_CurrentLocalGenerator->ConvertToOutputForExisting(l->c_str());
+        this->ConvertToRelativeOutputPath(l->c_str());
       if(emitted.insert(libpath).second)
       if(emitted.insert(libpath).second)
         {
         {
         dirs += libpath + " ";
         dirs += libpath + " ";
@@ -813,7 +882,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
   for(;i != includes.end(); ++i)
   for(;i != includes.end(); ++i)
     {
     {
     std::string incpath = 
     std::string incpath = 
-        m_CurrentLocalGenerator->ConvertToOutputForExisting(i->c_str());
+      this->ConvertToRelativeOutputPath(i->c_str());
     dirs += incpath + " ";
     dirs += incpath + " ";
     }
     }
   if(dirs.size())
   if(dirs.size())
@@ -849,6 +918,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
                               this->CreateString(pname.c_str()));
                               this->CreateString(pname.c_str()));
 }
 }
 
 
+//----------------------------------------------------------------------------
 cmXCodeObject* 
 cmXCodeObject* 
 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
 cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
 {
 {
@@ -893,6 +963,7 @@ cmGlobalXCodeGenerator::CreateUtilityTarget(cmTarget& cmtarget)
   return target;
   return target;
 }
 }
 
 
+//----------------------------------------------------------------------------
 cmXCodeObject*
 cmXCodeObject*
 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
 cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
                                           cmXCodeObject* buildPhases)
                                           cmXCodeObject* buildPhases)
@@ -933,6 +1004,7 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
   return target;
   return target;
 }
 }
 
 
+//----------------------------------------------------------------------------
 cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
 cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
 {
 {
   if(!t)
   if(!t)
@@ -951,7 +1023,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(cmTarget* t)
   return 0;
   return 0;
 }
 }
 
 
-  
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
 void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
                                              cmXCodeObject* dependTarget)
                                              cmXCodeObject* dependTarget)
 {
 {
@@ -1005,7 +1077,7 @@ void cmGlobalXCodeGenerator::AddDependTarget(cmXCodeObject* target,
     }
     }
 }
 }
 
 
-
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
 void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
                                             const char* library,
                                             const char* library,
                                             cmTarget* dtarget)
                                             cmTarget* dtarget)
@@ -1030,14 +1102,12 @@ void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
         // remove double quotes
         // remove double quotes
         libs = libs.substr(1, libs.size()-2);
         libs = libs.substr(1, libs.size()-2);
         libs += " ";
         libs += " ";
-        libs += 
-          m_CurrentLocalGenerator->ConvertToOutputForExisting(dir.c_str());
+        libs += this->ConvertToRelativeOutputPath(dir.c_str());
         spath->SetString(libs.c_str());
         spath->SetString(libs.c_str());
         }
         }
       else
       else
         {
         {
-        std::string libs =
-          m_CurrentLocalGenerator->ConvertToOutputForExisting(dir.c_str());
+        std::string libs = this->ConvertToRelativeOutputPath(dir.c_str());
         bset->AddAttribute("LIBRARY_SEARCH_PATHS",
         bset->AddAttribute("LIBRARY_SEARCH_PATHS",
                            this->CreateString(libs.c_str()));
                            this->CreateString(libs.c_str()));
         }
         }
@@ -1074,7 +1144,7 @@ void cmGlobalXCodeGenerator::AddLinkLibrary(cmXCodeObject* target,
   ldflags->SetString(link.c_str());
   ldflags->SetString(link.c_str());
 }
 }
 
 
-
+//----------------------------------------------------------------------------
 std::string cmGlobalXCodeGenerator::GetTargetFullPath(cmTarget* target)
 std::string cmGlobalXCodeGenerator::GetTargetFullPath(cmTarget* target)
 {
 {
   std::string libPath;
   std::string libPath;
@@ -1102,7 +1172,7 @@ std::string cmGlobalXCodeGenerator::GetTargetFullPath(cmTarget* target)
   return libPath;
   return libPath;
 }
 }
 
 
-
+//----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
 void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
 {
 {
   cmTarget* cmtarget = target->GetcmTarget();
   cmTarget* cmtarget = target->GetcmTarget();
@@ -1158,8 +1228,6 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
     }
     }
 }
 }
 
 
-// to force the location of a target
-// add this to build settings of target SYMROOT = /tmp/;
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* root,
 void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* root,
@@ -1235,8 +1303,6 @@ void cmGlobalXCodeGenerator::CreateXCodeObjects(cmLocalGenerator* root,
   m_RootObject->AddAttribute("hasScannedForEncodings",
   m_RootObject->AddAttribute("hasScannedForEncodings",
                              this->CreateString("0"));
                              this->CreateString("0"));
   std::vector<cmXCodeObject*> targets;
   std::vector<cmXCodeObject*> targets;
-  m_DoneAllBuild = false;
-  m_DoneXCodeHack = false;
   for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
   for(std::vector<cmLocalGenerator*>::iterator i = generators.begin();
       i != generators.end(); ++i)
       i != generators.end(); ++i)
     {
     {
@@ -1412,3 +1478,59 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
   entry.brief = "Generate XCode project files.";
   entry.brief = "Generate XCode project files.";
   entry.full = "";
   entry.full = "";
 }
 }
+
+//----------------------------------------------------------------------------
+std::string cmGlobalXCodeGenerator::ConvertToRelativeOutputPath(const char* p)
+{
+  if ( !m_CurrentMakefile->IsOn("CMAKE_USE_RELATIVE_PATHS") )
+    {
+    return cmSystemTools::ConvertToOutputPath(p);
+    }
+  // NOTE, much of this was copied from 
+  // cmLocalGenerator::ConvertToRelativeOutputPath
+  // fixes here should be made there as well.
+  //
+  // copy to a string class
+  std::string pathIn = p;
+  // check to see if the path is already relative, it is
+  // considered relative if one of the following is true
+  // - has no / in it at all
+  // - does not start with / or drive leter :
+  // - starts with a ".."
+  if(pathIn.find('/') == pathIn.npos ||        
+     (pathIn[0] != '/' && pathIn[1] != ':') || 
+     pathIn.find("..") == 0)
+    {
+    return cmSystemTools::ConvertToOutputPath(p);
+    } 
+  // Given that we are in m_CurrentOutputDirectory how to we
+  // get to pathIn with a relative path, store in ret
+  std::string ret = 
+    cmSystemTools::RelativePath(m_OutputDir.c_str(), pathIn.c_str());
+  
+  // If the path is 0 sized make it a .
+  // this happens when pathIn is the same as m_CurrentOutputDirectory
+  if(ret.size() == 0)
+    {
+    ret = ".";
+    }
+  // if there was a trailing / there still is one, and
+  // if there was not one, there still is not one
+  if(ret[ret.size()-1] == '/' && 
+     pathIn[pathIn.size()-1] != '/')
+    {
+    ret.erase(ret.size()-1, 1);
+    }
+  if(ret[ret.size()-1] != '/' && 
+     pathIn[pathIn.size()-1] == '/')
+    {
+    ret += "/";
+    }
+  // Now convert the relative path to an output path
+  ret = cmSystemTools::ConvertToOutputPath(ret.c_str());
+  // finally return the path 
+  // at this point it should be relative and in the correct format
+  // for the native build system.  (i.e. \ for windows and / for unix,
+  // and correct escaping/quoting of spaces in the path
+  return ret;
+}

+ 7 - 1
Source/cmGlobalXCodeGenerator.h

@@ -66,7 +66,8 @@ public:
    */
    */
   virtual void Generate();
   virtual void Generate();
 
 
-private:
+private: 
+  std::string ConvertToRelativeOutputPath(const char* p);
   void CreateCustomCommands(cmXCodeObject* buildPhases,
   void CreateCustomCommands(cmXCodeObject* buildPhases,
                             cmXCodeObject* sourceBuildPhase,
                             cmXCodeObject* sourceBuildPhase,
                             cmXCodeObject* headerBuildPhase,
                             cmXCodeObject* headerBuildPhase,
@@ -114,6 +115,9 @@ private:
   void ConfigureOutputPaths();
   void ConfigureOutputPaths();
   void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
   void CreateXCodeDependHackTarget(std::vector<cmXCodeObject*>& targets);
   std::string GetTargetFullPath(cmTarget*);
   std::string GetTargetFullPath(cmTarget*);
+  bool SpecialTargetEmitted(std::string const& tname);
+  void AddExtraTargets(cmLocalGenerator* root, 
+                       std::vector<cmLocalGenerator*>& gens);
 private:
 private:
   std::vector<cmXCodeObject*> m_XCodeObjects;
   std::vector<cmXCodeObject*> m_XCodeObjects;
   cmXCodeObject* m_RootObject;
   cmXCodeObject* m_RootObject;
@@ -124,9 +128,11 @@ private:
   std::string m_LibraryOutputPath;
   std::string m_LibraryOutputPath;
   std::string m_ExecutableOutputPath;
   std::string m_ExecutableOutputPath;
   cmLocalGenerator* m_CurrentLocalGenerator;
   cmLocalGenerator* m_CurrentLocalGenerator;
+  std::set<cmStdString> m_TargetDoneSet;
   bool m_DoneAllBuild;
   bool m_DoneAllBuild;
   bool m_DoneXCodeHack;
   bool m_DoneXCodeHack;
   std::string m_CurrentXCodeHackMakefile;
   std::string m_CurrentXCodeHackMakefile;
+  std::string m_OutputDir;
 };
 };
 
 
 #endif
 #endif

+ 4 - 0
Source/cmLocalGenerator.cxx

@@ -388,6 +388,10 @@ std::string cmLocalGenerator::ConvertToRelativeOutputPath(const char* p)
     {
     {
     return cmSystemTools::ConvertToOutputPath(p);
     return cmSystemTools::ConvertToOutputPath(p);
     }
     }
+  // NOTE, much of this was copied to 
+  // cmGlobalXCodeGenerator::ConvertToRelativeOutputPath
+  // fixes here should be made there as well.
+
   // copy to a string class
   // copy to a string class
   std::string pathIn = p;
   std::string pathIn = p;
   // check to see if the path is already relative, it is
   // check to see if the path is already relative, it is

+ 5 - 1
Tests/ExternalOBJ/CMakeLists.txt

@@ -34,7 +34,11 @@ ENDFOREACH(dir)
 IF(EXTERNAL_OBJECT)
 IF(EXTERNAL_OBJECT)
   MESSAGE("Found \"${EXTERNAL_OBJECT}\".")
   MESSAGE("Found \"${EXTERNAL_OBJECT}\".")
 ELSE(EXTERNAL_OBJECT)
 ELSE(EXTERNAL_OBJECT)
-  MESSAGE(FATAL_ERROR "Could not find ${EXTERNAL_OBJECT_NAME}.")
+  FILE(GLOB_RECURSE EXTERNAL_OBJECT
+    "${ExternalOBJ_BINARY_DIR}/Object/${EXTERNAL_OBJECT_NAME}")
+  IF(NOT EXTERNAL_OBJECT)
+    MESSAGE(FATAL_ERROR "Could not find ${EXTERNAL_OBJECT_NAME}.")
+  ENDIF(NOT EXTERNAL_OBJECT)
 ENDIF(EXTERNAL_OBJECT)
 ENDIF(EXTERNAL_OBJECT)
 
 
 # Build an executable using the external object file.
 # Build an executable using the external object file.