浏览代码

Add support for creating prebuilt Android.mk files

Add options to the `install()` and `export()` commands to export the
targets we build into Android.mk files that reference them as prebuilt
libraries with associated usage requirements (compile definitions,
include directories, link libraries).  This will allow CMake-built
projects to be imported into projects using the Android NDK build
system.

Closes: #15562
Bill Hoffman 9 年之前
父节点
当前提交
42ce9f1e71

+ 15 - 0
Help/command/export.rst

@@ -55,3 +55,18 @@ build tree. In some cases, for example for packaging and for system
 wide installations, it is not desirable to write the user package
 wide installations, it is not desirable to write the user package
 registry. If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable
 registry. If the :variable:`CMAKE_EXPORT_NO_PACKAGE_REGISTRY` variable
 is enabled, the ``export(PACKAGE)`` command will do nothing.
 is enabled, the ``export(PACKAGE)`` command will do nothing.
+
+::
+
+  export(TARGETS [target1 [target2 [...]]]  [ANDROID_MK <filename>])
+
+This signature exports cmake built targets to the android ndk build system
+by creating an Android.mk file that references the prebuilt targets. The
+Android NDK supports the use of prebuilt libraries, both static and shared.
+This allows cmake to build the libraries of a project and make them available
+to an ndk build system complete with transitive dependencies, include flags
+and defines required to use the libraries. The signature takes a list of
+targets and puts them in the Android.mk file specified by the ``<filename>``
+given. This signature can only be used if policy CMP0022 is NEW for all
+targets given. A error will be issued if that policy is set to OLD for one
+of the targets.

+ 12 - 2
Help/command/install.rst

@@ -314,7 +314,8 @@ Installing Exports
 ::
 ::
 
 
   install(EXPORT <export-name> DESTINATION <dir>
   install(EXPORT <export-name> DESTINATION <dir>
-          [NAMESPACE <namespace>] [FILE <name>.cmake]
+          [NAMESPACE <namespace>] [[FILE <name>.cmake]|
+          [EXPORT_ANDROID_MK <name>.mk]]
           [PERMISSIONS permissions...]
           [PERMISSIONS permissions...]
           [CONFIGURATIONS [Debug|Release|...]]
           [CONFIGURATIONS [Debug|Release|...]]
           [EXPORT_LINK_INTERFACE_LIBRARIES]
           [EXPORT_LINK_INTERFACE_LIBRARIES]
@@ -342,6 +343,13 @@ specified that does not match that given to the targets associated with
 included in the export but a target to which it links is not included
 included in the export but a target to which it links is not included
 the behavior is unspecified.
 the behavior is unspecified.
 
 
+In additon to cmake language files, the ``EXPORT_ANDROID_MK`` option maybe
+used to specifiy an export to the android ndk build system.  The Android
+NDK supports the use of prebuilt libraries, both static and shared. This
+allows cmake to build the libraries of a project and make them available
+to an ndk build system complete with transitive dependencies, include flags
+and defines required to use the libraries.
+
 The ``EXPORT`` form is useful to help outside projects use targets built
 The ``EXPORT`` form is useful to help outside projects use targets built
 and installed by the current project.  For example, the code
 and installed by the current project.  For example, the code
 
 
@@ -349,9 +357,11 @@ and installed by the current project.  For example, the code
 
 
   install(TARGETS myexe EXPORT myproj DESTINATION bin)
   install(TARGETS myexe EXPORT myproj DESTINATION bin)
   install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)
   install(EXPORT myproj NAMESPACE mp_ DESTINATION lib/myproj)
+  install(EXPORT_ANDROID_MK myexp DESTINATION share/ndk-modules)
 
 
 will install the executable myexe to ``<prefix>/bin`` and code to import
 will install the executable myexe to ``<prefix>/bin`` and code to import
-it in the file ``<prefix>/lib/myproj/myproj.cmake``.  An outside project
+it in the file ``<prefix>/lib/myproj/myproj.cmake`` and
+``<prefix>/lib/share/ndk-modules/Android.mk``.  An outside project
 may load this file with the include command and reference the ``myexe``
 may load this file with the include command and reference the ``myexe``
 executable from the installation tree using the imported target name
 executable from the installation tree using the imported target name
 ``mp_myexe`` as if the target were built in its own tree.
 ``mp_myexe`` as if the target were built in its own tree.

+ 10 - 0
Help/release/dev/add_androidmk_generator.rst

@@ -0,0 +1,10 @@
+add_androidmk_generator
+-----------------------
+
+* The :command:`install` command gained an ``EXPORT_ANDROID_MK``
+  subcommand to install ``Android.mk`` files referencing installed
+  libraries as prebuilts for the Android NDK build system.
+
+* The :command:`export` command gained an ``ANDROID_MK`` option
+  to generate ``Android.mk`` files referencing CMake-built
+  libraries as prebuilts for the Android NDK build system.

+ 4 - 0
Source/CMakeLists.txt

@@ -221,10 +221,14 @@ set(SRCS
   cmExprLexer.cxx
   cmExprLexer.cxx
   cmExprParser.cxx
   cmExprParser.cxx
   cmExprParserHelper.cxx
   cmExprParserHelper.cxx
+  cmExportBuildAndroidMKGenerator.h
+  cmExportBuildAndroidMKGenerator.cxx
   cmExportBuildFileGenerator.h
   cmExportBuildFileGenerator.h
   cmExportBuildFileGenerator.cxx
   cmExportBuildFileGenerator.cxx
   cmExportFileGenerator.h
   cmExportFileGenerator.h
   cmExportFileGenerator.cxx
   cmExportFileGenerator.cxx
+  cmExportInstallAndroidMKGenerator.h
+  cmExportInstallAndroidMKGenerator.cxx
   cmExportInstallFileGenerator.h
   cmExportInstallFileGenerator.h
   cmExportInstallFileGenerator.cxx
   cmExportInstallFileGenerator.cxx
   cmExportTryCompileFileGenerator.h
   cmExportTryCompileFileGenerator.h

+ 193 - 0
Source/cmExportBuildAndroidMKGenerator.cxx

@@ -0,0 +1,193 @@
+/*============================================================================
+  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 "cmExportBuildAndroidMKGenerator.h"
+
+#include "cmExportSet.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmTargetExport.h"
+
+cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
+{
+  this->LG = CM_NULLPTR;
+  this->ExportSet = CM_NULLPTR;
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
+  std::ostream& os, const std::string&)
+{
+  os << "LOCAL_PATH := $(call my-dir)\n\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
+  std::ostream&, const std::string&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
+  std::ostream& os, const cmGeneratorTarget* target)
+{
+  std::string targetName = this->Namespace;
+  targetName += target->GetExportName();
+  os << "include $(CLEAR_VARS)\n";
+  os << "LOCAL_MODULE := ";
+  os << targetName << "\n";
+  os << "LOCAL_SRC_FILES := ";
+  std::string path = target->GetLocalGenerator()->ConvertToOutputFormat(
+    target->GetFullPath(), cmOutputConverter::MAKERULE);
+  os << path << "\n";
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode(
+  std::ostream&, const std::string&, cmGeneratorTarget const*,
+  ImportPropertyMap const&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+  std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+  const cmGeneratorTarget* target, std::ostream& os,
+  const ImportPropertyMap& properties)
+{
+  std::string config = "";
+  if (this->Configurations.size()) {
+    config = this->Configurations[0];
+  }
+  cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+    target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
+}
+
+void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+  const cmGeneratorTarget* target, std::ostream& os,
+  const ImportPropertyMap& properties, GenerateType type,
+  std::string const& config)
+{
+  const bool newCMP0022Behavior =
+    target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
+    target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
+  if (!newCMP0022Behavior) {
+    std::ostringstream w;
+    if (type == cmExportBuildAndroidMKGenerator::BUILD) {
+      w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
+    } else {
+      w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
+    }
+    w << " set to OLD for target " << target->Target->GetName() << ". "
+      << "The export will only work with CMP0022 set to NEW.";
+    target->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+  }
+  if (!properties.empty()) {
+    os << "LOCAL_CPP_FEATURES := rtti exceptions\n";
+    for (ImportPropertyMap::const_iterator pi = properties.begin();
+         pi != properties.end(); ++pi) {
+      if (pi->first == "INTERFACE_COMPILE_OPTIONS") {
+        os << "LOCAL_CPP_FEATURES += ";
+        os << (pi->second) << "\n";
+      } else if (pi->first == "INTERFACE_LINK_LIBRARIES") {
+        // need to look at list in pi->second and see if static or shared
+        // FindTargetToLink
+        // target->GetLocalGenerator()->FindGeneratorTargetToUse()
+        // then add to LOCAL_CPPFLAGS
+        std::vector<std::string> libraries;
+        cmSystemTools::ExpandListArgument(pi->second, libraries);
+        std::string staticLibs;
+        std::string sharedLibs;
+        std::string ldlibs;
+        for (std::vector<std::string>::iterator i = libraries.begin();
+             i != libraries.end(); ++i) {
+          cmGeneratorTarget* gt =
+            target->GetLocalGenerator()->FindGeneratorTargetToUse(*i);
+          if (gt) {
+
+            if (gt->GetType() == cmState::SHARED_LIBRARY ||
+                gt->GetType() == cmState::MODULE_LIBRARY) {
+              sharedLibs += " " + *i;
+            } else {
+              staticLibs += " " + *i;
+            }
+          } else {
+            // evaluate any generator expressions with the current
+            // build type of the makefile
+            cmGeneratorExpression ge;
+            CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = ge.Parse(*i);
+            std::string evaluated =
+              cge->Evaluate(target->GetLocalGenerator(), config);
+            bool relpath = false;
+            if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
+              relpath = i->substr(0, 3) == "../";
+            }
+            // check for full path or if it already has a -l, or
+            // in the case of an install check for relative paths
+            // if it is full or a link library then use string directly
+            if (cmSystemTools::FileIsFullPath(evaluated) ||
+                evaluated.substr(0, 2) == "-l" || relpath) {
+              ldlibs += " " + evaluated;
+              // if it is not a path and does not have a -l then add -l
+            } else if (!evaluated.empty()) {
+              ldlibs += " -l" + evaluated;
+            }
+          }
+        }
+        if (!sharedLibs.empty()) {
+          os << "LOCAL_SHARED_LIBRARIES :=" << sharedLibs << "\n";
+        }
+        if (!staticLibs.empty()) {
+          os << "LOCAL_STATIC_LIBRARIES :=" << staticLibs << "\n";
+        }
+        if (!ldlibs.empty()) {
+          os << "LOCAL_EXPORT_LDLIBS :=" << ldlibs << "\n";
+        }
+      } else if (pi->first == "INTERFACE_INCLUDE_DIRECTORIES") {
+        std::string includes = pi->second;
+        std::vector<std::string> includeList;
+        cmSystemTools::ExpandListArgument(includes, includeList);
+        os << "LOCAL_EXPORT_C_INCLUDES := ";
+        std::string end;
+        for (std::vector<std::string>::iterator i = includeList.begin();
+             i != includeList.end(); ++i) {
+          os << end << *i;
+          end = "\\\n";
+        }
+        os << "\n";
+      } else {
+        os << "# " << pi->first << " " << (pi->second) << "\n";
+      }
+    }
+  }
+  switch (target->GetType()) {
+    case cmState::SHARED_LIBRARY:
+    case cmState::MODULE_LIBRARY:
+      os << "include $(PREBUILT_SHARED_LIBRARY)\n";
+      break;
+    case cmState::STATIC_LIBRARY:
+      os << "include $(PREBUILT_STATIC_LIBRARY)\n";
+      break;
+    case cmState::EXECUTABLE:
+    case cmState::UTILITY:
+    case cmState::OBJECT_LIBRARY:
+    case cmState::GLOBAL_TARGET:
+    case cmState::INTERFACE_LIBRARY:
+    case cmState::UNKNOWN_LIBRARY:
+      break;
+  }
+  os << "\n";
+}

+ 68 - 0
Source/cmExportBuildAndroidMKGenerator.h

@@ -0,0 +1,68 @@
+/*============================================================================
+  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 cmExportBuildAndroidMKGenerator_h
+#define cmExportBuildAndroidMKGenerator_h
+
+#include "cmExportBuildFileGenerator.h"
+#include "cmListFileCache.h"
+
+class cmExportSet;
+
+/** \class cmExportBuildAndroidMKGenerator
+ * \brief Generate a file exporting targets from a build tree.
+ *
+ * cmExportBuildAndroidMKGenerator generates a file exporting targets from
+ * a build tree.  This exports the targets to the Android ndk build tool
+ * makefile format for prebuilt libraries.
+ *
+ * This is used to implement the EXPORT() command.
+ */
+class cmExportBuildAndroidMKGenerator : public cmExportBuildFileGenerator
+{
+public:
+  cmExportBuildAndroidMKGenerator();
+  // this is so cmExportInstallAndroidMKGenerator can share this
+  // function as they are almost the same
+  enum GenerateType
+  {
+    BUILD,
+    INSTALL
+  };
+  static void GenerateInterfaceProperties(cmGeneratorTarget const* target,
+                                          std::ostream& os,
+                                          const ImportPropertyMap& properties,
+                                          GenerateType type,
+                                          std::string const& config);
+
+protected:
+  // Implement virtual methods from the superclass.
+  virtual void GeneratePolicyHeaderCode(std::ostream&) {}
+  virtual void GeneratePolicyFooterCode(std::ostream&) {}
+  virtual void GenerateImportHeaderCode(std::ostream& os,
+                                        const std::string& config = "");
+  virtual void GenerateImportFooterCode(std::ostream& os);
+  virtual void GenerateImportTargetCode(std::ostream& os,
+                                        const cmGeneratorTarget* target);
+  virtual void GenerateExpectedTargetsCode(std::ostream& os,
+                                           const std::string& expectedTargets);
+  virtual void GenerateImportPropertyCode(std::ostream& os,
+                                          const std::string& config,
+                                          cmGeneratorTarget const* target,
+                                          ImportPropertyMap const& properties);
+  virtual void GenerateMissingTargetsCheckCode(
+    std::ostream& os, const std::vector<std::string>& missingTargets);
+  virtual void GenerateInterfaceProperties(
+    cmGeneratorTarget const* target, std::ostream& os,
+    const ImportPropertyMap& properties);
+};
+
+#endif

+ 15 - 3
Source/cmExportCommand.cxx

@@ -18,6 +18,7 @@
 #include <cmsys/Encoding.hxx>
 #include <cmsys/Encoding.hxx>
 #include <cmsys/RegularExpression.hxx>
 #include <cmsys/RegularExpression.hxx>
 
 
+#include "cmExportBuildAndroidMKGenerator.h"
 #include "cmExportBuildFileGenerator.h"
 #include "cmExportBuildFileGenerator.h"
 
 
 #if defined(__HAIKU__)
 #if defined(__HAIKU__)
@@ -34,6 +35,7 @@ cmExportCommand::cmExportCommand()
   , Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
   , Namespace(&Helper, "NAMESPACE", &ArgumentGroup)
   , Filename(&Helper, "FILE", &ArgumentGroup)
   , Filename(&Helper, "FILE", &ArgumentGroup)
   , ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
   , ExportOld(&Helper, "EXPORT_LINK_INTERFACE_LIBRARIES", &ArgumentGroup)
+  , AndroidMKFile(&Helper, "ANDROID_MK")
 {
 {
   this->ExportSet = CM_NULLPTR;
   this->ExportSet = CM_NULLPTR;
 }
 }
@@ -66,13 +68,18 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
   }
   }
 
 
   std::string fname;
   std::string fname;
-  if (!this->Filename.WasFound()) {
+  bool android = false;
+  if (this->AndroidMKFile.WasFound()) {
+    fname = this->AndroidMKFile.GetString();
+    android = true;
+  }
+  if (!this->Filename.WasFound() && fname.empty()) {
     if (args[0] != "EXPORT") {
     if (args[0] != "EXPORT") {
       this->SetError("FILE <filename> option missing.");
       this->SetError("FILE <filename> option missing.");
       return false;
       return false;
     }
     }
     fname = this->ExportSetName.GetString() + ".cmake";
     fname = this->ExportSetName.GetString() + ".cmake";
-  } else {
+  } else if (fname.empty()) {
     // Make sure the file has a .cmake extension.
     // Make sure the file has a .cmake extension.
     if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
     if (cmSystemTools::GetFilenameLastExtension(this->Filename.GetCString()) !=
         ".cmake") {
         ".cmake") {
@@ -176,7 +183,12 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
   }
   }
 
 
   // Setup export file generation.
   // Setup export file generation.
-  cmExportBuildFileGenerator* ebfg = new cmExportBuildFileGenerator;
+  cmExportBuildFileGenerator* ebfg = CM_NULLPTR;
+  if (android) {
+    ebfg = new cmExportBuildAndroidMKGenerator;
+  } else {
+    ebfg = new cmExportBuildFileGenerator;
+  }
   ebfg->SetExportFile(fname.c_str());
   ebfg->SetExportFile(fname.c_str());
   ebfg->SetNamespace(this->Namespace.GetCString());
   ebfg->SetNamespace(this->Namespace.GetCString());
   ebfg->SetAppendMode(this->Append.IsEnabled());
   ebfg->SetAppendMode(this->Append.IsEnabled());

+ 1 - 0
Source/cmExportCommand.h

@@ -54,6 +54,7 @@ private:
   cmCAString Namespace;
   cmCAString Namespace;
   cmCAString Filename;
   cmCAString Filename;
   cmCAEnabler ExportOld;
   cmCAEnabler ExportOld;
+  cmCAString AndroidMKFile;
 
 
   cmExportSet* ExportSet;
   cmExportSet* ExportSet;
 
 

+ 146 - 0
Source/cmExportInstallAndroidMKGenerator.cxx

@@ -0,0 +1,146 @@
+/*============================================================================
+  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 "cmExportInstallAndroidMKGenerator.h"
+
+#include "cmAlgorithms.h"
+#include "cmExportBuildAndroidMKGenerator.h"
+#include "cmExportSet.h"
+#include "cmExportSetMap.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmTargetExport.h"
+
+cmExportInstallAndroidMKGenerator::cmExportInstallAndroidMKGenerator(
+  cmInstallExportGenerator* iegen)
+  : cmExportInstallFileGenerator(iegen)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportHeaderCode(
+  std::ostream& os, const std::string&)
+{
+  std::string installDir = this->IEGen->GetDestination();
+  os << "LOCAL_PATH := $(call my-dir)\n";
+  size_t numDotDot = cmSystemTools::CountChar(installDir.c_str(), '/');
+  numDotDot += (installDir.size() > 0) ? 1 : 0;
+  std::string path;
+  for (size_t n = 0; n < numDotDot; n++) {
+    path += "/..";
+  }
+  os << "_IMPORT_PREFIX := "
+     << "$(LOCAL_PATH)" << path << "\n\n";
+  for (std::vector<cmTargetExport*>::const_iterator tei =
+         this->IEGen->GetExportSet()->GetTargetExports()->begin();
+       tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei) {
+    // Collect import properties for this target.
+    cmTargetExport const* te = *tei;
+    if (te->Target->GetType() == cmState::INTERFACE_LIBRARY) {
+      continue;
+    }
+    std::string dest;
+    if (te->LibraryGenerator) {
+      dest = te->LibraryGenerator->GetDestination("");
+    }
+    if (te->ArchiveGenerator) {
+      dest = te->ArchiveGenerator->GetDestination("");
+    }
+    te->Target->Target->SetProperty("__dest", dest.c_str());
+  }
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
+  std::ostream& os, const cmGeneratorTarget* target)
+{
+  std::string targetName = this->Namespace;
+  targetName += target->GetExportName();
+  os << "include $(CLEAR_VARS)\n";
+  os << "LOCAL_MODULE := ";
+  os << targetName << "\n";
+  os << "LOCAL_SRC_FILES := $(_IMPORT_PREFIX)/";
+  os << target->Target->GetProperty("__dest") << "/";
+  std::string config = "";
+  if (this->Configurations.size()) {
+    config = this->Configurations[0];
+  }
+  os << target->GetFullName(config) << "\n";
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateExpectedTargetsCode(
+  std::ostream&, const std::string&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPropertyCode(
+  std::ostream&, const std::string&, cmGeneratorTarget const*,
+  ImportPropertyMap const&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateMissingTargetsCheckCode(
+  std::ostream&, const std::vector<std::string>&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateInterfaceProperties(
+  cmGeneratorTarget const* target, std::ostream& os,
+  const ImportPropertyMap& properties)
+{
+  std::string config = "";
+  if (this->Configurations.size()) {
+    config = this->Configurations[0];
+  }
+  cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
+    target, os, properties, cmExportBuildAndroidMKGenerator::INSTALL, config);
+}
+
+void cmExportInstallAndroidMKGenerator::LoadConfigFiles(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportPrefix(std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateRequiredCMakeVersion(
+  std::ostream&, const char*)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::CleanupTemporaryVariables(
+  std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileCheckLoop(
+  std::ostream&)
+{
+}
+
+void cmExportInstallAndroidMKGenerator::GenerateImportedFileChecksCode(
+  std::ostream&, cmGeneratorTarget*, ImportPropertyMap const&,
+  const std::set<std::string>&)
+{
+}
+
+bool cmExportInstallAndroidMKGenerator::GenerateImportFileConfig(
+  const std::string&, std::vector<std::string>&)
+{
+  return true;
+}

+ 72 - 0
Source/cmExportInstallAndroidMKGenerator.h

@@ -0,0 +1,72 @@
+/*============================================================================
+  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 cmExportInstallAndroidMKGenerator_h
+#define cmExportInstallAndroidMKGenerator_h
+
+#include "cmExportInstallFileGenerator.h"
+
+class cmInstallExportGenerator;
+class cmInstallTargetGenerator;
+
+/** \class cmExportInstallAndroidMKGenerator
+ * \brief Generate a file exporting targets from an install tree.
+ *
+ * cmExportInstallAndroidMKGenerator generates files exporting targets from
+ * install an installation tree.  The files are placed in a temporary
+ * location for installation by cmInstallExportGenerator.  The file format
+ * is for the ndk build system and is a makefile fragment specifing prebuilt
+ * libraries to the ndk build system.
+ *
+ * This is used to implement the INSTALL(EXPORT_ANDROID_MK) command.
+ */
+class cmExportInstallAndroidMKGenerator : public cmExportInstallFileGenerator
+{
+public:
+  /** Construct with the export installer that will install the
+      files.  */
+  cmExportInstallAndroidMKGenerator(cmInstallExportGenerator* iegen);
+
+protected:
+  // Implement virtual methods from the superclass.
+  virtual void GeneratePolicyHeaderCode(std::ostream&) {}
+  virtual void GeneratePolicyFooterCode(std::ostream&) {}
+  virtual void GenerateImportHeaderCode(std::ostream& os,
+                                        const std::string& config = "");
+  virtual void GenerateImportFooterCode(std::ostream& os);
+  virtual void GenerateImportTargetCode(std::ostream& os,
+                                        const cmGeneratorTarget* target);
+  virtual void GenerateExpectedTargetsCode(std::ostream& os,
+                                           const std::string& expectedTargets);
+  virtual void GenerateImportPropertyCode(std::ostream& os,
+                                          const std::string& config,
+                                          cmGeneratorTarget const* target,
+                                          ImportPropertyMap const& properties);
+  virtual void GenerateMissingTargetsCheckCode(
+    std::ostream& os, const std::vector<std::string>& missingTargets);
+  virtual void GenerateInterfaceProperties(
+    cmGeneratorTarget const* target, std::ostream& os,
+    const ImportPropertyMap& properties);
+  virtual void GenerateImportPrefix(std::ostream& os);
+  virtual void LoadConfigFiles(std::ostream&);
+  virtual void GenerateRequiredCMakeVersion(std::ostream& os,
+                                            const char* versionString);
+  virtual void CleanupTemporaryVariables(std::ostream&);
+  virtual void GenerateImportedFileCheckLoop(std::ostream& os);
+  virtual void GenerateImportedFileChecksCode(
+    std::ostream& os, cmGeneratorTarget* target,
+    ImportPropertyMap const& properties,
+    const std::set<std::string>& importedLocations);
+  virtual bool GenerateImportFileConfig(const std::string& config,
+                                        std::vector<std::string>&);
+};
+
+#endif

+ 97 - 1
Source/cmInstallCommand.cxx

@@ -83,6 +83,8 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
     return this->HandleDirectoryMode(args);
     return this->HandleDirectoryMode(args);
   } else if (args[0] == "EXPORT") {
   } else if (args[0] == "EXPORT") {
     return this->HandleExportMode(args);
     return this->HandleExportMode(args);
+  } else if (args[0] == "EXPORT_ANDROID_MK") {
+    return this->HandleExportAndroidMKMode(args);
   }
   }
 
 
   // Unknown mode.
   // Unknown mode.
@@ -1097,6 +1099,100 @@ bool cmInstallCommand::HandleDirectoryMode(
   return true;
   return true;
 }
 }
 
 
+bool cmInstallCommand::HandleExportAndroidMKMode(
+  std::vector<std::string> const& args)
+{
+#ifdef CMAKE_BUILD_WITH_CMAKE
+  // This is the EXPORT mode.
+  cmInstallCommandArguments ica(this->DefaultComponentName);
+  cmCAString exp(&ica.Parser, "EXPORT_ANDROID_MK");
+  cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
+  cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
+                        &ica.ArgumentGroup);
+  cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
+  exp.Follows(0);
+
+  ica.ArgumentGroup.Follows(&exp);
+  std::vector<std::string> unknownArgs;
+  ica.Parse(&args, &unknownArgs);
+
+  if (!unknownArgs.empty()) {
+    // Unknown argument.
+    std::ostringstream e;
+    e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
+    this->SetError(e.str());
+    return false;
+  }
+
+  if (!ica.Finalize()) {
+    return false;
+  }
+
+  // Make sure there is a destination.
+  if (ica.GetDestination().empty()) {
+    // A destination is required.
+    std::ostringstream e;
+    e << args[0] << " given no DESTINATION!";
+    this->SetError(e.str());
+    return false;
+  }
+
+  // Check the file name.
+  std::string fname = filename.GetString();
+  if (fname.find_first_of(":/\\") != fname.npos) {
+    std::ostringstream e;
+    e << args[0] << " given invalid export file name \"" << fname << "\".  "
+      << "The FILE argument may not contain a path.  "
+      << "Specify the path in the DESTINATION argument.";
+    this->SetError(e.str());
+    return false;
+  }
+
+  // Check the file extension.
+  if (!fname.empty() &&
+      cmSystemTools::GetFilenameLastExtension(fname) != ".mk") {
+    std::ostringstream e;
+    e << args[0] << " given invalid export file name \"" << fname << "\".  "
+      << "The FILE argument must specify a name ending in \".mk\".";
+    this->SetError(e.str());
+    return false;
+  }
+  if (fname.find_first_of(":/\\") != fname.npos) {
+    std::ostringstream e;
+    e << args[0] << " given export name \"" << exp.GetString() << "\".  "
+      << "This name cannot be safely converted to a file name.  "
+      << "Specify a different export name or use the FILE option to set "
+      << "a file name explicitly.";
+    this->SetError(e.str());
+    return false;
+  }
+  // Use the default name
+  if (fname.empty()) {
+    fname = "Android.mk";
+  }
+
+  cmExportSet* exportSet =
+    this->Makefile->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
+
+  cmInstallGenerator::MessageLevel message =
+    cmInstallGenerator::SelectMessageLevel(this->Makefile);
+
+  // Create the export install generator.
+  cmInstallExportGenerator* exportGenerator = new cmInstallExportGenerator(
+    exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
+    ica.GetConfigurations(), ica.GetComponent().c_str(), message,
+    ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
+    exportOld.IsEnabled(), true);
+  this->Makefile->AddInstallGenerator(exportGenerator);
+
+  return true;
+#else
+  static_cast<void>(args);
+  this->SetError("EXPORT_ANDROID_MK not supported in bootstrap cmake");
+  return false;
+#endif
+}
+
 bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 {
 {
   // This is the EXPORT mode.
   // This is the EXPORT mode.
@@ -1203,7 +1299,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
     exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
     exportSet, ica.GetDestination().c_str(), ica.GetPermissions().c_str(),
     ica.GetConfigurations(), ica.GetComponent().c_str(), message,
     ica.GetConfigurations(), ica.GetComponent().c_str(), message,
     ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
     ica.GetExcludeFromAll(), fname.c_str(), name_space.GetCString(),
-    exportOld.IsEnabled());
+    exportOld.IsEnabled(), false);
   this->Makefile->AddInstallGenerator(exportGenerator);
   this->Makefile->AddInstallGenerator(exportGenerator);
 
 
   return true;
   return true;

+ 1 - 0
Source/cmInstallCommand.h

@@ -48,6 +48,7 @@ private:
   bool HandleFilesMode(std::vector<std::string> const& args);
   bool HandleFilesMode(std::vector<std::string> const& args);
   bool HandleDirectoryMode(std::vector<std::string> const& args);
   bool HandleDirectoryMode(std::vector<std::string> const& args);
   bool HandleExportMode(std::vector<std::string> const& args);
   bool HandleExportMode(std::vector<std::string> const& args);
+  bool HandleExportAndroidMKMode(std::vector<std::string> const& args);
   bool MakeFilesFullPath(const char* modeName,
   bool MakeFilesFullPath(const char* modeName,
                          const std::vector<std::string>& relFiles,
                          const std::vector<std::string>& relFiles,
                          std::vector<std::string>& absFiles);
                          std::vector<std::string>& absFiles);

+ 149 - 0
Source/cmInstallExportAndroidMKGenerator.cxx

@@ -0,0 +1,149 @@
+
+/*============================================================================
+  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 "cmInstallExportAndroidMKGenerator.h"
+
+#include <stdio.h>
+
+#include "cmExportInstallFileGenerator.h"
+#include "cmExportSet.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallFilesGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmake.h"
+
+cmInstallExportAndroidMKGenerator::cmInstallExportAndroidMKGenerator(
+  cmExportSet* exportSet, const char* destination,
+  const char* file_permissions, std::vector<std::string> const& configurations,
+  const char* component, MessageLevel message, bool exclude_from_all,
+  const char* filename, const char* name_space, bool exportOld)
+  : cmInstallExportGenerator(exportSet, destination, file_permissions,
+                             configurations, component, message,
+                             exclude_from_all, filename, name_space, exportOld)
+{
+}
+
+cmInstallExportAndroidMKGenerator::~cmInstallExportAndroidMKGenerator()
+{
+}
+
+void cmInstallExportAndroidMKGenerator::Compute(cmLocalGenerator* lg)
+{
+  this->LocalGenerator = lg;
+  this->ExportSet->Compute(lg);
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScript(std::ostream& os)
+{
+  // Skip empty sets.
+  if (ExportSet->GetTargetExports()->empty()) {
+    std::ostringstream e;
+    e << "INSTALL(EXPORT) given unknown export \"" << ExportSet->GetName()
+      << "\"";
+    cmSystemTools::Error(e.str().c_str());
+    return;
+  }
+
+  // Create the temporary directory in which to store the files.
+  this->ComputeTempDir();
+  cmSystemTools::MakeDirectory(this->TempDir.c_str());
+
+  // Construct a temporary location for the file.
+  this->MainImportFile = this->TempDir;
+  this->MainImportFile += "/";
+  this->MainImportFile += this->FileName;
+
+  // Generate the import file for this export set.
+  this->EFGen->SetExportFile(this->MainImportFile.c_str());
+  this->EFGen->SetNamespace(this->Namespace);
+  this->EFGen->SetExportOld(this->ExportOld);
+  if (this->ConfigurationTypes->empty()) {
+    if (!this->ConfigurationName.empty()) {
+      this->EFGen->AddConfiguration(this->ConfigurationName);
+    } else {
+      this->EFGen->AddConfiguration("");
+    }
+  } else {
+    for (std::vector<std::string>::const_iterator ci =
+           this->ConfigurationTypes->begin();
+         ci != this->ConfigurationTypes->end(); ++ci) {
+      this->EFGen->AddConfiguration(*ci);
+    }
+  }
+  this->EFGen->GenerateImportFile();
+
+  // Perform the main install script generation.
+  this->cmInstallGenerator::GenerateScript(os);
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScriptConfigs(
+  std::ostream& os, Indent const& indent)
+{
+  // Create the main install rules first.
+  this->cmInstallGenerator::GenerateScriptConfigs(os, indent);
+
+  // Now create a configuration-specific install rule for the import
+  // file of each configuration.
+  std::vector<std::string> files;
+  for (std::map<std::string, std::string>::const_iterator i =
+         this->EFGen->GetConfigImportFiles().begin();
+       i != this->EFGen->GetConfigImportFiles().end(); ++i) {
+    files.push_back(i->second);
+    std::string config_test = this->CreateConfigTest(i->first);
+    os << indent << "if(" << config_test << ")\n";
+    this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
+                         false, this->FilePermissions.c_str(), CM_NULLPTR,
+                         CM_NULLPTR, CM_NULLPTR, indent.Next());
+    os << indent << "endif()\n";
+    files.clear();
+  }
+}
+
+void cmInstallExportAndroidMKGenerator::GenerateScriptActions(
+  std::ostream& os, Indent const& indent)
+{
+  // Remove old per-configuration export files if the main changes.
+  std::string installedDir = "$ENV{DESTDIR}";
+  installedDir += this->ConvertToAbsoluteDestination(this->Destination);
+  installedDir += "/";
+  std::string installedFile = installedDir;
+  installedFile += this->FileName;
+  os << indent << "if(EXISTS \"" << installedFile << "\")\n";
+  Indent indentN = indent.Next();
+  Indent indentNN = indentN.Next();
+  Indent indentNNN = indentNN.Next();
+  /* clang-format off */
+  os << indentN << "file(DIFFERENT EXPORT_FILE_CHANGED FILES\n"
+     << indentN << "     \"" << installedFile << "\"\n"
+     << indentN << "     \"" << this->MainImportFile << "\")\n";
+  os << indentN << "if(EXPORT_FILE_CHANGED)\n";
+  os << indentNN << "file(GLOB OLD_CONFIG_FILES \"" << installedDir
+     << this->EFGen->GetConfigImportFileGlob() << "\")\n";
+  os << indentNN << "if(OLD_CONFIG_FILES)\n";
+  os << indentNNN << "message(STATUS \"Old export file \\\"" << installedFile
+     << "\\\" will be replaced.  Removing files [${OLD_CONFIG_FILES}].\")\n";
+  os << indentNNN << "file(REMOVE ${OLD_CONFIG_FILES})\n";
+  os << indentNN << "endif()\n";
+  os << indentN << "endif()\n";
+  os << indent << "endif()\n";
+  /* clang-format on */
+
+  // Install the main export file.
+  std::vector<std::string> files;
+  files.push_back(this->MainImportFile);
+  this->AddInstallRule(os, this->Destination, cmInstallType_FILES, files,
+                       false, this->FilePermissions.c_str(), CM_NULLPTR,
+                       CM_NULLPTR, CM_NULLPTR, indent);
+}

+ 46 - 0
Source/cmInstallExportAndroidMKGenerator.h

@@ -0,0 +1,46 @@
+/*============================================================================
+  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 cmInstallExportAndroidMKGenerator_h
+#define cmInstallExportAndroidMKGenerator_h
+
+#include "cmInstallExportGenerator.h"
+
+class cmExportInstallFileGenerator;
+class cmInstallFilesGenerator;
+class cmInstallTargetGenerator;
+class cmExportSet;
+class cmMakefile;
+
+/** \class cmInstallExportAndroidMKGenerator
+ * \brief Generate rules for creating an export files.
+ */
+class cmInstallExportAndroidMKGenerator : public cmInstallExportGenerator
+{
+public:
+  cmInstallExportAndroidMKGenerator(
+    cmExportSet* exportSet, const char* dest, const char* file_permissions,
+    const std::vector<std::string>& configurations, const char* component,
+    MessageLevel message, bool exclude_from_all, const char* filename,
+    const char* name_space, bool exportOld);
+  ~cmInstallExportAndroidMKGenerator();
+
+  void Compute(cmLocalGenerator* lg);
+
+protected:
+  virtual void GenerateScript(std::ostream& os);
+  virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
+  virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
+  void GenerateImportFile(cmExportSet const* exportSet);
+  void GenerateImportFile(const char* config, cmExportSet const* exportSet);
+};
+
+#endif

+ 11 - 2
Source/cmInstallExportGenerator.cxx

@@ -16,6 +16,9 @@
 #include <sstream>
 #include <sstream>
 #include <utility>
 #include <utility>
 
 
+#ifdef CMAKE_BUILD_WITH_CMAKE
+#include "cmExportInstallAndroidMKGenerator.h"
+#endif
 #include "cmExportInstallFileGenerator.h"
 #include "cmExportInstallFileGenerator.h"
 #include "cmExportSet.h"
 #include "cmExportSet.h"
 #include "cmInstallType.h"
 #include "cmInstallType.h"
@@ -27,7 +30,7 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   cmExportSet* exportSet, const char* destination,
   cmExportSet* exportSet, const char* destination,
   const char* file_permissions, std::vector<std::string> const& configurations,
   const char* file_permissions, std::vector<std::string> const& configurations,
   const char* component, MessageLevel message, bool exclude_from_all,
   const char* component, MessageLevel message, bool exclude_from_all,
-  const char* filename, const char* name_space, bool exportOld)
+  const char* filename, const char* name_space, bool exportOld, bool android)
   : cmInstallGenerator(destination, configurations, component, message,
   : cmInstallGenerator(destination, configurations, component, message,
                        exclude_from_all)
                        exclude_from_all)
   , ExportSet(exportSet)
   , ExportSet(exportSet)
@@ -37,7 +40,13 @@ cmInstallExportGenerator::cmInstallExportGenerator(
   , ExportOld(exportOld)
   , ExportOld(exportOld)
   , LocalGenerator(CM_NULLPTR)
   , LocalGenerator(CM_NULLPTR)
 {
 {
-  this->EFGen = new cmExportInstallFileGenerator(this);
+  if (android) {
+#ifdef CMAKE_BUILD_WITH_CMAKE
+    this->EFGen = new cmExportInstallAndroidMKGenerator(this);
+#endif
+  } else {
+    this->EFGen = new cmExportInstallFileGenerator(this);
+  }
   exportSet->AddInstallation(this);
   exportSet->AddInstallation(this);
 }
 }
 
 

+ 2 - 1
Source/cmInstallExportGenerator.h

@@ -37,7 +37,8 @@ public:
                            const std::vector<std::string>& configurations,
                            const std::vector<std::string>& configurations,
                            const char* component, MessageLevel message,
                            const char* component, MessageLevel message,
                            bool exclude_from_all, const char* filename,
                            bool exclude_from_all, const char* filename,
-                           const char* name_space, bool exportOld);
+                           const char* name_space, bool exportOld,
+                           bool android);
   ~cmInstallExportGenerator() CM_OVERRIDE;
   ~cmInstallExportGenerator() CM_OVERRIDE;
 
 
   cmExportSet* GetExportSet() { return this->ExportSet; }
   cmExportSet* GetExportSet() { return this->ExportSet; }

+ 30 - 0
Tests/RunCMake/AndroidMK/AndroidMK-check.cmake

@@ -0,0 +1,30 @@
+# This file does a regex file compare on the generated
+# Android.mk files from the AndroidMK test
+
+macro(compare_file_to_expected file expected_file)
+  file(READ "${file}" ANDROID_MK)
+  # clean up new lines
+  string(REGEX REPLACE "\r\n" "\n" ANDROID_MK "${ANDROID_MK}")
+  string(REGEX REPLACE "\n+$" "" ANDROID_MK "${ANDROID_MK}")
+  # read in the expected regex file
+  file(READ "${expected_file}" expected)
+  # clean up new lines
+  string(REGEX REPLACE "\r\n" "\n" expected "${expected}")
+  string(REGEX REPLACE "\n+$" "" expected "${expected}")
+  # compare the file to the expected regex and if there is not a match
+  # put an error message in RunCMake_TEST_FAILED
+  if(NOT "${ANDROID_MK}" MATCHES "${expected}")
+    set(RunCMake_TEST_FAILED
+      "${file} does not match ${expected_file}:
+
+Android.mk contents = [\n${ANDROID_MK}\n]
+Expected = [\n${expected}\n]")
+  endif()
+endmacro()
+
+compare_file_to_expected(
+"${RunCMake_BINARY_DIR}/AndroidMK-build/Android.mk"
+"${RunCMake_TEST_SOURCE_DIR}/expectedBuildAndroidMK.txt")
+compare_file_to_expected(
+"${RunCMake_BINARY_DIR}/AndroidMK-build/CMakeFiles/Export/share/ndk-modules/Android.mk"
+"${RunCMake_TEST_SOURCE_DIR}/expectedInstallAndroidMK.txt")

+ 11 - 0
Tests/RunCMake/AndroidMK/AndroidMK.cmake

@@ -0,0 +1,11 @@
+project(build)
+set(CMAKE_BUILD_TYPE Debug)
+add_library(foo foo.cxx)
+add_library(car foo.cxx)
+add_library(bar  foo.cxx)
+add_library(dog  foo.cxx)
+target_link_libraries(foo car bar dog debug -lm)
+export(TARGETS bar dog car foo  ANDROID_MK
+  ${build_BINARY_DIR}/Android.mk)
+install(TARGETS bar dog car foo DESTINATION lib EXPORT myexp)
+install(EXPORT_ANDROID_MK myexp DESTINATION share/ndk-modules)

+ 3 - 0
Tests/RunCMake/AndroidMK/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.5)
+project(${RunCMake_TEST} NONE) # or languages needed
+include(${RunCMake_TEST}.cmake)

+ 2 - 0
Tests/RunCMake/AndroidMK/RunCMakeTest.cmake

@@ -0,0 +1,2 @@
+include(RunCMake)
+run_cmake(AndroidMK)

+ 23 - 0
Tests/RunCMake/AndroidMK/expectedBuildAndroidMK.txt

@@ -0,0 +1,23 @@
+LOCAL_PATH.*call my-dir.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*bar
+LOCAL_SRC_FILES.*bar.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*dog
+LOCAL_SRC_FILES.*.*dog.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*car
+LOCAL_SRC_FILES.*.*car.*
+include.*PREBUILT_STATIC_LIBRARY.*
+.*
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo
+LOCAL_SRC_FILES.*.*foo.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_STATIC_LIBRARIES.*car bar dog
+LOCAL_EXPORT_LDLIBS := -lm
+include.*PREBUILT_STATIC_LIBRARY.*

+ 25 - 0
Tests/RunCMake/AndroidMK/expectedInstallAndroidMK.txt

@@ -0,0 +1,25 @@
+LOCAL_PATH.*call my-dir.*
+_IMPORT_PREFIX.*LOCAL_PATH./../..
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*bar
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*bar.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.
+LOCAL_MODULE.*dog
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*dog.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*car
+LOCAL_SRC_FILES.*_IMPORT_PREFIX./lib.*car.*
+include.*PREBUILT_STATIC_LIBRARY.*
+
+include.*CLEAR_VARS.*
+LOCAL_MODULE.*foo
+LOCAL_SRC_FILES.*_IMPORT_PREFIX\)/lib.*foo.*
+LOCAL_CPP_FEATURES.*rtti exceptions
+LOCAL_STATIC_LIBRARIES.*car bar dog
+LOCAL_EXPORT_LDLIBS := -lm
+include.*PREBUILT_STATIC_LIBRARY.*

+ 3 - 0
Tests/RunCMake/AndroidMK/foo.cxx

@@ -0,0 +1,3 @@
+void foo()
+{
+}

+ 2 - 0
Tests/RunCMake/CMakeLists.txt

@@ -331,6 +331,8 @@ add_RunCMake_test_group(CPack "DEB;RPM;TGZ")
 # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
 # for MSVC compilers CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS property is used
 add_RunCMake_test(AutoExportDll)
 add_RunCMake_test(AutoExportDll)
 
 
+add_RunCMake_test(AndroidMK)
+
 if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN)
 if(CMake_TEST_ANDROID_NDK OR CMake_TEST_ANDROID_STANDALONE_TOOLCHAIN)
   if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
   if(NOT "${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
     message(FATAL_ERROR "Android tests supported only by Makefile and Ninja generators")
     message(FATAL_ERROR "Android tests supported only by Makefile and Ninja generators")