1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmExportBuildAndroidMKGenerator.h"
9 #include <cmext/algorithm>
11 #include "cmGeneratorTarget.h"
12 #include "cmLinkItem.h"
13 #include "cmMakefile.h"
14 #include "cmMessageType.h"
15 #include "cmPolicies.h"
16 #include "cmStateTypes.h"
17 #include "cmStringAlgorithms.h"
18 #include "cmSystemTools.h"
21 cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
24 this->ExportSet = nullptr;
27 void cmExportBuildAndroidMKGenerator::GenerateImportHeaderCode(
28 std::ostream& os, const std::string&)
30 os << "LOCAL_PATH := $(call my-dir)\n\n";
33 void cmExportBuildAndroidMKGenerator::GenerateImportFooterCode(std::ostream&)
37 void cmExportBuildAndroidMKGenerator::GenerateExpectedTargetsCode(
38 std::ostream&, const std::string&)
42 void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
43 std::ostream& os, cmGeneratorTarget const* target,
44 cmStateEnums::TargetType /*targetType*/)
46 std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
47 os << "include $(CLEAR_VARS)\n";
48 os << "LOCAL_MODULE := ";
49 os << targetName << "\n";
50 os << "LOCAL_SRC_FILES := ";
51 std::string const noConfig; // FIXME: What config to use here?
53 cmSystemTools::ConvertToOutputPath(target->GetFullPath(noConfig));
57 void cmExportBuildAndroidMKGenerator::GenerateImportPropertyCode(
58 std::ostream&, const std::string&, cmGeneratorTarget const*,
59 ImportPropertyMap const&)
63 void cmExportBuildAndroidMKGenerator::GenerateMissingTargetsCheckCode(
68 void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
69 const cmGeneratorTarget* target, std::ostream& os,
70 const ImportPropertyMap& properties)
73 if (!this->Configurations.empty()) {
74 config = this->Configurations[0];
76 cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
77 target, os, properties, cmExportBuildAndroidMKGenerator::BUILD, config);
80 void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
81 const cmGeneratorTarget* target, std::ostream& os,
82 const ImportPropertyMap& properties, GenerateType type,
83 std::string const& config)
85 const bool newCMP0022Behavior =
86 target->GetPolicyStatusCMP0022() != cmPolicies::WARN &&
87 target->GetPolicyStatusCMP0022() != cmPolicies::OLD;
88 if (!newCMP0022Behavior) {
90 if (type == cmExportBuildAndroidMKGenerator::BUILD) {
91 w << "export(TARGETS ... ANDROID_MK) called with policy CMP0022";
93 w << "install( EXPORT_ANDROID_MK ...) called with policy CMP0022";
95 w << " set to OLD for target " << target->Target->GetName() << ". "
96 << "The export will only work with CMP0022 set to NEW.";
97 target->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, w.str());
99 if (!properties.empty()) {
100 os << "LOCAL_CPP_FEATURES := rtti exceptions\n";
101 for (auto const& property : properties) {
102 if (property.first == "INTERFACE_COMPILE_OPTIONS") {
103 os << "LOCAL_CPP_FEATURES += ";
104 os << (property.second) << "\n";
105 } else if (property.first == "INTERFACE_LINK_LIBRARIES") {
106 std::string staticLibs;
107 std::string sharedLibs;
109 cmLinkInterfaceLibraries const* linkIFace =
110 target->GetLinkInterfaceLibraries(
111 config, target, cmGeneratorTarget::LinkInterfaceFor::Link);
112 for (cmLinkItem const& item : linkIFace->Libraries) {
113 cmGeneratorTarget const* gt = item.Target;
114 std::string const& lib = item.AsStr();
117 if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
118 gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
119 sharedLibs += " " + lib;
121 staticLibs += " " + lib;
124 bool relpath = false;
125 if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
126 relpath = cmHasLiteralPrefix(lib, "../");
128 // check for full path or if it already has a -l, or
129 // in the case of an install check for relative paths
130 // if it is full or a link library then use string directly
131 if (cmSystemTools::FileIsFullPath(lib) ||
132 cmHasLiteralPrefix(lib, "-l") || relpath) {
134 // if it is not a path and does not have a -l then add -l
135 } else if (!lib.empty()) {
136 ldlibs += " -l" + lib;
140 if (!sharedLibs.empty()) {
141 os << "LOCAL_SHARED_LIBRARIES :=" << sharedLibs << "\n";
143 if (!staticLibs.empty()) {
144 os << "LOCAL_STATIC_LIBRARIES :=" << staticLibs << "\n";
146 if (!ldlibs.empty()) {
147 os << "LOCAL_EXPORT_LDLIBS :=" << ldlibs << "\n";
149 } else if (property.first == "INTERFACE_INCLUDE_DIRECTORIES") {
150 std::string includes = property.second;
151 std::vector<std::string> includeList = cmExpandedList(includes);
152 os << "LOCAL_EXPORT_C_INCLUDES := ";
154 for (std::string const& i : includeList) {
159 } else if (property.first == "INTERFACE_LINK_OPTIONS") {
160 os << "LOCAL_EXPORT_LDFLAGS := ";
161 std::vector<std::string> linkFlagsList =
162 cmExpandedList(property.second);
163 os << cmJoin(linkFlagsList, " ") << "\n";
165 os << "# " << property.first << " " << (property.second) << "\n";
170 // Tell the NDK build system if prebuilt static libraries use C++.
171 if (target->GetType() == cmStateEnums::STATIC_LIBRARY) {
172 cmLinkImplementation const* li = target->GetLinkImplementation(
173 config, cmGeneratorTarget::LinkInterfaceFor::Link);
174 if (cm::contains(li->Languages, "CXX")) {
175 os << "LOCAL_HAS_CPP := true\n";
179 switch (target->GetType()) {
180 case cmStateEnums::SHARED_LIBRARY:
181 case cmStateEnums::MODULE_LIBRARY:
182 os << "include $(PREBUILT_SHARED_LIBRARY)\n";
184 case cmStateEnums::STATIC_LIBRARY:
185 os << "include $(PREBUILT_STATIC_LIBRARY)\n";
187 case cmStateEnums::EXECUTABLE:
188 case cmStateEnums::UTILITY:
189 case cmStateEnums::OBJECT_LIBRARY:
190 case cmStateEnums::GLOBAL_TARGET:
191 case cmStateEnums::INTERFACE_LIBRARY:
192 case cmStateEnums::UNKNOWN_LIBRARY: