فهرست منبع

Merge topic 'fix-11295-support-plugin-bundles-on-mac'

cabc407 CFBundle Test: Add PATHS for finding Rez (#11295)
5457b82 Add support for CFBundle targets on the Mac (#11295)
Brad King 14 سال پیش
والد
کامیت
64d997a78c

+ 6 - 0
Source/cmExportFileGenerator.cxx

@@ -325,6 +325,12 @@ cmExportFileGenerator
     os << "SET_PROPERTY(TARGET " << targetName
        << " PROPERTY MACOSX_BUNDLE 1)\n";
     }
+
+  if (target->IsCFBundleOnApple())
+    {
+    os << "SET_PROPERTY(TARGET " << targetName
+       << " PROPERTY BUNDLE 1)\n";
+    }
   os << "\n";
 }
 

+ 14 - 0
Source/cmExportInstallFileGenerator.cxx

@@ -263,6 +263,20 @@ cmExportInstallFileGenerator
       value += ".framework/";
       value += itgen->GetInstallFilename(target, config);
       }
+    else if(target->IsCFBundleOnApple())
+      {
+      const char *ext = target->GetProperty("BUNDLE_EXTENSION");
+      if (!ext)
+        {
+        ext = "bundle";
+        }
+
+      value += itgen->GetInstallFilename(target, config);
+      value += ".";
+      value += ext;
+      value += "/";
+      value += itgen->GetInstallFilename(target, config);
+      }
     else if(target->IsAppBundleOnApple())
       {
       value += itgen->GetInstallFilename(target, config);

+ 48 - 7
Source/cmGlobalXCodeGenerator.cxx

@@ -578,6 +578,12 @@ cmGlobalXCodeGenerator::CreateXCodeSourceFile(cmLocalGenerator* lg,
       }
     }
 
+  if(cmtarget.IsCFBundleOnApple())
+    {
+    cmtarget.SetProperty("PREFIX", "");
+    cmtarget.SetProperty("SUFFIX", "");
+    }
+
   // Add the fileRef to the top level Resources group/folder if it is not
   // already there.
   //
@@ -812,6 +818,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
     // some build phases only apply to bundles and/or frameworks
     bool isFrameworkTarget = cmtarget.IsFrameworkOnApple();
     bool isBundleTarget = cmtarget.GetPropertyAsBool("MACOSX_BUNDLE");
+    bool isCFBundleTarget = cmtarget.IsCFBundleOnApple();
 
     cmXCodeObject* buildFiles = 0;
 
@@ -857,7 +864,8 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
 
     // create resource build phase - only for framework or bundle targets
     cmXCodeObject* resourceBuildPhase = 0;
-    if (!resourceFiles.empty() && (isFrameworkTarget || isBundleTarget))
+    if (!resourceFiles.empty() &&
+        (isFrameworkTarget || isBundleTarget || isCFBundleTarget))
       {
       resourceBuildPhase =
         this->CreateObject(cmXCodeObject::PBXResourcesBuildPhase);
@@ -878,7 +886,7 @@ cmGlobalXCodeGenerator::CreateXCodeTargets(cmLocalGenerator* gen,
     // create vector of "non-resource content file" build phases - only for
     // framework or bundle targets
     std::vector<cmXCodeObject*> contentBuildPhases;
-    if (isFrameworkTarget || isBundleTarget)
+    if (isFrameworkTarget || isBundleTarget || isCFBundleTarget)
       {
       typedef std::map<cmStdString, std::vector<cmSourceFile*> >
         mapOfVectorOfSourceFiles;
@@ -1605,7 +1613,33 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
     {
     buildSettings->AddAttribute("LIBRARY_STYLE",
                                 this->CreateString("BUNDLE"));
-    if(this->XcodeVersion >= 22)
+    if (target.GetPropertyAsBool("BUNDLE"))
+      {
+      // It turns out that a BUNDLE is basically the same
+      // in many ways as an application bundle, as far as
+      // link flags go
+      std::string createFlags =
+        this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
+                          "-bundle");
+      if(!createFlags.empty())
+        {
+        extraLinkOptions += " ";
+        extraLinkOptions += createFlags;
+        }
+      std::string plist = this->ComputeInfoPListLocation(target);
+      // Xcode will create the final version of Info.plist at build time,
+      // so let it replace the cfbundle name. This avoids creating
+      // a per-configuration Info.plist file. The cfbundle plist
+      // is very similar to the application bundle plist
+      this->CurrentLocalGenerator
+        ->GenerateAppleInfoPList(&target, "$(EXECUTABLE_NAME)",
+                                 plist.c_str());
+      std::string path =
+        this->ConvertToRelativeForXCode(plist.c_str());
+      buildSettings->AddAttribute("INFOPLIST_FILE",
+                                  this->CreateString(path.c_str()));
+      }
+    else if(this->XcodeVersion >= 22)
       {
       buildSettings->AddAttribute("MACH_O_TYPE",
                                   this->CreateString("mh_bundle"));
@@ -1644,7 +1678,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
 
       std::string plist = this->ComputeInfoPListLocation(target);
       // Xcode will create the final version of Info.plist at build time,
-      // so let it replace the framework name.  This avoids creating
+      // so let it replace the framework name. This avoids creating
       // a per-configuration Info.plist file.
       this->CurrentLocalGenerator
         ->GenerateFrameworkInfoPList(&target, "$(EXECUTABLE_NAME)",
@@ -2043,7 +2077,10 @@ const char* cmGlobalXCodeGenerator::GetTargetFileType(cmTarget& cmtarget)
     case cmTarget::STATIC_LIBRARY:
       return "archive.ar";
     case cmTarget::MODULE_LIBRARY:
-      return ((this->XcodeVersion >= 22)?
+      if (cmtarget.IsCFBundleOnApple())
+        return "wrapper.plug-in";
+      else
+        return ((this->XcodeVersion >= 22)?
               "compiled.mach-o.executable" : "compiled.mach-o.dylib");
     case cmTarget::SHARED_LIBRARY:
       return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
@@ -2063,8 +2100,12 @@ const char* cmGlobalXCodeGenerator::GetTargetProductType(cmTarget& cmtarget)
     case cmTarget::STATIC_LIBRARY:
       return "com.apple.product-type.library.static";
     case cmTarget::MODULE_LIBRARY:
-      return ((this->XcodeVersion >= 22)? "com.apple.product-type.tool" :
-              "com.apple.product-type.library.dynamic");
+      if (cmtarget.IsCFBundleOnApple())
+        return "com.apple.product-type.bundle";
+      else
+        return ((this->XcodeVersion >= 22)?
+                "com.apple.product-type.tool" :
+                "com.apple.product-type.library.dynamic");
     case cmTarget::SHARED_LIBRARY:
       return (cmtarget.GetPropertyAsBool("FRAMEWORK")?
               "com.apple.product-type.framework" :

+ 49 - 0
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -26,6 +26,12 @@ cmMakefileLibraryTargetGenerator
 ::cmMakefileLibraryTargetGenerator(cmTarget* target):
   cmMakefileTargetGenerator(target)
 {
+  if(this->Target->IsCFBundleOnApple())
+    {
+    target->SetProperty("PREFIX", "");
+    target->SetProperty("SUFFIX", "");
+    }
+
   this->CustomCommandDriver = OnDepends;
   this->Target->GetLibraryNames(
     this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
@@ -41,6 +47,20 @@ cmMakefileLibraryTargetGenerator
     this->MacContentDirectory += this->FrameworkVersion;
     this->MacContentDirectory += "/";
     }
+  else if(this->Target->IsCFBundleOnApple())
+    {
+    this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
+    this->MacContentDirectory += "/";
+    this->MacContentDirectory += this->TargetNameOut;
+    this->MacContentDirectory += ".";
+    const char *ext = this->Target->GetProperty("BUNDLE_EXTENSION");
+    if (!ext)
+      {
+      ext = "bundle";
+      }
+    this->MacContentDirectory += ext;
+    this->MacContentDirectory += "/Contents/";
+    }
 }
 
 //----------------------------------------------------------------------------
@@ -300,6 +320,27 @@ cmMakefileLibraryTargetGenerator
     }
 }
 
+//----------------------------------------------------------------------------
+void
+cmMakefileLibraryTargetGenerator::CreateCFBundle(std::string& targetName,
+                                                 std::string& outpath)
+{
+  // Compute bundle directory names.
+  outpath = this->MacContentDirectory;
+  outpath += "MacOS";
+  cmSystemTools::MakeDirectory(outpath.c_str());
+  this->Makefile->AddCMakeOutputFile(outpath.c_str());
+  outpath += "/";
+
+  // Configure the Info.plist file.  Note that it needs the executable name
+  // to be set.
+  std::string plist = this->MacContentDirectory + "Info.plist";
+  this->LocalGenerator->GenerateAppleInfoPList(this->Target,
+                                               targetName.c_str(),
+                                               plist.c_str());
+  this->Makefile->AddCMakeOutputFile(plist.c_str());
+}
+
 //----------------------------------------------------------------------------
 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
 (const char* linkRuleVar, const char* extraFlags, bool relink)
@@ -354,6 +395,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
     outpath = this->MacContentDirectory;
     this->CreateFramework(targetName);
     }
+  else if(this->Target->IsCFBundleOnApple())
+    {
+    outpath = this->Target->GetDirectory(this->ConfigName);
+    outpath += "/";
+    this->CreateCFBundle(targetName, outpath);
+    }
   else if(relink)
     {
     outpath = this->Makefile->GetStartOutputDirectory();
@@ -417,6 +464,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
         buildEcho += " shared library ";
         break;
       case cmTarget::MODULE_LIBRARY:
+        if (this->Target->IsCFBundleOnApple())
+            buildEcho += " CFBundle";
         buildEcho += " shared module ";
         break;
       default:

+ 1 - 0
Source/cmMakefileLibraryTargetGenerator.h

@@ -33,6 +33,7 @@ protected:
   // MacOSX Framework support methods
   void WriteFrameworkRules(bool relink);
   void CreateFramework(std::string const& targetName);
+  void CreateCFBundle(std::string& targetName, std::string& outpath);
 
   // Store the computd framework version for OS X Frameworks.
   std::string FrameworkVersion;

+ 5 - 1
Source/cmSourceFile.cxx

@@ -482,17 +482,21 @@ void cmSourceFile::DefineProperties(cmake *cm)
 
   cm->DefineProperty
     ("MACOSX_PACKAGE_LOCATION", cmProperty::SOURCE_FILE, 
-     "Place a source file inside a Mac OS X bundle or framework.",
+     "Place a source file inside a Mac OS X bundle, CFBundle, or framework.",
      "Executable targets with the MACOSX_BUNDLE property set are built "
      "as Mac OS X application bundles on Apple platforms.  "
      "Shared library targets with the FRAMEWORK property set are built "
      "as Mac OS X frameworks on Apple platforms.  "
+     "Module library targets with the BUNDLE property set are built "
+     "as Mac OS X CFBundle bundles on Apple platforms.  "
      "Source files listed in the target with this property set will "
      "be copied to a directory inside the bundle or framework content "
      "folder specified by the property value.  "
      "For bundles the content folder is \"<name>.app/Contents\".  "
      "For frameworks the content folder is "
      "\"<name>.framework/Versions/<version>\".  "
+     "For cfbundles the content folder is "
+     "\"<name>.bundle/Contents\" (unless the extension is changed).  "
      "See the PUBLIC_HEADER, PRIVATE_HEADER, and RESOURCE target "
      "properties for specifying files meant for Headers, PrivateHeaders, "
      "or Resources directories.");

+ 24 - 0
Source/cmTarget.cxx

@@ -187,6 +187,22 @@ void cmTarget::DefineProperties(cmake *cm)
      "A message to display on some generators (such as makefiles) when "
      "the target is built.");
 
+  cm->DefineProperty
+    ("BUNDLE", cmProperty::TARGET,
+     "This target is a CFBundle on the Mac.",
+     "If a module library target has this property set to true it will "
+     "be built as a CFBundle when built on the mac. It will have the "
+     "directory structure required for a CFBundle and will be suitable "
+     "to be used for creating Browser Plugins or other application "
+     "resources.");
+
+  cm->DefineProperty
+    ("BUNDLE_EXTENSION", cmProperty::TARGET,
+     "The file extension used to name a BUNDLE target on the Mac.",
+     "The default value is \"bundle\" - you can also use \"plugin\" or "
+     "whatever file extension is required by the host app for your "
+     "bundle.");
+
   cm->DefineProperty
     ("FRAMEWORK", cmProperty::TARGET,
      "This target is a framework on the Mac.",
@@ -1210,6 +1226,14 @@ bool cmTarget::IsAppBundleOnApple()
           this->GetPropertyAsBool("MACOSX_BUNDLE"));
 }
 
+//----------------------------------------------------------------------------
+bool cmTarget::IsCFBundleOnApple()
+{
+  return (this->GetType() == cmTarget::MODULE_LIBRARY &&
+          this->Makefile->IsOn("APPLE") &&
+          this->GetPropertyAsBool("BUNDLE"));
+}
+
 //----------------------------------------------------------------------------
 class cmTargetTraceDependencies
 {

+ 3 - 0
Source/cmTarget.h

@@ -430,6 +430,9 @@ public:
       Apple.  */
   bool IsFrameworkOnApple();
 
+  /** Return whether this target is a CFBundle (plugin) on Apple.  */
+  bool IsCFBundleOnApple();
+
   /** Return whether this target is an executable Bundle on Apple.  */
   bool IsAppBundleOnApple();
 

+ 56 - 0
Tests/CFBundleTest/CMakeLists.txt

@@ -0,0 +1,56 @@
+#this is adapted from FireBreath (http://www.firebreath.org)
+
+cmake_minimum_required(VERSION 2.8)
+
+project(CFBundleTest)
+
+include(PluginConfig.cmake)
+
+message ("Creating Mac Browser Plugin project ${PROJECT_NAME}")
+set(SOURCES
+    np_macmain.cpp
+    Localized.r
+    ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
+    ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings
+    ${CMAKE_CURRENT_BINARY_DIR}/Localized.rsrc
+)
+
+add_library( ${PROJECT_NAME} MODULE
+    ${SOURCES}
+    )
+
+set (RCFILES ${CMAKE_CURRENT_SOURCE_DIR}/Localized.r)
+
+configure_file(Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
+configure_file(InfoPlist.strings.in ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings)
+
+# Compile the resource file
+find_program(RC_COMPILER Rez NO_DEFAULT_PATHS PATHS /Developer/Tools)
+if(NOT RC_COMPILER)
+  message(FATAL_ERROR "could not find Rez to build resources from .r file...")
+endif()
+
+execute_process(COMMAND
+    ${RC_COMPILER} ${RCFILES} -useDF -o ${CMAKE_CURRENT_BINARY_DIR}/Localized.rsrc
+    )
+
+set_source_files_properties(
+    ${CMAKE_CURRENT_BINARY_DIR}/Localized.rsrc
+    PROPERTIES GENERATED 1
+    )
+# note that for some reason, the makefile and xcode generators use a different
+# property to indicate where the Info.plist file is :-/ For that reason, we
+# specify it twice so it will work both places
+set_target_properties(CFBundleTest PROPERTIES
+    BUNDLE 1
+    BUNDLE_EXTENSION plugin
+    XCODE_ATTRIBUTE_WRAPPER_EXTENSION plugin  #sets the extension to .plugin
+    XCODE_ATTRIBUTE_MACH_O_TYPE mh_bundle
+    XCODE_ATTRIBUTE_INFOPLIST_FILE ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
+    MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist
+    LINK_FLAGS "-Wl,-exported_symbols_list,\"${CMAKE_CURRENT_SOURCE_DIR}/ExportList_plugin.txt\"")
+
+set_source_files_properties(
+    ${CMAKE_CURRENT_BINARY_DIR}/InfoPlist.strings
+    ${CMAKE_CURRENT_BINARY_DIR}/Localized.rsrc
+    PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/English.lproj")

+ 3 - 0
Tests/CFBundleTest/ExportList_plugin.txt

@@ -0,0 +1,3 @@
+_NP_GetEntryPoints
+_NP_Initialize
+_NP_Shutdown

+ 54 - 0
Tests/CFBundleTest/Info.plist.in

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>English</string>
+  <key>CFBundleExecutable</key>
+  <string>${PLUGIN_NAME}</string>
+  <key>CFBundleGetInfoString</key>
+    <string>${PLUGIN_NAME} ${FBSTRING_PLUGIN_VERSION}, ${FBSTRING_LegalCopyright}</string>
+  <key>CFBundleIdentifier</key>
+    <string>com.${ACTIVEX_PROGID}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundlePackageType</key>
+  <string>BRPL</string>
+  <key>CFBundleShortVersionString</key>
+    <string>${PLUGIN_NAME} ${FBSTRING_PLUGIN_VERSION}</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+    <string>${FBSTRING_PLUGIN_VERSION}</string>
+  <key>CFPlugInDynamicRegisterFunction</key>
+  <string></string>
+  <key>CFPlugInDynamicRegistration</key>
+  <string>NO</string>
+  <key>CFPlugInFactories</key>
+  <dict>
+    <key>00000000-0000-0000-0000-000000000000</key>
+    <string>MyFactoryFunction</string>
+  </dict>
+  <key>CFPlugInTypes</key>
+  <dict>
+    <key>00000000-0000-0000-0000-000000000000</key>
+    <array>
+      <string>00000000-0000-0000-0000-000000000000</string>
+    </array>
+  </dict>
+  <key>CFPlugInUnloadFunction</key>
+  <string></string>
+  <key>WebPluginName</key>
+  <string>${FBSTRING_ProductName}</string>
+  <key>WebPluginDescription</key>
+  <string>${FBSTRING_FileDescription}</string>
+  <key>WebPluginMIMETypes</key>
+  <dict>
+    <key>${FBSTRING_MIMEType}</key>
+    <dict>
+      <key>WebPluginTypeDescription</key>
+      <string>${FBSTRING_FileDescription}</string>
+    </dict>
+  </dict>
+</dict>
+</plist>

+ 4 - 0
Tests/CFBundleTest/InfoPlist.strings.in

@@ -0,0 +1,4 @@
+/* Localized versions of Info.plist keys */
+
+CFBundleName = "${PLUGIN_NAME}.plugin";
+NSHumanReadableCopyright = "${FBSTRING_LegalCopyright}";

+ 18 - 0
Tests/CFBundleTest/Localized.r

@@ -0,0 +1,18 @@
+#include <CoreServices/CoreServices.r>
+
+resource 'STR#' (126)
+{ {
+    "${FBSTRING_LegalCopyright}",
+    "${FBSTRING_ProductName}"
+} };
+
+resource 'STR#' (127)
+{ {
+    "${FBSTRING_FileDescription}"
+} };
+
+resource 'STR#' (128)
+{ {
+    "${FBSTRING_MIMEType}",
+    "${FBSTRING_FileExtents}"
+} };

BIN
Tests/CFBundleTest/Localized.rsrc


+ 21 - 0
Tests/CFBundleTest/PluginConfig.cmake

@@ -0,0 +1,21 @@
+#/**********************************************************\
+# Auto-Generated Plugin Configuration file
+# for CFTestPlugin
+#\**********************************************************/
+
+set(PLUGIN_NAME "CFTestPlugin")
+set(PLUGIN_PREFIX "CFTP")
+set(COMPANY_NAME "FBDevTeam")
+
+set(MOZILLA_PLUGINID "@firebreath.googlecode.com/CFTestPlugin")
+
+# strings
+set(FBSTRING_CompanyName "Firebreath Dev Team")
+set(FBSTRING_FileDescription "CFBundle Test Plugin - Plugin for testing cmake patch to improve FireBreath project generation")
+set(FBSTRING_PLUGIN_VERSION "1.0.0")
+set(FBSTRING_LegalCopyright "Copyright 2010 Firebreath Dev Team")
+set(FBSTRING_PluginFileName "np${PLUGIN_NAME}.dll")
+set(FBSTRING_ProductName "CFTestPlugin")
+set(FBSTRING_FileExtents "")
+set(FBSTRING_PluginName "CFTestPlugin")
+set(FBSTRING_MIMEType "application/x-fbtestplugin")

+ 16 - 0
Tests/CFBundleTest/README.txt

@@ -0,0 +1,16 @@
+
+CFBundle test project.  The generated .plugin/ bundle from either makefiles or XCode should look like this:
+
+./Contents
+./Contents/Info.plist
+./Contents/MacOS
+./Contents/MacOS/CFBundleTest
+./Contents/Resources
+./Contents/Resources/English.lproj
+./Contents/Resources/English.lproj/InfoPlist.strings
+./Contents/Resources/English.lproj/Localized.rsrc
+
+file Contents/MacOS/CFBundleTest should return something like:
+Contents/MacOS/CFBundleTest: Mach-O 64-bit bundle x86_64
+
+It is okay if it is a 32 bit binary; if it is not Mach-O, or is spelled differently, it is not okay.

+ 32 - 0
Tests/CFBundleTest/VerifyResult.cmake

@@ -0,0 +1,32 @@
+if(NOT DEFINED CTEST_CONFIGURATION_TYPE)
+  message(FATAL_ERROR "expected variable CTEST_CONFIGURATION_TYPE not defined")
+endif()
+
+if(NOT DEFINED dir)
+  message(FATAL_ERROR "expected variable dir not defined")
+endif()
+
+if(NOT DEFINED gen)
+  message(FATAL_ERROR "expected variable gen not defined")
+endif()
+
+message(STATUS "CTEST_CONFIGURATION_TYPE='${CTEST_CONFIGURATION_TYPE}'")
+message(STATUS "dir='${dir}'")
+message(STATUS "gen='${gen}'")
+
+if(gen MATCHES "Make" OR
+   "${CTEST_CONFIGURATION_TYPE}" STREQUAL "" OR
+   "${CTEST_CONFIGURATION_TYPE}" STREQUAL "." OR
+   "${CTEST_CONFIGURATION_TYPE}" STREQUAL "NoConfig")
+  set(expected_filename "${dir}/CFBundleTest.plugin/Contents/MacOS/CFBundleTest")
+else()
+  set(expected_filename "${dir}/${CTEST_CONFIGURATION_TYPE}/CFBundleTest.plugin/Contents/MacOS/CFBundleTest")
+endif()
+
+if(NOT EXISTS "${expected_filename}")
+  message(FATAL_ERROR "test fails: expected output file does not exist [${expected_filename}]")
+endif()
+
+file(COPY "${expected_filename}"
+  DESTINATION "${dir}/LatestBuildResult"
+  )

+ 49 - 0
Tests/CFBundleTest/np_macmain.cpp

@@ -0,0 +1,49 @@
+/***********************************************************\
+  Written by: Richard Bateman (taxilian)
+
+  Based on the default np_macmain.cpp from FireBreath
+  http://firebreath.googlecode.com
+
+  This file has been stripped to prevent it from accidently
+  doing anything useful.
+\***********************************************************/
+
+
+#include <stdio.h>
+
+typedef void (*NPP_ShutdownProcPtr)(void);
+typedef short NPError;
+
+#pragma GCC visibility push(default)
+
+struct NPNetscapeFuncs;
+struct NPPluginFuncs;
+
+extern "C" {
+    NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
+    NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
+    NPError NP_Shutdown(void);
+}
+
+#pragma GCC visibility pop
+
+void initPluginModule()
+{
+}
+
+NPError NP_GetEntryPoints(NPPluginFuncs* pFuncs)
+{
+    printf("NP_GetEntryPoints()\n");
+    return 0;
+}
+
+NPError NP_Initialize(NPNetscapeFuncs* pFuncs)
+{
+    printf("NP_Initialize()\n");
+    return 0;
+}
+
+NPError NP_Shutdown()
+{
+    return 0;
+}

+ 15 - 0
Tests/CMakeLists.txt

@@ -1141,6 +1141,21 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
       ${BundleTestInstallDir}/Applications/SecondBundleExe.app/Contents/MacOS/SecondBundleExe)
     LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/BundleTest")
 
+    ADD_TEST(CFBundleTest ${CMAKE_CTEST_COMMAND}
+      --build-and-test
+      "${CMake_SOURCE_DIR}/Tests/CFBundleTest"
+      "${CMake_BINARY_DIR}/Tests/CFBundleTest"
+      --build-two-config
+      --build-generator ${CMAKE_TEST_GENERATOR}
+      --build-makeprogram ${CMAKE_TEST_MAKEPROGRAM}
+      --build-project CFBundleTest
+      --test-command
+      ${CMAKE_CMAKE_COMMAND} -DCTEST_CONFIGURATION_TYPE=\${CTEST_CONFIGURATION_TYPE}
+        -Ddir=${CMake_BINARY_DIR}/Tests/CFBundleTest
+        -Dgen=${CMAKE_TEST_GENERATOR}
+        -P ${CMake_SOURCE_DIR}/Tests/CFBundleTest/VerifyResult.cmake)
+    LIST(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CFBundleTest")
+
     ADD_TEST_MACRO(ObjC++ ObjC++)
   ENDIF (APPLE AND CMAKE_COMPILER_IS_GNUCXX)