mirror of
https://github.com/Kitware/CMake.git
synced 2025-06-15 08:30:44 +08:00

If two imported targets in different directories have the same name we should still be able to propagate transitive usage requirements from both. Fix the DAG checker to work with target pointers instead of target names since the pointers will not be duplicated even if the names are. Fixes: #18345
211 lines
7.3 KiB
C++
211 lines
7.3 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
#include "cmExportBuildAndroidMKGenerator.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory> // IWYU pragma: keep
|
|
#include <sstream>
|
|
#include <utility>
|
|
|
|
#include "cmAlgorithms.h"
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmGeneratorExpressionDAGChecker.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmLinkItem.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmPolicies.h"
|
|
#include "cmStateTypes.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmTarget.h"
|
|
#include "cmake.h"
|
|
|
|
cmExportBuildAndroidMKGenerator::cmExportBuildAndroidMKGenerator()
|
|
{
|
|
this->LG = nullptr;
|
|
this->ExportSet = 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, cmGeneratorTarget const* target,
|
|
cmStateEnums::TargetType /*targetType*/)
|
|
{
|
|
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 = cmSystemTools::ConvertToOutputPath(target->GetFullPath());
|
|
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.empty()) {
|
|
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 (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") {
|
|
// evaluate any generator expressions with the current
|
|
// build type of the makefile
|
|
cmGeneratorExpression ge;
|
|
cmGeneratorExpressionDAGChecker dagChecker(
|
|
target, "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
|
|
std::unique_ptr<cmCompiledGeneratorExpression> cge =
|
|
ge.Parse(property.second);
|
|
std::string evaluated = cge->Evaluate(
|
|
target->GetLocalGenerator(), config, false, target, &dagChecker);
|
|
// 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(evaluated, libraries);
|
|
std::string staticLibs;
|
|
std::string sharedLibs;
|
|
std::string ldlibs;
|
|
for (std::string const& lib : libraries) {
|
|
cmGeneratorTarget* gt =
|
|
target->GetLocalGenerator()->FindGeneratorTargetToUse(lib);
|
|
if (gt) {
|
|
|
|
if (gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
|
|
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
|
|
sharedLibs += " " + lib;
|
|
} else {
|
|
staticLibs += " " + lib;
|
|
}
|
|
} else {
|
|
bool relpath = false;
|
|
if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
|
|
relpath = lib.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(lib) ||
|
|
lib.substr(0, 2) == "-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;
|
|
std::vector<std::string> includeList;
|
|
cmSystemTools::ExpandListArgument(includes, includeList);
|
|
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 := ";
|
|
std::vector<std::string> linkFlagsList;
|
|
cmSystemTools::ExpandListArgument(property.second, linkFlagsList);
|
|
os << cmJoin(linkFlagsList, " ") << "\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);
|
|
if (std::find(li->Languages.begin(), li->Languages.end(), "CXX") !=
|
|
li->Languages.end()) {
|
|
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";
|
|
}
|