This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  4da0681a70ac512367d59c93703e91e76cc62192 (commit)
       via  c294a115f2a44b60eb6343324e15933ef8a4593d (commit)
       via  e42da30782785a02f0fabc385d14ac8f561af602 (commit)
      from  15162ca3106d95b0f867b9a89d9b3a6dd0008297 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4da0681a70ac512367d59c93703e91e76cc62192
commit 4da0681a70ac512367d59c93703e91e76cc62192
Merge: 15162ca c294a11
Author:     Clinton Stimpson <clin...@elemtech.com>
AuthorDate: Mon Dec 22 13:34:20 2014 -0500
Commit:     CMake Topic Stage <kwro...@kitware.com>
CommitDate: Mon Dec 22 13:34:20 2014 -0500

    Merge topic 'macho-parser' into next
    
    c294a115 Mach-O: Use Mach-O parser to extract install names instead of 
otool.
    e42da307 Mach-O: Add Mach-O parser for OS X and iOS.


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c294a115f2a44b60eb6343324e15933ef8a4593d
commit c294a115f2a44b60eb6343324e15933ef8a4593d
Author:     Clinton Stimpson <clin...@elemtech.com>
AuthorDate: Fri Dec 19 12:31:22 2014 -0700
Commit:     Clinton Stimpson <clin...@elemtech.com>
CommitDate: Mon Dec 22 11:33:00 2014 -0700

    Mach-O: Use Mach-O parser to extract install names instead of otool.
    
    This has much better performance than calling "otool" or "xcrun -r otool"
    to extract install names for rpath support.
    
    Fixes bug #15178.

diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index c83dc2a..1c8c387 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -63,6 +63,10 @@
 # include "cmELF.h"
 #endif
 
+#if defined(CMAKE_USE_MACH_PARSER)
+# include "cmMachO.h"
+#endif
+
 class cmSystemToolsFileTime
 {
 public:
@@ -2357,31 +2361,17 @@ bool cmSystemTools::GuessLibrarySOName(std::string 
const& fullPath,
 bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
                                        std::string& soname)
 {
-  std::vector<std::string> cmds;
-  cmds.push_back("otool");
-  cmds.push_back("-D");
-  cmds.push_back(fullPath);
-
-  std::string output;
-  if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
+#if defined(CMAKE_USE_MACH_PARSER)
+  cmMachO macho(fullPath.c_str());
+  if(macho)
     {
-    cmds.insert(cmds.begin(), "-r");
-    cmds.insert(cmds.begin(), "xcrun");
-    if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
-      {
-      return false;
-      }
+    return macho.GetInstallName(soname);
     }
+#else
+  (void)fullPath;
+  (void)soname;
+#endif
 
-  std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n");
-  // otool returns extra lines reporting multiple install names
-  // in case the binary is multi-arch and none of the architectures
-  // is native (e.g. i386;ppc on x86_64)
-  if(strs.size() >= 2)
-    {
-    soname = strs[1];
-    return true;
-    }
   return false;
 }
 

http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e42da30782785a02f0fabc385d14ac8f561af602
commit e42da30782785a02f0fabc385d14ac8f561af602
Author:     Clinton Stimpson <clin...@elemtech.com>
AuthorDate: Fri Dec 19 12:30:22 2014 -0700
Commit:     Clinton Stimpson <clin...@elemtech.com>
CommitDate: Mon Dec 22 11:32:10 2014 -0700

    Mach-O: Add Mach-O parser for OS X and iOS.
    
    This parser also supports fat binaries which archive multiple
    Mach-O binaries.

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a4c982f..97f57a3 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -39,6 +39,10 @@ else()
   set(CMAKE_USE_ELF_PARSER)
 endif()
 
+if(APPLE)
+  set(CMAKE_USE_MACH_PARSER 1)
+endif()
+
 set(EXECUTABLE_OUTPUT_PATH ${CMake_BIN_DIR})
 
 # ensure Unicode friendly APIs are used on Windows
@@ -140,6 +144,11 @@ if(CMAKE_USE_ELF_PARSER)
   set(ELF_SRCS cmELF.h cmELF.cxx)
 endif()
 
+# Check if we can build the Mach-O parser.
+if(CMAKE_USE_MACH_PARSER)
+  set(MACH_SRCS cmMachO.h cmMachO.cxx)
+endif()
+
 #
 # Sources for CMakeLib
 #
@@ -267,6 +276,7 @@ set(SRCS
   cmLocalGenerator.cxx
   cmLocalGenerator.h
   cmLocalUnixMakefileGenerator3.cxx
+  ${MACH_SRCS}
   cmMakeDepend.cxx
   cmMakeDepend.h
   cmMakefile.cxx
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 2b0280d..79776f4 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -16,5 +16,6 @@
 #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE
 #cmakedefine HAVE_UNSETENV
 #cmakedefine CMAKE_USE_ELF_PARSER
+#cmakedefine CMAKE_USE_MACH_PARSER
 #cmakedefine CMAKE_ENCODING_UTF8
 #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
diff --git a/Source/cmMachO.cxx b/Source/cmMachO.cxx
new file mode 100644
index 0000000..1607845
--- /dev/null
+++ b/Source/cmMachO.cxx
@@ -0,0 +1,419 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#include "cmStandardIncludes.h" // to get CMAKE_USE_MACH_PARSER first
+#include "cmMachO.h"
+
+#include <cmsys/FStream.hxx>
+
+// Include the Mach-O format information system header.
+#include <mach-o/loader.h>
+#include <mach-o/fat.h>
+
+/**
+
+  https://developer.apple.com/library/mac/documentation/
+          DeveloperTools/Conceptual/MachORuntime/index.html
+
+  A Mach-O file has 3 major regions: header, load commands and segments.
+  Data Structures are provided from <mach-o/loader.h> which
+  correspond to the file structure.
+
+  The header can be either a struct mach_header or struct mach_header_64.
+  One can peek at the first 4 bytes to identify the type of header.
+
+  Following is the load command region which starts with
+  struct load_command, and is followed by n number of load commands.
+
+  In the case of a universal binary (an archive of multiple Mach-O files),
+  the file begins with a struct fat_header and is followed by multiple
+  struct fat_arch instances.  The struct fat_arch indicates the offset
+  for each Mach-O file.
+
+  */
+
+namespace {
+
+  // peek in the file
+  template <typename T>
+  bool peek(cmsys::ifstream& fin, T &v)
+    {
+    std::streampos p = fin.tellg();
+    if(!fin.read(reinterpret_cast<char*>(&v), sizeof(T)))
+      {
+      return false;
+      }
+    fin.seekg(p);
+    return fin.good();
+    }
+
+  // read from the file and fill a data structure
+  template <typename T>
+  bool read(cmsys::ifstream& fin, T& v)
+    {
+    if(!fin.read(reinterpret_cast<char*>(&v), sizeof(T)))
+      {
+      return false;
+      }
+    return true;
+    }
+
+  // read from the file and fill multiple data structures where
+  // the vector has been resized
+  template <typename T>
+  bool read(cmsys::ifstream& fin, std::vector<T>& v)
+    {
+    // nothing to read
+    if(v.empty())
+      {
+      return true;
+      }
+    if(!fin.read(reinterpret_cast<char*>(&v[0]), sizeof(T) * v.size()))
+      {
+      return false;
+      }
+    return true;
+    }
+}
+
+
+// Contains header and load commands for a single Mach-O file
+class cmMachOHeaderAndLoadCommands
+{
+public:
+  // A load_command and its associated data
+  struct RawLoadCommand
+    {
+    uint32_t type(const cmMachOHeaderAndLoadCommands* m) const
+      {
+      if(this->LoadCommand.size() < sizeof(load_command))
+        {
+        return 0;
+        }
+      const load_command* cmd =
+        reinterpret_cast<const load_command*>(&this->LoadCommand[0]);
+      return m->swap(cmd->cmd);
+      }
+    std::vector<char> LoadCommand;
+    };
+
+  cmMachOHeaderAndLoadCommands(bool _swap)
+    : Swap(_swap)
+    {
+    }
+  virtual ~cmMachOHeaderAndLoadCommands()
+    {
+    }
+
+  virtual bool read_mach_o(cmsys::ifstream& fin) = 0;
+
+  const std::vector<RawLoadCommand>& load_commands() const
+    {
+    return this->LoadCommands;
+    }
+
+  uint32_t swap(uint32_t v) const
+    {
+    if(this->Swap)
+      {
+      char* c = reinterpret_cast<char*>(&v);
+      std::swap(c[0], c[3]);
+      std::swap(c[1], c[2]);
+      }
+    return v;
+    }
+
+protected:
+  bool read_load_commands(uint32_t ncmds, uint32_t sizeofcmds,
+                          cmsys::ifstream& fin);
+
+  bool Swap;
+  std::vector<RawLoadCommand> LoadCommands;
+};
+
+// Implementation for reading Mach-O header and load commands.
+// This is 32 or 64 bit arch specific.
+template <class T>
+class cmMachOHeaderAndLoadCommandsImpl : public cmMachOHeaderAndLoadCommands
+{
+public:
+  cmMachOHeaderAndLoadCommandsImpl(bool _swap)
+    : cmMachOHeaderAndLoadCommands(_swap)
+    {
+    }
+  bool read_mach_o(cmsys::ifstream& fin)
+    {
+    if(!read(fin, this->Header))
+      {
+      return false;
+      }
+    this->Header.cputype = swap(this->Header.cputype);
+    this->Header.cpusubtype = swap(this->Header.cpusubtype);
+    this->Header.filetype = swap(this->Header.filetype);
+    this->Header.ncmds = swap(this->Header.ncmds);
+    this->Header.sizeofcmds = swap(this->Header.sizeofcmds);
+    this->Header.flags = swap(this->Header.flags);
+
+    return read_load_commands(this->Header.ncmds,
+                              this->Header.sizeofcmds,
+                              fin);
+    }
+protected:
+  T Header;
+};
+
+
+bool cmMachOHeaderAndLoadCommands::read_load_commands(uint32_t ncmds,
+                                                      uint32_t sizeofcmds,
+                                                      cmsys::ifstream& fin)
+{
+  uint32_t size_read = 0;
+  this->LoadCommands.resize(ncmds);
+  for(uint32_t i = 0; i<ncmds; i++)
+    {
+    load_command lc;
+    if(!peek(fin, lc))
+      {
+      return false;
+      }
+    lc.cmd = swap(lc.cmd);
+    lc.cmdsize = swap(lc.cmdsize);
+    size_read += lc.cmdsize;
+
+    RawLoadCommand& c = this->LoadCommands[i];
+    c.LoadCommand.resize(lc.cmdsize);
+    if(!read(fin, c.LoadCommand))
+      {
+      return false;
+      }
+    }
+
+  if(size_read != sizeofcmds)
+    {
+    this->LoadCommands.clear();
+    return false;
+    }
+
+  return true;
+}
+
+//----------------------------------------------------------------------------
+class cmMachOInternal
+{
+public:
+  cmMachOInternal(const char* fname);
+  ~cmMachOInternal();
+
+  // read a Mach-O file
+  bool read_mach_o(uint32_t file_offset);
+
+  // the file we are reading
+  cmsys::ifstream Fin;
+
+  // The archs in the universal binary
+  // If the binary is not a universal binary, this will be empty.
+  std::vector<fat_arch> FatArchs;
+
+  // the error message while parsing
+  std::string ErrorMessage;
+
+  // the list of Mach-O's
+  std::vector<cmMachOHeaderAndLoadCommands*> MachOList;
+};
+
+cmMachOInternal::cmMachOInternal(const char* fname)
+  : Fin(fname)
+{
+  // Quit now if the file could not be opened.
+  if(!this->Fin || !this->Fin.get() )
+    {
+    this->ErrorMessage = "Error opening input file.";
+    return;
+    }
+
+  if(!this->Fin.seekg(0))
+    {
+    this->ErrorMessage = "Error seeking to beginning of file.";
+    return;
+    }
+
+  // Read the binary identification block.
+  uint32_t magic = 0;
+  if(!peek(this->Fin, magic))
+    {
+    this->ErrorMessage = "Error reading Mach-O identification.";
+    return;
+    }
+
+  // Verify the binary identification.
+  if(!(magic == MH_CIGAM ||
+       magic == MH_MAGIC ||
+       magic == MH_CIGAM_64 ||
+       magic == MH_MAGIC_64 ||
+       magic == FAT_CIGAM ||
+       magic == FAT_MAGIC))
+    {
+    this->ErrorMessage = "File does not have a valid Mach-O identification.";
+    return;
+    }
+
+  if(magic == FAT_MAGIC || magic == FAT_CIGAM)
+    {
+    // this is a universal binary
+    fat_header header;
+    if(!read(this->Fin, header))
+      {
+      this->ErrorMessage = "Error reading fat header.";
+      return;
+      }
+
+    // read fat_archs
+    this->FatArchs.resize(OSSwapBigToHostInt32(header.nfat_arch));
+    if(!read(this->Fin, this->FatArchs))
+      {
+      this->ErrorMessage = "Error reading fat header archs.";
+      return;
+      }
+
+    // parse each Mach-O file
+    for(size_t i=0; i<this->FatArchs.size(); i++)
+      {
+      const fat_arch& arch = this->FatArchs[i];
+      if(!this->read_mach_o(OSSwapBigToHostInt32(arch.offset)))
+        {
+        return;
+        }
+      }
+    }
+  else
+    {
+    // parse Mach-O file at the beginning of the file
+    this->read_mach_o(0);
+    }
+}
+
+cmMachOInternal::~cmMachOInternal()
+{
+  for(size_t i=0; i<this->MachOList.size(); i++)
+    {
+    delete this->MachOList[i];
+    }
+}
+
+bool cmMachOInternal::read_mach_o(uint32_t file_offset)
+{
+  if(!this->Fin.seekg(file_offset))
+    {
+    this->ErrorMessage = "Failed to locate Mach-O content.";
+    return false;
+    }
+
+  uint32_t magic;
+  if(!peek(this->Fin, magic))
+    {
+    this->ErrorMessage = "Error reading Mach-O identification.";
+    return false;
+    }
+
+  cmMachOHeaderAndLoadCommands* f = NULL;
+  if(magic == MH_CIGAM || magic == MH_MAGIC)
+    {
+    bool swap = false;
+    if(magic == MH_CIGAM)
+      {
+      swap = true;
+      }
+    f = new cmMachOHeaderAndLoadCommandsImpl<mach_header>(swap);
+    }
+  else if(magic == MH_CIGAM_64 || magic == MH_MAGIC_64)
+    {
+    bool swap = false;
+    if(magic == MH_CIGAM_64)
+      {
+      swap = true;
+      }
+    f = new cmMachOHeaderAndLoadCommandsImpl<mach_header_64>(swap);
+    }
+
+  if(f && f->read_mach_o(this->Fin))
+    {
+    this->MachOList.push_back(f);
+    }
+  else
+    {
+    delete f;
+    this->ErrorMessage = "Failed to read Mach-O header.";
+    return false;
+    }
+
+  return true;
+}
+
+//============================================================================
+// External class implementation.
+
+//----------------------------------------------------------------------------
+cmMachO::cmMachO(const char* fname): Internal(0)
+{
+  this->Internal = new cmMachOInternal(fname);
+
+}
+
+//----------------------------------------------------------------------------
+cmMachO::~cmMachO()
+{
+  delete this->Internal;
+}
+
+std::string const& cmMachO::GetErrorMessage() const
+{
+  return this->Internal->ErrorMessage;
+}
+
+//----------------------------------------------------------------------------
+bool cmMachO::Valid() const
+{
+  return !this->Internal->MachOList.empty();
+}
+
+bool cmMachO::GetInstallName(std::string& install_name)
+{
+  if(this->Internal->MachOList.empty())
+    {
+    return false;
+    }
+
+  // grab the first Mach-O and get the install name from that one
+  cmMachOHeaderAndLoadCommands* macho = this->Internal->MachOList[0];
+  for(size_t i=0; i<macho->load_commands().size(); i++)
+    {
+    const cmMachOHeaderAndLoadCommands::RawLoadCommand &cmd =
+      macho->load_commands()[i];
+    uint32_t lc_cmd = cmd.type(macho);
+    if(lc_cmd == LC_ID_DYLIB ||
+       lc_cmd == LC_LOAD_WEAK_DYLIB ||
+       lc_cmd == LC_LOAD_DYLIB)
+      {
+      if(sizeof(dylib_command) < cmd.LoadCommand.size())
+        {
+        uint32_t namelen = cmd.LoadCommand.size() - sizeof(dylib_command);
+        install_name.assign(&cmd.LoadCommand[sizeof(dylib_command)], namelen);
+        return true;
+        }
+      }
+    }
+
+  return false;
+}
+
+void cmMachO::PrintInfo(std::ostream& /*os*/) const
+{
+}
diff --git a/Source/cmMachO.h b/Source/cmMachO.h
new file mode 100644
index 0000000..f06f8de
--- /dev/null
+++ b/Source/cmMachO.h
@@ -0,0 +1,51 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+#ifndef cmMachO_h
+#define cmMachO_h
+
+#if !defined(CMAKE_USE_MACH_PARSER)
+# error "This file may be included only if CMAKE_USE_MACH_PARSER is enabled."
+#endif
+
+class cmMachOInternal;
+
+/** \class cmMachO
+ * \brief Executable and Link Format (Mach-O) parser.
+ */
+class cmMachO
+{
+public:
+  /** Construct with the name of the Mach-O input file to parse.  */
+  cmMachO(const char* fname);
+
+  /** Destruct.   */
+  ~cmMachO();
+
+  /** Get the error message if any.  */
+  std::string const& GetErrorMessage() const;
+
+  /** Boolean conversion.  True if the Mach-O file is valid.  */
+  operator bool() const { return this->Valid(); }
+
+  /** Get Install name from binary **/
+  bool GetInstallName(std::string& install_name);
+
+  /** Print human-readable information about the Mach-O file.  */
+  void PrintInfo(std::ostream& os) const;
+
+private:
+  friend class cmMachOInternal;
+  bool Valid() const;
+  cmMachOInternal* Internal;
+};
+
+#endif

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake
_______________________________________________
Cmake-commits mailing list
Cmake-commits@cmake.org
http://public.kitware.com/mailman/listinfo/cmake-commits

Reply via email to