[Cmake-commits] CMake branch, next, updated. v2.8.12.1-6230-g3148250

Nils Gladitz nilsgladitz at gmail.com
Tue Dec 17 04:40:52 EST 2013


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  3148250b14264a869874d0d56f2b3ad8a232722e (commit)
       via  d0d29b02404a34b3689dbdc941c5aa808248cd9d (commit)
       via  b4fdbba55ad857a803a0d2e6c1f0b2bff10f4b51 (commit)
       via  5cd2e0fc44e5950285fcd2c3ae352915300d26c9 (commit)
      from  ee7986160ae5c0e4c755a2fbb2ec66e2d9ab5f9b (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=3148250b14264a869874d0d56f2b3ad8a232722e
commit 3148250b14264a869874d0d56f2b3ad8a232722e
Merge: ee79861 d0d29b0
Author:     Nils Gladitz <nilsgladitz at gmail.com>
AuthorDate: Tue Dec 17 04:40:46 2013 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Tue Dec 17 04:40:46 2013 -0500

    Merge topic 'wix-fragment-injection' into next
    
    d0d29b0 CPackWiX: allow customization of generated WiX sources
    b4fdbba CMake Nightly Date Stamp
    5cd2e0f CMake Nightly Date Stamp


http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d0d29b02404a34b3689dbdc941c5aa808248cd9d
commit d0d29b02404a34b3689dbdc941c5aa808248cd9d
Author:     Nils Gladitz <nilsgladitz at gmail.com>
AuthorDate: Mon Dec 16 22:30:11 2013 +0100
Commit:     Nils Gladitz <nilsgladitz at gmail.com>
CommitDate: Tue Dec 17 10:39:10 2013 +0100

    CPackWiX: allow customization of generated WiX sources
    
    Added a new variable CPACK_WIX_PATCH_FILE that users can point at an
    XML patch file. Fragments defined within the patch file will be inserted
    at supported insertion points (currently Component, File and Directory).

diff --git a/Modules/CPackWIX.cmake b/Modules/CPackWIX.cmake
index 237c5bc..d9e0ba7 100644
--- a/Modules/CPackWIX.cmake
+++ b/Modules/CPackWIX.cmake
@@ -116,6 +116,57 @@
 #  If this variable is not set, the default MSI template included with CMake
 #  will be used.
 #
+# .. variable:: CPACK_WIX_PATCH_FILE
+#
+#  Optional XML file with fragments to be inserted into generated WiX sources
+#
+#  This optional variable can be used to specify an XML file that the
+#  WiX generator will use to inject fragments into its generated
+#  source files.
+#
+#  Patch files understood by the CPack WiX generator
+#  roughly follow this RELAX NG compact schema:
+#
+#  .. code-block:: none
+#
+#     start = CPackWiXPatch
+#
+#     CPackWiXPatch = element CPackWiXPatch { CPackWiXFragment* }
+#
+#     CPackWiXFragment = element CPackWiXFragment
+#     {
+#         attribute Id { string },
+#         fragmentContent*
+#     }
+#
+#     fragmentContent = element * - CPackWiXFragment
+#     {
+#         (attribute * { text } | text | fragmentContent)*
+#     }
+#
+#  Currently fragments can be injected into most
+#  Component, File and Directory elements.
+#
+#  The following example illustrates how this works.
+#
+#  Given that the WiX generator creates the following XML element:
+#
+#  .. code-block:: xml
+#
+#     <Component Id="CM_CP_applications.bin.my_libapp.exe" Guid="*"/>
+#
+#  The following XML patch file may be used to inject an Environment element
+#  into it:
+#
+#  .. code-block:: xml
+#
+#     <CPackWiXPatch>
+#       <CPackWiXFragment Id="CM_CP_applications.bin.my_libapp.exe">
+#         <Environment Id="MyEnvironment" Action="set"
+#           Name="MyVariableName" Value="MyVariableValue"/>
+#       </CPackWiXFragment>
+#     </CPackWiXPatch>
+#
 # .. variable:: CPACK_WIX_EXTRA_SOURCES
 #
 #  Extra WiX source files
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 17fb52d..3c944fb 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -517,6 +517,7 @@ if(WIN32)
     CPack/WiX/cmCPackWIXGenerator.cxx
     CPack/WiX/cmWIXSourceWriter.cxx
     CPack/WiX/cmWIXRichTextFormatWriter.cxx
+    CPack/WiX/cmWIXPatchParser.cxx
   )
 endif()
 
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 1b9b20a..6f1daaa 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -218,6 +218,12 @@ bool cmCPackWIXGenerator::InitializeWiXConfiguration()
   CollectExtensions("CPACK_WIX_EXTENSIONS", lightExtensions);
   CollectExtensions("CPACK_WIX_LIGHT_EXTENSIONS", lightExtensions);
 
+  const char* patchFilePath = GetOption("CPACK_WIX_PATCH_FILE");
+  if(patchFilePath)
+    {
+    LoadPatchFragments(patchFilePath);
+    }
+
   return true;
 }
 
@@ -529,6 +535,28 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
 
   wixSources.push_back(mainSourceFilePath);
 
+  std::string fragmentList;
+  for(cmWIXPatchParser::fragment_map_t::const_iterator
+    i = fragments.begin(); i != fragments.end(); ++i)
+    {
+    if(!fragmentList.empty())
+      {
+      fragmentList += ", ";
+      }
+
+    fragmentList += "'";
+    fragmentList += i->first;
+    fragmentList += "'";
+    }
+
+  if(fragmentList.size())
+    {
+      cmCPackLogger(cmCPackLog::LOG_ERROR,
+        "Some XML patch fragments did not have matching IDs: " <<
+        fragmentList << std::endl);
+      return false;
+    }
+
   return true;
 }
 
@@ -872,6 +900,7 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
         packageExecutables,
         shortcutMap);
 
+      ApplyPatchFragment(subDirectoryId, directoryDefinitions);
       directoryDefinitions.EndElement("Directory");
       }
     else
@@ -891,7 +920,10 @@ void cmCPackWIXGenerator::AddDirectoryAndFileDefinitons(
       fileDefinitions.AddAttribute("Source", fullPath);
       fileDefinitions.AddAttribute("KeyPath", "yes");
 
+      ApplyPatchFragment(fileId, fileDefinitions);
       fileDefinitions.EndElement("File");
+
+      ApplyPatchFragment(componentId, fileDefinitions);
       fileDefinitions.EndElement("Component");
       fileDefinitions.EndElement("DirectoryRef");
 
@@ -1146,3 +1178,45 @@ void cmCPackWIXGenerator::CreateStartMenuFolder(
 
   directoryDefinitions.EndElement("Directory");
 }
+
+void cmCPackWIXGenerator::LoadPatchFragments(const std::string& patchFilePath)
+{
+  cmWIXPatchParser parser(fragments, Logger);
+  parser.ParseFile(patchFilePath.c_str());
+}
+
+void cmCPackWIXGenerator::ApplyPatchFragment(
+  const std::string& id, cmWIXSourceWriter& writer)
+{
+  cmWIXPatchParser::fragment_map_t::iterator i = fragments.find(id);
+  if(i == fragments.end()) return;
+
+  const cmWIXPatchElement& fragment = i->second;
+  for(cmWIXPatchElement::child_list_t::const_iterator
+    j = fragment.children.begin(); j != fragment.children.end(); ++j)
+    {
+    ApplyPatchElement(**j, writer);
+    }
+
+  fragments.erase(i);
+}
+
+void cmCPackWIXGenerator::ApplyPatchElement(
+  const cmWIXPatchElement& element, cmWIXSourceWriter& writer)
+{
+  writer.BeginElement(element.name);
+
+  for(cmWIXPatchElement::attributes_t::const_iterator
+    i = element.attributes.begin(); i != element.attributes.end(); ++i)
+    {
+    writer.AddAttribute(i->first, i->second);
+    }
+
+  for(cmWIXPatchElement::child_list_t::const_iterator
+    i = element.children.begin(); i != element.children.end(); ++i)
+    {
+    ApplyPatchElement(**i, writer);
+    }
+
+  writer.EndElement(element.name);
+}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index 84f68b6..a0a057c 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -13,6 +13,8 @@
 #ifndef cmCPackWIXGenerator_h
 #define cmCPackWIXGenerator_h
 
+#include "cmWIXPatchParser.h"
+
 #include <CPack/cmCPackGenerator.h>
 
 #include <string>
@@ -160,12 +162,21 @@ private:
 
   void CreateStartMenuFolder(cmWIXSourceWriter& directoryDefinitions);
 
+  void LoadPatchFragments(const std::string& patchFilePath);
+
+  void ApplyPatchFragment(const std::string& id, cmWIXSourceWriter& writer);
+
+  void ApplyPatchElement(const cmWIXPatchElement& element,
+    cmWIXSourceWriter& writer);
+
   std::vector<std::string> wixSources;
   id_map_t pathToIdMap;
   ambiguity_map_t idAmbiguityCounter;
 
   extension_set_t candleExtensions;
   extension_set_t lightExtensions;
+
+  cmWIXPatchParser::fragment_map_t fragments;
 };
 
 #endif
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
new file mode 100644
index 0000000..1db566d
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -0,0 +1,146 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Kitware, Inc.
+
+  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 "cmWIXPatchParser.h"
+
+#include <CPack/cmCPackGenerator.h>
+
+#include <cm_expat.h>
+
+cmWIXPatchElement::~cmWIXPatchElement()
+{
+  for(child_list_t::iterator i = children.begin(); i != children.end(); ++i)
+    {
+    delete *i;
+    }
+}
+
+cmWIXPatchParser::cmWIXPatchParser(
+  fragment_map_t& fragments, cmCPackLog* logger):
+    Logger(logger),
+    state(BEGIN_DOCUMENT),
+    valid(true),
+    fragments(fragments)
+{
+
+}
+
+void cmWIXPatchParser::StartElement(const char *name, const char **atts)
+{
+  std::string name_str = name;
+  if(state == BEGIN_DOCUMENT)
+    {
+    if(name_str == "CPackWiXPatch")
+      {
+      state = BEGIN_FRAGMENTS;
+      }
+    else
+      {
+      ReportValidationError("Expected root element 'CPackWiXPatch'");
+      }
+    }
+  else if(state == BEGIN_FRAGMENTS)
+    {
+      if(name_str == "CPackWiXFragment")
+        {
+        state = INSIDE_FRAGMENT;
+        StartFragment(name_str, atts);
+        }
+      else
+        {
+        ReportValidationError("Expected 'CPackWixFragment' element");
+        }
+    }
+  else if(state == INSIDE_FRAGMENT)
+    {
+      cmWIXPatchElement &parent = *elementStack.back();
+
+      parent.children.resize(parent.children.size() + 1);
+      cmWIXPatchElement*& currentElement = parent.children.back();
+      currentElement = new cmWIXPatchElement;
+      currentElement->name = name;
+
+      for(size_t i = 0; atts[i]; i += 2)
+        {
+        std::string key = atts[i];
+        std::string value = atts[i+1];
+
+        currentElement->attributes[key] = value;
+        }
+
+      elementStack.push_back(currentElement);
+    }
+}
+
+void cmWIXPatchParser::StartFragment(const std::string& name,
+  const char **attributes)
+{
+  for(size_t i = 0; attributes[i]; i += 2)
+    {
+    std::string key = attributes[i];
+    std::string value = attributes[i+1];
+
+    if(key == "Id")
+      {
+      if(fragments.find(value) != fragments.end())
+        {
+        std::stringstream tmp;
+        tmp << "Invalid reuse of 'CPackWixFragment' 'Id': " << value;
+        ReportValidationError(tmp.str());
+        }
+
+      elementStack.push_back(&fragments[value]);
+      }
+    else
+      {
+      ReportValidationError(
+        "The only allowed 'CPackWixFragment' attribute is 'Id'");
+      }
+    }
+}
+
+void cmWIXPatchParser::EndElement(const char *name)
+{
+  std::string name_str = name;
+  if(state == INSIDE_FRAGMENT)
+    {
+      if(name_str == "CPackWiXFragment")
+        {
+        state = BEGIN_FRAGMENTS;
+        elementStack.clear();
+        }
+      else
+        {
+          elementStack.pop_back();
+        }
+    }
+}
+
+void cmWIXPatchParser::ReportError(int line, int column, const char* msg)
+{
+  cmCPackLogger(cmCPackLog::LOG_ERROR,
+    "Error while processing XML patch file at " << line << ":" << column <<
+      ":  "<< msg << std::endl);
+  valid = false;
+}
+
+void cmWIXPatchParser::ReportValidationError(const std::string& message)
+{
+  ReportError(XML_GetCurrentLineNumber(Parser),
+    XML_GetCurrentColumnNumber(Parser),
+    message.c_str());
+}
+
+bool cmWIXPatchParser::IsValid() const
+{
+  return valid;
+}
diff --git a/Source/CPack/WiX/cmWIXPatchParser.h b/Source/CPack/WiX/cmWIXPatchParser.h
new file mode 100644
index 0000000..89159b4
--- /dev/null
+++ b/Source/CPack/WiX/cmWIXPatchParser.h
@@ -0,0 +1,76 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2013 Kitware, Inc.
+
+  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 cmCPackWIXPatchParser_h
+#define cmCPackWIXPatchParser_h
+
+#include <cmXMLParser.h>
+
+#include <CPack/cmCPackLog.h>
+
+#include <map>
+#include <list>
+
+struct cmWIXPatchElement
+{
+  ~cmWIXPatchElement();
+
+  typedef std::list<cmWIXPatchElement*> child_list_t;
+  typedef std::map<std::string, std::string> attributes_t;
+
+  std::string name;
+  child_list_t children;
+  attributes_t attributes;
+};
+
+/** \class cmWIXPatchParser
+ * \brief Helper class that parses XML patch files (CPACK_WIX_PATCH_FILE)
+ */
+class cmWIXPatchParser : public cmXMLParser
+{
+public:
+  typedef std::map<std::string, cmWIXPatchElement> fragment_map_t;
+
+  cmWIXPatchParser(fragment_map_t& fragments, cmCPackLog* logger);
+
+private:
+  virtual void StartElement(const char *name, const char **atts);
+
+  void StartFragment(
+    const std::string& name, const char **attributes);
+
+  virtual void EndElement(const char *name);
+  virtual void ReportError(int line, int column, const char* msg);
+
+  void ReportValidationError(const std::string& message);
+
+  bool IsValid() const;
+
+  cmCPackLog* Logger;
+
+  enum ParserState
+  {
+    BEGIN_DOCUMENT,
+    BEGIN_FRAGMENTS,
+    INSIDE_FRAGMENT
+  };
+
+  ParserState state;
+
+  bool valid;
+
+  fragment_map_t& fragments;
+
+  std::list<cmWIXPatchElement*> elementStack;
+};
+
+#endif
diff --git a/Tests/CPackWiXGenerator/CMakeLists.txt b/Tests/CPackWiXGenerator/CMakeLists.txt
index ecfecdb..0b06045 100644
--- a/Tests/CPackWiXGenerator/CMakeLists.txt
+++ b/Tests/CPackWiXGenerator/CMakeLists.txt
@@ -49,6 +49,8 @@ set(CPACK_PACKAGE_EXECUTABLES
   "my-other-app" "Second CPack WiX Test"
 )
 
+set(CPACK_WIX_PATCH_FILE "${CMAKE_CURRENT_SOURCE_DIR}/patch.xml")
+
 include(CPack)
 
 cpack_add_install_type(Full DISPLAY_NAME "Everything")
diff --git a/Tests/CPackWiXGenerator/patch.xml b/Tests/CPackWiXGenerator/patch.xml
new file mode 100644
index 0000000..13c392d
--- /dev/null
+++ b/Tests/CPackWiXGenerator/patch.xml
@@ -0,0 +1,7 @@
+<CPackWiXPatch>
+	<CPackWiXFragment Id="CM_CP_applications.bin.my_libapp.exe">
+		<Environment Id="MyEnvironment" Action="set"
+			Name="CPackWiXGeneratorTest"
+			Value="CPackWiXGeneratorTest"/>
+	</CPackWiXFragment>
+</CPackWiXPatch>

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

Summary of changes:
 Modules/CPackWIX.cmake                   |   51 +++++++++++
 Source/CMakeLists.txt                    |    1 +
 Source/CMakeVersion.cmake                |    2 +-
 Source/CPack/WiX/cmCPackWIXGenerator.cxx |   74 +++++++++++++++
 Source/CPack/WiX/cmCPackWIXGenerator.h   |   11 +++
 Source/CPack/WiX/cmWIXPatchParser.cxx    |  146 ++++++++++++++++++++++++++++++
 Source/CPack/WiX/cmWIXPatchParser.h      |   76 ++++++++++++++++
 Tests/CPackWiXGenerator/CMakeLists.txt   |    2 +
 Tests/CPackWiXGenerator/patch.xml        |    7 ++
 9 files changed, 369 insertions(+), 1 deletions(-)
 create mode 100644 Source/CPack/WiX/cmWIXPatchParser.cxx
 create mode 100644 Source/CPack/WiX/cmWIXPatchParser.h
 create mode 100644 Tests/CPackWiXGenerator/patch.xml


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list