Browse Source

Merge topic 'xcode-revise-make-program'

ab9fa54d Xcode: Switch to internal CMAKE_MAKE_PROGRAM lookup by generator (#15324)
11e2e6ca Xcode: Select make program at build time
e4055a61 Xcode: Add internal API to find xcodebuild
Brad King 10 years ago
parent
commit
326cfe2b30

+ 6 - 0
Help/release/dev/xcode-revise-make-program.rst

@@ -0,0 +1,6 @@
+xcode-revise-make-program
+-------------------------
+
+* The :generator:`Xcode` generator no longer requires a value for
+  the :variable:`CMAKE_MAKE_PROGRAM` variable to be located up front.
+  It now locates ``xcodebuild`` when needed at build time.

+ 9 - 2
Help/variable/CMAKE_MAKE_PROGRAM.rst

@@ -23,8 +23,15 @@ to configure the project:
   otherwise undocumented ``cmakexbuild`` wrapper implementing some
   workarounds).
 
-  This generator stores ``CMAKE_MAKE_PROGRAM`` in the CMake cache
-  so that it may be edited by the user.
+  This generator prefers to lookup the build tool at build time
+  rather than to store ``CMAKE_MAKE_PROGRAM`` in the CMake cache
+  ahead of time.  This is because ``xcodebuild`` is easy to find,
+  the ``cmakexbuild`` wrapper is needed only for older Xcode versions,
+  and the path to ``cmakexbuild`` may be outdated if CMake itself moves.
+
+  For compatibility with versions of CMake prior to 3.2, if
+  a user or project explicitly adds ``CMAKE_MAKE_PROGRAM`` to
+  the CMake cache then CMake will use the specified value.
 
 * The Visual Studio generators set this to the full path to
   ``MSBuild.exe`` (VS >= 10), ``devenv.com`` (VS 7,8,9),

+ 2 - 6
Modules/CMakeFindXCode.cmake

@@ -12,9 +12,5 @@
 # (To distribute this file outside of CMake, substitute the full
 #  License text for the above reference.)
 
-find_program(CMAKE_MAKE_PROGRAM
-  NAMES xcodebuild
-  PATHS
-  /usr/bin
-  )
-mark_as_advanced(CMAKE_MAKE_PROGRAM)
+# Empty placeholder for input dependencies in existing
+# build trees produced by older versions of CMake.

+ 0 - 19
Source/cmGlobalGenerator.cxx

@@ -315,25 +315,6 @@ void cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
                            "make program",
                            cmCacheManager::FILEPATH);
     }
-
-  if(makeProgram.find("xcodebuild") != makeProgram.npos)
-    {
-    // due to the text file busy /bin/sh problem with xcodebuild
-    // use the cmakexbuild wrapper instead.  This program
-    // will run xcodebuild and if it sees the error text file busy
-    // it will stop forwarding output, and let the build finish.
-    // Then it will retry the build.  It will continue this
-    // until no text file busy errors occur.
-    std::string cmakexbuild =
-      this->CMakeInstance->GetCacheManager()->GetCacheValue("CMAKE_COMMAND");
-    cmakexbuild = cmakexbuild.substr(0, cmakexbuild.length()-5);
-    cmakexbuild += "cmakexbuild";
-
-    mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM",
-                           cmakexbuild.c_str(),
-                           "make program",
-                           cmCacheManager::FILEPATH);
-    }
 }
 
 // enable the given language

+ 45 - 2
Source/cmGlobalXCodeGenerator.cxx

@@ -136,13 +136,13 @@ cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version)
   sscanf(this->VersionString.c_str(), "%u.%u", &v[0], &v[1]);
   this->XcodeVersion = 10*v[0] + v[1];
 
-  this->FindMakeProgramFile = "CMakeFindXCode.cmake";
   this->RootObject = 0;
   this->MainGroupChildren = 0;
   this->SourcesGroupChildren = 0;
   this->ResourcesGroupChildren = 0;
   this->CurrentMakefile = 0;
   this->CurrentLocalGenerator = 0;
+  this->XcodeBuildCommandInitialized = false;
 }
 
 //----------------------------------------------------------------------------
@@ -201,6 +201,49 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory
 #endif
 }
 
+//----------------------------------------------------------------------------
+void cmGlobalXCodeGenerator::FindMakeProgram(cmMakefile* mf)
+{
+  // The Xcode generator knows how to lookup its build tool
+  // directly instead of needing a helper module to do it, so we
+  // do not actually need to put CMAKE_MAKE_PROGRAM into the cache.
+  if(cmSystemTools::IsOff(mf->GetDefinition("CMAKE_MAKE_PROGRAM")))
+    {
+    mf->AddDefinition("CMAKE_MAKE_PROGRAM",
+                      this->GetXcodeBuildCommand().c_str());
+    }
+}
+
+//----------------------------------------------------------------------------
+std::string const& cmGlobalXCodeGenerator::GetXcodeBuildCommand()
+{
+  if(!this->XcodeBuildCommandInitialized)
+    {
+    this->XcodeBuildCommandInitialized = true;
+    this->XcodeBuildCommand = this->FindXcodeBuildCommand();
+    }
+  return this->XcodeBuildCommand;
+}
+
+//----------------------------------------------------------------------------
+std::string cmGlobalXCodeGenerator::FindXcodeBuildCommand()
+{
+  if (this->XcodeVersion >= 40)
+    {
+    std::string makeProgram = cmSystemTools::FindProgram("xcodebuild");
+    if (makeProgram.empty())
+      {
+      makeProgram = "xcodebuild";
+      }
+    return makeProgram;
+    }
+  else
+    {
+    // Use cmakexbuild wrapper to suppress environment dump from output.
+    return cmSystemTools::GetCMakeCommand() + "xbuild";
+    }
+}
+
 //----------------------------------------------------------------------------
 bool cmGlobalXCodeGenerator::SetGeneratorToolset(std::string const& ts,
                                                  cmMakefile* mf)
@@ -272,7 +315,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
 {
   // now build the test
   makeCommand.push_back(
-    this->SelectMakeProgram(makeProgram, "xcodebuild")
+    this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand())
     );
 
   makeCommand.push_back("-project");

+ 7 - 0
Source/cmGlobalXCodeGenerator.h

@@ -70,6 +70,8 @@ public:
                                         const std::string& suffix,
                                         std::string& dir);
 
+  virtual void FindMakeProgram(cmMakefile*);
+
   ///! What is the configurations directory variable called?
   virtual const char* GetCMakeCFGIntDir() const;
   ///! expand CFGIntDir
@@ -212,6 +214,11 @@ protected:
   std::vector<cmXCodeObject*> XCodeObjects;
   cmXCodeObject* RootObject;
 private:
+  std::string const& GetXcodeBuildCommand();
+  std::string FindXcodeBuildCommand();
+  std::string XcodeBuildCommand;
+  bool XcodeBuildCommandInitialized;
+
   void PrintCompilerAdvice(std::ostream&, std::string const&,
                            const char*) const {}
 

+ 1 - 1
Tests/CMakeLists.txt

@@ -51,7 +51,7 @@ if(BUILD_TESTING)
     set(CMake_TEST_DEVENV "${CMAKE_MAKE_PROGRAM}")
   endif()
 
-  if(CMAKE_GENERATOR MATCHES "Visual Studio")
+  if(CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
     set(CMake_TEST_EXPLICIT_MAKE_PROGRAM "")
   else()
     set(CMake_TEST_EXPLICIT_MAKE_PROGRAM "${CMAKE_MAKE_PROGRAM}")