Merge topic 'ALIAS-targets'
370bf55
Add the ALIAS target concept for libraries and executables.
This commit is contained in:
commit
87e0e6e497
|
@ -24,6 +24,13 @@ bool cmAddDependenciesCommand
|
|||
}
|
||||
|
||||
std::string target_name = args[0];
|
||||
if(this->Makefile->IsAlias(target_name.c_str()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "Cannot add target-level dependencies to alias target \""
|
||||
<< target_name << "\".\n";
|
||||
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
||||
}
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(target_name.c_str()))
|
||||
{
|
||||
std::vector<std::string>::const_iterator s = args.begin();
|
||||
|
|
|
@ -30,6 +30,7 @@ bool cmAddExecutableCommand
|
|||
bool excludeFromAll = false;
|
||||
bool importTarget = false;
|
||||
bool importGlobal = false;
|
||||
bool isAlias = false;
|
||||
while ( s != args.end() )
|
||||
{
|
||||
if (*s == "WIN32")
|
||||
|
@ -57,6 +58,11 @@ bool cmAddExecutableCommand
|
|||
++s;
|
||||
importGlobal = true;
|
||||
}
|
||||
else if(*s == "ALIAS")
|
||||
{
|
||||
++s;
|
||||
isAlias = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
@ -83,6 +89,72 @@ bool cmAddExecutableCommand
|
|||
}
|
||||
return false;
|
||||
}
|
||||
if (isAlias)
|
||||
{
|
||||
if(!cmGeneratorExpression::IsValidTargetName(exename.c_str()))
|
||||
{
|
||||
this->SetError(("Invalid name for ALIAS: " + exename).c_str());
|
||||
return false;
|
||||
}
|
||||
if(excludeFromAll)
|
||||
{
|
||||
this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
|
||||
return false;
|
||||
}
|
||||
if(importTarget || importGlobal)
|
||||
{
|
||||
this->SetError("IMPORTED with ALIAS is not allowed.");
|
||||
return false;
|
||||
}
|
||||
if(args.size() != 3)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "ALIAS requires exactly one target argument.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *aliasedName = s->c_str();
|
||||
if(this->Makefile->IsAlias(aliasedName))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << exename
|
||||
<< "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
cmTarget *aliasedTarget =
|
||||
this->Makefile->FindTargetToUse(aliasedName, true);
|
||||
if(!aliasedTarget)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << exename
|
||||
<< "\" because target \"" << aliasedName << "\" does not already "
|
||||
"exist.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
cmTarget::TargetType type = aliasedTarget->GetType();
|
||||
if(type != cmTarget::EXECUTABLE)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << exename
|
||||
<< "\" because target \"" << aliasedName << "\" is not an "
|
||||
"executable.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
if(aliasedTarget->IsImported())
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << exename
|
||||
<< "\" because target \"" << aliasedName << "\" is IMPORTED.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
this->Makefile->AddAlias(exename.c_str(), aliasedTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle imported target creation.
|
||||
if(importTarget)
|
||||
|
|
|
@ -107,6 +107,19 @@ public:
|
|||
"(and its per-configuration version IMPORTED_LOCATION_<CONFIG>) "
|
||||
"which specifies the location of the main executable file on disk. "
|
||||
"See documentation of the IMPORTED_* properties for more information."
|
||||
"\n"
|
||||
"The signature\n"
|
||||
" add_executable(<name> ALIAS <target>)\n"
|
||||
"creates an alias, such that <name> can be used to refer to <target> "
|
||||
"in subsequent commands. The <name> does not appear in the generated "
|
||||
"buildsystem as a make target. The <target> may not be an IMPORTED "
|
||||
"target or an ALIAS. Alias targets can be used as linkable targets, "
|
||||
"targets to read properties from, executables for custom commands and "
|
||||
"custom targets. They can also be tested for existance with the "
|
||||
"regular if(TARGET) subcommand. The <name> may not be used to modify "
|
||||
"properties of <target>, that is, it may not be used as the operand of "
|
||||
"set_property, set_target_properties, target_link_libraries etc. An "
|
||||
"ALIAS target may not be installed of exported."
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ bool cmAddLibraryCommand
|
|||
// the type of library. Otherwise, it is treated as a source or
|
||||
// source list name. There may be two keyword arguments, check for them
|
||||
bool haveSpecifiedType = false;
|
||||
bool isAlias = false;
|
||||
while ( s != args.end() )
|
||||
{
|
||||
std::string libType = *s;
|
||||
|
@ -76,6 +77,11 @@ bool cmAddLibraryCommand
|
|||
type = cmTarget::UNKNOWN_LIBRARY;
|
||||
haveSpecifiedType = true;
|
||||
}
|
||||
else if(libType == "ALIAS")
|
||||
{
|
||||
++s;
|
||||
isAlias = true;
|
||||
}
|
||||
else if(*s == "EXCLUDE_FROM_ALL")
|
||||
{
|
||||
++s;
|
||||
|
@ -96,6 +102,80 @@ bool cmAddLibraryCommand
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (isAlias)
|
||||
{
|
||||
if(!cmGeneratorExpression::IsValidTargetName(libName.c_str()))
|
||||
{
|
||||
this->SetError(("Invalid name for ALIAS: " + libName).c_str());
|
||||
return false;
|
||||
}
|
||||
if(excludeFromAll)
|
||||
{
|
||||
this->SetError("EXCLUDE_FROM_ALL with ALIAS makes no sense.");
|
||||
return false;
|
||||
}
|
||||
if(importTarget || importGlobal)
|
||||
{
|
||||
this->SetError("IMPORTED with ALIAS is not allowed.");
|
||||
return false;
|
||||
}
|
||||
if(args.size() != 3)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "ALIAS requires exactly one target argument.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *aliasedName = s->c_str();
|
||||
if(this->Makefile->IsAlias(aliasedName))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << libName
|
||||
<< "\" because target \"" << aliasedName << "\" is itself an ALIAS.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
cmTarget *aliasedTarget =
|
||||
this->Makefile->FindTargetToUse(aliasedName, true);
|
||||
if(!aliasedTarget)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << libName
|
||||
<< "\" because target \"" << aliasedName << "\" does not already "
|
||||
"exist.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
cmTarget::TargetType aliasedType = aliasedTarget->GetType();
|
||||
if(aliasedType != cmTarget::SHARED_LIBRARY
|
||||
&& aliasedType != cmTarget::STATIC_LIBRARY
|
||||
&& aliasedType != cmTarget::MODULE_LIBRARY
|
||||
&& aliasedType != cmTarget::OBJECT_LIBRARY)
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << libName
|
||||
<< "\" because target \"" << aliasedName << "\" is not a library.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
if(aliasedTarget->IsImported())
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create ALIAS target \"" << libName
|
||||
<< "\" because target \"" << aliasedName << "\" is IMPORTED.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
this->Makefile->AddAlias(libName.c_str(), aliasedTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(importTarget && excludeFromAll)
|
||||
{
|
||||
this->SetError("excludeFromAll with IMPORTED target makes no sense.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ideally we should check whether for the linker language of the target
|
||||
CMAKE_${LANG}_CREATE_SHARED_LIBRARY is defined and if not default to
|
||||
|
|
|
@ -138,6 +138,19 @@ public:
|
|||
"Some native build systems may not like targets that have only "
|
||||
"object files, so consider adding at least one real source file "
|
||||
"to any target that references $<TARGET_OBJECTS:objlib>."
|
||||
"\n"
|
||||
"The signature\n"
|
||||
" add_library(<name> ALIAS <target>)\n"
|
||||
"creates an alias, such that <name> can be used to refer to <target> "
|
||||
"in subsequent commands. The <name> does not appear in the generated "
|
||||
"buildsystem as a make target. The <target> may not be an IMPORTED "
|
||||
"target or an ALIAS. Alias targets can be used as linkable targets, "
|
||||
"targets to read properties from. They can also be tested for "
|
||||
"existance with the "
|
||||
"regular if(TARGET) subcommand. The <name> may not be used to modify "
|
||||
"properties of <target>, that is, it may not be used as the operand of "
|
||||
"set_property, set_target_properties, target_link_libraries etc. An "
|
||||
"ALIAS target may not be installed of exported."
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,6 +114,15 @@ bool cmExportCommand
|
|||
currentTarget != this->Targets.GetVector().end();
|
||||
++currentTarget)
|
||||
{
|
||||
if (this->Makefile->IsAlias(currentTarget->c_str()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given ALIAS target \"" << *currentTarget
|
||||
<< "\" which may not be exported.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cmTarget* target =
|
||||
this->Makefile->GetLocalGenerator()->
|
||||
GetGlobalGenerator()->FindTarget(0, currentTarget->c_str()))
|
||||
|
|
|
@ -747,6 +747,18 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
|
|||
"Target name not supported.");
|
||||
return std::string();
|
||||
}
|
||||
if(propertyName == "ALIASED_TARGET")
|
||||
{
|
||||
if(context->Makefile->IsAlias(targetName.c_str()))
|
||||
{
|
||||
if(cmTarget* tgt =
|
||||
context->Makefile->FindTargetToUse(targetName.c_str()))
|
||||
{
|
||||
return tgt->GetName();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
target = context->Makefile->FindTargetToUse(
|
||||
targetName.c_str());
|
||||
|
||||
|
|
|
@ -288,6 +288,18 @@ bool cmGetPropertyCommand::HandleTargetMode()
|
|||
return false;
|
||||
}
|
||||
|
||||
if(this->PropertyName == "ALIASED_TARGET")
|
||||
{
|
||||
if(this->Makefile->IsAlias(this->Name.c_str()))
|
||||
{
|
||||
if(cmTarget* target =
|
||||
this->Makefile->FindTargetToUse(this->Name.c_str()))
|
||||
{
|
||||
return this->StoreResult(target->GetName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(this->Name.c_str()))
|
||||
{
|
||||
return this->StoreResult(target->GetProperty(this->PropertyName.c_str()));
|
||||
|
|
|
@ -22,16 +22,29 @@ bool cmGetTargetPropertyCommand
|
|||
}
|
||||
std::string var = args[0].c_str();
|
||||
const char* targetName = args[1].c_str();
|
||||
const char *prop = 0;
|
||||
|
||||
if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
|
||||
if(args[2] == "ALIASED_TARGET")
|
||||
{
|
||||
if(this->Makefile->IsAlias(targetName))
|
||||
{
|
||||
if(cmTarget* target =
|
||||
this->Makefile->FindTargetToUse(targetName))
|
||||
{
|
||||
prop = target->GetName();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(cmTarget* tgt = this->Makefile->FindTargetToUse(targetName))
|
||||
{
|
||||
cmTarget& target = *tgt;
|
||||
const char *prop = target.GetProperty(args[2].c_str());
|
||||
if (prop)
|
||||
{
|
||||
this->Makefile->AddDefinition(var.c_str(), prop);
|
||||
return true;
|
||||
}
|
||||
prop = target.GetProperty(args[2].c_str());
|
||||
}
|
||||
|
||||
if (prop)
|
||||
{
|
||||
this->Makefile->AddDefinition(var.c_str(), prop);
|
||||
return true;
|
||||
}
|
||||
this->Makefile->AddDefinition(var.c_str(), (var+"-NOTFOUND").c_str());
|
||||
return true;
|
||||
|
|
|
@ -1769,10 +1769,22 @@ cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator(const char* start_dir)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmGlobalGenerator::AddAlias(const char *name, cmTarget *tgt)
|
||||
{
|
||||
this->AliasTargets[name] = tgt;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmGlobalGenerator::IsAlias(const char *name)
|
||||
{
|
||||
return this->AliasTargets.find(name) != this->AliasTargets.end();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget*
|
||||
cmGlobalGenerator::FindTarget(const char* project, const char* name)
|
||||
cmGlobalGenerator::FindTarget(const char* project, const char* name,
|
||||
bool excludeAliases)
|
||||
{
|
||||
// if project specific
|
||||
if(project)
|
||||
|
@ -1780,7 +1792,8 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
|
|||
std::vector<cmLocalGenerator*>* gens = &this->ProjectMap[project];
|
||||
for(unsigned int i = 0; i < gens->size(); ++i)
|
||||
{
|
||||
cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name);
|
||||
cmTarget* ret = (*gens)[i]->GetMakefile()->FindTarget(name,
|
||||
excludeAliases);
|
||||
if(ret)
|
||||
{
|
||||
return ret;
|
||||
|
@ -1790,6 +1803,15 @@ cmGlobalGenerator::FindTarget(const char* project, const char* name)
|
|||
// if all projects/directories
|
||||
else
|
||||
{
|
||||
if (!excludeAliases)
|
||||
{
|
||||
std::map<cmStdString, cmTarget*>::iterator ai
|
||||
= this->AliasTargets.find(name);
|
||||
if (ai != this->AliasTargets.end())
|
||||
{
|
||||
return ai->second;
|
||||
}
|
||||
}
|
||||
std::map<cmStdString,cmTarget *>::iterator i =
|
||||
this->TotalTargets.find ( name );
|
||||
if ( i != this->TotalTargets.end() )
|
||||
|
|
|
@ -196,7 +196,11 @@ public:
|
|||
void FindMakeProgram(cmMakefile*);
|
||||
|
||||
///! Find a target by name by searching the local generators.
|
||||
cmTarget* FindTarget(const char* project, const char* name);
|
||||
cmTarget* FindTarget(const char* project, const char* name,
|
||||
bool excludeAliases = false);
|
||||
|
||||
void AddAlias(const char *name, cmTarget *tgt);
|
||||
bool IsAlias(const char *name);
|
||||
|
||||
/** Determine if a name resolves to a framework on disk or a built target
|
||||
that is a framework. */
|
||||
|
@ -347,6 +351,7 @@ protected:
|
|||
|
||||
// All targets in the entire project.
|
||||
std::map<cmStdString,cmTarget *> TotalTargets;
|
||||
std::map<cmStdString,cmTarget *> AliasTargets;
|
||||
std::map<cmStdString,cmTarget *> ImportedTargets;
|
||||
std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
|
||||
|
||||
|
|
|
@ -362,6 +362,15 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
|
|||
targetIt!=targetList.GetVector().end();
|
||||
++targetIt)
|
||||
{
|
||||
|
||||
if (this->Makefile->IsAlias(targetIt->c_str()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "TARGETS given target \"" << (*targetIt)
|
||||
<< "\" which is an alias.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
// Lookup this target in the current directory.
|
||||
if(cmTarget* target=this->Makefile->FindTarget(targetIt->c_str()))
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <stack>
|
||||
#include <ctype.h> // for isspace
|
||||
#include <assert.h>
|
||||
|
||||
class cmMakefile::Internals
|
||||
{
|
||||
|
@ -1437,6 +1438,14 @@ void cmMakefile::AddLinkDirectoryForTarget(const char *target,
|
|||
cmTargets::iterator i = this->Targets.find(target);
|
||||
if ( i != this->Targets.end())
|
||||
{
|
||||
if(this->IsAlias(target))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "ALIAS target \"" << target << "\" "
|
||||
<< "may not be linked into another target.";
|
||||
this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
||||
return;
|
||||
}
|
||||
i->second.AddLinkDirectory( d );
|
||||
}
|
||||
else
|
||||
|
@ -1923,6 +1932,12 @@ void cmMakefile::AddGlobalLinkInformation(const char* name, cmTarget& target)
|
|||
}
|
||||
|
||||
|
||||
void cmMakefile::AddAlias(const char* lname, cmTarget *tgt)
|
||||
{
|
||||
this->AliasTargets[lname] = tgt;
|
||||
this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt);
|
||||
}
|
||||
|
||||
cmTarget* cmMakefile::AddLibrary(const char* lname, cmTarget::TargetType type,
|
||||
const std::vector<std::string> &srcs,
|
||||
bool excludeFromAll)
|
||||
|
@ -3758,8 +3773,17 @@ const char* cmMakefile::GetFeature(const char* feature, const char* config)
|
|||
return 0;
|
||||
}
|
||||
|
||||
cmTarget* cmMakefile::FindTarget(const char* name)
|
||||
cmTarget* cmMakefile::FindTarget(const char* name, bool excludeAliases)
|
||||
{
|
||||
if (!excludeAliases)
|
||||
{
|
||||
std::map<std::string, cmTarget*>::iterator i
|
||||
= this->AliasTargets.find(name);
|
||||
if (i != this->AliasTargets.end())
|
||||
{
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
cmTargets& tgts = this->GetTargets();
|
||||
|
||||
cmTargets::iterator i = tgts.find ( name );
|
||||
|
@ -4184,7 +4208,7 @@ cmMakefile::AddImportedTarget(const char* name, cmTarget::TargetType type,
|
|||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmTarget* cmMakefile::FindTargetToUse(const char* name)
|
||||
cmTarget* cmMakefile::FindTargetToUse(const char* name, bool excludeAliases)
|
||||
{
|
||||
// Look for an imported target. These take priority because they
|
||||
// are more local in scope and do not have to be globally unique.
|
||||
|
@ -4196,15 +4220,25 @@ cmTarget* cmMakefile::FindTargetToUse(const char* name)
|
|||
}
|
||||
|
||||
// Look for a target built in this directory.
|
||||
if(cmTarget* t = this->FindTarget(name))
|
||||
if(cmTarget* t = this->FindTarget(name, excludeAliases))
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
// Look for a target built in this project.
|
||||
return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name);
|
||||
return this->LocalGenerator->GetGlobalGenerator()->FindTarget(0, name,
|
||||
excludeAliases);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmMakefile::IsAlias(const char *name)
|
||||
{
|
||||
if (this->AliasTargets.find(name) != this->AliasTargets.end())
|
||||
return true;
|
||||
return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias(name);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
|
||||
{
|
||||
cmTarget *t = this->FindTargetToUse(name);
|
||||
|
@ -4215,6 +4249,14 @@ cmGeneratorTarget* cmMakefile::FindGeneratorTargetToUse(const char* name)
|
|||
bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg,
|
||||
bool isCustom)
|
||||
{
|
||||
if(this->IsAlias(name.c_str()))
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "cannot create target \"" << name
|
||||
<< "\" because an alias with the same name already exists.";
|
||||
msg = e.str();
|
||||
return false;
|
||||
}
|
||||
if(cmTarget* existing = this->FindTargetToUse(name.c_str()))
|
||||
{
|
||||
// The name given conflicts with an existing target. Produce an
|
||||
|
|
|
@ -337,6 +337,7 @@ public:
|
|||
cmTarget* AddLibrary(const char *libname, cmTarget::TargetType type,
|
||||
const std::vector<std::string> &srcs,
|
||||
bool excludeFromAll = false);
|
||||
void AddAlias(const char *libname, cmTarget *tgt);
|
||||
|
||||
#if defined(CMAKE_BUILD_WITH_CMAKE)
|
||||
/**
|
||||
|
@ -536,11 +537,12 @@ public:
|
|||
this->GeneratorTargets = targets;
|
||||
}
|
||||
|
||||
cmTarget* FindTarget(const char* name);
|
||||
cmTarget* FindTarget(const char* name, bool excludeAliases = false);
|
||||
|
||||
/** Find a target to use in place of the given name. The target
|
||||
returned may be imported or built within the project. */
|
||||
cmTarget* FindTargetToUse(const char* name);
|
||||
cmTarget* FindTargetToUse(const char* name, bool excludeAliases = false);
|
||||
bool IsAlias(const char *name);
|
||||
cmGeneratorTarget* FindGeneratorTargetToUse(const char* name);
|
||||
|
||||
/**
|
||||
|
@ -902,6 +904,7 @@ protected:
|
|||
|
||||
// libraries, classes, and executables
|
||||
cmTargets Targets;
|
||||
std::map<std::string, cmTarget*> AliasTargets;
|
||||
cmGeneratorTargetsType GeneratorTargets;
|
||||
std::vector<cmSourceFile*> SourceFiles;
|
||||
|
||||
|
|
|
@ -244,6 +244,11 @@ bool cmSetPropertyCommand::HandleTargetMode()
|
|||
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end(); ++ni)
|
||||
{
|
||||
if (this->Makefile->IsAlias(ni->c_str()))
|
||||
{
|
||||
this->SetError("can not be used on an ALIAS target.");
|
||||
return false;
|
||||
}
|
||||
if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
|
||||
{
|
||||
// Handle the current target.
|
||||
|
|
|
@ -72,6 +72,11 @@ bool cmSetTargetPropertiesCommand
|
|||
int i;
|
||||
for(i = 0; i < numFiles; ++i)
|
||||
{
|
||||
if (this->Makefile->IsAlias(args[i].c_str()))
|
||||
{
|
||||
this->SetError("can not be used on an ALIAS target.");
|
||||
return false;
|
||||
}
|
||||
bool ret = cmSetTargetPropertiesCommand::SetOneTarget
|
||||
(args[i].c_str(),propertyPairs,this->Makefile);
|
||||
if (!ret)
|
||||
|
|
|
@ -968,6 +968,12 @@ void cmTarget::DefineProperties(cmake *cm)
|
|||
"Per-configuration target file base name.",
|
||||
"This is the configuration-specific version of OUTPUT_NAME.");
|
||||
|
||||
cm->DefineProperty
|
||||
("ALIASED_TARGET", cmProperty::TARGET,
|
||||
"Name of target aliased by this target.",
|
||||
"If this is an ALIAS target, this property contains the name of the "
|
||||
"target aliased.");
|
||||
|
||||
cm->DefineProperty
|
||||
("<CONFIG>_OUTPUT_NAME", cmProperty::TARGET,
|
||||
"Old per-configuration target file base name.",
|
||||
|
|
|
@ -31,6 +31,11 @@ bool cmTargetLinkLibrariesCommand
|
|||
return false;
|
||||
}
|
||||
|
||||
if (this->Makefile->IsAlias(args[0].c_str()))
|
||||
{
|
||||
this->SetError("can not be used on an ALIAS target.");
|
||||
return false;
|
||||
}
|
||||
// Lookup the target for which libraries are specified.
|
||||
this->Target =
|
||||
this->Makefile->GetCMakeInstance()
|
||||
|
|
|
@ -26,6 +26,11 @@ bool cmTargetPropCommandBase
|
|||
}
|
||||
|
||||
// Lookup the target for which libraries are specified.
|
||||
if (this->Makefile->IsAlias(args[0].c_str()))
|
||||
{
|
||||
this->SetError("can not be used on an ALIAS target.");
|
||||
return false;
|
||||
}
|
||||
this->Target =
|
||||
this->Makefile->GetCMakeInstance()
|
||||
->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
project(AliasTarget)
|
||||
|
||||
add_library(foo SHARED empty.cpp)
|
||||
add_library(PREFIX::Foo ALIAS foo)
|
||||
add_library(Another::Alias ALIAS foo)
|
||||
|
||||
add_library(objects OBJECT object.cpp)
|
||||
add_library(Alias::Objects ALIAS objects)
|
||||
|
||||
target_compile_definitions(foo PUBLIC FOO_DEFINE)
|
||||
|
||||
add_library(bar SHARED empty.cpp)
|
||||
target_compile_definitions(bar PUBLIC BAR_DEFINE)
|
||||
|
||||
target_link_libraries(foo LINK_PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:PREFIX::Foo,ALIASED_TARGET>,foo>:bar>)
|
||||
|
||||
add_executable(AliasTarget commandgenerator.cpp $<TARGET_OBJECTS:Alias::Objects>)
|
||||
add_executable(PREFIX::AliasTarget ALIAS AliasTarget)
|
||||
add_executable(Generator::Command ALIAS AliasTarget)
|
||||
|
||||
add_custom_command(OUTPUT commandoutput.h COMMAND Generator::Command)
|
||||
|
||||
add_library(bat SHARED bat.cpp "${CMAKE_CURRENT_BINARY_DIR}/commandoutput.h")
|
||||
target_link_libraries(bat PREFIX::Foo)
|
||||
target_include_directories(bat PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
add_executable(targetgenerator targetgenerator.cpp)
|
||||
add_executable(Generator::Target ALIAS targetgenerator)
|
||||
|
||||
add_custom_target(usealias Generator::Target)
|
||||
add_dependencies(bat usealias)
|
||||
|
||||
if (NOT TARGET Another::Alias)
|
||||
message(SEND_ERROR "Another::Alias is not considered a target.")
|
||||
endif()
|
||||
|
||||
get_target_property(_alt PREFIX::Foo ALIASED_TARGET)
|
||||
if (NOT ${_alt} STREQUAL foo)
|
||||
message(SEND_ERROR "ALIASED_TARGET is not foo: ${_alt}")
|
||||
endif()
|
||||
|
||||
get_property(_alt2 TARGET PREFIX::Foo PROPERTY ALIASED_TARGET)
|
||||
if (NOT ${_alt2} STREQUAL foo)
|
||||
message(SEND_ERROR "ALIASED_TARGET is not foo.")
|
||||
endif()
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
#ifndef FOO_DEFINE
|
||||
#error Expected FOO_DEFINE
|
||||
#endif
|
||||
|
||||
#ifndef BAR_DEFINE
|
||||
#error Expected Bar_DEFINE
|
||||
#endif
|
||||
|
||||
#include "commandoutput.h"
|
||||
|
||||
#ifndef COMMANDOUTPUT_DEFINE
|
||||
#error Expected COMMANDOUTPUT_DEFINE
|
||||
#endif
|
||||
|
||||
#include "targetoutput.h"
|
||||
|
||||
#ifndef TARGETOUTPUT_DEFINE
|
||||
#error Expected TARGETOUTPUT_DEFINE
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int bar()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
#include "object.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::fstream fout;
|
||||
fout.open("commandoutput.h", std::ios::out);
|
||||
if (!fout)
|
||||
return 1;
|
||||
fout << "#define COMMANDOUTPUT_DEFINE\n";
|
||||
fout.close();
|
||||
return object();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
int object(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int object(void);
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::fstream fout;
|
||||
fout.open("targetoutput.h", std::ios::out);
|
||||
if (!fout)
|
||||
return 1;
|
||||
fout << "#define TARGETOUTPUT_DEFINE\n";
|
||||
fout.close();
|
||||
return 0;
|
||||
}
|
|
@ -245,6 +245,7 @@ if(BUILD_TESTING)
|
|||
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
|
||||
ADD_TEST_MACRO(CompileOptions CompileOptions)
|
||||
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
|
||||
ADD_TEST_MACRO(AliasTarget AliasTarget)
|
||||
set_tests_properties(EmptyLibrary PROPERTIES
|
||||
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
|
||||
ADD_TEST_MACRO(CrossCompile CrossCompile)
|
||||
|
|
|
@ -3,7 +3,8 @@ project(CTestTestDepends)
|
|||
include(CTest)
|
||||
|
||||
add_executable (simple simple.cxx)
|
||||
add_test (one simple)
|
||||
add_executable (TestExe::Simple ALIAS simple)
|
||||
add_test (NAME one COMMAND TestExe::Simple)
|
||||
add_test (two simple)
|
||||
add_test (three simple)
|
||||
|
||||
|
|
|
@ -163,6 +163,11 @@ add_library(imported4 SHARED IMPORTED)
|
|||
set_property(TARGET imported4 APPEND PROPERTY
|
||||
INCLUDE_DIRECTORIES $<TARGET_PROPERTY:imported3,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
|
||||
add_executable(someexe empty.cpp)
|
||||
add_executable(Alias::SomeExe ALIAS someexe)
|
||||
|
||||
add_library(Alias::SomeLib ALIAS empty1)
|
||||
|
||||
add_custom_target(check-part3 ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-Dtest_version_greater_1=$<VERSION_GREATER:1.0,1.1.1>
|
||||
|
@ -176,6 +181,9 @@ add_custom_target(check-part3 ALL
|
|||
-Dtest_imported_release=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
|
||||
-Dtest_imported_relwithdebinfo=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
|
||||
-Dtest_imported_minsizerel=$<TARGET_PROPERTY:imported4,INCLUDE_DIRECTORIES>
|
||||
-Dtest_alias_file_exe=$<STREQUAL:$<TARGET_FILE:Alias::SomeExe>,$<TARGET_FILE:someexe>>
|
||||
-Dtest_alias_file_lib=$<STREQUAL:$<TARGET_FILE:Alias::SomeLib>,$<TARGET_FILE:empty1>>
|
||||
-Dtest_alias_target_name=$<STREQUAL:$<TARGET_PROPERTY:Alias::SomeLib,NAME>,$<TARGET_PROPERTY:empty1,NAME>>
|
||||
-P ${CMAKE_CURRENT_SOURCE_DIR}/check-part3.cmake
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "check done (part 3 of 3)"
|
||||
VERBATIM
|
||||
|
|
|
@ -20,3 +20,7 @@ foreach(c debug release relwithdebinfo minsizerel)
|
|||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
check(test_alias_file_exe "1")
|
||||
check(test_alias_file_lib "1")
|
||||
check(test_alias_target_name "1")
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
|
||||
// empty
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int main() { return 0; }
|
||||
|
|
|
@ -98,6 +98,7 @@ add_RunCMake_test(try_compile)
|
|||
add_RunCMake_test(variable_watch)
|
||||
add_RunCMake_test(CMP0004)
|
||||
add_RunCMake_test(TargetPolicies)
|
||||
add_RunCMake_test(alias_targets)
|
||||
|
||||
find_package(Qt4 QUIET)
|
||||
find_package(Qt5Core QUIET)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1,20 @@
|
|||
include(RunCMake)
|
||||
|
||||
run_cmake(no-targets)
|
||||
run_cmake(multiple-targets)
|
||||
run_cmake(exclude-from-all)
|
||||
run_cmake(imported)
|
||||
run_cmake(invalid-name)
|
||||
run_cmake(invalid-target)
|
||||
run_cmake(imported-target)
|
||||
run_cmake(alias-target)
|
||||
run_cmake(set_property)
|
||||
run_cmake(set_target_properties)
|
||||
run_cmake(target_link_libraries)
|
||||
run_cmake(target_include_directories)
|
||||
run_cmake(export)
|
||||
run_cmake(install-export)
|
||||
run_cmake(name-conflict)
|
||||
run_cmake(add_dependencies)
|
||||
run_cmake(add_executable-library)
|
||||
run_cmake(add_library-executable)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at add_dependencies.cmake:9 \(add_dependencies\):
|
||||
Cannot add target-level dependencies to alias target "alias".
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
add_library(bar empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
add_dependencies(alias bar)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at add_executable-library.cmake:6 \(add_executable\):
|
||||
add_executable cannot create ALIAS target "alias" because target "foo" is
|
||||
not an executable.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_executable(alias ALIAS foo)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at add_library-executable.cmake:6 \(add_library\):
|
||||
add_library cannot create ALIAS target "alias" because target "foo" is not
|
||||
a library.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_executable(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at alias-target.cmake:8 \(add_library\):
|
||||
add_library cannot create ALIAS target "next_alias" because target "alias"
|
||||
is itself an ALIAS.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
add_library(next_alias ALIAS alias)
|
|
@ -0,0 +1,7 @@
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int empty()
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at exclude-from-all.cmake:6 \(add_library\):
|
||||
add_library EXCLUDE_FROM_ALL with ALIAS makes no sense.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS EXCLUDE_FROM_ALL foo)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at export.cmake:8 \(export\):
|
||||
export given ALIAS target "alias" which may not be exported.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
export(TARGETS alias FILE someFile.cmake)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at imported.cmake:2 \(add_library\):
|
||||
add_library IMPORTED with ALIAS is not allowed.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at imported-target.cmake:6 \(add_library\):
|
||||
add_library cannot create ALIAS target "alias" because target "foo" is
|
||||
IMPORTED.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo SHARED IMPORTED)
|
||||
|
||||
add_library(alias ALIAS foo)
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
add_library(alias IMPORTED ALIAS)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at install-export.cmake:8 \(install\):
|
||||
install TARGETS given target "alias" which is an alias.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
install(TARGETS alias EXPORT theTargets DESTINATION prefix)
|
||||
install(EXPORT theTargets DESTINATION lib/cmake)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at invalid-name.cmake:6 \(add_library\):
|
||||
add_library Invalid name for ALIAS: invalid\$name
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(invalid$name ALIAS foo)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at invalid-target.cmake:2 \(add_library\):
|
||||
add_library cannot create ALIAS target "alias" because target "foo" does
|
||||
not already exist.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
add_library(alias ALIAS foo)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at multiple-targets.cmake:7 \(add_library\):
|
||||
add_library ALIAS requires exactly one target argument.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
add_library(bar empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo bar)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,5 @@
|
|||
CMake Error at name-conflict.cmake:8 \(add_library\):
|
||||
add_library cannot create target "bar" because an alias with the same name
|
||||
already exists.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(bar ALIAS foo)
|
||||
|
||||
add_library(bar empty.cpp)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at no-targets.cmake:4 \(add_library\):
|
||||
add_library ALIAS requires exactly one target argument.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(alias ALIAS)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at set_property.cmake:8 \(set_property\):
|
||||
set_property can not be used on an ALIAS target.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
set_property(TARGET alias PROPERTY ANYTHING 1)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at set_target_properties.cmake:8 \(set_target_properties\):
|
||||
set_target_properties can not be used on an ALIAS target.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
set_target_properties(alias PROPERTIES ANYTHING 1)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at target_include_directories.cmake:8 \(target_include_directories\):
|
||||
target_include_directories can not be used on an ALIAS target.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
target_include_directories(alias PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,4 @@
|
|||
CMake Error at target_link_libraries.cmake:9 \(target_link_libraries\):
|
||||
target_link_libraries can not be used on an ALIAS target.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
enable_language(CXX)
|
||||
|
||||
add_library(foo empty.cpp)
|
||||
add_library(bar empty.cpp)
|
||||
|
||||
add_library(alias ALIAS foo)
|
||||
|
||||
target_link_libraries(alias bar)
|
Loading…
Reference in New Issue