/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmExportAndroidMKGenerator.h" #include #include #include #include #include #include "cmGeneratorTarget.h" #include "cmLinkItem.h" #include "cmList.h" #include "cmMakefile.h" #include "cmMessageType.h" #include "cmPolicies.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" cmExportAndroidMKGenerator::cmExportAndroidMKGenerator() = default; cm::string_view cmExportAndroidMKGenerator::GetImportPrefixWithSlash() const { return "$(_IMPORT_PREFIX)/"_s; } bool cmExportAndroidMKGenerator::GenerateImportFile(std::ostream& os) { if (!this->AppendMode) { // Start with the import file header. this->GenerateImportHeaderCode(os); } // Create all the imported targets. std::stringstream mainFileBuffer; bool result = this->GenerateMainFile(mainFileBuffer); // Write cached import code. os << mainFileBuffer.rdbuf(); return result; } void cmExportAndroidMKGenerator::GenerateInterfaceProperties( cmGeneratorTarget const* target, std::ostream& os, ImportPropertyMap const& properties) { std::string const config = (this->Configurations.empty() ? std::string{} : this->Configurations[0]); GenerateType const type = this->GetGenerateType(); bool const newCMP0022Behavior = target->GetPolicyStatusCMP0022() != cmPolicies::WARN && target->GetPolicyStatusCMP0022() != cmPolicies::OLD; if (!newCMP0022Behavior) { std::ostringstream w; if (type == 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(MessageType::AUTHOR_WARNING, w.str()); } if (!properties.empty()) { os << "LOCAL_CPP_FEATURES := rtti exceptions\n"; for (auto const& property : properties) { if (property.first == "INTERFACE_COMPILE_OPTIONS") { os << "LOCAL_CPP_FEATURES += "; os << (property.second) << "\n"; } else if (property.first == "INTERFACE_LINK_LIBRARIES") { std::string staticLibs; std::string sharedLibs; std::string ldlibs; cmLinkInterfaceLibraries const* linkIFace = target->GetLinkInterfaceLibraries(config, target, cmGeneratorTarget::UseTo::Link); for (cmLinkItem const& item : linkIFace->Libraries) { cmGeneratorTarget const* gt = item.Target; std::string const& lib = item.AsStr(); if (gt) { if (gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { sharedLibs += " " + lib; } else { staticLibs += " " + lib; } } else { bool relpath = false; if (type == INSTALL) { relpath = cmHasLiteralPrefix(lib, "../"); } // 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(lib) || cmHasLiteralPrefix(lib, "-l") || relpath) { ldlibs += " " + lib; // if it is not a path and does not have a -l then add -l } else if (!lib.empty()) { ldlibs += " -l" + lib; } } } 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 (property.first == "INTERFACE_INCLUDE_DIRECTORIES") { std::string includes = property.second; cmList includeList{ includes }; os << "LOCAL_EXPORT_C_INCLUDES := "; std::string end; for (std::string const& i : includeList) { os << end << i; end = "\\\n"; } os << "\n"; } else if (property.first == "INTERFACE_LINK_OPTIONS") { os << "LOCAL_EXPORT_LDFLAGS := "; cmList linkFlagsList{ property.second }; os << linkFlagsList.join(" ") << "\n"; } else { os << "# " << property.first << " " << (property.second) << "\n"; } } } // Tell the NDK build system if prebuilt static libraries use C++. if (target->GetType() == cmStateEnums::STATIC_LIBRARY) { cmLinkImplementation const* li = target->GetLinkImplementation(config, cmGeneratorTarget::UseTo::Link); if (cm::contains(li->Languages, "CXX")) { os << "LOCAL_HAS_CPP := true\n"; } } switch (target->GetType()) { case cmStateEnums::SHARED_LIBRARY: case cmStateEnums::MODULE_LIBRARY: os << "include $(PREBUILT_SHARED_LIBRARY)\n"; break; case cmStateEnums::STATIC_LIBRARY: os << "include $(PREBUILT_STATIC_LIBRARY)\n"; break; case cmStateEnums::EXECUTABLE: case cmStateEnums::UTILITY: case cmStateEnums::OBJECT_LIBRARY: case cmStateEnums::GLOBAL_TARGET: case cmStateEnums::INTERFACE_LIBRARY: case cmStateEnums::UNKNOWN_LIBRARY: break; } os << "\n"; }