2009-09-28 19:43:28 +04:00
|
|
|
/*============================================================================
|
|
|
|
CMake - Cross Platform Makefile Generator
|
|
|
|
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
|
2001-04-25 00:49:12 +04:00
|
|
|
|
2009-09-28 19:43:28 +04:00
|
|
|
Distributed under the OSI-approved BSD License (the "License");
|
|
|
|
see accompanying file Copyright.txt for details.
|
2001-04-25 00:49:12 +04:00
|
|
|
|
2009-09-28 19:43:28 +04:00
|
|
|
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.
|
|
|
|
============================================================================*/
|
2001-04-25 00:49:12 +04:00
|
|
|
#include "cmTarget.h"
|
2006-12-07 17:45:32 +03:00
|
|
|
#include "cmake.h"
|
2001-04-25 00:49:12 +04:00
|
|
|
#include "cmMakefile.h"
|
2002-09-28 00:24:10 +04:00
|
|
|
#include "cmSourceFile.h"
|
2005-04-22 23:23:21 +04:00
|
|
|
#include "cmLocalGenerator.h"
|
2004-09-22 22:42:05 +04:00
|
|
|
#include "cmGlobalGenerator.h"
|
2012-11-05 19:14:02 +04:00
|
|
|
#include "cmComputeLinkInformation.h"
|
2008-03-13 20:48:57 +03:00
|
|
|
#include "cmListFileCache.h"
|
2010-12-09 00:13:07 +03:00
|
|
|
#include "cmGeneratorExpression.h"
|
2012-11-20 01:47:30 +04:00
|
|
|
#include "cmGeneratorExpressionDAGChecker.h"
|
2008-08-19 19:43:51 +04:00
|
|
|
#include <cmsys/RegularExpression.hxx>
|
2002-05-01 22:00:21 +04:00
|
|
|
#include <map>
|
|
|
|
#include <set>
|
2003-06-24 23:10:47 +04:00
|
|
|
#include <queue>
|
2003-05-24 18:07:58 +04:00
|
|
|
#include <stdlib.h> // required for atof
|
2008-01-30 01:30:34 +03:00
|
|
|
#include <assert.h>
|
2011-03-20 19:57:42 +03:00
|
|
|
|
|
|
|
const char* cmTarget::GetTargetTypeName(TargetType targetType)
|
|
|
|
{
|
|
|
|
switch( targetType )
|
|
|
|
{
|
|
|
|
case cmTarget::STATIC_LIBRARY:
|
|
|
|
return "STATIC_LIBRARY";
|
|
|
|
case cmTarget::MODULE_LIBRARY:
|
|
|
|
return "MODULE_LIBRARY";
|
|
|
|
case cmTarget::SHARED_LIBRARY:
|
|
|
|
return "SHARED_LIBRARY";
|
2012-03-12 18:47:40 +04:00
|
|
|
case cmTarget::OBJECT_LIBRARY:
|
|
|
|
return "OBJECT_LIBRARY";
|
2011-03-20 19:57:42 +03:00
|
|
|
case cmTarget::EXECUTABLE:
|
|
|
|
return "EXECUTABLE";
|
|
|
|
case cmTarget::UTILITY:
|
|
|
|
return "UTILITY";
|
|
|
|
case cmTarget::GLOBAL_TARGET:
|
|
|
|
return "GLOBAL_TARGET";
|
2012-11-02 18:47:40 +04:00
|
|
|
case cmTarget::INTERFACE_LIBRARY:
|
|
|
|
return "INTERFACE_LIBRARY";
|
2011-03-20 19:57:42 +03:00
|
|
|
case cmTarget::UNKNOWN_LIBRARY:
|
|
|
|
return "UNKNOWN_LIBRARY";
|
|
|
|
}
|
|
|
|
assert(0 && "Unexpected target type");
|
|
|
|
return 0;
|
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2009-07-08 16:31:30 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
struct cmTarget::OutputInfo
|
|
|
|
{
|
|
|
|
std::string OutDir;
|
|
|
|
std::string ImpDir;
|
2012-09-25 05:30:42 +04:00
|
|
|
std::string PdbDir;
|
2009-07-08 16:31:30 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
struct cmTarget::ImportInfo
|
|
|
|
{
|
|
|
|
bool NoSOName;
|
|
|
|
std::string Location;
|
|
|
|
std::string SOName;
|
|
|
|
std::string ImportLibrary;
|
|
|
|
cmTarget::LinkInterface LinkInterface;
|
|
|
|
};
|
|
|
|
|
2013-01-04 16:31:01 +04:00
|
|
|
struct TargetConfigPair : public std::pair<cmTarget*, std::string> {
|
|
|
|
TargetConfigPair(cmTarget* tgt, const std::string &config)
|
|
|
|
: std::pair<cmTarget*, std::string>(tgt, config) {}
|
|
|
|
};
|
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class cmTargetInternals
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
cmTargetInternals()
|
|
|
|
{
|
|
|
|
this->SourceFileFlagsConstructed = false;
|
|
|
|
}
|
2009-10-06 00:14:17 +04:00
|
|
|
cmTargetInternals(cmTargetInternals const& r)
|
|
|
|
{
|
2009-10-06 17:59:05 +04:00
|
|
|
this->SourceFileFlagsConstructed = false;
|
2009-10-06 00:14:17 +04:00
|
|
|
// Only some of these entries are part of the object state.
|
|
|
|
// Others not copied here are result caches.
|
|
|
|
this->SourceEntries = r.SourceEntries;
|
|
|
|
}
|
2013-02-22 16:03:35 +04:00
|
|
|
~cmTargetInternals();
|
2008-02-19 00:38:34 +03:00
|
|
|
typedef cmTarget::SourceFileFlags SourceFileFlags;
|
|
|
|
std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
|
|
|
|
bool SourceFileFlagsConstructed;
|
2008-03-13 20:48:57 +03:00
|
|
|
|
|
|
|
// The backtrace when the target was created.
|
|
|
|
cmListFileBacktrace Backtrace;
|
2009-07-07 17:45:29 +04:00
|
|
|
|
|
|
|
// Cache link interface computation from each configuration.
|
|
|
|
struct OptionalLinkInterface: public cmTarget::LinkInterface
|
|
|
|
{
|
|
|
|
OptionalLinkInterface(): Exists(false) {}
|
|
|
|
bool Exists;
|
|
|
|
};
|
2013-01-04 16:31:01 +04:00
|
|
|
typedef std::map<TargetConfigPair, OptionalLinkInterface>
|
|
|
|
LinkInterfaceMapType;
|
2009-07-07 17:45:29 +04:00
|
|
|
LinkInterfaceMapType LinkInterfaceMap;
|
2009-07-08 16:31:30 +04:00
|
|
|
|
|
|
|
typedef std::map<cmStdString, cmTarget::OutputInfo> OutputInfoMapType;
|
|
|
|
OutputInfoMapType OutputInfoMap;
|
|
|
|
|
2013-01-04 16:31:01 +04:00
|
|
|
typedef std::map<TargetConfigPair, cmTarget::ImportInfo>
|
|
|
|
ImportInfoMapType;
|
2009-07-08 16:31:30 +04:00
|
|
|
ImportInfoMapType ImportInfoMap;
|
2009-07-08 20:04:48 +04:00
|
|
|
|
|
|
|
// Cache link implementation computation from each configuration.
|
2013-01-04 16:31:01 +04:00
|
|
|
typedef std::map<TargetConfigPair,
|
|
|
|
cmTarget::LinkImplementation> LinkImplMapType;
|
2009-07-08 20:04:48 +04:00
|
|
|
LinkImplMapType LinkImplMap;
|
2009-07-10 21:53:28 +04:00
|
|
|
|
2013-01-04 16:31:01 +04:00
|
|
|
typedef std::map<TargetConfigPair, cmTarget::LinkClosure>
|
|
|
|
LinkClosureMapType;
|
2009-07-10 21:53:28 +04:00
|
|
|
LinkClosureMapType LinkClosureMap;
|
2009-09-07 18:11:43 +04:00
|
|
|
|
|
|
|
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
|
|
|
|
typedef std::map<cmSourceFile*, SourceEntry> SourceEntriesType;
|
|
|
|
SourceEntriesType SourceEntries;
|
2012-11-20 01:47:30 +04:00
|
|
|
|
2013-05-28 14:32:39 +04:00
|
|
|
struct TargetPropertyEntry {
|
|
|
|
TargetPropertyEntry(cmsys::auto_ptr<cmCompiledGeneratorExpression> cge,
|
2013-03-25 00:18:21 +04:00
|
|
|
const std::string &targetName = std::string())
|
|
|
|
: ge(cge), TargetName(targetName)
|
2012-11-20 01:47:30 +04:00
|
|
|
{}
|
|
|
|
const cmsys::auto_ptr<cmCompiledGeneratorExpression> ge;
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<std::string> CachedEntries;
|
2013-03-25 00:18:21 +04:00
|
|
|
const std::string TargetName;
|
2012-11-20 01:47:30 +04:00
|
|
|
};
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
|
2013-05-16 17:15:28 +04:00
|
|
|
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
|
2013-06-12 12:12:51 +04:00
|
|
|
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
|
2013-05-28 14:39:32 +04:00
|
|
|
std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
|
2013-02-22 16:03:35 +04:00
|
|
|
|
2013-05-28 14:32:39 +04:00
|
|
|
std::map<std::string, std::vector<TargetPropertyEntry*> >
|
2013-02-22 16:03:35 +04:00
|
|
|
CachedLinkInterfaceIncludeDirectoriesEntries;
|
2013-05-16 17:15:28 +04:00
|
|
|
std::map<std::string, std::vector<TargetPropertyEntry*> >
|
|
|
|
CachedLinkInterfaceCompileOptionsEntries;
|
2013-06-12 12:12:51 +04:00
|
|
|
std::map<std::string, std::vector<TargetPropertyEntry*> >
|
|
|
|
CachedLinkInterfaceCompileDefinitionsEntries;
|
2013-02-22 16:03:35 +04:00
|
|
|
|
|
|
|
std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
|
|
|
|
std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
|
2013-05-16 17:15:28 +04:00
|
|
|
std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
|
2008-02-19 00:38:34 +03:00
|
|
|
};
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void deleteAndClear(
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*> &entries)
|
2013-02-22 16:03:35 +04:00
|
|
|
{
|
2013-05-28 14:32:39 +04:00
|
|
|
for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
|
2013-02-22 16:03:35 +04:00
|
|
|
it = entries.begin(),
|
|
|
|
end = entries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
|
|
|
delete *it;
|
|
|
|
}
|
|
|
|
entries.clear();
|
|
|
|
}
|
|
|
|
|
2013-05-02 18:52:48 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void deleteAndClear(
|
|
|
|
std::map<std::string,
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*> > &entries)
|
2013-05-02 18:52:48 +04:00
|
|
|
{
|
|
|
|
for (std::map<std::string,
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*> >::iterator
|
2013-05-02 18:52:48 +04:00
|
|
|
it = entries.begin(), end = entries.end(); it != end; ++it)
|
|
|
|
{
|
|
|
|
deleteAndClear(it->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetInternals::~cmTargetInternals()
|
|
|
|
{
|
2013-05-02 18:46:57 +04:00
|
|
|
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
|
2013-05-16 17:15:28 +04:00
|
|
|
deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
|
2013-06-12 12:12:51 +04:00
|
|
|
deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
|
2013-02-22 16:03:35 +04:00
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTarget::cmTarget()
|
|
|
|
{
|
2013-06-28 13:25:40 +04:00
|
|
|
#define INITIALIZE_TARGET_POLICY_MEMBER(POLICY) \
|
|
|
|
this->PolicyStatus ## POLICY = cmPolicies::WARN;
|
|
|
|
|
|
|
|
CM_FOR_EACH_TARGET_POLICY(INITIALIZE_TARGET_POLICY_MEMBER)
|
|
|
|
|
|
|
|
#undef INITIALIZE_TARGET_POLICY_MEMBER
|
|
|
|
|
2006-03-15 19:02:08 +03:00
|
|
|
this->Makefile = 0;
|
|
|
|
this->LinkLibrariesAnalyzed = false;
|
|
|
|
this->HaveInstallRule = false;
|
2007-03-19 17:00:36 +03:00
|
|
|
this->DLLPlatform = false;
|
2011-12-02 01:21:25 +04:00
|
|
|
this->IsApple = false;
|
2007-05-22 18:24:59 +04:00
|
|
|
this->IsImportedTarget = false;
|
2013-01-12 15:11:29 +04:00
|
|
|
this->BuildInterfaceIncludesAppended = false;
|
2013-01-20 15:50:53 +04:00
|
|
|
this->DebugIncludesDone = false;
|
2013-05-16 17:15:28 +04:00
|
|
|
this->DebugCompileOptionsDone = false;
|
2013-06-12 12:12:51 +04:00
|
|
|
this->DebugCompileDefinitionsDone = false;
|
2006-12-07 17:45:32 +03:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2006-12-07 17:45:32 +03:00
|
|
|
void cmTarget::DefineProperties(cmake *cm)
|
|
|
|
{
|
2009-02-10 16:51:15 +03:00
|
|
|
cm->DefineProperty
|
|
|
|
("RULE_LAUNCH_COMPILE", cmProperty::TARGET,
|
2013-09-16 22:38:23 +04:00
|
|
|
"", "", true);
|
2009-02-10 16:51:15 +03:00
|
|
|
cm->DefineProperty
|
|
|
|
("RULE_LAUNCH_LINK", cmProperty::TARGET,
|
2013-09-16 22:38:23 +04:00
|
|
|
"", "", true);
|
2009-02-10 16:51:15 +03:00
|
|
|
cm->DefineProperty
|
|
|
|
("RULE_LAUNCH_CUSTOM", cmProperty::TARGET,
|
2013-09-16 22:38:23 +04:00
|
|
|
"", "", true);
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
2002-05-04 00:34:05 +04:00
|
|
|
|
2004-09-22 22:42:05 +04:00
|
|
|
void cmTarget::SetType(TargetType type, const char* name)
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
2006-03-15 19:02:08 +03:00
|
|
|
this->Name = name;
|
2002-11-20 02:01:05 +03:00
|
|
|
// only add dependency information for library targets
|
2006-03-15 19:02:08 +03:00
|
|
|
this->TargetTypeValue = type;
|
2007-07-02 21:32:41 +04:00
|
|
|
if(this->TargetTypeValue >= STATIC_LIBRARY
|
|
|
|
&& this->TargetTypeValue <= MODULE_LIBRARY)
|
2006-03-15 19:02:08 +03:00
|
|
|
{
|
|
|
|
this->RecordDependencies = true;
|
2007-07-02 21:32:41 +04:00
|
|
|
}
|
|
|
|
else
|
2006-03-15 19:02:08 +03:00
|
|
|
{
|
|
|
|
this->RecordDependencies = false;
|
|
|
|
}
|
2002-11-20 02:01:05 +03:00
|
|
|
}
|
|
|
|
|
2006-02-16 23:19:00 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::SetMakefile(cmMakefile* mf)
|
|
|
|
{
|
|
|
|
// Set our makefile.
|
2006-03-15 19:02:08 +03:00
|
|
|
this->Makefile = mf;
|
2006-02-16 23:19:00 +03:00
|
|
|
|
2006-12-07 17:45:32 +03:00
|
|
|
// set the cmake instance of the properties
|
|
|
|
this->Properties.SetCMakeInstance(mf->GetCMakeInstance());
|
|
|
|
|
2007-03-19 17:00:36 +03:00
|
|
|
// Check whether this is a DLL platform.
|
|
|
|
this->DLLPlatform = (this->Makefile->IsOn("WIN32") ||
|
|
|
|
this->Makefile->IsOn("CYGWIN") ||
|
|
|
|
this->Makefile->IsOn("MINGW"));
|
|
|
|
|
2011-12-02 01:21:25 +04:00
|
|
|
// Check whether we are targeting an Apple platform.
|
|
|
|
this->IsApple = this->Makefile->IsOn("APPLE");
|
|
|
|
|
2006-02-16 23:19:00 +03:00
|
|
|
// Setup default property values.
|
2013-08-22 07:09:32 +04:00
|
|
|
this->SetPropertyDefault("INSTALL_NAME_DIR", 0);
|
2006-02-16 23:19:00 +03:00
|
|
|
this->SetPropertyDefault("INSTALL_RPATH", "");
|
2006-06-15 18:12:19 +04:00
|
|
|
this->SetPropertyDefault("INSTALL_RPATH_USE_LINK_PATH", "OFF");
|
2006-02-16 23:19:00 +03:00
|
|
|
this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
|
|
|
|
this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
|
2007-03-09 23:14:27 +03:00
|
|
|
this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
|
|
|
|
this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
|
|
|
|
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
|
2012-09-25 05:30:42 +04:00
|
|
|
this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
|
2011-08-31 18:24:43 +04:00
|
|
|
this->SetPropertyDefault("Fortran_FORMAT", 0);
|
2007-12-31 00:11:38 +03:00
|
|
|
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
|
2011-12-06 01:39:07 +04:00
|
|
|
this->SetPropertyDefault("GNUtoMS", 0);
|
2009-10-21 21:00:49 +04:00
|
|
|
this->SetPropertyDefault("OSX_ARCHITECTURES", 0);
|
2011-08-17 00:05:33 +04:00
|
|
|
this->SetPropertyDefault("AUTOMOC", 0);
|
2011-11-01 17:33:11 +04:00
|
|
|
this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", 0);
|
2012-10-26 16:25:36 +04:00
|
|
|
this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", 0);
|
2011-10-01 14:23:56 +04:00
|
|
|
this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", 0);
|
2012-03-05 18:36:46 +04:00
|
|
|
this->SetPropertyDefault("WIN32_EXECUTABLE", 0);
|
|
|
|
this->SetPropertyDefault("MACOSX_BUNDLE", 0);
|
2013-04-27 08:04:44 +04:00
|
|
|
this->SetPropertyDefault("MACOSX_RPATH", 0);
|
2013-08-29 12:28:09 +04:00
|
|
|
this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
|
2013-04-27 08:04:44 +04:00
|
|
|
|
2006-03-02 06:45:13 +03:00
|
|
|
|
|
|
|
// Collect the set of configuration types.
|
|
|
|
std::vector<std::string> configNames;
|
2010-09-08 22:54:49 +04:00
|
|
|
mf->GetConfigurations(configNames);
|
2006-03-02 06:45:13 +03:00
|
|
|
|
|
|
|
// Setup per-configuration property default values.
|
2009-10-28 20:35:25 +03:00
|
|
|
const char* configProps[] = {
|
|
|
|
"ARCHIVE_OUTPUT_DIRECTORY_",
|
|
|
|
"LIBRARY_OUTPUT_DIRECTORY_",
|
|
|
|
"RUNTIME_OUTPUT_DIRECTORY_",
|
2012-09-25 05:30:42 +04:00
|
|
|
"PDB_OUTPUT_DIRECTORY_",
|
2013-08-27 17:10:51 +04:00
|
|
|
"MAP_IMPORTED_CONFIG_",
|
2009-10-28 20:35:25 +03:00
|
|
|
0};
|
2006-03-02 06:45:13 +03:00
|
|
|
for(std::vector<std::string>::iterator ci = configNames.begin();
|
|
|
|
ci != configNames.end(); ++ci)
|
|
|
|
{
|
2009-10-28 20:35:25 +03:00
|
|
|
std::string configUpper = cmSystemTools::UpperCase(*ci);
|
|
|
|
for(const char** p = configProps; *p; ++p)
|
|
|
|
{
|
|
|
|
std::string property = *p;
|
|
|
|
property += configUpper;
|
|
|
|
this->SetPropertyDefault(property.c_str(), 0);
|
|
|
|
}
|
|
|
|
|
2006-03-02 06:45:13 +03:00
|
|
|
// Initialize per-configuration name postfix property from the
|
|
|
|
// variable only for non-executable targets. This preserves
|
|
|
|
// compatibility with previous CMake versions in which executables
|
|
|
|
// did not support this variable. Projects may still specify the
|
|
|
|
// property directly. TODO: Make this depend on backwards
|
|
|
|
// compatibility setting.
|
2006-03-15 19:02:08 +03:00
|
|
|
if(this->TargetTypeValue != cmTarget::EXECUTABLE)
|
2006-03-02 06:45:13 +03:00
|
|
|
{
|
|
|
|
std::string property = cmSystemTools::UpperCase(*ci);
|
|
|
|
property += "_POSTFIX";
|
|
|
|
this->SetPropertyDefault(property.c_str(), 0);
|
|
|
|
}
|
|
|
|
}
|
2008-03-13 20:48:57 +03:00
|
|
|
|
|
|
|
// Save the backtrace of target construction.
|
|
|
|
this->Makefile->GetBacktrace(this->Internal->Backtrace);
|
2008-03-13 23:23:18 +03:00
|
|
|
|
2011-12-04 19:40:39 +04:00
|
|
|
// Initialize the INCLUDE_DIRECTORIES property based on the current value
|
|
|
|
// of the same directory property:
|
2013-02-12 13:35:28 +04:00
|
|
|
const std::vector<cmValueWithOrigin> parentIncludes =
|
2012-11-20 01:47:30 +04:00
|
|
|
this->Makefile->GetIncludeDirectoriesEntries();
|
|
|
|
|
2013-02-12 13:35:28 +04:00
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator it
|
2012-11-20 01:47:30 +04:00
|
|
|
= parentIncludes.begin(); it != parentIncludes.end(); ++it)
|
|
|
|
{
|
|
|
|
this->InsertInclude(*it);
|
|
|
|
}
|
2013-07-02 00:55:25 +04:00
|
|
|
|
|
|
|
const std::set<cmStdString> parentSystemIncludes =
|
|
|
|
this->Makefile->GetSystemIncludeDirectories();
|
|
|
|
|
|
|
|
for (std::set<cmStdString>::const_iterator it
|
|
|
|
= parentSystemIncludes.begin();
|
|
|
|
it != parentSystemIncludes.end(); ++it)
|
|
|
|
{
|
|
|
|
this->SystemIncludeDirectories.insert(*it);
|
|
|
|
}
|
|
|
|
|
2013-06-04 12:30:24 +04:00
|
|
|
const std::vector<cmValueWithOrigin> parentOptions =
|
|
|
|
this->Makefile->GetCompileOptionsEntries();
|
|
|
|
|
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator it
|
|
|
|
= parentOptions.begin(); it != parentOptions.end(); ++it)
|
|
|
|
{
|
|
|
|
this->InsertCompileOption(*it);
|
|
|
|
}
|
2011-12-04 19:40:39 +04:00
|
|
|
|
2013-05-18 14:12:18 +04:00
|
|
|
this->SetPropertyDefault("C_VISIBILITY_PRESET", 0);
|
|
|
|
this->SetPropertyDefault("CXX_VISIBILITY_PRESET", 0);
|
2013-05-23 17:32:17 +04:00
|
|
|
this->SetPropertyDefault("VISIBILITY_INLINES_HIDDEN", 0);
|
2013-05-18 14:12:18 +04:00
|
|
|
|
2012-05-30 22:13:09 +04:00
|
|
|
if(this->TargetTypeValue == cmTarget::SHARED_LIBRARY
|
|
|
|
|| this->TargetTypeValue == cmTarget::MODULE_LIBRARY)
|
|
|
|
{
|
|
|
|
this->SetProperty("POSITION_INDEPENDENT_CODE", "True");
|
|
|
|
}
|
|
|
|
this->SetPropertyDefault("POSITION_INDEPENDENT_CODE", 0);
|
|
|
|
|
2008-03-13 23:23:18 +03:00
|
|
|
// Record current policies for later use.
|
2013-06-28 13:25:40 +04:00
|
|
|
#define CAPTURE_TARGET_POLICY(POLICY) \
|
|
|
|
this->PolicyStatus ## POLICY = \
|
|
|
|
this->Makefile->GetPolicyStatus(cmPolicies::POLICY);
|
|
|
|
|
|
|
|
CM_FOR_EACH_TARGET_POLICY(CAPTURE_TARGET_POLICY)
|
|
|
|
|
|
|
|
#undef CAPTURE_TARGET_POLICY
|
2012-11-02 18:47:40 +04:00
|
|
|
|
|
|
|
if (this->TargetTypeValue == INTERFACE_LIBRARY)
|
|
|
|
{
|
|
|
|
// This policy is checked in a few conditions. The properties relevant
|
|
|
|
// to the policy are always ignored for INTERFACE_LIBRARY targets,
|
|
|
|
// so ensure that the conditions don't lead to nonsense.
|
|
|
|
this->PolicyStatusCMP0022 = cmPolicies::NEW;
|
|
|
|
}
|
2008-03-13 20:48:57 +03:00
|
|
|
}
|
|
|
|
|
2009-10-05 17:06:29 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::FinishConfigure()
|
|
|
|
{
|
2009-10-05 17:06:59 +04:00
|
|
|
// Erase any cached link information that might have been comptued
|
|
|
|
// on-demand during the configuration. This ensures that build
|
|
|
|
// system generation uses up-to-date information even if other cache
|
|
|
|
// invalidation code in this source file is buggy.
|
|
|
|
this->ClearLinkMaps();
|
|
|
|
|
2009-10-05 17:06:29 +04:00
|
|
|
// Do old-style link dependency analysis.
|
|
|
|
this->AnalyzeLibDependencies(*this->Makefile);
|
|
|
|
}
|
|
|
|
|
2009-10-05 17:06:59 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ClearLinkMaps()
|
|
|
|
{
|
|
|
|
this->Internal->LinkImplMap.clear();
|
|
|
|
this->Internal->LinkInterfaceMap.clear();
|
|
|
|
this->Internal->LinkClosureMap.clear();
|
2013-01-20 20:18:23 +04:00
|
|
|
for (cmTargetLinkInformationMap::const_iterator it
|
|
|
|
= this->LinkInformation.begin();
|
|
|
|
it != this->LinkInformation.end(); ++it)
|
|
|
|
{
|
|
|
|
delete it->second;
|
|
|
|
}
|
|
|
|
this->LinkInformation.clear();
|
2009-10-05 17:06:59 +04:00
|
|
|
}
|
|
|
|
|
2008-03-13 20:48:57 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmListFileBacktrace const& cmTarget::GetBacktrace() const
|
|
|
|
{
|
|
|
|
return this->Internal->Backtrace;
|
2006-02-16 23:19:00 +03:00
|
|
|
}
|
2002-11-20 02:01:05 +03:00
|
|
|
|
2009-02-10 16:50:09 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetSupportDirectory() const
|
|
|
|
{
|
|
|
|
std::string dir = this->Makefile->GetCurrentOutputDirectory();
|
|
|
|
dir += cmake::GetCMakeFilesDirectory();
|
|
|
|
dir += "/";
|
|
|
|
dir += this->Name;
|
2009-06-10 21:03:11 +04:00
|
|
|
#if defined(__VMS)
|
|
|
|
dir += "_dir";
|
|
|
|
#else
|
2009-02-10 16:50:09 +03:00
|
|
|
dir += ".dir";
|
2009-06-10 21:03:11 +04:00
|
|
|
#endif
|
2009-02-10 16:50:09 +03:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsExecutableWithExports()
|
|
|
|
{
|
2008-01-28 21:05:58 +03:00
|
|
|
return (this->GetType() == cmTarget::EXECUTABLE &&
|
|
|
|
this->GetPropertyAsBool("ENABLE_EXPORTS"));
|
|
|
|
}
|
|
|
|
|
2008-08-18 19:39:22 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsLinkable()
|
|
|
|
{
|
|
|
|
return (this->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::UNKNOWN_LIBRARY ||
|
2012-11-02 18:47:40 +04:00
|
|
|
this->GetType() == cmTarget::INTERFACE_LIBRARY ||
|
2008-08-18 19:39:22 +04:00
|
|
|
this->IsExecutableWithExports());
|
|
|
|
}
|
|
|
|
|
2009-08-11 17:07:42 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HasImportLibrary()
|
|
|
|
{
|
|
|
|
return (this->DLLPlatform &&
|
|
|
|
(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->IsExecutableWithExports()));
|
|
|
|
}
|
|
|
|
|
2008-01-28 21:05:58 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsFrameworkOnApple()
|
|
|
|
{
|
|
|
|
return (this->GetType() == cmTarget::SHARED_LIBRARY &&
|
|
|
|
this->Makefile->IsOn("APPLE") &&
|
|
|
|
this->GetPropertyAsBool("FRAMEWORK"));
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
2008-01-28 22:46:16 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsAppBundleOnApple()
|
|
|
|
{
|
|
|
|
return (this->GetType() == cmTarget::EXECUTABLE &&
|
|
|
|
this->Makefile->IsOn("APPLE") &&
|
|
|
|
this->GetPropertyAsBool("MACOSX_BUNDLE"));
|
|
|
|
}
|
|
|
|
|
2010-10-07 06:43:04 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsCFBundleOnApple()
|
|
|
|
{
|
|
|
|
return (this->GetType() == cmTarget::MODULE_LIBRARY &&
|
|
|
|
this->Makefile->IsOn("APPLE") &&
|
|
|
|
this->GetPropertyAsBool("BUNDLE"));
|
|
|
|
}
|
|
|
|
|
2013-05-06 06:19:05 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsBundleOnApple()
|
|
|
|
{
|
|
|
|
return this->IsFrameworkOnApple() || this->IsAppBundleOnApple() ||
|
|
|
|
this->IsCFBundleOnApple();
|
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class cmTargetTraceDependencies
|
|
|
|
{
|
|
|
|
public:
|
2013-07-15 20:47:27 +04:00
|
|
|
cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal);
|
2007-06-18 19:59:23 +04:00
|
|
|
void Trace();
|
|
|
|
private:
|
|
|
|
cmTarget* Target;
|
2009-09-07 18:11:43 +04:00
|
|
|
cmTargetInternals* Internal;
|
2007-06-18 19:59:23 +04:00
|
|
|
cmMakefile* Makefile;
|
|
|
|
cmGlobalGenerator* GlobalGenerator;
|
2009-09-07 18:11:43 +04:00
|
|
|
typedef cmTargetInternals::SourceEntry SourceEntry;
|
|
|
|
SourceEntry* CurrentEntry;
|
2009-09-04 20:39:18 +04:00
|
|
|
std::queue<cmSourceFile*> SourceQueue;
|
|
|
|
std::set<cmSourceFile*> SourcesQueued;
|
|
|
|
typedef std::map<cmStdString, cmSourceFile*> NameMapType;
|
|
|
|
NameMapType NameMap;
|
|
|
|
|
|
|
|
void QueueSource(cmSourceFile* sf);
|
|
|
|
void FollowName(std::string const& name);
|
|
|
|
void FollowNames(std::vector<std::string> const& names);
|
2007-06-18 19:59:23 +04:00
|
|
|
bool IsUtility(std::string const& dep);
|
|
|
|
void CheckCustomCommand(cmCustomCommand const& cc);
|
|
|
|
void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
|
|
|
|
};
|
2007-05-09 16:25:45 +04:00
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetTraceDependencies
|
2013-07-15 20:47:27 +04:00
|
|
|
::cmTargetTraceDependencies(cmTarget* target, cmTargetInternals* internal):
|
2009-09-07 18:11:43 +04:00
|
|
|
Target(target), Internal(internal)
|
2007-05-23 21:27:00 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
// Convenience.
|
|
|
|
this->Makefile = this->Target->GetMakefile();
|
|
|
|
this->GlobalGenerator =
|
|
|
|
this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
2009-09-07 18:11:43 +04:00
|
|
|
this->CurrentEntry = 0;
|
2007-06-18 19:59:23 +04:00
|
|
|
|
|
|
|
// Queue all the source files already specified for the target.
|
|
|
|
std::vector<cmSourceFile*> const& sources = this->Target->GetSourceFiles();
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
|
|
|
|
si != sources.end(); ++si)
|
2007-05-23 21:27:00 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
this->QueueSource(*si);
|
2007-06-18 19:59:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Queue pre-build, pre-link, and post-build rule dependencies.
|
|
|
|
this->CheckCustomCommands(this->Target->GetPreBuildCommands());
|
|
|
|
this->CheckCustomCommands(this->Target->GetPreLinkCommands());
|
|
|
|
this->CheckCustomCommands(this->Target->GetPostBuildCommands());
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTargetTraceDependencies::Trace()
|
|
|
|
{
|
|
|
|
// Process one dependency at a time until the queue is empty.
|
2009-09-04 20:39:18 +04:00
|
|
|
while(!this->SourceQueue.empty())
|
2007-06-18 19:59:23 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
// Get the next source from the queue.
|
|
|
|
cmSourceFile* sf = this->SourceQueue.front();
|
|
|
|
this->SourceQueue.pop();
|
2009-09-07 18:11:43 +04:00
|
|
|
this->CurrentEntry = &this->Internal->SourceEntries[sf];
|
2007-06-18 19:59:23 +04:00
|
|
|
|
2009-09-04 20:39:18 +04:00
|
|
|
// Queue dependencies added explicitly by the user.
|
|
|
|
if(const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS"))
|
2007-05-23 21:27:00 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
std::vector<std::string> objDeps;
|
|
|
|
cmSystemTools::ExpandListArgument(additionalDeps, objDeps);
|
|
|
|
this->FollowNames(objDeps);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Queue the source needed to generate this file, if any.
|
|
|
|
this->FollowName(sf->GetFullPath());
|
2007-06-18 19:59:23 +04:00
|
|
|
|
2009-09-04 20:39:18 +04:00
|
|
|
// Queue dependencies added programatically by commands.
|
|
|
|
this->FollowNames(sf->GetDepends());
|
|
|
|
|
|
|
|
// Queue custom command dependencies.
|
|
|
|
if(cmCustomCommand const* cc = sf->GetCustomCommand())
|
|
|
|
{
|
|
|
|
this->CheckCustomCommand(*cc);
|
2007-05-23 21:27:00 +04:00
|
|
|
}
|
|
|
|
}
|
2009-09-07 18:11:43 +04:00
|
|
|
this->CurrentEntry = 0;
|
2007-05-23 21:27:00 +04:00
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-09-04 20:39:18 +04:00
|
|
|
void cmTargetTraceDependencies::QueueSource(cmSourceFile* sf)
|
|
|
|
{
|
|
|
|
if(this->SourcesQueued.insert(sf).second)
|
|
|
|
{
|
|
|
|
this->SourceQueue.push(sf);
|
|
|
|
|
|
|
|
// Make sure this file is in the target.
|
|
|
|
this->Target->AddSourceFile(sf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTargetTraceDependencies::FollowName(std::string const& name)
|
2007-06-18 19:59:23 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
NameMapType::iterator i = this->NameMap.find(name);
|
|
|
|
if(i == this->NameMap.end())
|
2007-06-18 19:59:23 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
// Check if we know how to generate this file.
|
|
|
|
cmSourceFile* sf = this->Makefile->GetSourceFileWithOutput(name.c_str());
|
|
|
|
NameMapType::value_type entry(name, sf);
|
|
|
|
i = this->NameMap.insert(entry).first;
|
|
|
|
}
|
|
|
|
if(cmSourceFile* sf = i->second)
|
|
|
|
{
|
2009-09-07 18:11:43 +04:00
|
|
|
// Record the dependency we just followed.
|
|
|
|
if(this->CurrentEntry)
|
|
|
|
{
|
|
|
|
this->CurrentEntry->Depends.push_back(sf);
|
|
|
|
}
|
|
|
|
|
2009-09-04 20:39:18 +04:00
|
|
|
this->QueueSource(sf);
|
2007-06-18 19:59:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2007-05-23 21:27:00 +04:00
|
|
|
void
|
2009-09-04 20:39:18 +04:00
|
|
|
cmTargetTraceDependencies::FollowNames(std::vector<std::string> const& names)
|
2007-05-09 16:25:45 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
for(std::vector<std::string>::const_iterator i = names.begin();
|
|
|
|
i != names.end(); ++i)
|
2007-05-09 16:25:45 +04:00
|
|
|
{
|
2009-09-04 20:39:18 +04:00
|
|
|
this->FollowName(*i);
|
2007-05-09 16:25:45 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
|
|
|
|
{
|
|
|
|
// Dependencies on targets (utilities) are supposed to be named by
|
|
|
|
// just the target name. However for compatibility we support
|
|
|
|
// naming the output file generated by the target (assuming there is
|
|
|
|
// no output-name property which old code would not have set). In
|
|
|
|
// that case the target name will be the file basename of the
|
|
|
|
// dependency.
|
|
|
|
std::string util = cmSystemTools::GetFilenameName(dep);
|
|
|
|
if(cmSystemTools::GetFilenameLastExtension(util) == ".exe")
|
|
|
|
{
|
|
|
|
util = cmSystemTools::GetFilenameWithoutLastExtension(util);
|
|
|
|
}
|
2007-05-09 16:25:45 +04:00
|
|
|
|
2010-12-08 20:22:13 +03:00
|
|
|
// Check for a target with this name.
|
|
|
|
if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
// If we find the target and the dep was given as a full path,
|
|
|
|
// then make sure it was not a full path to something else, and
|
|
|
|
// the fact that the name matched a target was just a coincidence.
|
|
|
|
if(cmSystemTools::FileIsFullPath(dep.c_str()))
|
2003-07-31 23:32:53 +04:00
|
|
|
{
|
2011-08-17 00:05:33 +04:00
|
|
|
if(t->GetType() >= cmTarget::EXECUTABLE &&
|
2009-09-25 21:23:19 +04:00
|
|
|
t->GetType() <= cmTarget::MODULE_LIBRARY)
|
2005-07-26 21:26:37 +04:00
|
|
|
{
|
2009-09-25 21:23:19 +04:00
|
|
|
// This is really only for compatibility so we do not need to
|
|
|
|
// worry about configuration names and output names.
|
|
|
|
std::string tLocation = t->GetLocation(0);
|
|
|
|
tLocation = cmSystemTools::GetFilenamePath(tLocation);
|
|
|
|
std::string depLocation = cmSystemTools::GetFilenamePath(dep);
|
|
|
|
depLocation = cmSystemTools::CollapseFullPath(depLocation.c_str());
|
|
|
|
tLocation = cmSystemTools::CollapseFullPath(tLocation.c_str());
|
|
|
|
if(depLocation == tLocation)
|
|
|
|
{
|
|
|
|
this->Target->AddUtility(util.c_str());
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-31 23:32:53 +04:00
|
|
|
}
|
|
|
|
}
|
2007-06-18 19:59:23 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// The original name of the dependency was not a full path. It
|
|
|
|
// must name a target, so add the target-level dependency.
|
|
|
|
this->Target->AddUtility(util.c_str());
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-31 23:32:53 +04:00
|
|
|
}
|
2007-06-18 19:59:23 +04:00
|
|
|
|
|
|
|
// The dependency does not name a target built in this project.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmTargetTraceDependencies
|
|
|
|
::CheckCustomCommand(cmCustomCommand const& cc)
|
|
|
|
{
|
|
|
|
// Transform command names that reference targets built in this
|
|
|
|
// project to corresponding target-level dependencies.
|
2012-09-12 17:11:25 +04:00
|
|
|
cmGeneratorExpression ge(cc.GetBacktrace());
|
|
|
|
|
|
|
|
// Add target-level dependencies referenced by generator expressions.
|
|
|
|
std::set<cmTarget*> targets;
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
|
|
|
|
cit != cc.GetCommandLines().end(); ++cit)
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
std::string const& command = *cit->begin();
|
2010-12-08 20:22:13 +03:00
|
|
|
// Check for a target with this name.
|
|
|
|
if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
if(t->GetType() == cmTarget::EXECUTABLE)
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
// The command refers to an executable target built in
|
|
|
|
// this project. Add the target-level dependency to make
|
|
|
|
// sure the executable is up to date before this custom
|
|
|
|
// command possibly runs.
|
|
|
|
this->Target->AddUtility(command.c_str());
|
2003-06-24 23:10:47 +04:00
|
|
|
}
|
|
|
|
}
|
2010-12-09 00:13:07 +03:00
|
|
|
|
|
|
|
// Check for target references in generator expressions.
|
|
|
|
for(cmCustomCommandLine::const_iterator cli = cit->begin();
|
|
|
|
cli != cit->end(); ++cli)
|
|
|
|
{
|
2012-11-19 22:30:56 +04:00
|
|
|
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge
|
|
|
|
= ge.Parse(*cli);
|
|
|
|
cge->Evaluate(this->Makefile, 0, true);
|
|
|
|
std::set<cmTarget*> geTargets = cge->GetTargets();
|
2012-09-12 17:11:25 +04:00
|
|
|
for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
|
|
|
|
it != geTargets.end(); ++it)
|
|
|
|
{
|
|
|
|
targets.insert(*it);
|
|
|
|
}
|
2010-12-09 00:13:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for(std::set<cmTarget*>::iterator ti = targets.begin();
|
|
|
|
ti != targets.end(); ++ti)
|
|
|
|
{
|
|
|
|
this->Target->AddUtility((*ti)->GetName());
|
2003-06-24 23:10:47 +04:00
|
|
|
}
|
2007-05-09 17:35:59 +04:00
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
// Queue the custom command dependencies.
|
|
|
|
std::vector<std::string> const& depends = cc.GetDepends();
|
|
|
|
for(std::vector<std::string>::const_iterator di = depends.begin();
|
|
|
|
di != depends.end(); ++di)
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
std::string const& dep = *di;
|
|
|
|
if(!this->IsUtility(dep))
|
2003-06-24 23:10:47 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
// The dependency does not name a target and may be a file we
|
|
|
|
// know how to generate. Queue it.
|
2009-09-04 20:39:18 +04:00
|
|
|
this->FollowName(dep);
|
2003-06-24 23:10:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmTargetTraceDependencies
|
|
|
|
::CheckCustomCommands(const std::vector<cmCustomCommand>& commands)
|
2001-04-25 00:49:12 +04:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
for(std::vector<cmCustomCommand>::const_iterator cli = commands.begin();
|
|
|
|
cli != commands.end(); ++cli)
|
2007-02-17 00:12:17 +03:00
|
|
|
{
|
2007-06-18 19:59:23 +04:00
|
|
|
this->CheckCustomCommand(*cli);
|
2007-02-17 00:12:17 +03:00
|
|
|
}
|
2007-06-18 19:59:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-07-15 20:47:27 +04:00
|
|
|
void cmTarget::TraceDependencies()
|
2007-06-18 19:59:23 +04:00
|
|
|
{
|
2010-12-09 18:12:12 +03:00
|
|
|
// CMake-generated targets have no dependencies to trace. Normally tracing
|
|
|
|
// would find nothing anyway, but when building CMake itself the "install"
|
|
|
|
// target command ends up referencing the "cmake" target but we do not
|
|
|
|
// really want the dependency because "install" depend on "all" anyway.
|
|
|
|
if(this->GetType() == cmTarget::GLOBAL_TARGET)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
// Use a helper object to trace the dependencies.
|
2013-07-15 20:47:27 +04:00
|
|
|
cmTargetTraceDependencies tracer(this, this->Internal.Get());
|
2007-06-18 19:59:23 +04:00
|
|
|
tracer.Trace();
|
|
|
|
}
|
|
|
|
|
2008-05-13 01:43:45 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::FindSourceFiles()
|
|
|
|
{
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator
|
|
|
|
si = this->SourceFiles.begin();
|
|
|
|
si != this->SourceFiles.end(); ++si)
|
|
|
|
{
|
2010-09-13 23:56:06 +04:00
|
|
|
std::string e;
|
|
|
|
if((*si)->GetFullPath(&e).empty())
|
2008-05-13 01:43:45 +04:00
|
|
|
{
|
2010-09-13 23:56:06 +04:00
|
|
|
if(!e.empty())
|
|
|
|
{
|
|
|
|
cmake* cm = this->Makefile->GetCMakeInstance();
|
|
|
|
cm->IssueMessage(cmake::FATAL_ERROR, e,
|
|
|
|
this->GetBacktrace());
|
|
|
|
}
|
2008-05-13 01:43:45 +04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-09-04 20:39:05 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::vector<cmSourceFile*> const& cmTarget::GetSourceFiles()
|
|
|
|
{
|
|
|
|
return this->SourceFiles;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::AddSourceFile(cmSourceFile* sf)
|
|
|
|
{
|
2009-09-07 18:11:43 +04:00
|
|
|
typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
|
|
|
|
SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
|
|
|
|
if(i == this->Internal->SourceEntries.end())
|
2009-09-04 20:39:05 +04:00
|
|
|
{
|
2009-09-07 18:11:43 +04:00
|
|
|
typedef cmTargetInternals::SourceEntry SourceEntry;
|
|
|
|
SourceEntriesType::value_type entry(sf, SourceEntry());
|
|
|
|
i = this->Internal->SourceEntries.insert(entry).first;
|
2009-09-04 20:39:05 +04:00
|
|
|
this->SourceFiles.push_back(sf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-07 18:11:43 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::vector<cmSourceFile*> const*
|
|
|
|
cmTarget::GetSourceDepends(cmSourceFile* sf)
|
|
|
|
{
|
|
|
|
typedef cmTargetInternals::SourceEntriesType SourceEntriesType;
|
|
|
|
SourceEntriesType::iterator i = this->Internal->SourceEntries.find(sf);
|
|
|
|
if(i != this->Internal->SourceEntries.end())
|
|
|
|
{
|
|
|
|
return &i->second.Depends;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-06-18 19:59:23 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::AddSources(std::vector<std::string> const& srcs)
|
|
|
|
{
|
|
|
|
for(std::vector<std::string>::const_iterator i = srcs.begin();
|
|
|
|
i != srcs.end(); ++i)
|
2001-04-25 00:49:12 +04:00
|
|
|
{
|
2012-03-12 22:40:58 +04:00
|
|
|
const char* src = i->c_str();
|
|
|
|
if(src[0] == '$' && src[1] == '<')
|
|
|
|
{
|
|
|
|
this->ProcessSourceExpression(*i);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->AddSource(src);
|
|
|
|
}
|
2001-04-25 00:49:12 +04:00
|
|
|
}
|
|
|
|
}
|
2001-04-30 18:44:00 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2007-06-18 19:59:23 +04:00
|
|
|
cmSourceFile* cmTarget::AddSource(const char* s)
|
|
|
|
{
|
|
|
|
std::string src = s;
|
|
|
|
|
|
|
|
// For backwards compatibility replace varibles in source names.
|
|
|
|
// This should eventually be removed.
|
|
|
|
this->Makefile->ExpandVariablesInString(src);
|
|
|
|
|
|
|
|
cmSourceFile* sf = this->Makefile->GetOrCreateSource(src.c_str());
|
|
|
|
this->AddSourceFile(sf);
|
|
|
|
return sf;
|
|
|
|
}
|
|
|
|
|
2012-03-12 22:40:58 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ProcessSourceExpression(std::string const& expr)
|
|
|
|
{
|
|
|
|
if(strncmp(expr.c_str(), "$<TARGET_OBJECTS:", 17) == 0 &&
|
|
|
|
expr[expr.size()-1] == '>')
|
|
|
|
{
|
|
|
|
std::string objLibName = expr.substr(17, expr.size()-18);
|
|
|
|
this->ObjectLibraries.push_back(objLibName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Unrecognized generator expression:\n"
|
|
|
|
<< " " << expr;
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-10 19:06:15 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
struct cmTarget::SourceFileFlags
|
|
|
|
cmTarget::GetTargetSourceFileFlags(const cmSourceFile* sf)
|
|
|
|
{
|
|
|
|
struct SourceFileFlags flags;
|
2008-02-19 00:38:34 +03:00
|
|
|
this->ConstructSourceFileFlags();
|
|
|
|
std::map<cmSourceFile const*, SourceFileFlags>::iterator si =
|
|
|
|
this->Internal->SourceFlagsMap.find(sf);
|
|
|
|
if(si != this->Internal->SourceFlagsMap.end())
|
|
|
|
{
|
|
|
|
flags = si->second;
|
|
|
|
}
|
|
|
|
return flags;
|
|
|
|
}
|
2007-10-10 19:06:15 +04:00
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ConstructSourceFileFlags()
|
|
|
|
{
|
|
|
|
if(this->Internal->SourceFileFlagsConstructed)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->Internal->SourceFileFlagsConstructed = true;
|
2007-10-10 19:06:15 +04:00
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
// Process public headers to mark the source files.
|
|
|
|
if(const char* files = this->GetProperty("PUBLIC_HEADER"))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
|
|
|
std::vector<std::string> relFiles;
|
|
|
|
cmSystemTools::ExpandListArgument(files, relFiles);
|
2008-02-19 00:38:34 +03:00
|
|
|
for(std::vector<std::string>::iterator it = relFiles.begin();
|
|
|
|
it != relFiles.end(); ++it)
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
|
|
|
|
flags.MacFolder = "Headers";
|
|
|
|
flags.Type = cmTarget::SourceFileTypePublicHeader;
|
2007-10-10 19:06:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
// Process private headers after public headers so that they take
|
|
|
|
// precedence if a file is listed in both.
|
|
|
|
if(const char* files = this->GetProperty("PRIVATE_HEADER"))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
std::vector<std::string> relFiles;
|
|
|
|
cmSystemTools::ExpandListArgument(files, relFiles);
|
|
|
|
for(std::vector<std::string>::iterator it = relFiles.begin();
|
|
|
|
it != relFiles.end(); ++it)
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
|
|
|
|
flags.MacFolder = "PrivateHeaders";
|
|
|
|
flags.Type = cmTarget::SourceFileTypePrivateHeader;
|
2007-10-10 19:06:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
// Mark sources listed as resources.
|
|
|
|
if(const char* files = this->GetProperty("RESOURCE"))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
std::vector<std::string> relFiles;
|
|
|
|
cmSystemTools::ExpandListArgument(files, relFiles);
|
|
|
|
for(std::vector<std::string>::iterator it = relFiles.begin();
|
|
|
|
it != relFiles.end(); ++it)
|
|
|
|
{
|
|
|
|
if(cmSourceFile* sf = this->Makefile->GetSource(it->c_str()))
|
|
|
|
{
|
|
|
|
SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
|
|
|
|
flags.MacFolder = "Resources";
|
|
|
|
flags.Type = cmTarget::SourceFileTypeResource;
|
|
|
|
}
|
|
|
|
}
|
2007-10-10 19:06:15 +04:00
|
|
|
}
|
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
// Handle the MACOSX_PACKAGE_LOCATION property on source files that
|
|
|
|
// were not listed in one of the other lists.
|
|
|
|
std::vector<cmSourceFile*> const& sources = this->GetSourceFiles();
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator si = sources.begin();
|
|
|
|
si != sources.end(); ++si)
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
cmSourceFile* sf = *si;
|
|
|
|
if(const char* location = sf->GetProperty("MACOSX_PACKAGE_LOCATION"))
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
SourceFileFlags& flags = this->Internal->SourceFlagsMap[sf];
|
|
|
|
if(flags.Type == cmTarget::SourceFileTypeNormal)
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
flags.MacFolder = location;
|
|
|
|
if(strcmp(location, "Resources") == 0)
|
2007-10-10 19:06:15 +04:00
|
|
|
{
|
2008-02-19 00:38:34 +03:00
|
|
|
flags.Type = cmTarget::SourceFileTypeResource;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
flags.Type = cmTarget::SourceFileTypeMacContent;
|
2007-10-10 19:06:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-05-04 00:34:05 +04:00
|
|
|
void cmTarget::MergeLinkLibraries( cmMakefile& mf,
|
|
|
|
const char *selfname,
|
2006-03-15 19:02:08 +03:00
|
|
|
const LinkLibraryVectorType& libs )
|
2002-05-04 00:34:05 +04:00
|
|
|
{
|
2002-05-10 21:35:42 +04:00
|
|
|
// Only add on libraries we haven't added on before.
|
|
|
|
// Assumption: the global link libraries could only grow, never shrink
|
2006-03-15 19:02:08 +03:00
|
|
|
LinkLibraryVectorType::const_iterator i = libs.begin();
|
|
|
|
i += this->PrevLinkedLibraries.size();
|
2002-05-10 21:35:42 +04:00
|
|
|
for( ; i != libs.end(); ++i )
|
2002-05-04 00:34:05 +04:00
|
|
|
{
|
2002-05-10 21:35:42 +04:00
|
|
|
// We call this so that the dependencies get written to the cache
|
|
|
|
this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
|
2013-06-04 18:21:33 +04:00
|
|
|
|
|
|
|
if (this->GetType() == cmTarget::STATIC_LIBRARY)
|
|
|
|
{
|
|
|
|
this->AppendProperty("INTERFACE_LINK_LIBRARIES",
|
|
|
|
("$<LINK_ONLY:" +
|
|
|
|
this->GetDebugGeneratorExpressions(i->first.c_str(), i->second) +
|
|
|
|
">").c_str());
|
|
|
|
}
|
2002-05-04 00:34:05 +04:00
|
|
|
}
|
2006-03-15 19:02:08 +03:00
|
|
|
this->PrevLinkedLibraries = libs;
|
2002-05-04 00:34:05 +04:00
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2002-05-04 00:34:05 +04:00
|
|
|
void cmTarget::AddLinkDirectory(const char* d)
|
|
|
|
{
|
|
|
|
// Make sure we don't add unnecessary search directories.
|
2008-01-22 17:13:04 +03:00
|
|
|
if(this->LinkDirectoriesEmmitted.insert(d).second)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2008-01-22 17:13:04 +03:00
|
|
|
this->LinkDirectories.push_back(d);
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
2002-05-04 00:34:05 +04:00
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
const std::vector<std::string>& cmTarget::GetLinkDirectories()
|
|
|
|
{
|
2006-03-15 19:02:08 +03:00
|
|
|
return this->LinkDirectories;
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
2002-05-04 00:34:05 +04:00
|
|
|
|
2008-09-05 01:34:25 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTarget::LinkLibraryType cmTarget::ComputeLinkType(const char* config)
|
|
|
|
{
|
|
|
|
// No configuration is always optimized.
|
|
|
|
if(!(config && *config))
|
|
|
|
{
|
|
|
|
return cmTarget::OPTIMIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the list of configurations considered to be DEBUG.
|
|
|
|
std::vector<std::string> const& debugConfigs =
|
|
|
|
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
|
|
|
|
|
|
|
|
// Check if any entry in the list matches this configuration.
|
|
|
|
std::string configUpper = cmSystemTools::UpperCase(config);
|
|
|
|
for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
|
|
|
|
i != debugConfigs.end(); ++i)
|
|
|
|
{
|
|
|
|
if(*i == configUpper)
|
|
|
|
{
|
|
|
|
return cmTarget::DEBUG;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The current configuration is not a debug configuration.
|
|
|
|
return cmTarget::OPTIMIZED;
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ClearDependencyInformation( cmMakefile& mf,
|
2006-05-12 22:12:13 +04:00
|
|
|
const char* target )
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
|
|
|
// Clear the dependencies. The cache variable must exist iff we are
|
|
|
|
// recording dependency information for this target.
|
|
|
|
std::string depname = target;
|
|
|
|
depname += "_LIB_DEPENDS";
|
2006-03-15 19:02:08 +03:00
|
|
|
if (this->RecordDependencies)
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
|
|
|
mf.AddCacheDefinition(depname.c_str(), "",
|
|
|
|
"Dependencies for target", cmCacheManager::STATIC);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (mf.GetDefinition( depname.c_str() ))
|
|
|
|
{
|
|
|
|
std::string message = "Target ";
|
|
|
|
message += target;
|
|
|
|
message += " has dependency information when it shouldn't.\n";
|
|
|
|
message += "Your cache is probably stale. Please remove the entry\n ";
|
|
|
|
message += depname;
|
|
|
|
message += "\nfrom the cache.";
|
2007-07-02 21:32:41 +04:00
|
|
|
cmSystemTools::Error( message.c_str() );
|
2002-11-20 02:01:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-10-10 19:06:15 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::NameResolvesToFramework(const std::string& libname)
|
|
|
|
{
|
|
|
|
return this->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
|
|
|
|
NameResolvesToFramework(libname);
|
|
|
|
}
|
|
|
|
|
2012-12-06 15:14:03 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetDirectLinkLibraries(const char *config,
|
|
|
|
std::vector<std::string> &libs, cmTarget *head)
|
|
|
|
{
|
|
|
|
const char *prop = this->GetProperty("LINK_LIBRARIES");
|
|
|
|
if (prop)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
2012-11-05 17:48:42 +04:00
|
|
|
const cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
|
2012-12-06 15:14:03 +04:00
|
|
|
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
|
|
|
this->GetName(),
|
|
|
|
"LINK_LIBRARIES", 0, 0);
|
2012-11-05 17:48:42 +04:00
|
|
|
cmSystemTools::ExpandListArgument(cge->Evaluate(this->Makefile,
|
2012-12-06 15:14:03 +04:00
|
|
|
config,
|
|
|
|
false,
|
|
|
|
head,
|
|
|
|
&dagChecker),
|
|
|
|
libs);
|
2012-11-05 17:48:42 +04:00
|
|
|
|
2013-02-07 16:04:46 +04:00
|
|
|
std::set<cmStdString> seenProps = cge->GetSeenTargetProperties();
|
|
|
|
for (std::set<cmStdString>::const_iterator it = seenProps.begin();
|
|
|
|
it != seenProps.end(); ++it)
|
|
|
|
{
|
|
|
|
if (!this->GetProperty(it->c_str()))
|
|
|
|
{
|
|
|
|
this->LinkImplicitNullProperties.insert(*it);
|
|
|
|
}
|
|
|
|
}
|
2012-12-06 15:14:03 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetDebugGeneratorExpressions(const std::string &value,
|
|
|
|
cmTarget::LinkLibraryType llt)
|
|
|
|
{
|
|
|
|
if (llt == GENERAL)
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the list of configurations considered to be DEBUG.
|
|
|
|
std::vector<std::string> const& debugConfigs =
|
|
|
|
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
|
|
|
|
|
|
|
|
std::string configString = "$<CONFIG:" + debugConfigs[0] + ">";
|
|
|
|
|
|
|
|
if (debugConfigs.size() > 1)
|
|
|
|
{
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
li = debugConfigs.begin() + 1; li != debugConfigs.end(); ++li)
|
|
|
|
{
|
|
|
|
configString += ",$<CONFIG:" + *li + ">";
|
|
|
|
}
|
|
|
|
configString = "$<OR:" + configString + ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (llt == OPTIMIZED)
|
|
|
|
{
|
|
|
|
configString = "$<NOT:" + configString + ">";
|
|
|
|
}
|
|
|
|
return "$<" + configString + ":" + value + ">";
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static std::string targetNameGenex(const char *lib)
|
|
|
|
{
|
|
|
|
return std::string("$<TARGET_NAME:") + lib + ">";
|
|
|
|
}
|
|
|
|
|
2013-06-04 18:21:33 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::PushTLLCommandTrace(TLLSignature signature)
|
|
|
|
{
|
|
|
|
bool ret = true;
|
|
|
|
if (!this->TLLCommands.empty())
|
|
|
|
{
|
|
|
|
if (this->TLLCommands.back().first != signature)
|
|
|
|
{
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
this->TLLCommands.push_back(std::make_pair(signature, lfbt));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetTllSignatureTraces(cmOStringStream &s,
|
|
|
|
TLLSignature sig) const
|
|
|
|
{
|
|
|
|
std::vector<cmListFileBacktrace> sigs;
|
|
|
|
typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container;
|
|
|
|
for(Container::const_iterator it = this->TLLCommands.begin();
|
|
|
|
it != this->TLLCommands.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it->first == sig)
|
|
|
|
{
|
|
|
|
sigs.push_back(it->second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!sigs.empty())
|
|
|
|
{
|
|
|
|
const char *sigString
|
|
|
|
= (sig == cmTarget::KeywordTLLSignature ? "keyword"
|
|
|
|
: "plain");
|
|
|
|
s << "The uses of the " << sigString << " signature are here:\n";
|
2013-07-26 16:02:18 +04:00
|
|
|
std::set<cmStdString> emitted;
|
2013-06-04 18:21:33 +04:00
|
|
|
for(std::vector<cmListFileBacktrace>::const_iterator it = sigs.begin();
|
|
|
|
it != sigs.end(); ++it)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace::const_iterator i = it->begin();
|
|
|
|
if(i != it->end())
|
|
|
|
{
|
|
|
|
cmListFileContext const& lfc = *i;
|
2013-07-26 16:02:18 +04:00
|
|
|
cmOStringStream line;
|
|
|
|
line << " * " << (lfc.Line? "": " in ") << lfc << std::endl;
|
|
|
|
if (emitted.insert(line.str()).second)
|
|
|
|
{
|
|
|
|
s << line.str();
|
|
|
|
}
|
2013-06-04 18:21:33 +04:00
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-05-01 22:00:21 +04:00
|
|
|
void cmTarget::AddLinkLibrary(cmMakefile& mf,
|
2007-07-02 21:32:41 +04:00
|
|
|
const char *target, const char* lib,
|
2002-05-01 22:00:21 +04:00
|
|
|
LinkLibraryType llt)
|
|
|
|
{
|
2002-05-29 23:00:37 +04:00
|
|
|
// Never add a self dependency, even if the user asks for it.
|
|
|
|
if(strcmp( target, lib ) == 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2012-12-06 15:14:03 +04:00
|
|
|
|
|
|
|
cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
|
2012-11-02 18:47:40 +04:00
|
|
|
{
|
2012-12-06 15:14:03 +04:00
|
|
|
const bool isNonImportedTarget = tgt && !tgt->IsImported();
|
|
|
|
|
2013-01-20 14:25:35 +04:00
|
|
|
const std::string libName = (isNonImportedTarget && llt != GENERAL)
|
|
|
|
? targetNameGenex(lib)
|
|
|
|
: std::string(lib);
|
2012-12-06 15:14:03 +04:00
|
|
|
this->AppendProperty("LINK_LIBRARIES",
|
|
|
|
this->GetDebugGeneratorExpressions(libName,
|
|
|
|
llt).c_str());
|
|
|
|
}
|
|
|
|
|
2012-11-02 18:47:40 +04:00
|
|
|
if (cmGeneratorExpression::Find(lib) != std::string::npos
|
|
|
|
|| (tgt && tgt->GetType() == INTERFACE_LIBRARY))
|
2012-12-23 22:00:18 +04:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-11-30 01:10:29 +03:00
|
|
|
cmTarget::LibraryID tmp;
|
2006-11-29 23:45:49 +03:00
|
|
|
tmp.first = lib;
|
|
|
|
tmp.second = llt;
|
|
|
|
this->LinkLibraries.push_back( tmp );
|
2008-01-27 21:42:49 +03:00
|
|
|
this->OriginalLinkLibraries.push_back(tmp);
|
2009-10-05 17:06:59 +04:00
|
|
|
this->ClearLinkMaps();
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2002-05-02 23:56:13 +04:00
|
|
|
// Add the explicit dependency information for this target. This is
|
|
|
|
// simply a set of libraries separated by ";". There should always
|
|
|
|
// be a trailing ";". These library names are not canonical, in that
|
|
|
|
// they may be "-framework x", "-ly", "/path/libz.a", etc.
|
2002-11-20 02:01:05 +03:00
|
|
|
// We shouldn't remove duplicates here because external libraries
|
|
|
|
// may be purposefully duplicated to handle recursive dependencies,
|
|
|
|
// and we removing one instance will break the link line. Duplicates
|
|
|
|
// will be appropriately eliminated at emit time.
|
2006-03-15 19:02:08 +03:00
|
|
|
if(this->RecordDependencies)
|
2002-05-02 23:56:13 +04:00
|
|
|
{
|
2002-06-03 18:25:55 +04:00
|
|
|
std::string targetEntry = target;
|
|
|
|
targetEntry += "_LIB_DEPENDS";
|
|
|
|
std::string dependencies;
|
|
|
|
const char* old_val = mf.GetDefinition( targetEntry.c_str() );
|
|
|
|
if( old_val )
|
|
|
|
{
|
|
|
|
dependencies += old_val;
|
|
|
|
}
|
2006-11-29 19:00:17 +03:00
|
|
|
switch (llt)
|
|
|
|
{
|
|
|
|
case cmTarget::GENERAL:
|
|
|
|
dependencies += "general";
|
|
|
|
break;
|
|
|
|
case cmTarget::DEBUG:
|
|
|
|
dependencies += "debug";
|
|
|
|
break;
|
|
|
|
case cmTarget::OPTIMIZED:
|
|
|
|
dependencies += "optimized";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
dependencies += ";";
|
2002-11-20 02:01:05 +03:00
|
|
|
dependencies += lib;
|
|
|
|
dependencies += ";";
|
2002-06-03 18:25:55 +04:00
|
|
|
mf.AddCacheDefinition( targetEntry.c_str(), dependencies.c_str(),
|
2007-07-02 21:32:41 +04:00
|
|
|
"Dependencies for the target",
|
2002-06-03 18:25:55 +04:00
|
|
|
cmCacheManager::STATIC );
|
2002-05-02 23:56:13 +04:00
|
|
|
}
|
2007-07-02 21:32:41 +04:00
|
|
|
|
2001-04-30 18:44:00 +04:00
|
|
|
}
|
|
|
|
|
2013-07-02 00:55:25 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmTarget::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
|
|
|
|
{
|
|
|
|
for(std::set<cmStdString>::const_iterator li = incs.begin();
|
|
|
|
li != incs.end(); ++li)
|
|
|
|
{
|
|
|
|
this->SystemIncludeDirectories.insert(*li);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
|
|
cmTarget::AddSystemIncludeDirectories(const std::vector<std::string> &incs)
|
|
|
|
{
|
|
|
|
for(std::vector<std::string>::const_iterator li = incs.begin();
|
|
|
|
li != incs.end(); ++li)
|
|
|
|
{
|
|
|
|
this->SystemIncludeDirectories.insert(*li);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-02 16:30:10 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::FinalizeSystemIncludeDirectories()
|
|
|
|
{
|
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
|
|
|
it = this->Internal->LinkInterfacePropertyEntries.begin(),
|
|
|
|
end = this->Internal->LinkInterfacePropertyEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
2013-08-06 13:19:56 +04:00
|
|
|
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
|
|
|
|
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-07-02 16:30:10 +04:00
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(it->Value);
|
|
|
|
std::string targetName = cge->Evaluate(this->Makefile, 0,
|
|
|
|
false, this, 0, 0);
|
2013-08-29 12:28:09 +04:00
|
|
|
cmTarget *tgt = this->Makefile->FindTargetToUse(targetName.c_str());
|
|
|
|
if (!tgt)
|
2013-07-02 16:30:10 +04:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-08-29 12:28:09 +04:00
|
|
|
if (tgt->IsImported()
|
|
|
|
&& tgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")
|
|
|
|
&& !this->GetPropertyAsBool("NO_SYSTEM_FROM_IMPORTED"))
|
|
|
|
{
|
|
|
|
std::string includeGenex = "$<TARGET_PROPERTY:" +
|
|
|
|
it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
|
|
|
|
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
|
|
|
|
{
|
|
|
|
// Because it->Value is a generator expression, ensure that it
|
|
|
|
// evaluates to the non-empty string before being used in the
|
|
|
|
// TARGET_PROPERTY expression.
|
|
|
|
includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
|
|
|
|
}
|
|
|
|
this->SystemIncludeDirectories.insert(includeGenex);
|
|
|
|
return; // The INTERFACE_SYSTEM_INCLUDE_DIRECTORIES are a subset
|
|
|
|
// of the INTERFACE_INCLUDE_DIRECTORIES
|
|
|
|
}
|
2013-07-02 16:30:10 +04:00
|
|
|
}
|
|
|
|
std::string includeGenex = "$<TARGET_PROPERTY:" +
|
|
|
|
it->Value + ",INTERFACE_SYSTEM_INCLUDE_DIRECTORIES>";
|
|
|
|
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
|
|
|
|
{
|
|
|
|
// Because it->Value is a generator expression, ensure that it
|
|
|
|
// evaluates to the non-empty string before being used in the
|
|
|
|
// TARGET_PROPERTY expression.
|
|
|
|
includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
|
|
|
|
}
|
|
|
|
this->SystemIncludeDirectories.insert(includeGenex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-05-01 22:00:21 +04:00
|
|
|
void
|
|
|
|
cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
|
|
|
|
{
|
2002-05-03 08:27:34 +04:00
|
|
|
// There are two key parts of the dependency analysis: (1)
|
|
|
|
// determining the libraries in the link line, and (2) constructing
|
|
|
|
// the dependency graph for those libraries.
|
|
|
|
//
|
|
|
|
// The latter is done using the cache entries that record the
|
|
|
|
// dependencies of each library.
|
|
|
|
//
|
|
|
|
// The former is a more thorny issue, since it is not clear how to
|
|
|
|
// determine if two libraries listed on the link line refer to the a
|
|
|
|
// single library or not. For example, consider the link "libraries"
|
2007-07-02 21:32:41 +04:00
|
|
|
// /usr/lib/libtiff.so -ltiff
|
2002-05-03 08:27:34 +04:00
|
|
|
// Is this one library or two? The solution implemented here is the
|
|
|
|
// simplest (and probably the only practical) one: two libraries are
|
|
|
|
// the same if their "link strings" are identical. Thus, the two
|
|
|
|
// libraries above are considered distinct. This also means that for
|
|
|
|
// dependency analysis to be effective, the CMake user must specify
|
|
|
|
// libraries build by his project without using any linker flags or
|
|
|
|
// file extensions. That is,
|
|
|
|
// LINK_LIBRARIES( One Two )
|
|
|
|
// instead of
|
|
|
|
// LINK_LIBRARIES( -lOne ${binarypath}/libTwo.a )
|
|
|
|
// The former is probably what most users would do, but it never
|
|
|
|
// hurts to document the assumptions. :-) Therefore, in the analysis
|
|
|
|
// code, the "canonical name" of a library is simply its name as
|
|
|
|
// given to a LINK_LIBRARIES command.
|
2002-05-04 00:34:05 +04:00
|
|
|
//
|
|
|
|
// Also, we will leave the original link line intact; we will just add any
|
|
|
|
// dependencies that were missing.
|
2002-11-20 02:01:05 +03:00
|
|
|
//
|
|
|
|
// There is a problem with recursive external libraries
|
|
|
|
// (i.e. libraries with no dependency information that are
|
|
|
|
// recursively dependent). We must make sure that the we emit one of
|
|
|
|
// the libraries twice to satisfy the recursion, but we shouldn't
|
|
|
|
// emit it more times than necessary. In particular, we must make
|
|
|
|
// sure that handling this improbable case doesn't cost us when
|
|
|
|
// dealing with the common case of non-recursive libraries. The
|
|
|
|
// solution is to assume that the recursion is satisfied at one node
|
|
|
|
// of the dependency tree. To illustrate, assume libA and libB are
|
|
|
|
// extrenal and mutually dependent. Suppose libX depends on
|
|
|
|
// libA, and libY on libA and libX. Then
|
|
|
|
// TARGET_LINK_LIBRARIES( Y X A B A )
|
|
|
|
// TARGET_LINK_LIBRARIES( X A B A )
|
|
|
|
// TARGET_LINK_LIBRARIES( Exec Y )
|
|
|
|
// would result in "-lY -lX -lA -lB -lA". This is the correct way to
|
|
|
|
// specify the dependencies, since the mutual dependency of A and B
|
|
|
|
// is resolved *every time libA is specified*.
|
|
|
|
//
|
|
|
|
// Something like
|
|
|
|
// TARGET_LINK_LIBRARIES( Y X A B A )
|
|
|
|
// TARGET_LINK_LIBRARIES( X A B )
|
|
|
|
// TARGET_LINK_LIBRARIES( Exec Y )
|
|
|
|
// would result in "-lY -lX -lA -lB", and the mutual dependency
|
|
|
|
// information is lost. This is because in some case (Y), the mutual
|
|
|
|
// dependency of A and B is listed, while in another other case (X),
|
|
|
|
// it is not. Depending on which line actually emits A, the mutual
|
|
|
|
// dependency may or may not be on the final link line. We can't
|
|
|
|
// handle this pathalogical case cleanly without emitting extra
|
|
|
|
// libraries for the normal cases. Besides, the dependency
|
|
|
|
// information for X is wrong anyway: if we build an executable
|
|
|
|
// depending on X alone, we would not have the mutual dependency on
|
|
|
|
// A and B resolved.
|
|
|
|
//
|
|
|
|
// IMPROVEMENTS:
|
|
|
|
// -- The current algorithm will not always pick the "optimal" link line
|
|
|
|
// when recursive dependencies are present. It will instead break the
|
|
|
|
// cycles at an aribtrary point. The majority of projects won't have
|
|
|
|
// cyclic dependencies, so this is probably not a big deal. Note that
|
|
|
|
// the link line is always correct, just not necessary optimal.
|
2002-05-03 08:27:34 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
{
|
|
|
|
// Expand variables in link library names. This is for backwards
|
|
|
|
// compatibility with very early CMake versions and should
|
|
|
|
// eventually be removed. This code was moved here from the end of
|
|
|
|
// old source list processing code which was called just before this
|
|
|
|
// method.
|
|
|
|
for(LinkLibraryVectorType::iterator p = this->LinkLibraries.begin();
|
|
|
|
p != this->LinkLibraries.end(); ++p)
|
|
|
|
{
|
|
|
|
this->Makefile->ExpandVariablesInString(p->first, true, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The dependency map.
|
|
|
|
DependencyMap dep_map;
|
|
|
|
|
|
|
|
// 1. Build the dependency graph
|
|
|
|
//
|
|
|
|
for(LinkLibraryVectorType::reverse_iterator lib
|
|
|
|
= this->LinkLibraries.rbegin();
|
|
|
|
lib != this->LinkLibraries.rend(); ++lib)
|
|
|
|
{
|
|
|
|
this->GatherDependencies( mf, *lib, dep_map);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2. Remove any dependencies that are already satisfied in the original
|
|
|
|
// link line.
|
|
|
|
//
|
|
|
|
for(LinkLibraryVectorType::iterator lib = this->LinkLibraries.begin();
|
|
|
|
lib != this->LinkLibraries.end(); ++lib)
|
|
|
|
{
|
|
|
|
for( LinkLibraryVectorType::iterator lib2 = lib;
|
|
|
|
lib2 != this->LinkLibraries.end(); ++lib2)
|
|
|
|
{
|
|
|
|
this->DeleteDependency( dep_map, *lib, *lib2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 3. Create the new link line by simply emitting any dependencies that are
|
|
|
|
// missing. Start from the back and keep adding.
|
|
|
|
//
|
|
|
|
std::set<DependencyMap::key_type> done, visited;
|
|
|
|
std::vector<DependencyMap::key_type> newLinkLibraries;
|
|
|
|
for(LinkLibraryVectorType::reverse_iterator lib =
|
|
|
|
this->LinkLibraries.rbegin();
|
|
|
|
lib != this->LinkLibraries.rend(); ++lib)
|
|
|
|
{
|
|
|
|
// skip zero size library entries, this may happen
|
|
|
|
// if a variable expands to nothing.
|
|
|
|
if (lib->first.size() != 0)
|
|
|
|
{
|
|
|
|
this->Emit( *lib, dep_map, done, visited, newLinkLibraries );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 4. Add the new libraries to the link line.
|
|
|
|
//
|
|
|
|
for( std::vector<DependencyMap::key_type>::reverse_iterator k =
|
|
|
|
newLinkLibraries.rbegin();
|
|
|
|
k != newLinkLibraries.rend(); ++k )
|
|
|
|
{
|
|
|
|
// get the llt from the dep_map
|
|
|
|
this->LinkLibraries.push_back( std::make_pair(k->first,k->second) );
|
|
|
|
}
|
|
|
|
this->LinkLibrariesAnalyzed = true;
|
2002-05-01 22:00:21 +04:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-11-20 02:01:05 +03:00
|
|
|
void cmTarget::InsertDependency( DependencyMap& depMap,
|
2006-11-29 19:00:17 +03:00
|
|
|
const LibraryID& lib,
|
2007-07-02 21:32:41 +04:00
|
|
|
const LibraryID& dep)
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
|
|
|
depMap[lib].push_back(dep);
|
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-11-20 02:01:05 +03:00
|
|
|
void cmTarget::DeleteDependency( DependencyMap& depMap,
|
2006-11-29 19:00:17 +03:00
|
|
|
const LibraryID& lib,
|
2007-07-02 21:32:41 +04:00
|
|
|
const LibraryID& dep)
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
|
|
|
// Make sure there is an entry in the map for lib. If so, delete all
|
|
|
|
// dependencies to dep. There may be repeated entries because of
|
|
|
|
// external libraries that are specified multiple times.
|
|
|
|
DependencyMap::iterator map_itr = depMap.find( lib );
|
|
|
|
if( map_itr != depMap.end() )
|
|
|
|
{
|
|
|
|
DependencyList& depList = map_itr->second;
|
|
|
|
DependencyList::iterator itr;
|
2007-07-02 21:32:41 +04:00
|
|
|
while( (itr = std::find(depList.begin(), depList.end(), dep)) !=
|
2006-03-10 21:54:57 +03:00
|
|
|
depList.end() )
|
2002-11-20 02:01:05 +03:00
|
|
|
{
|
|
|
|
depList.erase( itr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2006-11-29 19:00:17 +03:00
|
|
|
void cmTarget::Emit(const LibraryID lib,
|
|
|
|
const DependencyMap& dep_map,
|
|
|
|
std::set<LibraryID>& emitted,
|
|
|
|
std::set<LibraryID>& visited,
|
|
|
|
DependencyList& link_line )
|
2002-05-01 22:00:21 +04:00
|
|
|
{
|
|
|
|
// It's already been emitted
|
|
|
|
if( emitted.find(lib) != emitted.end() )
|
2006-11-16 18:57:00 +03:00
|
|
|
{
|
2002-05-01 22:00:21 +04:00
|
|
|
return;
|
2006-11-16 18:57:00 +03:00
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2002-11-20 02:01:05 +03:00
|
|
|
// Emit the dependencies only if this library node hasn't been
|
|
|
|
// visited before. If it has, then we have a cycle. The recursion
|
|
|
|
// that got us here should take care of everything.
|
2002-05-01 22:00:21 +04:00
|
|
|
|
|
|
|
if( visited.insert(lib).second )
|
|
|
|
{
|
|
|
|
if( dep_map.find(lib) != dep_map.end() ) // does it have dependencies?
|
|
|
|
{
|
2002-11-20 02:01:05 +03:00
|
|
|
const DependencyList& dep_on = dep_map.find( lib )->second;
|
|
|
|
DependencyList::const_reverse_iterator i;
|
|
|
|
|
|
|
|
// To cater for recursive external libraries, we must emit
|
|
|
|
// duplicates on this link line *unless* they were emitted by
|
|
|
|
// some other node, in which case we assume that the recursion
|
|
|
|
// was resolved then. We making the simplifying assumption that
|
|
|
|
// any duplicates on a single link line are on purpose, and must
|
|
|
|
// be preserved.
|
|
|
|
|
|
|
|
// This variable will keep track of the libraries that were
|
2012-09-23 17:02:29 +04:00
|
|
|
// emitted directly from the current node, and not from a
|
2002-11-20 02:01:05 +03:00
|
|
|
// recursive call. This way, if we come across a library that
|
|
|
|
// has already been emitted, we repeat it iff it has been
|
|
|
|
// emitted here.
|
2006-11-29 19:00:17 +03:00
|
|
|
std::set<DependencyMap::key_type> emitted_here;
|
2002-11-20 02:01:05 +03:00
|
|
|
for( i = dep_on.rbegin(); i != dep_on.rend(); ++i )
|
2002-05-01 22:00:21 +04:00
|
|
|
{
|
2002-11-20 02:01:05 +03:00
|
|
|
if( emitted_here.find(*i) != emitted_here.end() )
|
|
|
|
{
|
|
|
|
// a repeat. Must emit.
|
|
|
|
emitted.insert(*i);
|
|
|
|
link_line.push_back( *i );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Emit only if no-one else has
|
|
|
|
if( emitted.find(*i) == emitted.end() )
|
|
|
|
{
|
|
|
|
// emit dependencies
|
|
|
|
Emit( *i, dep_map, emitted, visited, link_line );
|
|
|
|
// emit self
|
|
|
|
emitted.insert(*i);
|
|
|
|
emitted_here.insert(*i);
|
|
|
|
link_line.push_back( *i );
|
|
|
|
}
|
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-05-01 22:00:21 +04:00
|
|
|
void cmTarget::GatherDependencies( const cmMakefile& mf,
|
2006-11-29 19:00:17 +03:00
|
|
|
const LibraryID& lib,
|
|
|
|
DependencyMap& dep_map)
|
2002-05-01 22:00:21 +04:00
|
|
|
{
|
|
|
|
// If the library is already in the dependency map, then it has
|
|
|
|
// already been fully processed.
|
|
|
|
if( dep_map.find(lib) != dep_map.end() )
|
2006-11-16 18:57:00 +03:00
|
|
|
{
|
2002-05-01 22:00:21 +04:00
|
|
|
return;
|
2006-11-16 18:57:00 +03:00
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
|
2006-11-29 19:00:17 +03:00
|
|
|
const char* deps = mf.GetDefinition( (lib.first+"_LIB_DEPENDS").c_str() );
|
2002-05-02 10:27:26 +04:00
|
|
|
if( deps && strcmp(deps,"") != 0 )
|
2002-05-01 22:00:21 +04:00
|
|
|
{
|
|
|
|
// Make sure this library is in the map, even if it has an empty
|
|
|
|
// set of dependencies. This distinguishes the case of explicitly
|
|
|
|
// no dependencies with that of unspecified dependencies.
|
|
|
|
dep_map[lib];
|
|
|
|
|
2006-11-29 19:00:17 +03:00
|
|
|
// Parse the dependency information, which is a set of
|
|
|
|
// type, library pairs separated by ";". There is always a trailing ";".
|
|
|
|
cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
|
2002-05-01 22:00:21 +04:00
|
|
|
std::string depline = deps;
|
|
|
|
std::string::size_type start = 0;
|
|
|
|
std::string::size_type end;
|
|
|
|
end = depline.find( ";", start );
|
|
|
|
while( end != std::string::npos )
|
|
|
|
{
|
|
|
|
std::string l = depline.substr( start, end-start );
|
|
|
|
if( l.size() != 0 )
|
|
|
|
{
|
2006-11-29 19:00:17 +03:00
|
|
|
if (l == "debug")
|
|
|
|
{
|
|
|
|
llt = cmTarget::DEBUG;
|
|
|
|
}
|
|
|
|
else if (l == "optimized")
|
|
|
|
{
|
|
|
|
llt = cmTarget::OPTIMIZED;
|
|
|
|
}
|
|
|
|
else if (l == "general")
|
|
|
|
{
|
|
|
|
llt = cmTarget::GENERAL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LibraryID lib2(l,llt);
|
|
|
|
this->InsertDependency( dep_map, lib, lib2);
|
|
|
|
this->GatherDependencies( mf, lib2, dep_map);
|
|
|
|
llt = cmTarget::GENERAL;
|
|
|
|
}
|
2002-05-01 22:00:21 +04:00
|
|
|
}
|
|
|
|
start = end+1; // skip the ;
|
|
|
|
end = depline.find( ";", start );
|
|
|
|
}
|
2006-11-29 19:00:17 +03:00
|
|
|
// cannot depend on itself
|
2007-07-02 21:32:41 +04:00
|
|
|
this->DeleteDependency( dep_map, lib, lib);
|
2002-05-01 22:00:21 +04:00
|
|
|
}
|
|
|
|
}
|
2002-12-21 01:15:45 +03:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2002-12-21 01:15:45 +03:00
|
|
|
void cmTarget::SetProperty(const char* prop, const char* value)
|
|
|
|
{
|
|
|
|
if (!prop)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-07-31 15:16:29 +04:00
|
|
|
if (strcmp(prop, "NAME") == 0)
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "NAME property is read-only\n";
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
|
|
|
return;
|
|
|
|
}
|
2012-11-20 01:47:30 +04:00
|
|
|
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
2012-12-18 19:16:14 +04:00
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
2012-11-20 01:47:30 +04:00
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
deleteAndClear(this->Internal->IncludeDirectoriesEntries);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
|
|
|
this->Internal->IncludeDirectoriesEntries.push_back(
|
2013-05-28 14:32:39 +04:00
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge));
|
2012-11-20 01:47:30 +04:00
|
|
|
return;
|
|
|
|
}
|
2013-05-16 17:15:28 +04:00
|
|
|
if(strcmp(prop,"COMPILE_OPTIONS") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
deleteAndClear(this->Internal->CompileOptionsEntries);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
|
|
|
this->Internal->CompileOptionsEntries.push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge));
|
2012-11-20 01:47:30 +04:00
|
|
|
return;
|
|
|
|
}
|
2013-06-12 12:12:51 +04:00
|
|
|
if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
deleteAndClear(this->Internal->CompileDefinitionsEntries);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
|
|
|
|
this->Internal->CompileDefinitionsEntries.push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge));
|
|
|
|
return;
|
|
|
|
}
|
2013-05-17 12:12:02 +04:00
|
|
|
if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "EXPORT_NAME property can't be set on imported targets (\""
|
|
|
|
<< this->Name << "\")\n";
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
|
|
|
return;
|
|
|
|
}
|
2013-04-29 13:54:19 +04:00
|
|
|
if (strcmp(prop, "LINK_LIBRARIES") == 0)
|
|
|
|
{
|
2013-05-28 14:39:32 +04:00
|
|
|
this->Internal->LinkInterfacePropertyEntries.clear();
|
2013-08-06 13:19:56 +04:00
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmValueWithOrigin entry(value, lfbt);
|
|
|
|
this->Internal->LinkInterfacePropertyEntries.push_back(entry);
|
|
|
|
return;
|
2013-04-29 13:54:19 +04:00
|
|
|
}
|
2006-12-07 17:45:32 +03:00
|
|
|
this->Properties.SetProperty(prop, value, cmProperty::TARGET);
|
2009-10-05 17:06:44 +04:00
|
|
|
this->MaybeInvalidatePropertyCache(prop);
|
2008-01-18 02:13:55 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2011-07-14 01:14:41 +04:00
|
|
|
void cmTarget::AppendProperty(const char* prop, const char* value,
|
|
|
|
bool asString)
|
2008-01-18 02:13:55 +03:00
|
|
|
{
|
|
|
|
if (!prop)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-07-31 15:16:29 +04:00
|
|
|
if (strcmp(prop, "NAME") == 0)
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "NAME property is read-only\n";
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
|
|
|
return;
|
|
|
|
}
|
2012-11-20 01:47:30 +04:00
|
|
|
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
2012-12-18 19:16:14 +04:00
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
2012-11-20 01:47:30 +04:00
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
this->Internal->IncludeDirectoriesEntries.push_back(
|
2013-05-28 14:32:39 +04:00
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
|
2012-11-20 01:47:30 +04:00
|
|
|
return;
|
|
|
|
}
|
2013-05-16 17:15:28 +04:00
|
|
|
if(strcmp(prop,"COMPILE_OPTIONS") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
this->Internal->CompileOptionsEntries.push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
|
2012-11-20 01:47:30 +04:00
|
|
|
return;
|
|
|
|
}
|
2013-06-12 12:12:51 +04:00
|
|
|
if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
this->Internal->CompileDefinitionsEntries.push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
|
|
|
|
return;
|
|
|
|
}
|
2013-05-17 12:12:02 +04:00
|
|
|
if(strcmp(prop,"EXPORT_NAME") == 0 && this->IsImported())
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "EXPORT_NAME property can't be set on imported targets (\""
|
|
|
|
<< this->Name << "\")\n";
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
|
|
|
return;
|
|
|
|
}
|
2013-04-29 13:54:19 +04:00
|
|
|
if (strcmp(prop, "LINK_LIBRARIES") == 0)
|
|
|
|
{
|
2013-08-06 13:19:56 +04:00
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
this->Makefile->GetBacktrace(lfbt);
|
|
|
|
cmValueWithOrigin entry(value, lfbt);
|
|
|
|
this->Internal->LinkInterfacePropertyEntries.push_back(entry);
|
|
|
|
return;
|
2013-04-29 13:54:19 +04:00
|
|
|
}
|
2011-07-14 01:14:41 +04:00
|
|
|
this->Properties.AppendProperty(prop, value, cmProperty::TARGET, asString);
|
2009-10-05 17:06:44 +04:00
|
|
|
this->MaybeInvalidatePropertyCache(prop);
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
|
2013-05-17 12:12:02 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
const char* cmTarget::GetExportName()
|
|
|
|
{
|
|
|
|
const char *exportName = this->GetProperty("EXPORT_NAME");
|
|
|
|
|
|
|
|
if (exportName && *exportName)
|
|
|
|
{
|
|
|
|
if (!cmGeneratorExpression::IsValidTargetName(exportName))
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "EXPORT_NAME property \"" << exportName << "\" for \""
|
|
|
|
<< this->GetName() << "\": is not valid.";
|
|
|
|
cmSystemTools::Error(e.str().c_str());
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
return exportName;
|
|
|
|
}
|
|
|
|
return this->GetName();
|
|
|
|
}
|
|
|
|
|
2013-01-12 15:11:29 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::AppendBuildInterfaceIncludes()
|
|
|
|
{
|
2013-02-07 22:31:23 +04:00
|
|
|
if(this->GetType() != cmTarget::SHARED_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::STATIC_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::MODULE_LIBRARY &&
|
|
|
|
!this->IsExecutableWithExports())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-01-12 15:11:29 +04:00
|
|
|
if (this->BuildInterfaceIncludesAppended)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this->BuildInterfaceIncludesAppended = true;
|
|
|
|
|
2013-03-20 00:40:06 +04:00
|
|
|
if (this->Makefile->IsOn("CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE"))
|
2013-01-12 15:11:29 +04:00
|
|
|
{
|
|
|
|
const char *binDir = this->Makefile->GetStartOutputDirectory();
|
|
|
|
const char *srcDir = this->Makefile->GetStartDirectory();
|
|
|
|
const std::string dirs = std::string(binDir ? binDir : "")
|
|
|
|
+ std::string(binDir ? ";" : "")
|
|
|
|
+ std::string(srcDir ? srcDir : "");
|
|
|
|
if (!dirs.empty())
|
|
|
|
{
|
|
|
|
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
|
|
|
|
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-20 01:47:30 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-02-12 13:35:28 +04:00
|
|
|
void cmTarget::InsertInclude(const cmValueWithOrigin &entry,
|
2012-11-20 01:47:30 +04:00
|
|
|
bool before)
|
|
|
|
{
|
|
|
|
cmGeneratorExpression ge(entry.Backtrace);
|
|
|
|
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
|
2012-11-20 01:47:30 +04:00
|
|
|
= before ? this->Internal->IncludeDirectoriesEntries.begin()
|
|
|
|
: this->Internal->IncludeDirectoriesEntries.end();
|
|
|
|
|
|
|
|
this->Internal->IncludeDirectoriesEntries.insert(position,
|
2013-05-28 14:32:39 +04:00
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
|
2012-11-20 01:47:30 +04:00
|
|
|
}
|
|
|
|
|
2013-05-16 17:20:16 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::InsertCompileOption(const cmValueWithOrigin &entry,
|
|
|
|
bool before)
|
|
|
|
{
|
|
|
|
cmGeneratorExpression ge(entry.Backtrace);
|
|
|
|
|
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
|
|
|
|
= before ? this->Internal->CompileOptionsEntries.begin()
|
|
|
|
: this->Internal->CompileOptionsEntries.end();
|
|
|
|
|
|
|
|
this->Internal->CompileOptionsEntries.insert(position,
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
|
2012-11-20 01:47:30 +04:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::InsertCompileDefinition(const cmValueWithOrigin &entry,
|
|
|
|
bool before)
|
|
|
|
{
|
|
|
|
cmGeneratorExpression ge(entry.Backtrace);
|
|
|
|
|
|
|
|
std::vector<cmTargetInternals::TargetPropertyEntry*>::iterator position
|
|
|
|
= before ? this->Internal->CompileDefinitionsEntries.begin()
|
|
|
|
: this->Internal->CompileDefinitionsEntries.end();
|
|
|
|
|
|
|
|
this->Internal->CompileDefinitionsEntries.insert(position,
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(ge.Parse(entry.Value)));
|
|
|
|
}
|
|
|
|
|
2012-11-20 01:47:30 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-02-12 14:29:09 +04:00
|
|
|
static void processIncludeDirectories(cmTarget *tgt,
|
2013-05-28 14:32:39 +04:00
|
|
|
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
|
2013-02-12 14:29:09 +04:00
|
|
|
std::vector<std::string> &includes,
|
|
|
|
std::set<std::string> &uniqueIncludes,
|
|
|
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
|
const char *config, bool debugIncludes)
|
2012-11-20 01:47:30 +04:00
|
|
|
{
|
2013-02-12 14:29:09 +04:00
|
|
|
cmMakefile *mf = tgt->GetMakefile();
|
2013-01-20 15:50:53 +04:00
|
|
|
|
2013-05-28 14:32:39 +04:00
|
|
|
for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
|
2013-02-12 14:29:09 +04:00
|
|
|
it = entries.begin(), end = entries.end(); it != end; ++it)
|
2012-11-20 01:47:30 +04:00
|
|
|
{
|
2013-02-03 10:33:15 +04:00
|
|
|
bool testIsOff = true;
|
|
|
|
bool cacheIncludes = false;
|
2013-05-28 14:32:39 +04:00
|
|
|
std::vector<std::string> entryIncludes = (*it)->CachedEntries;
|
2013-02-03 10:33:15 +04:00
|
|
|
if(!entryIncludes.empty())
|
|
|
|
{
|
|
|
|
testIsOff = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-02-12 14:29:09 +04:00
|
|
|
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
|
2013-02-03 10:33:15 +04:00
|
|
|
config,
|
|
|
|
false,
|
2013-02-12 14:29:09 +04:00
|
|
|
tgt,
|
|
|
|
dagChecker),
|
2013-02-03 10:33:15 +04:00
|
|
|
entryIncludes);
|
2013-02-12 14:29:09 +04:00
|
|
|
if (mf->IsGeneratingBuildSystem()
|
2013-02-07 22:35:00 +04:00
|
|
|
&& !(*it)->ge->GetHadContextSensitiveCondition())
|
2013-02-03 10:33:15 +04:00
|
|
|
{
|
|
|
|
cacheIncludes = true;
|
|
|
|
}
|
|
|
|
}
|
2012-12-18 19:16:14 +04:00
|
|
|
std::string usedIncludes;
|
2013-02-03 10:33:15 +04:00
|
|
|
for(std::vector<std::string>::iterator
|
2012-11-20 01:47:30 +04:00
|
|
|
li = entryIncludes.begin(); li != entryIncludes.end(); ++li)
|
|
|
|
{
|
2013-03-25 00:18:21 +04:00
|
|
|
cmTarget *dependentTarget =
|
|
|
|
mf->FindTargetToUse((*it)->TargetName.c_str());
|
|
|
|
|
|
|
|
const bool fromImported = dependentTarget
|
|
|
|
&& dependentTarget->IsImported();
|
|
|
|
|
|
|
|
if (fromImported && !cmSystemTools::FileExists(li->c_str()))
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Imported target \"" << (*it)->TargetName << "\" includes "
|
|
|
|
"non-existent path\n \"" << *li << "\"\nin its "
|
|
|
|
"INTERFACE_INCLUDE_DIRECTORIES. Possible reasons include:\n"
|
|
|
|
"* The path was deleted, renamed, or moved to another "
|
|
|
|
"location.\n"
|
|
|
|
"* An install or uninstall procedure did not complete "
|
|
|
|
"successfully.\n"
|
|
|
|
"* The installation package was faulty and references files it "
|
|
|
|
"does not provide.\n";
|
|
|
|
tgt->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-26 21:08:26 +04:00
|
|
|
if (!cmSystemTools::FileIsFullPath(li->c_str()))
|
|
|
|
{
|
2013-03-26 21:08:29 +04:00
|
|
|
cmOStringStream e;
|
|
|
|
bool noMessage = false;
|
|
|
|
cmake::MessageType messageType = cmake::FATAL_ERROR;
|
2013-03-26 21:08:26 +04:00
|
|
|
if (!(*it)->TargetName.empty())
|
|
|
|
{
|
|
|
|
e << "Target \"" << (*it)->TargetName << "\" contains relative "
|
|
|
|
"path in its INTERFACE_INCLUDE_DIRECTORIES:\n"
|
2013-07-18 13:46:50 +04:00
|
|
|
" \"" << *li << "\"";
|
2013-03-26 21:08:29 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(tgt->GetPolicyStatusCMP0021())
|
|
|
|
{
|
|
|
|
case cmPolicies::WARN:
|
|
|
|
{
|
|
|
|
cmOStringStream w;
|
|
|
|
e << (mf->GetPolicies()
|
|
|
|
->GetPolicyWarning(cmPolicies::CMP0021)) << "\n";
|
|
|
|
messageType = cmake::AUTHOR_WARNING;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cmPolicies::OLD:
|
|
|
|
noMessage = true;
|
|
|
|
case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
case cmPolicies::NEW:
|
|
|
|
// Issue the fatal message.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
e << "Found relative path while evaluating include directories of "
|
|
|
|
"\"" << tgt->GetName() << "\":\n \"" << *li << "\"\n";
|
|
|
|
}
|
|
|
|
if (!noMessage)
|
|
|
|
{
|
|
|
|
tgt->GetMakefile()->IssueMessage(messageType, e.str().c_str());
|
2013-08-23 01:52:00 +04:00
|
|
|
if (messageType == cmake::FATAL_ERROR)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-03-26 21:08:26 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-03 10:33:15 +04:00
|
|
|
if (testIsOff && !cmSystemTools::IsOff(li->c_str()))
|
2012-11-20 01:47:30 +04:00
|
|
|
{
|
2013-02-03 10:33:15 +04:00
|
|
|
cmSystemTools::ConvertToUnixSlashes(*li);
|
2012-11-20 01:47:30 +04:00
|
|
|
}
|
2013-02-03 10:33:15 +04:00
|
|
|
std::string inc = *li;
|
2012-11-20 01:47:30 +04:00
|
|
|
|
|
|
|
if(uniqueIncludes.insert(inc).second)
|
|
|
|
{
|
2013-02-02 15:46:30 +04:00
|
|
|
includes.push_back(inc);
|
2012-12-18 19:16:14 +04:00
|
|
|
if (debugIncludes)
|
|
|
|
{
|
2013-02-02 15:46:30 +04:00
|
|
|
usedIncludes += " * " + inc + "\n";
|
2012-12-18 19:16:14 +04:00
|
|
|
}
|
2012-11-20 01:47:30 +04:00
|
|
|
}
|
|
|
|
}
|
2013-02-03 10:33:15 +04:00
|
|
|
if (cacheIncludes)
|
|
|
|
{
|
2013-05-28 14:32:39 +04:00
|
|
|
(*it)->CachedEntries = entryIncludes;
|
2013-02-03 10:33:15 +04:00
|
|
|
}
|
2012-12-18 19:16:14 +04:00
|
|
|
if (!usedIncludes.empty())
|
|
|
|
{
|
2013-02-12 14:29:09 +04:00
|
|
|
mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
|
|
|
|
std::string("Used includes for target ")
|
|
|
|
+ tgt->GetName() + ":\n"
|
2013-01-20 15:57:25 +04:00
|
|
|
+ usedIncludes, (*it)->ge->GetBacktrace());
|
2012-12-18 19:16:14 +04:00
|
|
|
}
|
2012-11-20 01:47:30 +04:00
|
|
|
}
|
2013-02-12 14:29:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
|
|
|
|
{
|
|
|
|
std::vector<std::string> includes;
|
|
|
|
std::set<std::string> uniqueIncludes;
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
2013-05-27 19:45:47 +04:00
|
|
|
this->GetName(),
|
|
|
|
"INCLUDE_DIRECTORIES", 0, 0);
|
2013-02-12 14:29:09 +04:00
|
|
|
|
|
|
|
this->AppendBuildInterfaceIncludes();
|
|
|
|
|
|
|
|
std::vector<std::string> debugProperties;
|
|
|
|
const char *debugProp =
|
|
|
|
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
|
if (debugProp)
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool debugIncludes = !this->DebugIncludesDone
|
|
|
|
&& std::find(debugProperties.begin(),
|
|
|
|
debugProperties.end(),
|
|
|
|
"INCLUDE_DIRECTORIES")
|
|
|
|
!= debugProperties.end();
|
|
|
|
|
|
|
|
if (this->Makefile->IsGeneratingBuildSystem())
|
|
|
|
{
|
|
|
|
this->DebugIncludesDone = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
processIncludeDirectories(this,
|
|
|
|
this->Internal->IncludeDirectoriesEntries,
|
|
|
|
includes,
|
|
|
|
uniqueIncludes,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugIncludes);
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
std::string configString = config ? config : "";
|
|
|
|
if (!this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString])
|
2013-02-12 14:29:09 +04:00
|
|
|
{
|
2013-02-22 16:03:35 +04:00
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
2013-05-28 14:39:32 +04:00
|
|
|
it = this->Internal->LinkInterfacePropertyEntries.begin(),
|
|
|
|
end = this->Internal->LinkInterfacePropertyEntries.end();
|
2013-02-22 16:03:35 +04:00
|
|
|
it != end; ++it)
|
|
|
|
{
|
2013-08-06 13:19:56 +04:00
|
|
|
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
|
|
|
|
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-02-12 14:29:09 +04:00
|
|
|
{
|
2013-02-22 16:03:35 +04:00
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(it->Value);
|
|
|
|
std::string result = cge->Evaluate(this->Makefile, config,
|
|
|
|
false, this, 0, 0);
|
2013-04-29 14:00:53 +04:00
|
|
|
if (!this->Makefile->FindTargetToUse(result.c_str()))
|
2013-02-22 16:03:35 +04:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-02-12 14:29:09 +04:00
|
|
|
}
|
2013-04-29 14:00:53 +04:00
|
|
|
std::string includeGenex = "$<TARGET_PROPERTY:" +
|
|
|
|
it->Value + ",INTERFACE_INCLUDE_DIRECTORIES>";
|
|
|
|
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
|
|
|
|
{
|
|
|
|
// Because it->Value is a generator expression, ensure that it
|
|
|
|
// evaluates to the non-empty string before being used in the
|
|
|
|
// TARGET_PROPERTY expression.
|
|
|
|
includeGenex = "$<$<BOOL:" + it->Value + ">:" + includeGenex + ">";
|
|
|
|
}
|
2013-02-22 16:03:35 +04:00
|
|
|
cmGeneratorExpression ge(it->Backtrace);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
|
2013-04-29 14:00:53 +04:00
|
|
|
includeGenex);
|
2013-02-12 14:29:09 +04:00
|
|
|
|
2013-05-02 18:52:48 +04:00
|
|
|
this->Internal
|
|
|
|
->CachedLinkInterfaceIncludeDirectoriesEntries[configString].push_back(
|
2013-05-28 14:32:39 +04:00
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge,
|
2013-03-25 00:18:21 +04:00
|
|
|
it->Value));
|
2013-02-22 16:03:35 +04:00
|
|
|
}
|
2013-07-08 18:59:03 +04:00
|
|
|
|
|
|
|
if(this->Makefile->IsOn("APPLE"))
|
|
|
|
{
|
|
|
|
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
|
|
|
this);
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
it = impl->Libraries.begin();
|
|
|
|
it != impl->Libraries.end(); ++it)
|
|
|
|
{
|
|
|
|
std::string libDir = cmSystemTools::CollapseFullPath(it->c_str());
|
|
|
|
|
|
|
|
static cmsys::RegularExpression
|
|
|
|
frameworkCheck("(.*\\.framework)(/Versions/[^/]+)?/[^/]+$");
|
|
|
|
if(!frameworkCheck.find(libDir))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
libDir = frameworkCheck.match(1);
|
|
|
|
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(libDir.c_str());
|
|
|
|
this->Internal
|
|
|
|
->CachedLinkInterfaceIncludeDirectoriesEntries[configString]
|
|
|
|
.push_back(new cmTargetInternals::TargetPropertyEntry(cge));
|
|
|
|
}
|
|
|
|
}
|
2013-02-12 14:29:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
processIncludeDirectories(this,
|
2013-05-02 18:52:48 +04:00
|
|
|
this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries[configString],
|
2013-02-12 14:29:09 +04:00
|
|
|
includes,
|
|
|
|
uniqueIncludes,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugIncludes);
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
if (!this->Makefile->IsGeneratingBuildSystem())
|
|
|
|
{
|
|
|
|
deleteAndClear(
|
2013-05-02 18:52:48 +04:00
|
|
|
this->Internal->CachedLinkInterfaceIncludeDirectoriesEntries);
|
2013-02-22 16:03:35 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->Internal->CacheLinkInterfaceIncludeDirectoriesDone[configString]
|
|
|
|
= true;
|
|
|
|
}
|
2013-02-12 14:29:09 +04:00
|
|
|
|
2012-11-20 01:47:30 +04:00
|
|
|
return includes;
|
|
|
|
}
|
|
|
|
|
2013-05-16 17:15:28 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-06-12 12:12:51 +04:00
|
|
|
static void processCompileOptionsInternal(cmTarget *tgt,
|
2013-05-16 17:15:28 +04:00
|
|
|
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
|
|
|
|
std::vector<std::string> &options,
|
|
|
|
std::set<std::string> &uniqueOptions,
|
|
|
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
2013-06-12 12:12:51 +04:00
|
|
|
const char *config, bool debugOptions, const char *logName)
|
2013-05-16 17:15:28 +04:00
|
|
|
{
|
|
|
|
cmMakefile *mf = tgt->GetMakefile();
|
|
|
|
|
|
|
|
for (std::vector<cmTargetInternals::TargetPropertyEntry*>::const_iterator
|
|
|
|
it = entries.begin(), end = entries.end(); it != end; ++it)
|
|
|
|
{
|
|
|
|
bool cacheOptions = false;
|
|
|
|
std::vector<std::string> entryOptions = (*it)->CachedEntries;
|
|
|
|
if(entryOptions.empty())
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument((*it)->ge->Evaluate(mf,
|
|
|
|
config,
|
|
|
|
false,
|
|
|
|
tgt,
|
|
|
|
dagChecker),
|
|
|
|
entryOptions);
|
|
|
|
if (mf->IsGeneratingBuildSystem()
|
|
|
|
&& !(*it)->ge->GetHadContextSensitiveCondition())
|
|
|
|
{
|
|
|
|
cacheOptions = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string usedOptions;
|
|
|
|
for(std::vector<std::string>::iterator
|
|
|
|
li = entryOptions.begin(); li != entryOptions.end(); ++li)
|
|
|
|
{
|
|
|
|
std::string opt = *li;
|
|
|
|
|
|
|
|
if(uniqueOptions.insert(opt).second)
|
|
|
|
{
|
|
|
|
options.push_back(opt);
|
|
|
|
if (debugOptions)
|
|
|
|
{
|
|
|
|
usedOptions += " * " + opt + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cacheOptions)
|
|
|
|
{
|
|
|
|
(*it)->CachedEntries = entryOptions;
|
|
|
|
}
|
|
|
|
if (!usedOptions.empty())
|
|
|
|
{
|
|
|
|
mf->GetCMakeInstance()->IssueMessage(cmake::LOG,
|
2013-06-12 12:12:51 +04:00
|
|
|
std::string("Used compile ") + logName
|
|
|
|
+ std::string(" for target ")
|
2013-05-16 17:15:28 +04:00
|
|
|
+ tgt->GetName() + ":\n"
|
|
|
|
+ usedOptions, (*it)->ge->GetBacktrace());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static void processCompileOptions(cmTarget *tgt,
|
|
|
|
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
|
|
|
|
std::vector<std::string> &options,
|
|
|
|
std::set<std::string> &uniqueOptions,
|
|
|
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
|
const char *config, bool debugOptions)
|
|
|
|
{
|
|
|
|
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
|
|
|
dagChecker, config, debugOptions, "options");
|
|
|
|
}
|
|
|
|
|
2013-05-16 17:15:28 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetCompileOptions(std::vector<std::string> &result,
|
|
|
|
const char *config)
|
|
|
|
{
|
|
|
|
std::set<std::string> uniqueOptions;
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
|
|
|
this->GetName(),
|
|
|
|
"COMPILE_OPTIONS", 0, 0);
|
|
|
|
|
|
|
|
std::vector<std::string> debugProperties;
|
|
|
|
const char *debugProp =
|
|
|
|
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
|
if (debugProp)
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool debugOptions = !this->DebugCompileOptionsDone
|
|
|
|
&& std::find(debugProperties.begin(),
|
|
|
|
debugProperties.end(),
|
|
|
|
"COMPILE_OPTIONS")
|
|
|
|
!= debugProperties.end();
|
|
|
|
|
|
|
|
if (this->Makefile->IsGeneratingBuildSystem())
|
|
|
|
{
|
|
|
|
this->DebugCompileOptionsDone = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
processCompileOptions(this,
|
|
|
|
this->Internal->CompileOptionsEntries,
|
|
|
|
result,
|
|
|
|
uniqueOptions,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugOptions);
|
|
|
|
|
|
|
|
std::string configString = config ? config : "";
|
|
|
|
if (!this->Internal->CacheLinkInterfaceCompileOptionsDone[configString])
|
|
|
|
{
|
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
|
|
|
it = this->Internal->LinkInterfacePropertyEntries.begin(),
|
|
|
|
end = this->Internal->LinkInterfacePropertyEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
2013-08-06 13:19:56 +04:00
|
|
|
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
|
|
|
|
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-05-16 17:15:28 +04:00
|
|
|
{
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(it->Value);
|
|
|
|
std::string targetResult = cge->Evaluate(this->Makefile, config,
|
|
|
|
false, this, 0, 0);
|
|
|
|
if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string optionGenex = "$<TARGET_PROPERTY:" +
|
|
|
|
it->Value + ",INTERFACE_COMPILE_OPTIONS>";
|
|
|
|
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
|
|
|
|
{
|
|
|
|
// Because it->Value is a generator expression, ensure that it
|
|
|
|
// evaluates to the non-empty string before being used in the
|
|
|
|
// TARGET_PROPERTY expression.
|
|
|
|
optionGenex = "$<$<BOOL:" + it->Value + ">:" + optionGenex + ">";
|
|
|
|
}
|
|
|
|
cmGeneratorExpression ge(it->Backtrace);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
|
|
|
|
optionGenex);
|
|
|
|
|
|
|
|
this->Internal
|
|
|
|
->CachedLinkInterfaceCompileOptionsEntries[configString].push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge,
|
|
|
|
it->Value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
processCompileOptions(this,
|
|
|
|
this->Internal->CachedLinkInterfaceCompileOptionsEntries[configString],
|
|
|
|
result,
|
|
|
|
uniqueOptions,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugOptions);
|
|
|
|
|
|
|
|
if (!this->Makefile->IsGeneratingBuildSystem())
|
|
|
|
{
|
|
|
|
deleteAndClear(this->Internal->CachedLinkInterfaceCompileOptionsEntries);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this->Internal->CacheLinkInterfaceCompileOptionsDone[configString] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-26 06:40:49 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-06-12 12:12:51 +04:00
|
|
|
static void processCompileDefinitions(cmTarget *tgt,
|
|
|
|
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
|
|
|
|
std::vector<std::string> &options,
|
|
|
|
std::set<std::string> &uniqueOptions,
|
|
|
|
cmGeneratorExpressionDAGChecker *dagChecker,
|
|
|
|
const char *config, bool debugOptions)
|
2012-12-26 06:40:49 +04:00
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
|
|
|
|
dagChecker, config, debugOptions,
|
|
|
|
"definitions");
|
|
|
|
}
|
2012-12-26 06:40:49 +04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-06-06 20:13:35 +04:00
|
|
|
void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
|
|
|
|
const char *config)
|
2012-12-26 06:40:49 +04:00
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
std::set<std::string> uniqueOptions;
|
2013-02-12 14:29:09 +04:00
|
|
|
cmListFileBacktrace lfbt;
|
2013-06-12 12:12:51 +04:00
|
|
|
|
2013-02-12 14:29:09 +04:00
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
2013-06-12 12:12:51 +04:00
|
|
|
this->GetName(),
|
|
|
|
"COMPILE_DEFINITIONS", 0, 0);
|
2012-12-26 06:40:49 +04:00
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
std::vector<std::string> debugProperties;
|
|
|
|
const char *debugProp =
|
|
|
|
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
|
|
|
|
if (debugProp)
|
2012-12-26 06:40:49 +04:00
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
|
2012-12-26 06:40:49 +04:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
bool debugDefines = !this->DebugCompileDefinitionsDone
|
|
|
|
&& std::find(debugProperties.begin(),
|
|
|
|
debugProperties.end(),
|
|
|
|
"COMPILE_DEFINITIONS")
|
|
|
|
!= debugProperties.end();
|
2012-12-26 06:40:49 +04:00
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
if (this->Makefile->IsGeneratingBuildSystem())
|
2013-02-12 14:29:09 +04:00
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
this->DebugCompileDefinitionsDone = true;
|
2013-02-12 14:29:09 +04:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
processCompileDefinitions(this,
|
|
|
|
this->Internal->CompileDefinitionsEntries,
|
|
|
|
list,
|
|
|
|
uniqueOptions,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugDefines);
|
2013-02-12 14:29:09 +04:00
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
std::string configString = config ? config : "";
|
|
|
|
if (!this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString])
|
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
|
|
|
it = this->Internal->LinkInterfacePropertyEntries.begin(),
|
|
|
|
end = this->Internal->LinkInterfacePropertyEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
2013-08-06 13:19:56 +04:00
|
|
|
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
|
|
|
|
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2013-06-12 12:12:51 +04:00
|
|
|
{
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(it->Value);
|
|
|
|
std::string targetResult = cge->Evaluate(this->Makefile, config,
|
|
|
|
false, this, 0, 0);
|
|
|
|
if (!this->Makefile->FindTargetToUse(targetResult.c_str()))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string defsGenex = "$<TARGET_PROPERTY:" +
|
|
|
|
it->Value + ",INTERFACE_COMPILE_DEFINITIONS>";
|
|
|
|
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
|
|
|
|
{
|
|
|
|
// Because it->Value is a generator expression, ensure that it
|
|
|
|
// evaluates to the non-empty string before being used in the
|
|
|
|
// TARGET_PROPERTY expression.
|
|
|
|
defsGenex = "$<$<BOOL:" + it->Value + ">:" + defsGenex + ">";
|
|
|
|
}
|
|
|
|
cmGeneratorExpression ge(it->Backtrace);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
|
|
|
|
defsGenex);
|
|
|
|
|
|
|
|
this->Internal
|
|
|
|
->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge,
|
|
|
|
it->Value));
|
|
|
|
}
|
|
|
|
if (config)
|
|
|
|
{
|
|
|
|
std::string configPropName = "COMPILE_DEFINITIONS_"
|
|
|
|
+ cmSystemTools::UpperCase(config);
|
|
|
|
const char *configProp = this->GetProperty(configPropName.c_str());
|
|
|
|
std::string defsString = (configProp ? configProp : "");
|
|
|
|
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
|
|
|
|
ge.Parse(defsString);
|
|
|
|
this->Internal
|
|
|
|
->CachedLinkInterfaceCompileDefinitionsEntries[configString].push_back(
|
|
|
|
new cmTargetInternals::TargetPropertyEntry(cge));
|
|
|
|
}
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
}
|
|
|
|
|
2013-06-12 12:12:51 +04:00
|
|
|
processCompileDefinitions(this,
|
|
|
|
this->Internal->CachedLinkInterfaceCompileDefinitionsEntries[configString],
|
|
|
|
list,
|
|
|
|
uniqueOptions,
|
|
|
|
&dagChecker,
|
|
|
|
config,
|
|
|
|
debugDefines);
|
|
|
|
|
2013-02-22 16:03:35 +04:00
|
|
|
if (!this->Makefile->IsGeneratingBuildSystem())
|
|
|
|
{
|
2013-06-12 12:12:51 +04:00
|
|
|
deleteAndClear(this->Internal
|
|
|
|
->CachedLinkInterfaceCompileDefinitionsEntries);
|
2013-02-22 16:03:35 +04:00
|
|
|
}
|
|
|
|
else
|
2013-02-12 14:29:09 +04:00
|
|
|
{
|
2013-02-22 16:03:35 +04:00
|
|
|
this->Internal->CacheLinkInterfaceCompileDefinitionsDone[configString]
|
|
|
|
= true;
|
2013-02-12 14:29:09 +04:00
|
|
|
}
|
2012-12-26 06:40:49 +04:00
|
|
|
}
|
|
|
|
|
2009-10-05 17:06:44 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
|
|
|
|
{
|
2012-09-23 17:02:29 +04:00
|
|
|
// Wipe out maps caching information affected by this property.
|
2008-01-28 16:38:36 +03:00
|
|
|
if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
|
|
|
|
{
|
2009-07-08 16:31:30 +04:00
|
|
|
this->Internal->ImportInfoMap.clear();
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
2009-10-05 17:06:59 +04:00
|
|
|
if(!this->IsImported() && strncmp(prop, "LINK_INTERFACE_", 15) == 0)
|
|
|
|
{
|
|
|
|
this->ClearLinkMaps();
|
|
|
|
}
|
2002-12-21 01:15:45 +03:00
|
|
|
}
|
|
|
|
|
2008-08-19 19:43:51 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static void cmTargetCheckLINK_INTERFACE_LIBRARIES(
|
|
|
|
const char* prop, const char* value, cmMakefile* context, bool imported
|
|
|
|
)
|
|
|
|
{
|
|
|
|
// Look for link-type keywords in the value.
|
|
|
|
static cmsys::RegularExpression
|
|
|
|
keys("(^|;)(debug|optimized|general)(;|$)");
|
|
|
|
if(!keys.find(value))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Support imported and non-imported versions of the property.
|
|
|
|
const char* base = (imported?
|
|
|
|
"IMPORTED_LINK_INTERFACE_LIBRARIES" :
|
|
|
|
"LINK_INTERFACE_LIBRARIES");
|
|
|
|
|
|
|
|
// Report an error.
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Property " << prop << " may not contain link-type keyword \""
|
|
|
|
<< keys.match(2) << "\". "
|
|
|
|
<< "The " << base << " property has a per-configuration "
|
|
|
|
<< "version called " << base << "_<CONFIG> which may be "
|
|
|
|
<< "used to specify per-configuration rules.";
|
|
|
|
if(!imported)
|
|
|
|
{
|
|
|
|
e << " "
|
|
|
|
<< "Alternatively, an IMPORTED library may be created, configured "
|
|
|
|
<< "with a per-configuration location, and then named in the "
|
|
|
|
<< "property value. "
|
|
|
|
<< "See the add_library command's IMPORTED mode for details."
|
|
|
|
<< "\n"
|
|
|
|
<< "If you have a list of libraries that already contains the "
|
|
|
|
<< "keyword, use the target_link_libraries command with its "
|
|
|
|
<< "LINK_INTERFACE_LIBRARIES mode to set the property. "
|
|
|
|
<< "The command automatically recognizes link-type keywords and sets "
|
|
|
|
<< "the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG "
|
|
|
|
<< "properties accordingly.";
|
|
|
|
}
|
|
|
|
context->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
|
}
|
|
|
|
|
2013-06-04 18:25:47 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
|
|
|
|
cmMakefile* context)
|
|
|
|
{
|
|
|
|
// Look for link-type keywords in the value.
|
|
|
|
static cmsys::RegularExpression
|
|
|
|
keys("(^|;)(debug|optimized|general)(;|$)");
|
|
|
|
if(!keys.find(value))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Report an error.
|
|
|
|
cmOStringStream e;
|
|
|
|
|
|
|
|
e << "Property INTERFACE_LINK_LIBRARIES may not contain link-type "
|
|
|
|
"keyword \"" << keys.match(2) << "\". The INTERFACE_LINK_LIBRARIES "
|
|
|
|
"property may contain configuration-sensitive generator-expressions "
|
|
|
|
"which may be used to specify per-configuration rules.";
|
|
|
|
|
|
|
|
context->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
|
}
|
|
|
|
|
2008-08-19 19:43:51 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::CheckProperty(const char* prop, cmMakefile* context)
|
|
|
|
{
|
|
|
|
// Certain properties need checking.
|
|
|
|
if(strncmp(prop, "LINK_INTERFACE_LIBRARIES", 24) == 0)
|
|
|
|
{
|
|
|
|
if(const char* value = this->GetProperty(prop))
|
|
|
|
{
|
|
|
|
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES", 33) == 0)
|
|
|
|
{
|
|
|
|
if(const char* value = this->GetProperty(prop))
|
|
|
|
{
|
|
|
|
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
|
|
|
|
}
|
|
|
|
}
|
2013-06-04 18:25:47 +04:00
|
|
|
if(strncmp(prop, "INTERFACE_LINK_LIBRARIES", 24) == 0)
|
|
|
|
{
|
|
|
|
if(const char* value = this->GetProperty(prop))
|
|
|
|
{
|
|
|
|
cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
|
|
|
|
}
|
|
|
|
}
|
2008-08-19 19:43:51 +04:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2007-05-22 18:24:59 +04:00
|
|
|
void cmTarget::MarkAsImported()
|
|
|
|
{
|
|
|
|
this->IsImportedTarget = true;
|
|
|
|
}
|
|
|
|
|
2012-07-16 21:42:56 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HaveWellDefinedOutputFiles()
|
|
|
|
{
|
|
|
|
return
|
|
|
|
this->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::EXECUTABLE;
|
|
|
|
}
|
|
|
|
|
2009-07-03 18:33:59 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
|
|
|
|
{
|
|
|
|
// There is no output information for imported targets.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only libraries and executables have well-defined output files.
|
2012-07-16 21:42:56 +04:00
|
|
|
if(!this->HaveWellDefinedOutputFiles())
|
2009-07-03 18:33:59 +04:00
|
|
|
{
|
|
|
|
std::string msg = "cmTarget::GetOutputInfo called for ";
|
|
|
|
msg += this->GetName();
|
|
|
|
msg += " which has type ";
|
2011-03-20 19:57:42 +03:00
|
|
|
msg += cmTarget::GetTargetTypeName(this->GetType());
|
2009-07-03 18:33:59 +04:00
|
|
|
this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg);
|
2009-07-10 17:12:39 +04:00
|
|
|
abort();
|
2009-07-03 18:33:59 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup/compute/cache the output information for this configuration.
|
|
|
|
std::string config_upper;
|
|
|
|
if(config && *config)
|
|
|
|
{
|
|
|
|
config_upper = cmSystemTools::UpperCase(config);
|
|
|
|
}
|
2009-07-08 16:31:30 +04:00
|
|
|
typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType;
|
2009-07-03 18:33:59 +04:00
|
|
|
OutputInfoMapType::const_iterator i =
|
2009-07-08 16:31:30 +04:00
|
|
|
this->Internal->OutputInfoMap.find(config_upper);
|
|
|
|
if(i == this->Internal->OutputInfoMap.end())
|
2009-07-03 18:33:59 +04:00
|
|
|
{
|
|
|
|
OutputInfo info;
|
|
|
|
this->ComputeOutputDir(config, false, info.OutDir);
|
|
|
|
this->ComputeOutputDir(config, true, info.ImpDir);
|
2012-11-02 20:49:44 +04:00
|
|
|
if(!this->ComputePDBOutputDir(config, info.PdbDir))
|
|
|
|
{
|
|
|
|
info.PdbDir = info.OutDir;
|
|
|
|
}
|
2009-07-03 18:33:59 +04:00
|
|
|
OutputInfoMapType::value_type entry(config_upper, info);
|
2009-07-08 16:31:30 +04:00
|
|
|
i = this->Internal->OutputInfoMap.insert(entry).first;
|
2009-07-03 18:33:59 +04:00
|
|
|
}
|
|
|
|
return &i->second;
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2008-04-08 08:06:47 +04:00
|
|
|
std::string cmTarget::GetDirectory(const char* config, bool implib)
|
2007-05-22 18:24:59 +04:00
|
|
|
{
|
|
|
|
if (this->IsImported())
|
|
|
|
{
|
2008-04-08 08:06:47 +04:00
|
|
|
// Return the directory from which the target is imported.
|
|
|
|
return
|
|
|
|
cmSystemTools::GetFilenamePath(
|
2008-01-28 16:38:36 +03:00
|
|
|
this->ImportedGetFullPath(config, implib));
|
2007-03-08 23:33:19 +03:00
|
|
|
}
|
2009-07-03 18:33:59 +04:00
|
|
|
else if(OutputInfo const* info = this->GetOutputInfo(config))
|
2007-03-08 23:33:19 +03:00
|
|
|
{
|
2008-04-08 08:06:47 +04:00
|
|
|
// Return the directory in which the target will be built.
|
2009-07-03 18:33:59 +04:00
|
|
|
return implib? info->ImpDir : info->OutDir;
|
2006-02-24 21:13:14 +03:00
|
|
|
}
|
2009-07-03 18:33:59 +04:00
|
|
|
return "";
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
|
|
|
|
2012-09-25 05:30:42 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetPDBDirectory(const char* config)
|
|
|
|
{
|
|
|
|
if(OutputInfo const* info = this->GetOutputInfo(config))
|
|
|
|
{
|
|
|
|
// Return the directory in which the target will be built.
|
|
|
|
return info->PdbDir;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2006-01-14 02:18:32 +03:00
|
|
|
const char* cmTarget::GetLocation(const char* config)
|
2007-05-22 18:24:59 +04:00
|
|
|
{
|
|
|
|
if (this->IsImported())
|
|
|
|
{
|
|
|
|
return this->ImportedGetLocation(config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return this->NormalGetLocation(config);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2007-05-22 18:24:59 +04:00
|
|
|
const char* cmTarget::ImportedGetLocation(const char* config)
|
|
|
|
{
|
2008-01-28 16:38:36 +03:00
|
|
|
this->Location = this->ImportedGetFullPath(config, false);
|
|
|
|
return this->Location.c_str();
|
2007-05-22 18:24:59 +04:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2007-05-22 18:24:59 +04:00
|
|
|
const char* cmTarget::NormalGetLocation(const char* config)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2008-04-08 08:06:47 +04:00
|
|
|
// Handle the configuration-specific case first.
|
|
|
|
if(config)
|
|
|
|
{
|
|
|
|
this->Location = this->GetFullPath(config, false);
|
|
|
|
return this->Location.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now handle the deprecated build-time configuration location.
|
|
|
|
this->Location = this->GetDirectory();
|
|
|
|
const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR");
|
|
|
|
if(cfgid && strcmp(cfgid, ".") != 0)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2008-04-08 08:06:47 +04:00
|
|
|
this->Location += "/";
|
2013-05-06 06:19:05 +04:00
|
|
|
this->Location += cfgid;
|
|
|
|
}
|
|
|
|
|
2013-06-02 08:47:18 +04:00
|
|
|
if(this->IsAppBundleOnApple())
|
2013-05-06 06:19:05 +04:00
|
|
|
{
|
|
|
|
std::string macdir = this->BuildMacContentDirectory("", config, false);
|
|
|
|
if(!macdir.empty())
|
|
|
|
{
|
|
|
|
this->Location += "/";
|
|
|
|
this->Location += macdir;
|
|
|
|
}
|
2008-04-08 08:06:47 +04:00
|
|
|
}
|
2013-05-06 06:19:05 +04:00
|
|
|
this->Location += "/";
|
2006-03-15 19:02:08 +03:00
|
|
|
this->Location += this->GetFullName(config, false);
|
|
|
|
return this->Location.c_str();
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
|
|
|
|
2006-10-17 02:17:14 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetTargetVersion(int& major, int& minor)
|
2008-07-09 18:09:00 +04:00
|
|
|
{
|
|
|
|
int patch;
|
|
|
|
this->GetTargetVersion(false, major, minor, patch);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetTargetVersion(bool soversion,
|
|
|
|
int& major, int& minor, int& patch)
|
2006-10-17 02:17:14 +04:00
|
|
|
{
|
|
|
|
// Set the default values.
|
|
|
|
major = 0;
|
|
|
|
minor = 0;
|
2008-07-09 18:09:00 +04:00
|
|
|
patch = 0;
|
2006-10-17 02:17:14 +04:00
|
|
|
|
2008-07-09 18:09:00 +04:00
|
|
|
// Look for a VERSION or SOVERSION property.
|
|
|
|
const char* prop = soversion? "SOVERSION" : "VERSION";
|
|
|
|
if(const char* version = this->GetProperty(prop))
|
2006-10-17 02:17:14 +04:00
|
|
|
{
|
|
|
|
// Try to parse the version number and store the results that were
|
|
|
|
// successfully parsed.
|
|
|
|
int parsed_major;
|
|
|
|
int parsed_minor;
|
2008-07-09 18:09:00 +04:00
|
|
|
int parsed_patch;
|
|
|
|
switch(sscanf(version, "%d.%d.%d",
|
|
|
|
&parsed_major, &parsed_minor, &parsed_patch))
|
2006-10-17 02:17:14 +04:00
|
|
|
{
|
2008-07-09 18:09:00 +04:00
|
|
|
case 3: patch = parsed_patch; // no break!
|
2006-10-17 02:17:14 +04:00
|
|
|
case 2: minor = parsed_minor; // no break!
|
|
|
|
case 1: major = parsed_major; // no break!
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-10-02 21:52:01 +04:00
|
|
|
const char* cmTarget::GetFeature(const char* feature, const char* config)
|
|
|
|
{
|
|
|
|
if(config && *config)
|
|
|
|
{
|
|
|
|
std::string featureConfig = feature;
|
|
|
|
featureConfig += "_";
|
|
|
|
featureConfig += cmSystemTools::UpperCase(config);
|
|
|
|
if(const char* value = this->GetProperty(featureConfig.c_str()))
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(const char* value = this->GetProperty(feature))
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
return this->Makefile->GetFeature(feature, config);
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2005-06-22 17:06:46 +04:00
|
|
|
const char *cmTarget::GetProperty(const char* prop)
|
2006-12-07 17:45:32 +03:00
|
|
|
{
|
|
|
|
return this->GetProperty(prop, cmProperty::TARGET);
|
|
|
|
}
|
|
|
|
|
2013-06-28 18:37:39 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HandleLocationPropertyPolicy()
|
|
|
|
{
|
|
|
|
if (this->IsImported())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
const char *modal = 0;
|
|
|
|
cmake::MessageType messageType = cmake::AUTHOR_WARNING;
|
|
|
|
switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0026))
|
|
|
|
{
|
|
|
|
case cmPolicies::WARN:
|
|
|
|
modal = "should";
|
|
|
|
case cmPolicies::OLD:
|
|
|
|
break;
|
|
|
|
case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
case cmPolicies::NEW:
|
|
|
|
modal = "may";
|
|
|
|
messageType = cmake::FATAL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modal)
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << (this->Makefile->GetPolicies()
|
|
|
|
->GetPolicyWarning(cmPolicies::CMP0026)) << "\n";
|
|
|
|
e << "The LOCATION property " << modal << " not be read from target \""
|
|
|
|
<< this->GetName() << "\". Use the target name directly with "
|
|
|
|
"add_custom_command, or use the generator expression $<TARGET_FILE>, "
|
|
|
|
"as appropriate.\n";
|
|
|
|
this->Makefile->IssueMessage(messageType, e.str().c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
return messageType != cmake::FATAL_ERROR;
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2006-12-07 17:45:32 +03:00
|
|
|
const char *cmTarget::GetProperty(const char* prop,
|
|
|
|
cmProperty::ScopeType scope)
|
2005-06-22 17:06:46 +04:00
|
|
|
{
|
2007-03-09 23:14:27 +03:00
|
|
|
if(!prop)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-07-31 15:16:29 +04:00
|
|
|
if (strcmp(prop, "NAME") == 0)
|
|
|
|
{
|
|
|
|
return this->GetName();
|
|
|
|
}
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
// Watch for special "computed" properties that are dependent on
|
|
|
|
// other properties or variables. Always recompute them.
|
|
|
|
if(this->GetType() == cmTarget::EXECUTABLE ||
|
|
|
|
this->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
2008-08-18 19:39:22 +04:00
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
2012-11-02 18:47:40 +04:00
|
|
|
this->GetType() == cmTarget::INTERFACE_LIBRARY ||
|
2008-08-18 19:39:22 +04:00
|
|
|
this->GetType() == cmTarget::UNKNOWN_LIBRARY)
|
2007-07-02 21:32:41 +04:00
|
|
|
{
|
2009-01-05 17:53:14 +03:00
|
|
|
if(strcmp(prop,"LOCATION") == 0)
|
2007-05-22 18:24:59 +04:00
|
|
|
{
|
2013-06-28 18:37:39 +04:00
|
|
|
if (!this->HandleLocationPropertyPolicy())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-01-05 17:53:14 +03:00
|
|
|
// Set the LOCATION property of the target.
|
|
|
|
//
|
|
|
|
// For an imported target this is the location of an arbitrary
|
|
|
|
// available configuration.
|
|
|
|
//
|
|
|
|
// For a non-imported target this is deprecated because it
|
2007-07-02 21:32:41 +04:00
|
|
|
// cannot take into account the per-configuration name of the
|
|
|
|
// target because the configuration type may not be known at
|
2009-01-05 17:53:14 +03:00
|
|
|
// CMake time.
|
2007-07-02 21:32:41 +04:00
|
|
|
this->SetProperty("LOCATION", this->GetLocation(0));
|
|
|
|
}
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
// Support "LOCATION_<CONFIG>".
|
|
|
|
if(strncmp(prop, "LOCATION_", 9) == 0)
|
2007-07-02 21:32:41 +04:00
|
|
|
{
|
2013-06-28 18:37:39 +04:00
|
|
|
if (!this->HandleLocationPropertyPolicy())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
std::string configName = prop+9;
|
2007-07-02 21:32:41 +04:00
|
|
|
this->SetProperty(prop, this->GetLocation(configName.c_str()));
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
else
|
2007-07-02 21:32:41 +04:00
|
|
|
{
|
2013-09-12 17:29:49 +04:00
|
|
|
// Support "<CONFIG>_LOCATION" for compatibility.
|
2008-01-28 16:38:36 +03:00
|
|
|
int len = static_cast<int>(strlen(prop));
|
|
|
|
if(len > 9 && strcmp(prop+len-9, "_LOCATION") == 0)
|
|
|
|
{
|
|
|
|
std::string configName(prop, len-9);
|
|
|
|
if(configName != "IMPORTED")
|
|
|
|
{
|
2013-06-28 18:37:39 +04:00
|
|
|
if (!this->HandleLocationPropertyPolicy())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
this->SetProperty(prop, this->GetLocation(configName.c_str()));
|
|
|
|
}
|
|
|
|
}
|
2007-05-22 18:24:59 +04:00
|
|
|
}
|
2007-07-02 21:32:41 +04:00
|
|
|
}
|
2012-11-20 01:47:30 +04:00
|
|
|
if(strcmp(prop,"INCLUDE_DIRECTORIES") == 0)
|
|
|
|
{
|
|
|
|
static std::string output;
|
|
|
|
output = "";
|
|
|
|
std::string sep;
|
2013-05-28 14:32:39 +04:00
|
|
|
typedef cmTargetInternals::TargetPropertyEntry
|
|
|
|
TargetPropertyEntry;
|
|
|
|
for (std::vector<TargetPropertyEntry*>::const_iterator
|
2012-11-20 01:47:30 +04:00
|
|
|
it = this->Internal->IncludeDirectoriesEntries.begin(),
|
|
|
|
end = this->Internal->IncludeDirectoriesEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
|
|
|
output += sep;
|
|
|
|
output += (*it)->ge->GetInput();
|
|
|
|
sep = ";";
|
|
|
|
}
|
|
|
|
return output.c_str();
|
|
|
|
}
|
2013-05-16 17:15:28 +04:00
|
|
|
if(strcmp(prop,"COMPILE_OPTIONS") == 0)
|
|
|
|
{
|
|
|
|
static std::string output;
|
|
|
|
output = "";
|
|
|
|
std::string sep;
|
|
|
|
typedef cmTargetInternals::TargetPropertyEntry
|
|
|
|
TargetPropertyEntry;
|
|
|
|
for (std::vector<TargetPropertyEntry*>::const_iterator
|
|
|
|
it = this->Internal->CompileOptionsEntries.begin(),
|
|
|
|
end = this->Internal->CompileOptionsEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
|
|
|
output += sep;
|
|
|
|
output += (*it)->ge->GetInput();
|
|
|
|
sep = ";";
|
|
|
|
}
|
|
|
|
return output.c_str();
|
|
|
|
}
|
2013-06-12 12:12:51 +04:00
|
|
|
if(strcmp(prop,"COMPILE_DEFINITIONS") == 0)
|
|
|
|
{
|
|
|
|
static std::string output;
|
|
|
|
output = "";
|
|
|
|
std::string sep;
|
|
|
|
typedef cmTargetInternals::TargetPropertyEntry
|
|
|
|
TargetPropertyEntry;
|
|
|
|
for (std::vector<TargetPropertyEntry*>::const_iterator
|
|
|
|
it = this->Internal->CompileDefinitionsEntries.begin(),
|
|
|
|
end = this->Internal->CompileDefinitionsEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
|
|
|
output += sep;
|
|
|
|
output += (*it)->ge->GetInput();
|
|
|
|
sep = ";";
|
|
|
|
}
|
|
|
|
return output.c_str();
|
|
|
|
}
|
2013-08-06 13:19:56 +04:00
|
|
|
if(strcmp(prop,"LINK_LIBRARIES") == 0)
|
|
|
|
{
|
|
|
|
static std::string output;
|
|
|
|
output = "";
|
|
|
|
std::string sep;
|
|
|
|
for (std::vector<cmValueWithOrigin>::const_iterator
|
|
|
|
it = this->Internal->LinkInterfacePropertyEntries.begin(),
|
|
|
|
end = this->Internal->LinkInterfacePropertyEntries.end();
|
|
|
|
it != end; ++it)
|
|
|
|
{
|
|
|
|
output += sep;
|
|
|
|
output += it->Value;
|
|
|
|
sep = ";";
|
|
|
|
}
|
|
|
|
return output.c_str();
|
|
|
|
}
|
2007-07-02 21:32:41 +04:00
|
|
|
|
2007-05-22 18:24:59 +04:00
|
|
|
if (strcmp(prop,"IMPORTED") == 0)
|
2007-02-17 00:12:17 +03:00
|
|
|
{
|
2007-05-22 18:24:59 +04:00
|
|
|
return this->IsImported()?"TRUE":"FALSE";
|
2007-02-17 00:12:17 +03:00
|
|
|
}
|
2007-02-19 21:20:27 +03:00
|
|
|
|
2007-12-17 18:12:22 +03:00
|
|
|
if(!strcmp(prop,"SOURCES"))
|
|
|
|
{
|
|
|
|
cmOStringStream ss;
|
|
|
|
const char* sep = "";
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator
|
|
|
|
i = this->SourceFiles.begin();
|
|
|
|
i != this->SourceFiles.end(); ++i)
|
|
|
|
{
|
|
|
|
// Separate from the previous list entries.
|
|
|
|
ss << sep;
|
|
|
|
sep = ";";
|
|
|
|
|
|
|
|
// Construct what is known about this source file location.
|
|
|
|
cmSourceFileLocation const& location = (*i)->GetLocation();
|
|
|
|
std::string sname = location.GetDirectory();
|
|
|
|
if(!sname.empty())
|
|
|
|
{
|
|
|
|
sname += "/";
|
|
|
|
}
|
|
|
|
sname += location.GetName();
|
|
|
|
|
|
|
|
// Append this list entry.
|
|
|
|
ss << sname;
|
|
|
|
}
|
|
|
|
this->SetProperty("SOURCES", ss.str().c_str());
|
|
|
|
}
|
|
|
|
|
2005-07-01 18:57:39 +04:00
|
|
|
// the type property returns what type the target is
|
|
|
|
if (!strcmp(prop,"TYPE"))
|
|
|
|
{
|
2011-03-20 19:57:42 +03:00
|
|
|
return cmTarget::GetTargetTypeName(this->GetType());
|
2005-07-01 18:57:39 +04:00
|
|
|
}
|
2006-12-07 17:45:32 +03:00
|
|
|
bool chain = false;
|
2007-07-02 21:32:41 +04:00
|
|
|
const char *retVal =
|
2006-12-07 17:45:32 +03:00
|
|
|
this->Properties.GetPropertyValue(prop, scope, chain);
|
|
|
|
if (chain)
|
2002-12-21 01:15:45 +03:00
|
|
|
{
|
2006-12-07 17:45:32 +03:00
|
|
|
return this->Makefile->GetProperty(prop,scope);
|
2002-12-21 01:15:45 +03:00
|
|
|
}
|
2007-07-02 21:32:41 +04:00
|
|
|
return retVal;
|
2002-12-21 01:15:45 +03:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2005-06-22 17:06:46 +04:00
|
|
|
bool cmTarget::GetPropertyAsBool(const char* prop)
|
2002-12-21 01:15:45 +03:00
|
|
|
{
|
2006-12-07 17:45:32 +03:00
|
|
|
return cmSystemTools::IsOn(this->GetProperty(prop));
|
2002-12-21 01:15:45 +03:00
|
|
|
}
|
2004-09-22 22:42:05 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-07-10 21:53:28 +04:00
|
|
|
class cmTargetCollectLinkLanguages
|
2004-09-22 22:42:05 +04:00
|
|
|
{
|
2009-07-10 21:53:28 +04:00
|
|
|
public:
|
|
|
|
cmTargetCollectLinkLanguages(cmTarget* target, const char* config,
|
2013-01-04 16:31:01 +04:00
|
|
|
std::set<cmStdString>& languages,
|
|
|
|
cmTarget* head):
|
|
|
|
Config(config), Languages(languages), HeadTarget(head)
|
|
|
|
{ this->Visited.insert(target); }
|
|
|
|
|
2009-07-10 21:53:28 +04:00
|
|
|
void Visit(cmTarget* target)
|
2004-09-22 22:42:05 +04:00
|
|
|
{
|
2009-07-10 21:53:28 +04:00
|
|
|
if(!target || !this->Visited.insert(target).second)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
cmTarget::LinkInterface const* iface =
|
2013-01-04 16:31:01 +04:00
|
|
|
target->GetLinkInterface(this->Config, this->HeadTarget);
|
2009-07-10 21:53:28 +04:00
|
|
|
if(!iface) { return; }
|
|
|
|
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
li = iface->Languages.begin(); li != iface->Languages.end(); ++li)
|
|
|
|
{
|
|
|
|
this->Languages.insert(*li);
|
|
|
|
}
|
|
|
|
|
|
|
|
cmMakefile* mf = target->GetMakefile();
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
li = iface->Libraries.begin(); li != iface->Libraries.end(); ++li)
|
|
|
|
{
|
|
|
|
this->Visit(mf->FindTargetToUse(li->c_str()));
|
|
|
|
}
|
2004-09-22 22:42:05 +04:00
|
|
|
}
|
2009-07-10 21:53:28 +04:00
|
|
|
private:
|
|
|
|
const char* Config;
|
|
|
|
std::set<cmStdString>& Languages;
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget* HeadTarget;
|
2009-07-10 21:53:28 +04:00
|
|
|
std::set<cmTarget*> Visited;
|
|
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-01-04 16:31:01 +04:00
|
|
|
const char* cmTarget::GetLinkerLanguage(const char* config, cmTarget *head)
|
2009-07-10 21:53:28 +04:00
|
|
|
{
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget *headTarget = head ? head : this;
|
|
|
|
const char* lang = this->GetLinkClosure(config, headTarget)
|
|
|
|
->LinkerLanguage.c_str();
|
2009-07-10 21:53:28 +04:00
|
|
|
return *lang? lang : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget::LinkClosure const* cmTarget::GetLinkClosure(const char* config,
|
|
|
|
cmTarget *head)
|
2009-07-10 21:53:28 +04:00
|
|
|
{
|
2013-01-04 16:31:01 +04:00
|
|
|
TargetConfigPair key(head, cmSystemTools::UpperCase(config ? config : ""));
|
2009-07-10 21:53:28 +04:00
|
|
|
cmTargetInternals::LinkClosureMapType::iterator
|
|
|
|
i = this->Internal->LinkClosureMap.find(key);
|
|
|
|
if(i == this->Internal->LinkClosureMap.end())
|
2004-09-22 22:42:05 +04:00
|
|
|
{
|
2009-07-10 21:53:28 +04:00
|
|
|
LinkClosure lc;
|
2013-01-04 16:31:01 +04:00
|
|
|
this->ComputeLinkClosure(config, lc, head);
|
2009-07-10 21:53:28 +04:00
|
|
|
cmTargetInternals::LinkClosureMapType::value_type entry(key, lc);
|
|
|
|
i = this->Internal->LinkClosureMap.insert(entry).first;
|
|
|
|
}
|
|
|
|
return &i->second;
|
|
|
|
}
|
2007-07-12 16:37:10 +04:00
|
|
|
|
2009-07-30 18:59:25 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class cmTargetSelectLinker
|
|
|
|
{
|
|
|
|
int Preference;
|
|
|
|
cmTarget* Target;
|
|
|
|
cmMakefile* Makefile;
|
|
|
|
cmGlobalGenerator* GG;
|
|
|
|
std::set<cmStdString> Preferred;
|
|
|
|
public:
|
|
|
|
cmTargetSelectLinker(cmTarget* target): Preference(0), Target(target)
|
|
|
|
{
|
|
|
|
this->Makefile = this->Target->GetMakefile();
|
|
|
|
this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
|
|
|
|
}
|
|
|
|
void Consider(const char* lang)
|
|
|
|
{
|
|
|
|
int preference = this->GG->GetLinkerPreference(lang);
|
|
|
|
if(preference > this->Preference)
|
|
|
|
{
|
|
|
|
this->Preference = preference;
|
|
|
|
this->Preferred.clear();
|
|
|
|
}
|
|
|
|
if(preference == this->Preference)
|
|
|
|
{
|
|
|
|
this->Preferred.insert(lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::string Choose()
|
|
|
|
{
|
|
|
|
if(this->Preferred.empty())
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
else if(this->Preferred.size() > 1)
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Target " << this->Target->GetName()
|
|
|
|
<< " contains multiple languages with the highest linker preference"
|
|
|
|
<< " (" << this->Preference << "):\n";
|
|
|
|
for(std::set<cmStdString>::const_iterator
|
|
|
|
li = this->Preferred.begin(); li != this->Preferred.end(); ++li)
|
|
|
|
{
|
|
|
|
e << " " << *li << "\n";
|
|
|
|
}
|
|
|
|
e << "Set the LINKER_LANGUAGE property for this target.";
|
|
|
|
cmake* cm = this->Makefile->GetCMakeInstance();
|
|
|
|
cm->IssueMessage(cmake::FATAL_ERROR, e.str(),
|
|
|
|
this->Target->GetBacktrace());
|
|
|
|
}
|
|
|
|
return *this->Preferred.begin();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2009-07-10 21:53:28 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-01-04 16:31:01 +04:00
|
|
|
void cmTarget::ComputeLinkClosure(const char* config, LinkClosure& lc,
|
|
|
|
cmTarget *head)
|
2009-07-10 21:53:28 +04:00
|
|
|
{
|
|
|
|
// Get languages built in this target.
|
|
|
|
std::set<cmStdString> languages;
|
2013-01-04 16:31:01 +04:00
|
|
|
LinkImplementation const* impl = this->GetLinkImplementation(config, head);
|
2009-07-10 21:53:28 +04:00
|
|
|
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
|
|
|
|
li != impl->Languages.end(); ++li)
|
|
|
|
{
|
|
|
|
languages.insert(*li);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add interface languages from linked targets.
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTargetCollectLinkLanguages cll(this, config, languages, head);
|
2009-07-10 21:53:28 +04:00
|
|
|
for(std::vector<std::string>::const_iterator li = impl->Libraries.begin();
|
|
|
|
li != impl->Libraries.end(); ++li)
|
|
|
|
{
|
|
|
|
cll.Visit(this->Makefile->FindTargetToUse(li->c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the transitive closure of languages.
|
|
|
|
for(std::set<cmStdString>::const_iterator li = languages.begin();
|
|
|
|
li != languages.end(); ++li)
|
|
|
|
{
|
|
|
|
lc.Languages.push_back(*li);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Choose the language whose linker should be used.
|
|
|
|
if(this->GetProperty("HAS_CXX"))
|
|
|
|
{
|
|
|
|
lc.LinkerLanguage = "CXX";
|
|
|
|
}
|
|
|
|
else if(const char* linkerLang = this->GetProperty("LINKER_LANGUAGE"))
|
|
|
|
{
|
|
|
|
lc.LinkerLanguage = linkerLang;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Find the language with the highest preference value.
|
2009-07-30 18:59:25 +04:00
|
|
|
cmTargetSelectLinker tsl(this);
|
2009-07-30 18:59:37 +04:00
|
|
|
|
|
|
|
// First select from the languages compiled directly in this target.
|
|
|
|
for(std::vector<std::string>::const_iterator li = impl->Languages.begin();
|
|
|
|
li != impl->Languages.end(); ++li)
|
|
|
|
{
|
|
|
|
tsl.Consider(li->c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now consider languages that propagate from linked targets.
|
2007-07-12 16:37:10 +04:00
|
|
|
for(std::set<cmStdString>::const_iterator sit = languages.begin();
|
|
|
|
sit != languages.end(); ++sit)
|
2004-09-22 22:42:05 +04:00
|
|
|
{
|
2009-07-30 18:59:37 +04:00
|
|
|
std::string propagates = "CMAKE_"+*sit+"_LINKER_PREFERENCE_PROPAGATES";
|
|
|
|
if(this->Makefile->IsOn(propagates.c_str()))
|
|
|
|
{
|
|
|
|
tsl.Consider(sit->c_str());
|
|
|
|
}
|
2007-07-12 16:37:10 +04:00
|
|
|
}
|
2009-07-30 18:59:37 +04:00
|
|
|
|
2009-07-30 18:59:25 +04:00
|
|
|
lc.LinkerLanguage = tsl.Choose();
|
2004-09-22 22:42:05 +04:00
|
|
|
}
|
|
|
|
}
|
2004-10-21 22:34:02 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-05-01 18:39:44 +04:00
|
|
|
const char* cmTarget::GetSuffixVariableInternal(bool implib)
|
2005-04-22 23:23:21 +04:00
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
switch(this->GetType())
|
2004-10-21 22:34:02 +04:00
|
|
|
{
|
|
|
|
case cmTarget::STATIC_LIBRARY:
|
|
|
|
return "CMAKE_STATIC_LIBRARY_SUFFIX";
|
|
|
|
case cmTarget::SHARED_LIBRARY:
|
2006-02-18 23:37:23 +03:00
|
|
|
return (implib
|
|
|
|
? "CMAKE_IMPORT_LIBRARY_SUFFIX"
|
|
|
|
: "CMAKE_SHARED_LIBRARY_SUFFIX");
|
2004-10-21 22:34:02 +04:00
|
|
|
case cmTarget::MODULE_LIBRARY:
|
2007-03-19 17:00:36 +03:00
|
|
|
return (implib
|
|
|
|
? "CMAKE_IMPORT_LIBRARY_SUFFIX"
|
|
|
|
: "CMAKE_SHARED_MODULE_SUFFIX");
|
2004-10-21 22:34:02 +04:00
|
|
|
case cmTarget::EXECUTABLE:
|
2007-03-19 17:00:36 +03:00
|
|
|
return (implib
|
|
|
|
? "CMAKE_IMPORT_LIBRARY_SUFFIX"
|
|
|
|
: "CMAKE_EXECUTABLE_SUFFIX");
|
2008-08-18 19:26:51 +04:00
|
|
|
default:
|
2004-10-21 22:34:02 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-05-01 18:39:44 +04:00
|
|
|
const char* cmTarget::GetPrefixVariableInternal(bool implib)
|
2005-04-22 23:23:21 +04:00
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
switch(this->GetType())
|
2004-10-21 22:34:02 +04:00
|
|
|
{
|
|
|
|
case cmTarget::STATIC_LIBRARY:
|
|
|
|
return "CMAKE_STATIC_LIBRARY_PREFIX";
|
|
|
|
case cmTarget::SHARED_LIBRARY:
|
2006-02-18 23:37:23 +03:00
|
|
|
return (implib
|
|
|
|
? "CMAKE_IMPORT_LIBRARY_PREFIX"
|
|
|
|
: "CMAKE_SHARED_LIBRARY_PREFIX");
|
2004-10-21 22:34:02 +04:00
|
|
|
case cmTarget::MODULE_LIBRARY:
|
2007-03-19 17:00:36 +03:00
|
|
|
return (implib
|
|
|
|
? "CMAKE_IMPORT_LIBRARY_PREFIX"
|
|
|
|
: "CMAKE_SHARED_MODULE_PREFIX");
|
2004-10-21 22:34:02 +04:00
|
|
|
case cmTarget::EXECUTABLE:
|
2007-03-19 17:00:36 +03:00
|
|
|
return (implib? "CMAKE_IMPORT_LIBRARY_PREFIX" : "");
|
2008-08-18 19:26:51 +04:00
|
|
|
default:
|
2004-10-21 22:34:02 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
2005-04-22 23:23:21 +04:00
|
|
|
|
2007-02-02 00:54:49 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetPDBName(const char* config)
|
|
|
|
{
|
|
|
|
std::string prefix;
|
|
|
|
std::string base;
|
|
|
|
std::string suffix;
|
2009-05-01 18:39:44 +04:00
|
|
|
this->GetFullNameInternal(config, false, prefix, base, suffix);
|
2012-09-25 05:30:42 +04:00
|
|
|
|
|
|
|
std::vector<std::string> props;
|
|
|
|
std::string configUpper =
|
|
|
|
cmSystemTools::UpperCase(config? config : "");
|
|
|
|
if(!configUpper.empty())
|
|
|
|
{
|
|
|
|
// PDB_NAME_<CONFIG>
|
|
|
|
props.push_back("PDB_NAME_" + configUpper);
|
|
|
|
}
|
|
|
|
|
|
|
|
// PDB_NAME
|
|
|
|
props.push_back("PDB_NAME");
|
|
|
|
|
|
|
|
for(std::vector<std::string>::const_iterator i = props.begin();
|
|
|
|
i != props.end(); ++i)
|
|
|
|
{
|
|
|
|
if(const char* outName = this->GetProperty(i->c_str()))
|
|
|
|
{
|
|
|
|
base = outName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-02-02 00:54:49 +03:00
|
|
|
return prefix+base+".pdb";
|
|
|
|
}
|
|
|
|
|
2012-04-22 17:42:55 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HasSOName(const char* config)
|
|
|
|
{
|
|
|
|
// soname is supported only for shared libraries and modules,
|
|
|
|
// and then only when the platform supports an soname flag.
|
|
|
|
return ((this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY) &&
|
|
|
|
!this->GetPropertyAsBool("NO_SONAME") &&
|
2013-01-04 16:31:01 +04:00
|
|
|
this->Makefile->GetSONameFlag(this->GetLinkerLanguage(config,
|
|
|
|
this)));
|
2012-04-22 17:42:55 +04:00
|
|
|
}
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetSOName(const char* config)
|
|
|
|
{
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
|
|
|
// Lookup the imported soname.
|
2013-01-04 16:31:01 +04:00
|
|
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2008-02-21 19:41:11 +03:00
|
|
|
if(info->NoSOName)
|
|
|
|
{
|
|
|
|
// The imported library has no builtin soname so the name
|
|
|
|
// searched at runtime will be just the filename.
|
|
|
|
return cmSystemTools::GetFilenameName(info->Location);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Use the soname given if any.
|
2013-05-21 02:57:58 +04:00
|
|
|
if(info->SOName.find("@rpath/") == 0)
|
|
|
|
{
|
|
|
|
return info->SOName.substr(6);
|
|
|
|
}
|
2008-02-21 19:41:11 +03:00
|
|
|
return info->SOName;
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Compute the soname that will be built.
|
|
|
|
std::string name;
|
|
|
|
std::string soName;
|
|
|
|
std::string realName;
|
|
|
|
std::string impName;
|
|
|
|
std::string pdbName;
|
|
|
|
this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
|
|
|
|
return soName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-27 08:04:44 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HasMacOSXRpath(const char* config)
|
|
|
|
{
|
|
|
|
bool install_name_is_rpath = false;
|
|
|
|
bool macosx_rpath = this->GetPropertyAsBool("MACOSX_RPATH");
|
|
|
|
|
|
|
|
if(!this->IsImportedTarget)
|
|
|
|
{
|
|
|
|
const char* install_name = this->GetProperty("INSTALL_NAME_DIR");
|
|
|
|
bool use_install_name =
|
|
|
|
this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
|
|
|
|
if(install_name && use_install_name &&
|
|
|
|
std::string(install_name) == "@rpath")
|
|
|
|
{
|
|
|
|
install_name_is_rpath = true;
|
|
|
|
}
|
2013-08-22 07:09:32 +04:00
|
|
|
else if(install_name && use_install_name)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-27 08:04:44 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Lookup the imported soname.
|
|
|
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
|
|
|
|
{
|
|
|
|
if(!info->NoSOName && !info->SOName.empty())
|
|
|
|
{
|
|
|
|
if(info->SOName.find("@rpath/") == 0)
|
|
|
|
{
|
|
|
|
install_name_is_rpath = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string install_name;
|
|
|
|
cmSystemTools::GuessLibraryInstallName(info->Location, install_name);
|
|
|
|
if(install_name.find("@rpath") != std::string::npos)
|
|
|
|
{
|
|
|
|
install_name_is_rpath = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!install_name_is_rpath && !macosx_rpath)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!this->Makefile->IsSet("CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG"))
|
|
|
|
{
|
|
|
|
cmOStringStream w;
|
|
|
|
w << "Attempting to use";
|
|
|
|
if(macosx_rpath)
|
|
|
|
{
|
|
|
|
w << " MACOSX_RPATH";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w << " @rpath";
|
|
|
|
}
|
|
|
|
w << " without CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG being set.";
|
|
|
|
w << " This could be because you are using a Mac OS X version";
|
|
|
|
w << " less than 10.5 or because CMake's platform configuration is";
|
|
|
|
w << " corrupt.";
|
|
|
|
cmake* cm = this->Makefile->GetCMakeInstance();
|
|
|
|
cm->IssueMessage(cmake::FATAL_ERROR, w.str(), this->GetBacktrace());
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2008-02-21 19:41:11 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsImportedSharedLibWithoutSOName(const char* config)
|
|
|
|
{
|
|
|
|
if(this->IsImported() && this->GetType() == cmTarget::SHARED_LIBRARY)
|
|
|
|
{
|
2013-01-04 16:31:01 +04:00
|
|
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
|
2008-02-21 19:41:11 +03:00
|
|
|
{
|
|
|
|
return info->NoSOName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-02-06 21:34:44 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::NormalGetRealName(const char* config)
|
|
|
|
{
|
|
|
|
// This should not be called for imported targets.
|
|
|
|
// TODO: Split cmTarget into a class hierarchy to get compile-time
|
|
|
|
// enforcement of the limited imported target API.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
2008-03-13 04:06:32 +03:00
|
|
|
std::string msg = "NormalGetRealName called on imported target: ";
|
|
|
|
msg += this->GetName();
|
|
|
|
this->GetMakefile()->
|
|
|
|
IssueMessage(cmake::INTERNAL_ERROR,
|
|
|
|
msg.c_str());
|
2008-02-06 21:34:44 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if(this->GetType() == cmTarget::EXECUTABLE)
|
|
|
|
{
|
|
|
|
// Compute the real name that will be built.
|
|
|
|
std::string name;
|
|
|
|
std::string realName;
|
|
|
|
std::string impName;
|
|
|
|
std::string pdbName;
|
|
|
|
this->GetExecutableNames(name, realName, impName, pdbName, config);
|
|
|
|
return realName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Compute the real name that will be built.
|
|
|
|
std::string name;
|
|
|
|
std::string soName;
|
|
|
|
std::string realName;
|
|
|
|
std::string impName;
|
|
|
|
std::string pdbName;
|
|
|
|
this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
|
|
|
|
return realName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2006-02-18 23:37:23 +03:00
|
|
|
std::string cmTarget::GetFullName(const char* config, bool implib)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2008-01-28 16:38:36 +03:00
|
|
|
if(this->IsImported())
|
|
|
|
{
|
|
|
|
return this->GetFullNameImported(config, implib);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
return this->GetFullNameInternal(config, implib);
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetFullNameImported(const char* config, bool implib)
|
|
|
|
{
|
|
|
|
return cmSystemTools::GetFilenameName(
|
|
|
|
this->ImportedGetFullPath(config, implib));
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2008-01-28 16:38:36 +03:00
|
|
|
void cmTarget::GetFullNameComponents(std::string& prefix, std::string& base,
|
|
|
|
std::string& suffix, const char* config,
|
|
|
|
bool implib)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
this->GetFullNameInternal(config, implib, prefix, base, suffix);
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2008-02-06 21:34:44 +03:00
|
|
|
std::string cmTarget::GetFullPath(const char* config, bool implib,
|
|
|
|
bool realname)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
|
|
|
return this->ImportedGetFullPath(config, implib);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-02-06 21:34:44 +03:00
|
|
|
return this->NormalGetFullPath(config, implib, realname);
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2008-02-06 21:34:44 +03:00
|
|
|
std::string cmTarget::NormalGetFullPath(const char* config, bool implib,
|
|
|
|
bool realname)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
std::string fpath = this->GetDirectory(config, implib);
|
|
|
|
fpath += "/";
|
2013-06-02 08:47:18 +04:00
|
|
|
if(this->IsAppBundleOnApple())
|
2013-05-06 06:19:05 +04:00
|
|
|
{
|
|
|
|
fpath = this->BuildMacContentDirectory(fpath, config, false);
|
|
|
|
fpath += "/";
|
|
|
|
}
|
2008-04-08 08:06:47 +04:00
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
// Add the full name of the target.
|
2008-02-06 22:19:03 +03:00
|
|
|
if(implib)
|
|
|
|
{
|
|
|
|
fpath += this->GetFullName(config, true);
|
|
|
|
}
|
|
|
|
else if(realname)
|
2008-02-06 21:34:44 +03:00
|
|
|
{
|
|
|
|
fpath += this->NormalGetRealName(config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2008-02-06 22:19:03 +03:00
|
|
|
fpath += this->GetFullName(config, false);
|
2008-02-06 21:34:44 +03:00
|
|
|
}
|
2006-01-14 02:18:32 +03:00
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2008-01-28 16:38:36 +03:00
|
|
|
std::string cmTarget::ImportedGetFullPath(const char* config, bool implib)
|
|
|
|
{
|
2009-04-09 00:29:04 +04:00
|
|
|
std::string result;
|
2013-01-04 16:31:01 +04:00
|
|
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, this))
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2009-04-09 00:29:04 +04:00
|
|
|
result = implib? info->ImportLibrary : info->Location;
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
2009-04-09 00:29:04 +04:00
|
|
|
if(result.empty())
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2009-04-09 00:29:04 +04:00
|
|
|
result = this->GetName();
|
2008-01-28 16:38:36 +03:00
|
|
|
result += "-NOTFOUND";
|
|
|
|
}
|
2009-04-09 00:29:04 +04:00
|
|
|
return result;
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2009-05-01 18:39:44 +04:00
|
|
|
std::string cmTarget::GetFullNameInternal(const char* config, bool implib)
|
2005-04-22 23:23:21 +04:00
|
|
|
{
|
2006-01-14 02:18:32 +03:00
|
|
|
std::string prefix;
|
|
|
|
std::string base;
|
|
|
|
std::string suffix;
|
2009-05-01 18:39:44 +04:00
|
|
|
this->GetFullNameInternal(config, implib, prefix, base, suffix);
|
2006-01-14 02:18:32 +03:00
|
|
|
return prefix+base+suffix;
|
2005-04-22 23:23:21 +04:00
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2009-05-01 18:39:44 +04:00
|
|
|
void cmTarget::GetFullNameInternal(const char* config,
|
2007-07-02 21:32:41 +04:00
|
|
|
bool implib,
|
|
|
|
std::string& outPrefix,
|
|
|
|
std::string& outBase,
|
|
|
|
std::string& outSuffix)
|
2005-04-22 23:23:21 +04:00
|
|
|
{
|
2006-01-14 02:18:32 +03:00
|
|
|
// Use just the target name for non-main target types.
|
2009-05-01 18:39:44 +04:00
|
|
|
if(this->GetType() != cmTarget::STATIC_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::SHARED_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::MODULE_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::EXECUTABLE)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
|
|
|
outPrefix = "";
|
|
|
|
outBase = this->GetName();
|
|
|
|
outSuffix = "";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-08-03 17:42:48 +04:00
|
|
|
// Return an empty name for the import library if this platform
|
|
|
|
// does not support import libraries.
|
|
|
|
if(implib &&
|
|
|
|
!this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"))
|
|
|
|
{
|
|
|
|
outPrefix = "";
|
|
|
|
outBase = "";
|
|
|
|
outSuffix = "";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-19 17:00:36 +03:00
|
|
|
// The implib option is only allowed for shared libraries, module
|
|
|
|
// libraries, and executables.
|
2009-05-01 18:39:44 +04:00
|
|
|
if(this->GetType() != cmTarget::SHARED_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::MODULE_LIBRARY &&
|
|
|
|
this->GetType() != cmTarget::EXECUTABLE)
|
2006-02-18 23:37:23 +03:00
|
|
|
{
|
|
|
|
implib = false;
|
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
// Compute the full name for main target types.
|
2006-02-18 23:37:23 +03:00
|
|
|
const char* targetPrefix = (implib
|
|
|
|
? this->GetProperty("IMPORT_PREFIX")
|
|
|
|
: this->GetProperty("PREFIX"));
|
|
|
|
const char* targetSuffix = (implib
|
|
|
|
? this->GetProperty("IMPORT_SUFFIX")
|
|
|
|
: this->GetProperty("SUFFIX"));
|
2006-01-14 02:18:32 +03:00
|
|
|
const char* configPostfix = 0;
|
2006-03-02 06:45:13 +03:00
|
|
|
if(config && *config)
|
2006-01-14 02:18:32 +03:00
|
|
|
{
|
2006-03-02 06:45:13 +03:00
|
|
|
std::string configProp = cmSystemTools::UpperCase(config);
|
|
|
|
configProp += "_POSTFIX";
|
|
|
|
configPostfix = this->GetProperty(configProp.c_str());
|
2008-04-14 23:27:27 +04:00
|
|
|
// Mac application bundles and frameworks have no postfix.
|
|
|
|
if(configPostfix &&
|
|
|
|
(this->IsAppBundleOnApple() || this->IsFrameworkOnApple()))
|
|
|
|
{
|
|
|
|
configPostfix = 0;
|
|
|
|
}
|
2006-01-14 02:18:32 +03:00
|
|
|
}
|
2009-05-01 18:39:44 +04:00
|
|
|
const char* prefixVar = this->GetPrefixVariableInternal(implib);
|
|
|
|
const char* suffixVar = this->GetSuffixVariableInternal(implib);
|
2005-04-22 23:23:21 +04:00
|
|
|
|
2009-07-08 22:33:08 +04:00
|
|
|
// Check for language-specific default prefix and suffix.
|
2013-01-04 16:31:01 +04:00
|
|
|
if(const char* ll = this->GetLinkerLanguage(config, this))
|
2009-07-08 22:33:08 +04:00
|
|
|
{
|
|
|
|
if(!targetSuffix && suffixVar && *suffixVar)
|
|
|
|
{
|
|
|
|
std::string langSuff = suffixVar + std::string("_") + ll;
|
|
|
|
targetSuffix = this->Makefile->GetDefinition(langSuff.c_str());
|
|
|
|
}
|
|
|
|
if(!targetPrefix && prefixVar && *prefixVar)
|
|
|
|
{
|
|
|
|
std::string langPrefix = prefixVar + std::string("_") + ll;
|
|
|
|
targetPrefix = this->Makefile->GetDefinition(langPrefix.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-22 23:23:21 +04:00
|
|
|
// if there is no prefix on the target use the cmake definition
|
|
|
|
if(!targetPrefix && prefixVar)
|
|
|
|
{
|
2006-03-15 19:02:08 +03:00
|
|
|
targetPrefix = this->Makefile->GetSafeDefinition(prefixVar);
|
2005-04-22 23:23:21 +04:00
|
|
|
}
|
|
|
|
// if there is no suffix on the target use the cmake definition
|
|
|
|
if(!targetSuffix && suffixVar)
|
|
|
|
{
|
2006-03-15 19:02:08 +03:00
|
|
|
targetSuffix = this->Makefile->GetSafeDefinition(suffixVar);
|
2005-04-22 23:23:21 +04:00
|
|
|
}
|
2008-01-28 21:05:58 +03:00
|
|
|
|
2013-05-06 06:19:05 +04:00
|
|
|
// frameworks have directory prefix but no suffix
|
|
|
|
std::string fw_prefix;
|
2008-01-28 21:05:58 +03:00
|
|
|
if(this->IsFrameworkOnApple())
|
2007-05-08 18:32:54 +04:00
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
fw_prefix = this->GetOutputName(config, false);
|
|
|
|
fw_prefix += ".framework/";
|
|
|
|
targetPrefix = fw_prefix.c_str();
|
2007-05-08 18:32:54 +04:00
|
|
|
targetSuffix = 0;
|
|
|
|
}
|
2005-08-18 00:11:18 +04:00
|
|
|
|
2013-06-02 08:47:18 +04:00
|
|
|
if(this->IsCFBundleOnApple())
|
|
|
|
{
|
|
|
|
fw_prefix = this->GetOutputName(config, false);
|
|
|
|
fw_prefix += ".";
|
|
|
|
const char *ext = this->GetProperty("BUNDLE_EXTENSION");
|
|
|
|
if (!ext)
|
|
|
|
{
|
|
|
|
ext = "bundle";
|
|
|
|
}
|
|
|
|
fw_prefix += ext;
|
|
|
|
fw_prefix += "/Contents/MacOS/";
|
|
|
|
targetPrefix = fw_prefix.c_str();
|
|
|
|
targetSuffix = 0;
|
|
|
|
}
|
|
|
|
|
2005-08-18 00:11:18 +04:00
|
|
|
// Begin the final name with the prefix.
|
2006-01-14 02:18:32 +03:00
|
|
|
outPrefix = targetPrefix?targetPrefix:"";
|
2005-08-18 00:11:18 +04:00
|
|
|
|
2006-03-02 06:45:13 +03:00
|
|
|
// Append the target name or property-specified name.
|
2009-05-01 17:45:43 +04:00
|
|
|
outBase += this->GetOutputName(config, implib);
|
2005-08-18 00:11:18 +04:00
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
// Append the per-configuration postfix.
|
|
|
|
outBase += configPostfix?configPostfix:"";
|
2005-04-22 23:23:21 +04:00
|
|
|
|
2006-10-06 00:30:47 +04:00
|
|
|
// Name shared libraries with their version number on some platforms.
|
2010-01-13 21:00:29 +03:00
|
|
|
if(const char* soversion = this->GetProperty("SOVERSION"))
|
2006-10-06 00:30:47 +04:00
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY && !implib &&
|
2006-10-06 00:30:47 +04:00
|
|
|
this->Makefile->IsOn("CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION"))
|
|
|
|
{
|
|
|
|
outBase += "-";
|
2010-01-13 21:00:29 +03:00
|
|
|
outBase += soversion;
|
2006-10-06 00:30:47 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-14 02:18:32 +03:00
|
|
|
// Append the suffix.
|
|
|
|
outSuffix = targetSuffix?targetSuffix:"";
|
2005-04-22 23:23:21 +04:00
|
|
|
}
|
2005-04-23 00:11:00 +04:00
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2005-12-14 18:47:33 +03:00
|
|
|
void cmTarget::GetLibraryNames(std::string& name,
|
2005-04-23 00:11:00 +04:00
|
|
|
std::string& soName,
|
|
|
|
std::string& realName,
|
2006-02-18 23:37:23 +03:00
|
|
|
std::string& impName,
|
2007-02-01 17:57:24 +03:00
|
|
|
std::string& pdbName,
|
2006-01-14 02:18:32 +03:00
|
|
|
const char* config)
|
2005-04-23 00:11:00 +04:00
|
|
|
{
|
2008-01-28 16:38:36 +03:00
|
|
|
// This should not be called for imported targets.
|
|
|
|
// TODO: Split cmTarget into a class hierarchy to get compile-time
|
|
|
|
// enforcement of the limited imported target API.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
std::string msg = "GetLibraryNames called on imported target: ";
|
2008-03-13 04:06:32 +03:00
|
|
|
msg += this->GetName();
|
|
|
|
this->Makefile->IssueMessage(cmake::INTERNAL_ERROR,
|
|
|
|
msg.c_str());
|
|
|
|
return;
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
2005-04-23 00:11:00 +04:00
|
|
|
// Check for library version properties.
|
|
|
|
const char* version = this->GetProperty("VERSION");
|
|
|
|
const char* soversion = this->GetProperty("SOVERSION");
|
2012-04-22 17:42:55 +04:00
|
|
|
if(!this->HasSOName(config) ||
|
2008-04-08 08:06:47 +04:00
|
|
|
this->IsFrameworkOnApple())
|
2005-04-23 00:11:00 +04:00
|
|
|
{
|
|
|
|
// Versioning is supported only for shared libraries and modules,
|
|
|
|
// and then only when the platform supports an soname flag.
|
|
|
|
version = 0;
|
|
|
|
soversion = 0;
|
|
|
|
}
|
|
|
|
if(version && !soversion)
|
|
|
|
{
|
|
|
|
// The soversion must be set if the library version is set. Use
|
|
|
|
// the library version as the soversion.
|
|
|
|
soversion = version;
|
|
|
|
}
|
2011-12-02 01:21:25 +04:00
|
|
|
if(!version && soversion)
|
|
|
|
{
|
|
|
|
// Use the soversion as the library version.
|
|
|
|
version = soversion;
|
|
|
|
}
|
2005-04-23 00:11:00 +04:00
|
|
|
|
2006-06-05 21:45:43 +04:00
|
|
|
// Get the components of the library name.
|
|
|
|
std::string prefix;
|
|
|
|
std::string base;
|
|
|
|
std::string suffix;
|
2009-05-01 18:39:44 +04:00
|
|
|
this->GetFullNameInternal(config, false, prefix, base, suffix);
|
2006-06-05 21:45:43 +04:00
|
|
|
|
2005-04-23 00:11:00 +04:00
|
|
|
// The library name.
|
2006-06-05 21:45:43 +04:00
|
|
|
name = prefix+base+suffix;
|
2005-04-23 00:11:00 +04:00
|
|
|
|
2013-05-06 06:19:05 +04:00
|
|
|
if(this->IsFrameworkOnApple())
|
|
|
|
{
|
|
|
|
realName = prefix;
|
|
|
|
realName += "Versions/";
|
|
|
|
realName += this->GetFrameworkVersion();
|
|
|
|
realName += "/";
|
|
|
|
realName += base;
|
|
|
|
soName = realName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The library's soname.
|
|
|
|
this->ComputeVersionedName(soName, prefix, base, suffix,
|
|
|
|
name, soversion);
|
|
|
|
// The library's real name on disk.
|
|
|
|
this->ComputeVersionedName(realName, prefix, base, suffix,
|
|
|
|
name, version);
|
|
|
|
}
|
2006-02-18 23:37:23 +03:00
|
|
|
|
|
|
|
// The import library name.
|
2009-05-01 18:39:44 +04:00
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY)
|
2006-02-18 23:37:23 +03:00
|
|
|
{
|
2009-05-01 18:39:44 +04:00
|
|
|
impName = this->GetFullNameInternal(config, true);
|
2006-02-18 23:37:23 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
impName = "";
|
|
|
|
}
|
2007-02-01 17:57:24 +03:00
|
|
|
|
|
|
|
// The program database file name.
|
2012-09-25 05:30:42 +04:00
|
|
|
pdbName = this->GetPDBName(config);
|
2005-04-23 00:11:00 +04:00
|
|
|
}
|
2005-08-18 00:11:18 +04:00
|
|
|
|
2011-12-02 01:21:25 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ComputeVersionedName(std::string& vName,
|
|
|
|
std::string const& prefix,
|
|
|
|
std::string const& base,
|
|
|
|
std::string const& suffix,
|
|
|
|
std::string const& name,
|
|
|
|
const char* version)
|
|
|
|
{
|
|
|
|
vName = this->IsApple? (prefix+base) : name;
|
|
|
|
if(version)
|
|
|
|
{
|
|
|
|
vName += ".";
|
|
|
|
vName += version;
|
|
|
|
}
|
|
|
|
vName += this->IsApple? suffix : std::string();
|
|
|
|
}
|
|
|
|
|
2007-07-02 21:32:41 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2005-12-14 18:47:33 +03:00
|
|
|
void cmTarget::GetExecutableNames(std::string& name,
|
2006-01-14 02:18:32 +03:00
|
|
|
std::string& realName,
|
2007-03-19 17:00:36 +03:00
|
|
|
std::string& impName,
|
2007-02-01 17:57:24 +03:00
|
|
|
std::string& pdbName,
|
2006-01-14 02:18:32 +03:00
|
|
|
const char* config)
|
2005-08-18 00:11:18 +04:00
|
|
|
{
|
2008-01-28 16:38:36 +03:00
|
|
|
// This should not be called for imported targets.
|
|
|
|
// TODO: Split cmTarget into a class hierarchy to get compile-time
|
|
|
|
// enforcement of the limited imported target API.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
2008-03-15 17:00:07 +03:00
|
|
|
std::string msg =
|
2009-05-01 18:39:44 +04:00
|
|
|
"GetExecutableNames called on imported target: ";
|
2008-03-13 04:06:32 +03:00
|
|
|
msg += this->GetName();
|
2008-03-15 17:00:07 +03:00
|
|
|
this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg.c_str());
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
2005-08-18 00:11:18 +04:00
|
|
|
// This versioning is supported only for executables and then only
|
|
|
|
// when the platform supports symbolic links.
|
|
|
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
|
|
|
const char* version = 0;
|
|
|
|
#else
|
|
|
|
// Check for executable version properties.
|
|
|
|
const char* version = this->GetProperty("VERSION");
|
2009-05-01 18:39:44 +04:00
|
|
|
if(this->GetType() != cmTarget::EXECUTABLE || this->Makefile->IsOn("XCODE"))
|
2005-08-18 00:11:18 +04:00
|
|
|
{
|
|
|
|
version = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-10-17 02:17:14 +04:00
|
|
|
// Get the components of the executable name.
|
|
|
|
std::string prefix;
|
|
|
|
std::string base;
|
|
|
|
std::string suffix;
|
2009-05-01 18:39:44 +04:00
|
|
|
this->GetFullNameInternal(config, false, prefix, base, suffix);
|
2006-10-17 02:17:14 +04:00
|
|
|
|
2005-08-18 00:11:18 +04:00
|
|
|
// The executable name.
|
2006-10-17 02:17:14 +04:00
|
|
|
name = prefix+base+suffix;
|
2005-08-18 00:11:18 +04:00
|
|
|
|
|
|
|
// The executable's real name on disk.
|
2006-10-17 02:17:14 +04:00
|
|
|
#if defined(__CYGWIN__)
|
|
|
|
realName = prefix+base;
|
|
|
|
#else
|
2005-08-18 00:11:18 +04:00
|
|
|
realName = name;
|
2006-10-17 02:17:14 +04:00
|
|
|
#endif
|
2005-08-18 00:11:18 +04:00
|
|
|
if(version)
|
|
|
|
{
|
|
|
|
realName += "-";
|
|
|
|
realName += version;
|
|
|
|
}
|
2006-10-17 02:17:14 +04:00
|
|
|
#if defined(__CYGWIN__)
|
|
|
|
realName += suffix;
|
|
|
|
#endif
|
2007-02-01 17:57:24 +03:00
|
|
|
|
2007-03-19 17:00:36 +03:00
|
|
|
// The import library name.
|
2009-05-01 18:39:44 +04:00
|
|
|
impName = this->GetFullNameInternal(config, true);
|
2007-03-19 17:00:36 +03:00
|
|
|
|
2007-02-01 17:57:24 +03:00
|
|
|
// The program database file name.
|
2012-09-25 05:30:42 +04:00
|
|
|
pdbName = this->GetPDBName(config);
|
2005-08-18 00:11:18 +04:00
|
|
|
}
|
2006-02-16 23:19:00 +03:00
|
|
|
|
2011-12-06 01:39:07 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HasImplibGNUtoMS()
|
|
|
|
{
|
|
|
|
return this->HasImportLibrary() && this->GetPropertyAsBool("GNUtoMS");
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::GetImplibGNUtoMS(std::string const& gnuName,
|
|
|
|
std::string& out, const char* newExt)
|
|
|
|
{
|
|
|
|
if(this->HasImplibGNUtoMS() &&
|
|
|
|
gnuName.size() > 6 && gnuName.substr(gnuName.size()-6) == ".dll.a")
|
|
|
|
{
|
|
|
|
out = gnuName.substr(0, gnuName.size()-6);
|
|
|
|
out += newExt? newExt : ".lib";
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-09-20 10:32:58 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GenerateTargetManifest(const char* config)
|
|
|
|
{
|
|
|
|
cmMakefile* mf = this->Makefile;
|
|
|
|
cmLocalGenerator* lg = mf->GetLocalGenerator();
|
|
|
|
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
|
|
|
|
|
|
|
|
// Get the names.
|
|
|
|
std::string name;
|
|
|
|
std::string soName;
|
|
|
|
std::string realName;
|
|
|
|
std::string impName;
|
|
|
|
std::string pdbName;
|
|
|
|
if(this->GetType() == cmTarget::EXECUTABLE)
|
|
|
|
{
|
|
|
|
this->GetExecutableNames(name, realName, impName, pdbName, config);
|
|
|
|
}
|
|
|
|
else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY)
|
|
|
|
{
|
|
|
|
this->GetLibraryNames(name, soName, realName, impName, pdbName, config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the directory.
|
|
|
|
std::string dir = this->GetDirectory(config, false);
|
|
|
|
|
|
|
|
// Add each name.
|
|
|
|
std::string f;
|
|
|
|
if(!name.empty())
|
|
|
|
{
|
|
|
|
f = dir;
|
|
|
|
f += "/";
|
|
|
|
f += name;
|
|
|
|
gg->AddToManifest(config? config:"", f);
|
|
|
|
}
|
|
|
|
if(!soName.empty())
|
|
|
|
{
|
|
|
|
f = dir;
|
|
|
|
f += "/";
|
|
|
|
f += soName;
|
|
|
|
gg->AddToManifest(config? config:"", f);
|
|
|
|
}
|
|
|
|
if(!realName.empty())
|
|
|
|
{
|
|
|
|
f = dir;
|
|
|
|
f += "/";
|
|
|
|
f += realName;
|
|
|
|
gg->AddToManifest(config? config:"", f);
|
|
|
|
}
|
|
|
|
if(!pdbName.empty())
|
|
|
|
{
|
2012-09-25 05:30:42 +04:00
|
|
|
f = this->GetPDBDirectory(config);
|
2012-09-20 10:32:58 +04:00
|
|
|
f += "/";
|
|
|
|
f += pdbName;
|
|
|
|
gg->AddToManifest(config? config:"", f);
|
|
|
|
}
|
|
|
|
if(!impName.empty())
|
|
|
|
{
|
|
|
|
f = this->GetDirectory(config, true);
|
|
|
|
f += "/";
|
|
|
|
f += impName;
|
|
|
|
gg->AddToManifest(config? config:"", f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-02-16 23:19:00 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::SetPropertyDefault(const char* property,
|
|
|
|
const char* default_value)
|
|
|
|
{
|
|
|
|
// Compute the name of the variable holding the default value.
|
|
|
|
std::string var = "CMAKE_";
|
|
|
|
var += property;
|
|
|
|
|
2006-03-15 19:02:08 +03:00
|
|
|
if(const char* value = this->Makefile->GetDefinition(var.c_str()))
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
this->SetProperty(property, value);
|
|
|
|
}
|
|
|
|
else if(default_value)
|
|
|
|
{
|
|
|
|
this->SetProperty(property, default_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-02-28 21:25:25 +04:00
|
|
|
bool cmTarget::HaveBuildTreeRPATH(const char *config)
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
2013-02-28 21:25:25 +04:00
|
|
|
if (this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::vector<std::string> libs;
|
|
|
|
this->GetDirectLinkLibraries(config, libs, this);
|
|
|
|
return !libs.empty();
|
2006-02-16 23:19:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::HaveInstallTreeRPATH()
|
|
|
|
{
|
|
|
|
const char* install_rpath = this->GetProperty("INSTALL_RPATH");
|
2012-02-20 03:34:11 +04:00
|
|
|
return (install_rpath && *install_rpath) &&
|
|
|
|
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH");
|
2006-02-16 23:19:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2009-07-08 21:03:47 +04:00
|
|
|
bool cmTarget::NeedRelinkBeforeInstall(const char* config)
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
// Only executables and shared libraries can have an rpath and may
|
|
|
|
// need relinking.
|
2006-03-15 19:02:08 +03:00
|
|
|
if(this->TargetTypeValue != cmTarget::EXECUTABLE &&
|
|
|
|
this->TargetTypeValue != cmTarget::SHARED_LIBRARY &&
|
|
|
|
this->TargetTypeValue != cmTarget::MODULE_LIBRARY)
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there is no install location this target will not be installed
|
|
|
|
// and therefore does not need relinking.
|
2006-02-20 01:27:47 +03:00
|
|
|
if(!this->GetHaveInstallRule())
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If skipping all rpaths completely then no relinking is needed.
|
2006-03-15 19:02:08 +03:00
|
|
|
if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If building with the install-tree rpath no relinking is needed.
|
|
|
|
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-01-29 23:07:33 +03:00
|
|
|
// If chrpath is going to be used no relinking is needed.
|
2009-07-08 21:03:47 +04:00
|
|
|
if(this->IsChrpathUsed(config))
|
2008-01-29 23:07:33 +03:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2006-02-16 23:19:00 +03:00
|
|
|
// Check for rpath support on this platform.
|
2013-01-04 16:31:01 +04:00
|
|
|
if(const char* ll = this->GetLinkerLanguage(config, this))
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
|
|
|
|
flagVar += ll;
|
|
|
|
flagVar += "_FLAG";
|
2006-03-15 19:02:08 +03:00
|
|
|
if(!this->Makefile->IsSet(flagVar.c_str()))
|
2006-02-16 23:19:00 +03:00
|
|
|
{
|
|
|
|
// There is no rpath support on this platform so nothing needs
|
|
|
|
// relinking.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// No linker language is known. This error will be reported by
|
|
|
|
// other code.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If either a build or install tree rpath is set then the rpath
|
|
|
|
// will likely change between the build tree and install tree and
|
|
|
|
// this target must be relinked.
|
2013-02-28 21:25:25 +04:00
|
|
|
return this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH();
|
2006-02-16 23:19:00 +03:00
|
|
|
}
|
2006-02-24 21:13:14 +03:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-05-06 06:19:05 +04:00
|
|
|
std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
|
2006-02-24 21:13:14 +03:00
|
|
|
{
|
|
|
|
// If building directly for installation then the build tree install_name
|
|
|
|
// is the same as the install tree.
|
|
|
|
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
return GetInstallNameDirForInstallTree();
|
2006-02-24 21:13:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Use the build tree directory for the target.
|
2006-03-15 19:02:08 +03:00
|
|
|
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
|
|
|
|
!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
|
2006-02-24 21:13:14 +03:00
|
|
|
!this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
|
|
|
|
{
|
2013-04-27 08:04:44 +04:00
|
|
|
std::string dir;
|
|
|
|
if(this->GetPropertyAsBool("MACOSX_RPATH"))
|
|
|
|
{
|
|
|
|
dir = "@rpath";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dir = this->GetDirectory(config);
|
|
|
|
}
|
2006-02-24 21:13:14 +03:00
|
|
|
dir += "/";
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2013-05-06 06:19:05 +04:00
|
|
|
std::string cmTarget::GetInstallNameDirForInstallTree()
|
2006-02-24 21:13:14 +03:00
|
|
|
{
|
2009-12-15 01:46:29 +03:00
|
|
|
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
|
2006-02-24 21:13:14 +03:00
|
|
|
{
|
2009-12-15 01:46:29 +03:00
|
|
|
std::string dir;
|
2013-08-22 07:09:32 +04:00
|
|
|
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
|
2009-12-15 01:46:29 +03:00
|
|
|
|
2012-02-20 03:34:11 +04:00
|
|
|
if(!this->Makefile->IsOn("CMAKE_SKIP_RPATH") &&
|
|
|
|
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"))
|
2009-12-15 01:46:29 +03:00
|
|
|
{
|
|
|
|
if(install_name_dir && *install_name_dir)
|
|
|
|
{
|
|
|
|
dir = install_name_dir;
|
|
|
|
dir += "/";
|
|
|
|
}
|
|
|
|
}
|
2013-08-22 07:09:32 +04:00
|
|
|
if(!install_name_dir && this->GetPropertyAsBool("MACOSX_RPATH"))
|
2013-04-27 08:04:44 +04:00
|
|
|
{
|
|
|
|
dir = "@rpath/";
|
|
|
|
}
|
2006-02-24 21:13:14 +03:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
2007-03-08 22:57:28 +03:00
|
|
|
|
2009-05-01 17:45:19 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
const char* cmTarget::GetOutputTargetType(bool implib)
|
|
|
|
{
|
|
|
|
switch(this->GetType())
|
|
|
|
{
|
|
|
|
case cmTarget::SHARED_LIBRARY:
|
|
|
|
if(this->DLLPlatform)
|
|
|
|
{
|
|
|
|
if(implib)
|
|
|
|
{
|
|
|
|
// A DLL import library is treated as an archive target.
|
|
|
|
return "ARCHIVE";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// A DLL shared library is treated as a runtime target.
|
|
|
|
return "RUNTIME";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// For non-DLL platforms shared libraries are treated as
|
|
|
|
// library targets.
|
|
|
|
return "LIBRARY";
|
|
|
|
}
|
|
|
|
case cmTarget::STATIC_LIBRARY:
|
|
|
|
// Static libraries are always treated as archive targets.
|
|
|
|
return "ARCHIVE";
|
|
|
|
case cmTarget::MODULE_LIBRARY:
|
|
|
|
if(implib)
|
|
|
|
{
|
|
|
|
// Module libraries are always treated as library targets.
|
|
|
|
return "ARCHIVE";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Module import libraries are treated as archive targets.
|
|
|
|
return "LIBRARY";
|
|
|
|
}
|
|
|
|
case cmTarget::EXECUTABLE:
|
|
|
|
if(implib)
|
|
|
|
{
|
|
|
|
// Executable import libraries are treated as archive targets.
|
|
|
|
return "ARCHIVE";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Executables are always treated as runtime targets.
|
|
|
|
return "RUNTIME";
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2007-03-08 22:57:28 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2011-07-18 23:25:30 +04:00
|
|
|
bool cmTarget::ComputeOutputDir(const char* config,
|
2009-07-03 18:33:59 +04:00
|
|
|
bool implib, std::string& out)
|
2008-04-08 08:06:47 +04:00
|
|
|
{
|
2011-07-18 23:25:30 +04:00
|
|
|
bool usesDefaultOutputDir = false;
|
|
|
|
|
2008-04-08 08:06:47 +04:00
|
|
|
// Look for a target property defining the target output directory
|
|
|
|
// based on the target type.
|
2009-10-28 20:35:25 +03:00
|
|
|
std::string targetTypeName = this->GetOutputTargetType(implib);
|
2008-04-08 08:06:47 +04:00
|
|
|
const char* propertyName = 0;
|
2009-10-28 20:35:25 +03:00
|
|
|
std::string propertyNameStr = targetTypeName;
|
2009-05-01 17:45:19 +04:00
|
|
|
if(!propertyNameStr.empty())
|
2007-03-08 22:57:28 +03:00
|
|
|
{
|
2009-05-01 17:45:19 +04:00
|
|
|
propertyNameStr += "_OUTPUT_DIRECTORY";
|
|
|
|
propertyName = propertyNameStr.c_str();
|
2008-04-08 08:06:47 +04:00
|
|
|
}
|
2007-03-08 22:57:28 +03:00
|
|
|
|
2009-10-28 20:35:25 +03:00
|
|
|
// Check for a per-configuration output directory target property.
|
|
|
|
std::string configUpper = cmSystemTools::UpperCase(config? config : "");
|
|
|
|
const char* configProp = 0;
|
|
|
|
std::string configPropStr = targetTypeName;
|
|
|
|
if(!configPropStr.empty())
|
|
|
|
{
|
|
|
|
configPropStr += "_OUTPUT_DIRECTORY_";
|
|
|
|
configPropStr += configUpper;
|
|
|
|
configProp = configPropStr.c_str();
|
|
|
|
}
|
|
|
|
|
2008-04-08 08:06:47 +04:00
|
|
|
// Select an output directory.
|
2009-10-28 20:35:25 +03:00
|
|
|
if(const char* config_outdir = this->GetProperty(configProp))
|
|
|
|
{
|
|
|
|
// Use the user-specified per-configuration output directory.
|
|
|
|
out = config_outdir;
|
|
|
|
|
|
|
|
// Skip per-configuration subdirectory.
|
|
|
|
config = 0;
|
|
|
|
}
|
|
|
|
else if(const char* outdir = this->GetProperty(propertyName))
|
2008-04-08 08:06:47 +04:00
|
|
|
{
|
|
|
|
// Use the user-specified output directory.
|
|
|
|
out = outdir;
|
|
|
|
}
|
|
|
|
else if(this->GetType() == cmTarget::EXECUTABLE)
|
|
|
|
{
|
|
|
|
// Lookup the output path for executables.
|
|
|
|
out = this->Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
|
|
|
|
}
|
|
|
|
else if(this->GetType() == cmTarget::STATIC_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY)
|
|
|
|
{
|
|
|
|
// Lookup the output path for libraries.
|
|
|
|
out = this->Makefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH");
|
|
|
|
}
|
|
|
|
if(out.empty())
|
|
|
|
{
|
|
|
|
// Default to the current output directory.
|
2011-07-18 23:25:30 +04:00
|
|
|
usesDefaultOutputDir = true;
|
2008-04-08 08:06:47 +04:00
|
|
|
out = ".";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the output path to a full path in case it is
|
|
|
|
// specified as a relative path. Treat a relative path as
|
|
|
|
// relative to the current output directory for this makefile.
|
|
|
|
out = (cmSystemTools::CollapseFullPath
|
|
|
|
(out.c_str(), this->Makefile->GetStartOutputDirectory()));
|
2009-07-03 18:33:59 +04:00
|
|
|
|
|
|
|
// The generator may add the configuration's subdirectory.
|
|
|
|
if(config && *config)
|
|
|
|
{
|
2011-08-12 23:55:01 +04:00
|
|
|
const char *platforms = this->Makefile->GetDefinition(
|
|
|
|
"CMAKE_XCODE_EFFECTIVE_PLATFORMS");
|
|
|
|
std::string suffix =
|
|
|
|
usesDefaultOutputDir && platforms ? "$(EFFECTIVE_PLATFORM_NAME)" : "";
|
2009-07-03 18:33:59 +04:00
|
|
|
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
2011-08-12 23:55:01 +04:00
|
|
|
AppendDirectoryForConfig("/", config, suffix.c_str(), out);
|
2009-07-03 18:33:59 +04:00
|
|
|
}
|
2011-07-18 23:25:30 +04:00
|
|
|
|
|
|
|
return usesDefaultOutputDir;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
2012-11-02 20:49:44 +04:00
|
|
|
bool cmTarget::ComputePDBOutputDir(const char* config, std::string& out)
|
2012-09-25 05:30:42 +04:00
|
|
|
{
|
|
|
|
// Look for a target property defining the target output directory
|
|
|
|
// based on the target type.
|
|
|
|
std::string targetTypeName = "PDB";
|
|
|
|
const char* propertyName = 0;
|
|
|
|
std::string propertyNameStr = targetTypeName;
|
|
|
|
if(!propertyNameStr.empty())
|
|
|
|
{
|
|
|
|
propertyNameStr += "_OUTPUT_DIRECTORY";
|
|
|
|
propertyName = propertyNameStr.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for a per-configuration output directory target property.
|
|
|
|
std::string configUpper = cmSystemTools::UpperCase(config? config : "");
|
|
|
|
const char* configProp = 0;
|
|
|
|
std::string configPropStr = targetTypeName;
|
|
|
|
if(!configPropStr.empty())
|
|
|
|
{
|
|
|
|
configPropStr += "_OUTPUT_DIRECTORY_";
|
|
|
|
configPropStr += configUpper;
|
|
|
|
configProp = configPropStr.c_str();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select an output directory.
|
|
|
|
if(const char* config_outdir = this->GetProperty(configProp))
|
|
|
|
{
|
|
|
|
// Use the user-specified per-configuration output directory.
|
|
|
|
out = config_outdir;
|
|
|
|
|
|
|
|
// Skip per-configuration subdirectory.
|
|
|
|
config = 0;
|
|
|
|
}
|
|
|
|
else if(const char* outdir = this->GetProperty(propertyName))
|
|
|
|
{
|
|
|
|
// Use the user-specified output directory.
|
|
|
|
out = outdir;
|
|
|
|
}
|
|
|
|
if(out.empty())
|
|
|
|
{
|
2012-11-02 20:49:44 +04:00
|
|
|
return false;
|
2012-09-25 05:30:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the output path to a full path in case it is
|
|
|
|
// specified as a relative path. Treat a relative path as
|
|
|
|
// relative to the current output directory for this makefile.
|
|
|
|
out = (cmSystemTools::CollapseFullPath
|
|
|
|
(out.c_str(), this->Makefile->GetStartOutputDirectory()));
|
|
|
|
|
|
|
|
// The generator may add the configuration's subdirectory.
|
|
|
|
if(config && *config)
|
|
|
|
{
|
|
|
|
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
|
|
|
AppendDirectoryForConfig("/", config, "", out);
|
|
|
|
}
|
2012-11-02 20:49:44 +04:00
|
|
|
return true;
|
2012-09-25 05:30:42 +04:00
|
|
|
}
|
|
|
|
|
2011-07-18 23:25:30 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib)
|
|
|
|
{
|
|
|
|
std::string dir;
|
|
|
|
return this->ComputeOutputDir(config, implib, dir);
|
2008-04-08 08:06:47 +04:00
|
|
|
}
|
|
|
|
|
2009-05-01 17:45:43 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetOutputName(const char* config, bool implib)
|
|
|
|
{
|
|
|
|
std::vector<std::string> props;
|
|
|
|
std::string type = this->GetOutputTargetType(implib);
|
|
|
|
std::string configUpper = cmSystemTools::UpperCase(config? config : "");
|
|
|
|
if(!type.empty() && !configUpper.empty())
|
|
|
|
{
|
|
|
|
// <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME_<CONFIG>
|
|
|
|
props.push_back(type + "_OUTPUT_NAME_" + configUpper);
|
|
|
|
}
|
|
|
|
if(!type.empty())
|
|
|
|
{
|
|
|
|
// <ARCHIVE|LIBRARY|RUNTIME>_OUTPUT_NAME
|
|
|
|
props.push_back(type + "_OUTPUT_NAME");
|
|
|
|
}
|
|
|
|
if(!configUpper.empty())
|
|
|
|
{
|
|
|
|
// OUTPUT_NAME_<CONFIG>
|
|
|
|
props.push_back("OUTPUT_NAME_" + configUpper);
|
|
|
|
// <CONFIG>_OUTPUT_NAME
|
|
|
|
props.push_back(configUpper + "_OUTPUT_NAME");
|
|
|
|
}
|
|
|
|
// OUTPUT_NAME
|
|
|
|
props.push_back("OUTPUT_NAME");
|
|
|
|
|
|
|
|
for(std::vector<std::string>::const_iterator i = props.begin();
|
|
|
|
i != props.end(); ++i)
|
|
|
|
{
|
|
|
|
if(const char* outName = this->GetProperty(i->c_str()))
|
|
|
|
{
|
|
|
|
return outName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return this->GetName();
|
|
|
|
}
|
|
|
|
|
2008-04-08 08:06:47 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetFrameworkVersion()
|
|
|
|
{
|
|
|
|
if(const char* fversion = this->GetProperty("FRAMEWORK_VERSION"))
|
|
|
|
{
|
|
|
|
return fversion;
|
|
|
|
}
|
|
|
|
else if(const char* tversion = this->GetProperty("VERSION"))
|
|
|
|
{
|
|
|
|
return tversion;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return "A";
|
|
|
|
}
|
2007-03-08 22:57:28 +03:00
|
|
|
}
|
2007-03-28 07:13:25 +04:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
const char* cmTarget::GetExportMacro()
|
|
|
|
{
|
|
|
|
// Define the symbol for targets that export symbols.
|
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
2008-01-28 16:38:36 +03:00
|
|
|
this->IsExecutableWithExports())
|
2007-03-28 07:13:25 +04:00
|
|
|
{
|
|
|
|
if(const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL"))
|
|
|
|
{
|
|
|
|
this->ExportMacro = custom_export_name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string in = this->GetName();
|
|
|
|
in += "_EXPORTS";
|
|
|
|
this->ExportMacro = cmSystemTools::MakeCindentifier(in.c_str());
|
|
|
|
}
|
|
|
|
return this->ExportMacro.c_str();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2007-08-02 21:38:39 +04:00
|
|
|
|
2012-11-05 17:48:42 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsNullImpliedByLinkLibraries(const std::string &p)
|
|
|
|
{
|
|
|
|
return this->LinkImplicitNullProperties.find(p)
|
|
|
|
!= this->LinkImplicitNullProperties.end();
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:05 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-01-06 16:49:16 +04:00
|
|
|
template<typename PropertyType>
|
|
|
|
PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
|
|
|
|
PropertyType *);
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<>
|
|
|
|
bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
|
2013-01-06 16:49:05 +04:00
|
|
|
{
|
2013-01-06 16:49:16 +04:00
|
|
|
return tgt->GetPropertyAsBool(prop);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:20 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<>
|
|
|
|
const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop,
|
|
|
|
const char **)
|
|
|
|
{
|
|
|
|
return tgt->GetProperty(prop);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename PropertyType>
|
|
|
|
bool consistentProperty(PropertyType lhs, PropertyType rhs);
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<>
|
|
|
|
bool consistentProperty(bool lhs, bool rhs)
|
|
|
|
{
|
|
|
|
return lhs == rhs;
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:20 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<>
|
|
|
|
bool consistentProperty(const char *lhs, const char *rhs)
|
|
|
|
{
|
|
|
|
if (!lhs && !rhs)
|
|
|
|
return true;
|
|
|
|
if (!lhs || !rhs)
|
|
|
|
return false;
|
|
|
|
return strcmp(lhs, rhs) == 0;
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename PropertyType>
|
|
|
|
PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
|
|
|
|
const std::string &p,
|
|
|
|
const char *config,
|
|
|
|
const char *defaultValue,
|
|
|
|
PropertyType *)
|
|
|
|
{
|
|
|
|
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
|
|
|
|
0);
|
|
|
|
const bool explicitlySet = tgt->GetProperties()
|
2013-01-06 16:49:05 +04:00
|
|
|
.find(p.c_str())
|
2013-01-06 16:49:16 +04:00
|
|
|
!= tgt->GetProperties().end();
|
2013-01-06 16:49:05 +04:00
|
|
|
const bool impliedByUse =
|
2013-01-06 16:49:16 +04:00
|
|
|
tgt->IsNullImpliedByLinkLibraries(p);
|
2013-01-06 16:49:05 +04:00
|
|
|
assert((impliedByUse ^ explicitlySet)
|
|
|
|
|| (!impliedByUse && !explicitlySet));
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
|
2013-03-13 01:25:59 +04:00
|
|
|
if(!info)
|
|
|
|
{
|
|
|
|
return propContent;
|
|
|
|
}
|
2013-01-06 16:49:05 +04:00
|
|
|
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
|
|
|
|
bool propInitialized = explicitlySet;
|
|
|
|
|
|
|
|
for(cmComputeLinkInformation::ItemVector::const_iterator li =
|
|
|
|
deps.begin();
|
|
|
|
li != deps.end(); ++li)
|
|
|
|
{
|
|
|
|
// An error should be reported if one dependency
|
|
|
|
// has INTERFACE_POSITION_INDEPENDENT_CODE ON and the other
|
|
|
|
// has INTERFACE_POSITION_INDEPENDENT_CODE OFF, or if the
|
|
|
|
// target itself has a POSITION_INDEPENDENT_CODE which disagrees
|
|
|
|
// with a dependency.
|
|
|
|
|
|
|
|
if (!li->Target)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool ifaceIsSet = li->Target->GetProperties()
|
|
|
|
.find("INTERFACE_" + p)
|
|
|
|
!= li->Target->GetProperties().end();
|
2013-01-06 16:49:16 +04:00
|
|
|
PropertyType ifacePropContent =
|
|
|
|
getTypedProperty<PropertyType>(li->Target,
|
|
|
|
("INTERFACE_" + p).c_str(), 0);
|
2013-01-06 16:49:05 +04:00
|
|
|
if (explicitlySet)
|
|
|
|
{
|
|
|
|
if (ifaceIsSet)
|
|
|
|
{
|
2013-01-06 16:49:16 +04:00
|
|
|
if (!consistentProperty(propContent, ifacePropContent))
|
2013-01-06 16:49:05 +04:00
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Property " << p << " on target \""
|
2013-01-06 16:49:16 +04:00
|
|
|
<< tgt->GetName() << "\" does\nnot match the "
|
2013-01-06 16:49:05 +04:00
|
|
|
"INTERFACE_" << p << " property requirement\nof "
|
|
|
|
"dependency \"" << li->Target->GetName() << "\".\n";
|
|
|
|
cmSystemTools::Error(e.str().c_str());
|
2013-01-18 19:10:20 +04:00
|
|
|
break;
|
2013-01-06 16:49:05 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Agree
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Explicitly set on target and not set in iface. Can't disagree.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (impliedByUse)
|
|
|
|
{
|
|
|
|
if (ifaceIsSet)
|
|
|
|
{
|
2013-01-06 16:49:16 +04:00
|
|
|
if (!consistentProperty(propContent, ifacePropContent))
|
2013-01-06 16:49:05 +04:00
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Property " << p << " on target \""
|
2013-01-06 16:49:16 +04:00
|
|
|
<< tgt->GetName() << "\" is\nimplied to be " << defaultValue
|
|
|
|
<< " because it was used to determine the link libraries\n"
|
|
|
|
"already. The INTERFACE_" << p << " property on\ndependency \""
|
2013-01-06 16:49:05 +04:00
|
|
|
<< li->Target->GetName() << "\" is in conflict.\n";
|
|
|
|
cmSystemTools::Error(e.str().c_str());
|
2013-01-18 19:10:20 +04:00
|
|
|
break;
|
2013-01-06 16:49:05 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Agree
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Implicitly set on target and not set in iface. Can't disagree.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ifaceIsSet)
|
|
|
|
{
|
|
|
|
if (propInitialized)
|
|
|
|
{
|
2013-01-06 16:49:16 +04:00
|
|
|
if (!consistentProperty(propContent, ifacePropContent))
|
2013-01-06 16:49:05 +04:00
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "The INTERFACE_" << p << " property of \""
|
|
|
|
<< li->Target->GetName() << "\" does\nnot agree with the value "
|
|
|
|
"of " << p << " already determined\nfor \""
|
2013-01-06 16:49:16 +04:00
|
|
|
<< tgt->GetName() << "\".\n";
|
2013-01-06 16:49:05 +04:00
|
|
|
cmSystemTools::Error(e.str().c_str());
|
2013-01-18 19:10:20 +04:00
|
|
|
break;
|
2013-01-06 16:49:05 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Agree.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
propContent = ifacePropContent;
|
|
|
|
propInitialized = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Not set. Nothing to agree on.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return propContent;
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
|
|
|
|
const char *config)
|
|
|
|
{
|
|
|
|
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:20 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
const char * cmTarget::GetLinkInterfaceDependentStringProperty(
|
|
|
|
const std::string &p,
|
|
|
|
const char *config)
|
|
|
|
{
|
|
|
|
return checkInterfacePropertyCompatibility<const char *>(this,
|
|
|
|
p,
|
|
|
|
config,
|
|
|
|
"empty", 0);
|
|
|
|
}
|
|
|
|
|
2013-01-19 14:21:14 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
|
|
|
|
const char *interfaceProperty,
|
|
|
|
const char *config)
|
|
|
|
{
|
|
|
|
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
|
2013-03-13 01:13:42 +04:00
|
|
|
if(!info)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-01-19 14:21:14 +04:00
|
|
|
|
|
|
|
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
|
|
|
|
|
|
|
|
for(cmComputeLinkInformation::ItemVector::const_iterator li =
|
|
|
|
deps.begin();
|
|
|
|
li != deps.end(); ++li)
|
|
|
|
{
|
|
|
|
if (!li->Target)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const char *prop = li->Target->GetProperty(interfaceProperty);
|
|
|
|
if (!prop)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> props;
|
|
|
|
cmSystemTools::ExpandListArgument(prop, props);
|
|
|
|
|
|
|
|
for(std::vector<std::string>::iterator pi = props.begin();
|
|
|
|
pi != props.end(); ++pi)
|
|
|
|
{
|
|
|
|
if (*pi == p)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p,
|
|
|
|
const char *config)
|
|
|
|
{
|
2013-02-08 23:10:22 +04:00
|
|
|
if (this->TargetTypeValue == OBJECT_LIBRARY)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-02-07 16:13:44 +04:00
|
|
|
return (p == "POSITION_INDEPENDENT_CODE") ||
|
|
|
|
isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL",
|
2013-01-19 14:21:14 +04:00
|
|
|
config);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:20 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
|
|
|
|
const char *config)
|
|
|
|
{
|
2013-02-08 23:10:22 +04:00
|
|
|
if (this->TargetTypeValue == OBJECT_LIBRARY)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2013-01-06 16:49:20 +04:00
|
|
|
return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
|
|
|
|
config);
|
|
|
|
}
|
|
|
|
|
2007-08-02 21:38:39 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
|
|
|
|
{
|
|
|
|
for(std::vector<cmSourceFile*>::const_iterator
|
|
|
|
i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
|
|
|
|
{
|
|
|
|
if(const char* lang = (*i)->GetLanguage())
|
|
|
|
{
|
|
|
|
languages.insert(lang);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-12-19 01:50:27 +03:00
|
|
|
|
2008-01-29 23:07:33 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2009-07-08 21:03:47 +04:00
|
|
|
bool cmTarget::IsChrpathUsed(const char* config)
|
2007-12-19 01:50:27 +03:00
|
|
|
{
|
2008-03-02 22:35:23 +03:00
|
|
|
// Only certain target types have an rpath.
|
|
|
|
if(!(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::MODULE_LIBRARY ||
|
|
|
|
this->GetType() == cmTarget::EXECUTABLE))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the target will not be installed we do not need to change its
|
|
|
|
// rpath.
|
|
|
|
if(!this->GetHaveInstallRule())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-03-01 21:02:08 +03:00
|
|
|
// Skip chrpath if skipping rpath altogether.
|
|
|
|
if(this->Makefile->IsOn("CMAKE_SKIP_RPATH"))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip chrpath if it does not need to be changed at install time.
|
|
|
|
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-03-03 00:37:34 +03:00
|
|
|
// Allow the user to disable builtin chrpath explicitly.
|
|
|
|
if(this->Makefile->IsOn("CMAKE_NO_BUILTIN_CHRPATH"))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-04-27 08:04:44 +04:00
|
|
|
if(this->Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(CMAKE_USE_ELF_PARSER)
|
2008-03-01 20:51:07 +03:00
|
|
|
// Enable if the rpath flag uses a separator and the target uses ELF
|
|
|
|
// binaries.
|
2013-01-04 16:31:01 +04:00
|
|
|
if(const char* ll = this->GetLinkerLanguage(config, this))
|
2007-12-19 01:50:27 +03:00
|
|
|
{
|
2008-01-29 23:07:33 +03:00
|
|
|
std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
|
|
|
|
sepVar += ll;
|
|
|
|
sepVar += "_FLAG_SEP";
|
|
|
|
const char* sep = this->Makefile->GetDefinition(sepVar.c_str());
|
|
|
|
if(sep && *sep)
|
|
|
|
{
|
2008-03-01 20:51:07 +03:00
|
|
|
// TODO: Add ELF check to ABI detection and get rid of
|
|
|
|
// CMAKE_EXECUTABLE_FORMAT.
|
|
|
|
if(const char* fmt =
|
|
|
|
this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT"))
|
2008-01-29 23:07:33 +03:00
|
|
|
{
|
2008-03-01 20:51:07 +03:00
|
|
|
return strcmp(fmt, "ELF") == 0;
|
2008-01-29 23:07:33 +03:00
|
|
|
}
|
|
|
|
}
|
2007-12-19 01:50:27 +03:00
|
|
|
}
|
2008-03-01 20:51:07 +03:00
|
|
|
#endif
|
2009-07-08 21:03:47 +04:00
|
|
|
static_cast<void>(config);
|
2008-01-29 23:07:33 +03:00
|
|
|
return false;
|
2007-12-19 01:50:27 +03:00
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTarget::ImportInfo const*
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget::GetImportInfo(const char* config, cmTarget *headTarget)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
// There is no imported information for non-imported targets.
|
|
|
|
if(!this->IsImported())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup/compute/cache the import information for this
|
|
|
|
// configuration.
|
|
|
|
std::string config_upper;
|
|
|
|
if(config && *config)
|
|
|
|
{
|
|
|
|
config_upper = cmSystemTools::UpperCase(config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
config_upper = "NOCONFIG";
|
|
|
|
}
|
2013-01-04 16:31:01 +04:00
|
|
|
TargetConfigPair key(headTarget, config_upper);
|
2009-07-08 16:31:30 +04:00
|
|
|
typedef cmTargetInternals::ImportInfoMapType ImportInfoMapType;
|
2013-01-04 16:31:01 +04:00
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
ImportInfoMapType::const_iterator i =
|
2013-01-04 16:31:01 +04:00
|
|
|
this->Internal->ImportInfoMap.find(key);
|
2009-07-08 16:31:30 +04:00
|
|
|
if(i == this->Internal->ImportInfoMap.end())
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
ImportInfo info;
|
2013-01-04 16:31:01 +04:00
|
|
|
this->ComputeImportInfo(config_upper, info, headTarget);
|
|
|
|
ImportInfoMapType::value_type entry(key, info);
|
2009-07-08 16:31:30 +04:00
|
|
|
i = this->Internal->ImportInfoMap.insert(entry).first;
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
2012-11-02 18:47:40 +04:00
|
|
|
if(this->GetType() == INTERFACE_LIBRARY)
|
|
|
|
{
|
|
|
|
return &i->second;
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
// If the location is empty then the target is not available for
|
|
|
|
// this configuration.
|
2009-04-09 00:29:04 +04:00
|
|
|
if(i->second.Location.empty() && i->second.ImportLibrary.empty())
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return the import information.
|
|
|
|
return &i->second;
|
|
|
|
}
|
|
|
|
|
2012-12-23 14:20:37 +04:00
|
|
|
bool cmTarget::GetMappedConfig(std::string const& desired_config,
|
|
|
|
const char** loc,
|
|
|
|
const char** imp,
|
|
|
|
std::string& suffix)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
// Track the configuration-specific property suffix.
|
2012-12-23 14:20:37 +04:00
|
|
|
suffix = "_";
|
2008-01-28 16:38:36 +03:00
|
|
|
suffix += desired_config;
|
|
|
|
|
|
|
|
std::vector<std::string> mappedConfigs;
|
|
|
|
{
|
|
|
|
std::string mapProp = "MAP_IMPORTED_CONFIG_";
|
|
|
|
mapProp += desired_config;
|
|
|
|
if(const char* mapValue = this->GetProperty(mapProp.c_str()))
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(mapValue, mappedConfigs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-23 14:20:37 +04:00
|
|
|
// If we needed to find one of the mapped configurations but did not
|
|
|
|
// On a DLL platform there may be only IMPORTED_IMPLIB for a shared
|
|
|
|
// library or an executable with exports.
|
|
|
|
bool allowImp = this->HasImportLibrary();
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
// If a mapping was found, check its configurations.
|
|
|
|
for(std::vector<std::string>::const_iterator mci = mappedConfigs.begin();
|
2012-12-23 14:20:37 +04:00
|
|
|
!*loc && !*imp && mci != mappedConfigs.end(); ++mci)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
// Look for this configuration.
|
|
|
|
std::string mcUpper = cmSystemTools::UpperCase(mci->c_str());
|
|
|
|
std::string locProp = "IMPORTED_LOCATION_";
|
|
|
|
locProp += mcUpper;
|
2012-12-23 14:20:37 +04:00
|
|
|
*loc = this->GetProperty(locProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
if(allowImp)
|
|
|
|
{
|
|
|
|
std::string impProp = "IMPORTED_IMPLIB_";
|
|
|
|
impProp += mcUpper;
|
2012-12-23 14:20:37 +04:00
|
|
|
*imp = this->GetProperty(impProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
|
|
|
|
// If it was found, use it for all properties below.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(*loc || *imp)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
suffix = "_";
|
|
|
|
suffix += mcUpper;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we needed to find one of the mapped configurations but did not
|
|
|
|
// then the target is not found. The project does not want any
|
|
|
|
// other configuration.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(!mappedConfigs.empty() && !*loc && !*imp)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2012-12-23 14:20:37 +04:00
|
|
|
return false;
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have not yet found it then there are no mapped
|
|
|
|
// configurations. Look for an exact-match.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(!*loc && !*imp)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
std::string locProp = "IMPORTED_LOCATION";
|
|
|
|
locProp += suffix;
|
2012-12-23 14:20:37 +04:00
|
|
|
*loc = this->GetProperty(locProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
if(allowImp)
|
|
|
|
{
|
|
|
|
std::string impProp = "IMPORTED_IMPLIB";
|
|
|
|
impProp += suffix;
|
2012-12-23 14:20:37 +04:00
|
|
|
*imp = this->GetProperty(impProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have not yet found it then there are no mapped
|
|
|
|
// configurations and no exact match.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(!*loc && !*imp)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
// The suffix computed above is not useful.
|
|
|
|
suffix = "";
|
|
|
|
|
|
|
|
// Look for a configuration-less location. This may be set by
|
|
|
|
// manually-written code.
|
2012-12-23 14:20:37 +04:00
|
|
|
*loc = this->GetProperty("IMPORTED_LOCATION");
|
2009-04-09 00:29:04 +04:00
|
|
|
if(allowImp)
|
|
|
|
{
|
2012-12-23 14:20:37 +04:00
|
|
|
*imp = this->GetProperty("IMPORTED_IMPLIB");
|
2009-04-09 00:29:04 +04:00
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we have not yet found it then the project is willing to try
|
|
|
|
// any available configuration.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(!*loc && !*imp)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
std::vector<std::string> availableConfigs;
|
|
|
|
if(const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS"))
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(iconfigs, availableConfigs);
|
|
|
|
}
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
aci = availableConfigs.begin();
|
2012-12-23 14:20:37 +04:00
|
|
|
!*loc && !*imp && aci != availableConfigs.end(); ++aci)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
suffix = "_";
|
2009-04-09 00:28:55 +04:00
|
|
|
suffix += cmSystemTools::UpperCase(*aci);
|
2008-01-28 16:38:36 +03:00
|
|
|
std::string locProp = "IMPORTED_LOCATION";
|
|
|
|
locProp += suffix;
|
2012-12-23 14:20:37 +04:00
|
|
|
*loc = this->GetProperty(locProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
if(allowImp)
|
|
|
|
{
|
|
|
|
std::string impProp = "IMPORTED_IMPLIB";
|
|
|
|
impProp += suffix;
|
2012-12-23 14:20:37 +04:00
|
|
|
*imp = this->GetProperty(impProp.c_str());
|
2009-04-09 00:29:04 +04:00
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we have not yet found it then the target is not available.
|
2012-12-23 14:20:37 +04:00
|
|
|
if(!*loc && !*imp)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ComputeImportInfo(std::string const& desired_config,
|
2013-01-04 16:31:01 +04:00
|
|
|
ImportInfo& info,
|
|
|
|
cmTarget *headTarget)
|
2012-12-23 14:20:37 +04:00
|
|
|
{
|
|
|
|
// This method finds information about an imported target from its
|
|
|
|
// properties. The "IMPORTED_" namespace is reserved for properties
|
|
|
|
// defined by the project exporting the target.
|
|
|
|
|
|
|
|
// Initialize members.
|
|
|
|
info.NoSOName = false;
|
|
|
|
|
|
|
|
const char* loc = 0;
|
|
|
|
const char* imp = 0;
|
|
|
|
std::string suffix;
|
2012-11-20 13:58:15 +04:00
|
|
|
if (this->GetType() != INTERFACE_LIBRARY &&
|
|
|
|
!this->GetMappedConfig(desired_config, &loc, &imp, suffix))
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-11-02 18:47:40 +04:00
|
|
|
// Get the link interface.
|
|
|
|
{
|
|
|
|
std::string linkProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
|
const char *propertyLibs = this->GetProperty(linkProp.c_str());
|
|
|
|
|
|
|
|
if (this->GetType() != INTERFACE_LIBRARY)
|
|
|
|
{
|
|
|
|
if(!propertyLibs)
|
|
|
|
{
|
|
|
|
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
|
|
|
|
linkProp += suffix;
|
|
|
|
propertyLibs = this->GetProperty(linkProp.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!propertyLibs)
|
|
|
|
{
|
|
|
|
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
|
|
|
|
propertyLibs = this->GetProperty(linkProp.c_str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(propertyLibs)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
|
|
|
|
this->GetName(),
|
|
|
|
linkProp, 0, 0);
|
|
|
|
cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
|
|
|
|
->Evaluate(this->Makefile,
|
|
|
|
desired_config.c_str(),
|
|
|
|
false,
|
|
|
|
headTarget,
|
|
|
|
this,
|
|
|
|
&dagChecker),
|
|
|
|
info.LinkInterface.Libraries);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(this->GetType() == INTERFACE_LIBRARY)
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A provided configuration has been chosen. Load the
|
|
|
|
// configuration's properties.
|
2009-04-09 00:29:04 +04:00
|
|
|
|
|
|
|
// Get the location.
|
|
|
|
if(loc)
|
|
|
|
{
|
|
|
|
info.Location = loc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string impProp = "IMPORTED_LOCATION";
|
|
|
|
impProp += suffix;
|
|
|
|
if(const char* config_location = this->GetProperty(impProp.c_str()))
|
|
|
|
{
|
|
|
|
info.Location = config_location;
|
|
|
|
}
|
|
|
|
else if(const char* location = this->GetProperty("IMPORTED_LOCATION"))
|
|
|
|
{
|
|
|
|
info.Location = location;
|
|
|
|
}
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
|
|
|
|
// Get the soname.
|
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
|
|
|
{
|
|
|
|
std::string soProp = "IMPORTED_SONAME";
|
|
|
|
soProp += suffix;
|
|
|
|
if(const char* config_soname = this->GetProperty(soProp.c_str()))
|
|
|
|
{
|
|
|
|
info.SOName = config_soname;
|
|
|
|
}
|
|
|
|
else if(const char* soname = this->GetProperty("IMPORTED_SONAME"))
|
|
|
|
{
|
|
|
|
info.SOName = soname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-21 19:41:11 +03:00
|
|
|
// Get the "no-soname" mark.
|
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY)
|
|
|
|
{
|
|
|
|
std::string soProp = "IMPORTED_NO_SONAME";
|
|
|
|
soProp += suffix;
|
|
|
|
if(const char* config_no_soname = this->GetProperty(soProp.c_str()))
|
|
|
|
{
|
|
|
|
info.NoSOName = cmSystemTools::IsOn(config_no_soname);
|
|
|
|
}
|
|
|
|
else if(const char* no_soname = this->GetProperty("IMPORTED_NO_SONAME"))
|
|
|
|
{
|
|
|
|
info.NoSOName = cmSystemTools::IsOn(no_soname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-28 16:38:36 +03:00
|
|
|
// Get the import library.
|
2009-04-09 00:29:04 +04:00
|
|
|
if(imp)
|
|
|
|
{
|
|
|
|
info.ImportLibrary = imp;
|
|
|
|
}
|
|
|
|
else if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->IsExecutableWithExports())
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
|
|
|
std::string impProp = "IMPORTED_IMPLIB";
|
|
|
|
impProp += suffix;
|
|
|
|
if(const char* config_implib = this->GetProperty(impProp.c_str()))
|
|
|
|
{
|
|
|
|
info.ImportLibrary = config_implib;
|
|
|
|
}
|
|
|
|
else if(const char* implib = this->GetProperty("IMPORTED_IMPLIB"))
|
|
|
|
{
|
|
|
|
info.ImportLibrary = implib;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-01-31 23:45:31 +03:00
|
|
|
// Get the link dependencies.
|
|
|
|
{
|
|
|
|
std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
|
|
|
|
linkProp += suffix;
|
|
|
|
if(const char* config_libs = this->GetProperty(linkProp.c_str()))
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2008-01-31 23:45:31 +03:00
|
|
|
cmSystemTools::ExpandListArgument(config_libs,
|
|
|
|
info.LinkInterface.SharedDeps);
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
2008-01-31 23:45:31 +03:00
|
|
|
else if(const char* libs =
|
|
|
|
this->GetProperty("IMPORTED_LINK_DEPENDENT_LIBRARIES"))
|
2008-01-28 16:38:36 +03:00
|
|
|
{
|
2008-01-31 23:45:31 +03:00
|
|
|
cmSystemTools::ExpandListArgument(libs, info.LinkInterface.SharedDeps);
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
2008-01-31 23:45:31 +03:00
|
|
|
}
|
2009-07-11 18:12:05 +04:00
|
|
|
|
|
|
|
// Get the link languages.
|
2013-07-25 11:12:28 +04:00
|
|
|
if(this->LinkLanguagePropagatesToDependents())
|
2009-07-11 18:12:05 +04:00
|
|
|
{
|
|
|
|
std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
|
|
|
|
linkProp += suffix;
|
|
|
|
if(const char* config_libs = this->GetProperty(linkProp.c_str()))
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(config_libs,
|
|
|
|
info.LinkInterface.Languages);
|
|
|
|
}
|
|
|
|
else if(const char* libs =
|
|
|
|
this->GetProperty("IMPORTED_LINK_INTERFACE_LANGUAGES"))
|
|
|
|
{
|
|
|
|
cmSystemTools::ExpandListArgument(libs,
|
|
|
|
info.LinkInterface.Languages);
|
|
|
|
}
|
|
|
|
}
|
2009-09-01 18:37:37 +04:00
|
|
|
|
|
|
|
// Get the cyclic repetition count.
|
|
|
|
if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
|
|
|
{
|
|
|
|
std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
|
|
|
|
linkProp += suffix;
|
|
|
|
if(const char* config_reps = this->GetProperty(linkProp.c_str()))
|
|
|
|
{
|
|
|
|
sscanf(config_reps, "%u", &info.LinkInterface.Multiplicity);
|
|
|
|
}
|
|
|
|
else if(const char* reps =
|
|
|
|
this->GetProperty("IMPORTED_LINK_INTERFACE_MULTIPLICITY"))
|
|
|
|
{
|
|
|
|
sscanf(reps, "%u", &info.LinkInterface.Multiplicity);
|
|
|
|
}
|
|
|
|
}
|
2008-01-28 16:38:36 +03:00
|
|
|
}
|
2008-01-29 23:07:33 +03:00
|
|
|
|
2008-01-31 01:25:52 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget::LinkInterface const* cmTarget::GetLinkInterface(const char* config,
|
|
|
|
cmTarget *head)
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
2008-01-31 23:45:31 +03:00
|
|
|
// Imported targets have their own link interface.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
2013-01-04 16:31:01 +04:00
|
|
|
if(cmTarget::ImportInfo const* info = this->GetImportInfo(config, head))
|
2008-01-31 23:45:31 +03:00
|
|
|
{
|
|
|
|
return &info->LinkInterface;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-07-07 00:25:20 +04:00
|
|
|
// Link interfaces are not supported for executables that do not
|
|
|
|
// export symbols.
|
|
|
|
if(this->GetType() == cmTarget::EXECUTABLE &&
|
|
|
|
!this->IsExecutableWithExports())
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup any existing link interface for this configuration.
|
2013-01-04 16:31:01 +04:00
|
|
|
TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
|
|
|
|
|
2009-07-07 17:45:29 +04:00
|
|
|
cmTargetInternals::LinkInterfaceMapType::iterator
|
2009-07-07 19:30:36 +04:00
|
|
|
i = this->Internal->LinkInterfaceMap.find(key);
|
2009-07-07 17:45:29 +04:00
|
|
|
if(i == this->Internal->LinkInterfaceMap.end())
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
|
|
|
// Compute the link interface for this configuration.
|
2009-07-07 17:45:29 +04:00
|
|
|
cmTargetInternals::OptionalLinkInterface iface;
|
2013-01-04 16:31:01 +04:00
|
|
|
iface.Exists = this->ComputeLinkInterface(config, iface, head);
|
2008-01-31 01:25:52 +03:00
|
|
|
|
|
|
|
// Store the information for this configuration.
|
2009-07-07 19:30:36 +04:00
|
|
|
cmTargetInternals::LinkInterfaceMapType::value_type entry(key, iface);
|
2009-07-07 17:45:29 +04:00
|
|
|
i = this->Internal->LinkInterfaceMap.insert(entry).first;
|
2008-01-31 01:25:52 +03:00
|
|
|
}
|
|
|
|
|
2009-07-07 17:45:29 +04:00
|
|
|
return i->second.Exists? &i->second : 0;
|
2008-01-31 01:25:52 +03:00
|
|
|
}
|
|
|
|
|
2013-06-04 18:17:18 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::GetTransitivePropertyLinkLibraries(
|
|
|
|
const char* config,
|
|
|
|
cmTarget *headTarget,
|
|
|
|
std::vector<std::string> &libs)
|
|
|
|
{
|
|
|
|
cmTarget::LinkInterface const* iface = this->GetLinkInterface(config,
|
|
|
|
headTarget);
|
|
|
|
if (!iface)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2013-06-04 18:25:47 +04:00
|
|
|
if(this->GetType() != STATIC_LIBRARY
|
|
|
|
|| this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|
|
|
|
|| this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
|
|
|
|
{
|
|
|
|
libs = iface->Libraries;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
|
const char* interfaceLibs = this->GetProperty(linkIfaceProp);
|
2013-06-04 18:17:18 +04:00
|
|
|
|
2013-06-04 18:25:47 +04:00
|
|
|
if (!interfaceLibs)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The interface libraries have been explicitly set.
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
|
|
|
|
linkIfaceProp, 0, 0);
|
|
|
|
dagChecker.SetTransitivePropertiesOnly();
|
|
|
|
cmSystemTools::ExpandListArgument(ge.Parse(interfaceLibs)->Evaluate(
|
|
|
|
this->Makefile,
|
|
|
|
config,
|
|
|
|
false,
|
|
|
|
headTarget,
|
|
|
|
this, &dagChecker), libs);
|
2013-06-04 18:17:18 +04:00
|
|
|
}
|
|
|
|
|
2008-01-31 01:25:52 +03:00
|
|
|
//----------------------------------------------------------------------------
|
2013-01-04 16:31:01 +04:00
|
|
|
bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
|
|
|
|
cmTarget *headTarget)
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
|
|
|
// Construct the property name suffix for this configuration.
|
|
|
|
std::string suffix = "_";
|
|
|
|
if(config && *config)
|
|
|
|
{
|
|
|
|
suffix += cmSystemTools::UpperCase(config);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
suffix += "NOCONFIG";
|
|
|
|
}
|
|
|
|
|
2009-07-07 00:25:20 +04:00
|
|
|
// An explicit list of interface libraries may be set for shared
|
|
|
|
// libraries and executables that export symbols.
|
|
|
|
const char* explicitLibraries = 0;
|
2013-06-04 18:25:47 +04:00
|
|
|
const char* newExplicitLibraries =
|
|
|
|
this->GetProperty("INTERFACE_LINK_LIBRARIES");
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
std::string linkIfaceProp;
|
2009-07-07 00:25:20 +04:00
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
|
|
|
|
this->IsExecutableWithExports())
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
2009-07-07 00:25:20 +04:00
|
|
|
// Lookup the per-configuration property.
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
|
|
|
|
linkIfaceProp += suffix;
|
|
|
|
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
|
2009-07-07 00:25:20 +04:00
|
|
|
|
|
|
|
// If not set, try the generic property.
|
|
|
|
if(!explicitLibraries)
|
|
|
|
{
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
|
|
|
|
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
|
2009-07-07 00:25:20 +04:00
|
|
|
}
|
2013-06-04 18:25:47 +04:00
|
|
|
if (newExplicitLibraries
|
|
|
|
&& (!explicitLibraries ||
|
|
|
|
(explicitLibraries
|
|
|
|
&& strcmp(newExplicitLibraries, explicitLibraries) != 0)))
|
|
|
|
{
|
|
|
|
switch(this->GetPolicyStatusCMP0022())
|
|
|
|
{
|
|
|
|
case cmPolicies::WARN:
|
|
|
|
{
|
|
|
|
cmOStringStream w;
|
|
|
|
w << (this->Makefile->GetPolicies()
|
|
|
|
->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
|
|
|
|
<< "Target \"" << this->GetName() << "\" has a "
|
|
|
|
"INTERFACE_LINK_LIBRARIES property which differs from its "
|
2013-09-12 00:28:32 +04:00
|
|
|
<< linkIfaceProp << " properties."
|
|
|
|
"\n"
|
|
|
|
"INTERFACE_LINK_LIBRARIES:\n "
|
|
|
|
<< newExplicitLibraries
|
|
|
|
<< "\n"
|
|
|
|
<< linkIfaceProp << ":\n "
|
2013-09-12 19:12:42 +04:00
|
|
|
<< (explicitLibraries ? explicitLibraries : "(empty)") << "\n";
|
2013-06-04 18:25:47 +04:00
|
|
|
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
|
|
|
|
}
|
|
|
|
// Fall through
|
|
|
|
case cmPolicies::OLD:
|
|
|
|
break;
|
|
|
|
case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
case cmPolicies::NEW:
|
|
|
|
explicitLibraries = newExplicitLibraries;
|
|
|
|
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
|
|
|
{
|
|
|
|
if (newExplicitLibraries)
|
|
|
|
{
|
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
|
|
|
|
"INTERFACE_LINK_LIBRARIES", 0, 0);
|
|
|
|
std::vector<std::string> ifaceLibs;
|
|
|
|
cmSystemTools::ExpandListArgument(
|
|
|
|
ge.Parse(newExplicitLibraries)->Evaluate(
|
|
|
|
this->Makefile,
|
|
|
|
config,
|
|
|
|
false,
|
|
|
|
headTarget,
|
|
|
|
this, &dagChecker), ifaceLibs);
|
|
|
|
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
|
|
|
headTarget);
|
|
|
|
if (ifaceLibs != impl->Libraries)
|
|
|
|
{
|
|
|
|
switch(this->GetPolicyStatusCMP0022())
|
|
|
|
{
|
|
|
|
case cmPolicies::WARN:
|
|
|
|
{
|
|
|
|
cmOStringStream w;
|
|
|
|
w << (this->Makefile->GetPolicies()
|
|
|
|
->GetPolicyWarning(cmPolicies::CMP0022)) << "\n"
|
|
|
|
<< "Static library target \"" << this->GetName() << "\" has a "
|
|
|
|
"INTERFACE_LINK_LIBRARIES property. This should be preferred "
|
|
|
|
"as the source of the link interface for this library. "
|
|
|
|
"Ignoring the property and using the link implementation "
|
|
|
|
"as the link interface instead.";
|
|
|
|
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
|
|
|
|
}
|
|
|
|
// Fall through
|
|
|
|
case cmPolicies::OLD:
|
|
|
|
break;
|
|
|
|
case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
case cmPolicies::NEW:
|
|
|
|
explicitLibraries = newExplicitLibraries;
|
|
|
|
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2013-07-26 16:03:44 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
iface.Libraries = impl->Libraries;
|
2013-07-25 11:12:28 +04:00
|
|
|
if(this->LinkLanguagePropagatesToDependents())
|
2013-07-26 16:03:44 +04:00
|
|
|
{
|
|
|
|
// Targets using this archive need its language runtime libraries.
|
|
|
|
iface.Languages = impl->Languages;
|
|
|
|
}
|
|
|
|
}
|
2013-06-04 18:25:47 +04:00
|
|
|
}
|
2008-01-31 01:25:52 +03:00
|
|
|
}
|
2012-11-02 18:47:40 +04:00
|
|
|
else if (this->GetType() == cmTarget::INTERFACE_LIBRARY)
|
|
|
|
{
|
|
|
|
explicitLibraries = newExplicitLibraries;
|
|
|
|
linkIfaceProp = "INTERFACE_LINK_LIBRARIES";
|
|
|
|
}
|
2008-01-31 01:25:52 +03:00
|
|
|
|
2011-03-09 17:52:46 +03:00
|
|
|
// There is no implicit link interface for executables or modules
|
|
|
|
// so if none was explicitly set then there is no link interface.
|
|
|
|
// Note that CMake versions 2.2 and below allowed linking to modules.
|
|
|
|
bool canLinkModules = this->Makefile->NeedBackwardsCompatibility(2,2);
|
|
|
|
if(!explicitLibraries &&
|
|
|
|
(this->GetType() == cmTarget::EXECUTABLE ||
|
2011-03-14 22:34:26 +03:00
|
|
|
(this->GetType() == cmTarget::MODULE_LIBRARY && !canLinkModules)))
|
2008-01-31 01:25:52 +03:00
|
|
|
{
|
2009-07-07 17:45:29 +04:00
|
|
|
return false;
|
2008-01-31 23:45:31 +03:00
|
|
|
}
|
|
|
|
|
2009-07-07 00:25:20 +04:00
|
|
|
if(explicitLibraries)
|
2008-01-31 23:45:31 +03:00
|
|
|
{
|
2009-07-07 00:25:20 +04:00
|
|
|
// The interface libraries have been explicitly set.
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
cmListFileBacktrace lfbt;
|
|
|
|
cmGeneratorExpression ge(lfbt);
|
|
|
|
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
|
|
|
|
linkIfaceProp, 0, 0);
|
|
|
|
cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
|
|
|
|
this->Makefile,
|
|
|
|
config,
|
|
|
|
false,
|
|
|
|
headTarget,
|
|
|
|
this, &dagChecker), iface.Libraries);
|
2008-01-31 23:45:31 +03:00
|
|
|
|
2013-07-26 16:03:44 +04:00
|
|
|
if(this->GetType() == cmTarget::SHARED_LIBRARY
|
2012-11-02 18:47:40 +04:00
|
|
|
|| this->GetType() == cmTarget::STATIC_LIBRARY
|
|
|
|
|| this->GetType() == cmTarget::INTERFACE_LIBRARY)
|
2008-01-31 23:45:31 +03:00
|
|
|
{
|
2009-07-08 20:04:48 +04:00
|
|
|
// Shared libraries may have runtime implementation dependencies
|
|
|
|
// on other shared libraries that are not in the interface.
|
|
|
|
std::set<cmStdString> emitted;
|
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
li = iface.Libraries.begin(); li != iface.Libraries.end(); ++li)
|
2008-01-31 23:45:31 +03:00
|
|
|
{
|
2009-07-08 20:04:48 +04:00
|
|
|
emitted.insert(*li);
|
2008-01-31 23:45:31 +03:00
|
|
|
}
|
2013-01-04 16:31:01 +04:00
|
|
|
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
|
|
|
headTarget);
|
2009-07-08 20:04:48 +04:00
|
|
|
for(std::vector<std::string>::const_iterator
|
|
|
|
li = impl->Libraries.begin(); li != impl->Libraries.end(); ++li)
|
2008-01-31 23:45:31 +03:00
|
|
|
{
|
2009-07-08 20:04:48 +04:00
|
|
|
if(emitted.insert(*li).second)
|
2009-07-07 00:25:20 +04:00
|
|
|
{
|
2009-07-08 20:04:48 +04:00
|
|
|
if(cmTarget* tgt = this->Makefile->FindTargetToUse(li->c_str()))
|
|
|
|
{
|
|
|
|
// This is a runtime dependency on another shared library.
|
|
|
|
if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
|
|
|
|
{
|
|
|
|
iface.SharedDeps.push_back(*li);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO: Recognize shared library file names. Perhaps this
|
|
|
|
// should be moved to cmComputeLinkInformation, but that creates
|
|
|
|
// a chicken-and-egg problem since this list is needed for its
|
|
|
|
// construction.
|
|
|
|
}
|
2008-01-31 23:45:31 +03:00
|
|
|
}
|
|
|
|
}
|
2013-07-25 11:12:28 +04:00
|
|
|
if(this->LinkLanguagePropagatesToDependents())
|
2013-07-26 16:03:44 +04:00
|
|
|
{
|
|
|
|
// Targets using this archive need its language runtime libraries.
|
|
|
|
iface.Languages = impl->Languages;
|
|
|
|
}
|
2008-01-31 23:45:31 +03:00
|
|
|
}
|
2008-01-31 01:25:52 +03:00
|
|
|
}
|
2013-06-04 18:25:47 +04:00
|
|
|
else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN
|
|
|
|
|| this->GetPolicyStatusCMP0022() == cmPolicies::OLD)
|
|
|
|
// The implementation shouldn't be the interface if CMP0022 is NEW. That
|
|
|
|
// way, the LINK_LIBRARIES property can be set directly without having to
|
|
|
|
// empty the INTERFACE_LINK_LIBRARIES
|
2009-07-08 20:04:48 +04:00
|
|
|
{
|
|
|
|
// The link implementation is the default link interface.
|
2013-01-04 16:31:01 +04:00
|
|
|
LinkImplementation const* impl = this->GetLinkImplementation(config,
|
|
|
|
headTarget);
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
iface.ImplementationIsInterface = true;
|
2009-07-08 20:04:48 +04:00
|
|
|
iface.Libraries = impl->Libraries;
|
|
|
|
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
|
2013-07-25 11:12:28 +04:00
|
|
|
if(this->LinkLanguagePropagatesToDependents())
|
2009-07-10 21:53:28 +04:00
|
|
|
{
|
|
|
|
// Targets using this archive need its language runtime libraries.
|
|
|
|
iface.Languages = impl->Languages;
|
|
|
|
}
|
2009-07-08 20:04:48 +04:00
|
|
|
}
|
2008-01-31 23:45:31 +03:00
|
|
|
|
2009-09-01 18:37:37 +04:00
|
|
|
if(this->GetType() == cmTarget::STATIC_LIBRARY)
|
|
|
|
{
|
|
|
|
// How many repetitions are needed if this library has cyclic
|
|
|
|
// dependencies?
|
|
|
|
std::string propName = "LINK_INTERFACE_MULTIPLICITY";
|
|
|
|
propName += suffix;
|
|
|
|
if(const char* config_reps = this->GetProperty(propName.c_str()))
|
|
|
|
{
|
|
|
|
sscanf(config_reps, "%u", &iface.Multiplicity);
|
|
|
|
}
|
|
|
|
else if(const char* reps =
|
|
|
|
this->GetProperty("LINK_INTERFACE_MULTIPLICITY"))
|
|
|
|
{
|
|
|
|
sscanf(reps, "%u", &iface.Multiplicity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-07 17:45:29 +04:00
|
|
|
return true;
|
2008-01-31 01:25:52 +03:00
|
|
|
}
|
|
|
|
|
2009-07-08 20:04:48 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTarget::LinkImplementation const*
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget::GetLinkImplementation(const char* config, cmTarget *head)
|
2009-07-08 20:04:48 +04:00
|
|
|
{
|
|
|
|
// There is no link implementation for imported targets.
|
|
|
|
if(this->IsImported())
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Lookup any existing link implementation for this configuration.
|
2013-01-04 16:31:01 +04:00
|
|
|
TargetConfigPair key(head, cmSystemTools::UpperCase(config? config : ""));
|
|
|
|
|
2009-07-08 20:04:48 +04:00
|
|
|
cmTargetInternals::LinkImplMapType::iterator
|
|
|
|
i = this->Internal->LinkImplMap.find(key);
|
|
|
|
if(i == this->Internal->LinkImplMap.end())
|
|
|
|
{
|
|
|
|
// Compute the link implementation for this configuration.
|
|
|
|
LinkImplementation impl;
|
2013-01-04 16:31:01 +04:00
|
|
|
this->ComputeLinkImplementation(config, impl, head);
|
2009-07-08 20:04:48 +04:00
|
|
|
|
|
|
|
// Store the information for this configuration.
|
|
|
|
cmTargetInternals::LinkImplMapType::value_type entry(key, impl);
|
|
|
|
i = this->Internal->LinkImplMap.insert(entry).first;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &i->second;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::ComputeLinkImplementation(const char* config,
|
2013-01-04 16:31:01 +04:00
|
|
|
LinkImplementation& impl,
|
|
|
|
cmTarget *head)
|
2009-07-08 20:04:48 +04:00
|
|
|
{
|
|
|
|
// Compute which library configuration to link.
|
|
|
|
cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config);
|
|
|
|
|
2009-07-10 21:53:28 +04:00
|
|
|
// Collect libraries directly linked in this configuration.
|
2012-12-06 15:14:03 +04:00
|
|
|
std::vector<std::string> llibs;
|
|
|
|
this->GetDirectLinkLibraries(config, llibs, head);
|
|
|
|
for(std::vector<std::string>::const_iterator li = llibs.begin();
|
2009-07-08 20:04:48 +04:00
|
|
|
li != llibs.end(); ++li)
|
|
|
|
{
|
|
|
|
// Skip entries that resolve to the target itself or are empty.
|
2012-12-06 15:14:03 +04:00
|
|
|
std::string item = this->CheckCMP0004(*li);
|
2009-07-08 20:04:48 +04:00
|
|
|
if(item == this->GetName() || item.empty())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2012-12-06 15:14:03 +04:00
|
|
|
// The entry is meant for this configuration.
|
|
|
|
impl.Libraries.push_back(item);
|
2012-11-01 13:16:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
LinkLibraryVectorType const& oldllibs = this->GetOriginalLinkLibraries();
|
|
|
|
for(cmTarget::LinkLibraryVectorType::const_iterator li = oldllibs.begin();
|
|
|
|
li != oldllibs.end(); ++li)
|
|
|
|
{
|
|
|
|
if(li->second != cmTarget::GENERAL && li->second != linkType)
|
2009-07-08 20:04:48 +04:00
|
|
|
{
|
2012-11-01 13:16:56 +04:00
|
|
|
std::string item = this->CheckCMP0004(li->first);
|
|
|
|
if(item == this->GetName() || item.empty())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2009-07-08 20:04:48 +04:00
|
|
|
// Support OLD behavior for CMP0003.
|
|
|
|
impl.WrongConfigLibraries.push_back(item);
|
|
|
|
}
|
|
|
|
}
|
2009-07-10 21:53:28 +04:00
|
|
|
|
|
|
|
// This target needs runtime libraries for its source languages.
|
|
|
|
std::set<cmStdString> languages;
|
2012-03-12 22:40:58 +04:00
|
|
|
// Get languages used in our source files.
|
2009-07-10 21:53:28 +04:00
|
|
|
this->GetLanguages(languages);
|
2012-03-12 22:40:58 +04:00
|
|
|
// Get languages used in object library sources.
|
|
|
|
for(std::vector<std::string>::iterator i = this->ObjectLibraries.begin();
|
|
|
|
i != this->ObjectLibraries.end(); ++i)
|
|
|
|
{
|
|
|
|
if(cmTarget* objLib = this->Makefile->FindTargetToUse(i->c_str()))
|
|
|
|
{
|
|
|
|
if(objLib->GetType() == cmTarget::OBJECT_LIBRARY)
|
|
|
|
{
|
|
|
|
objLib->GetLanguages(languages);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Copy the set of langauges to the link implementation.
|
2009-07-10 21:53:28 +04:00
|
|
|
for(std::set<cmStdString>::iterator li = languages.begin();
|
|
|
|
li != languages.end(); ++li)
|
|
|
|
{
|
|
|
|
impl.Languages.push_back(*li);
|
|
|
|
}
|
2009-07-08 20:04:48 +04:00
|
|
|
}
|
|
|
|
|
2009-07-07 00:24:45 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::CheckCMP0004(std::string const& item)
|
|
|
|
{
|
|
|
|
// Strip whitespace off the library names because we used to do this
|
|
|
|
// in case variables were expanded at generate time. We no longer
|
|
|
|
// do the expansion but users link to libraries like " ${VAR} ".
|
|
|
|
std::string lib = item;
|
|
|
|
std::string::size_type pos = lib.find_first_not_of(" \t\r\n");
|
|
|
|
if(pos != lib.npos)
|
|
|
|
{
|
|
|
|
lib = lib.substr(pos, lib.npos);
|
|
|
|
}
|
|
|
|
pos = lib.find_last_not_of(" \t\r\n");
|
|
|
|
if(pos != lib.npos)
|
|
|
|
{
|
|
|
|
lib = lib.substr(0, pos+1);
|
|
|
|
}
|
|
|
|
if(lib != item)
|
|
|
|
{
|
|
|
|
cmake* cm = this->Makefile->GetCMakeInstance();
|
|
|
|
switch(this->PolicyStatusCMP0004)
|
|
|
|
{
|
|
|
|
case cmPolicies::WARN:
|
|
|
|
{
|
|
|
|
cmOStringStream w;
|
|
|
|
w << (this->Makefile->GetPolicies()
|
|
|
|
->GetPolicyWarning(cmPolicies::CMP0004)) << "\n"
|
|
|
|
<< "Target \"" << this->GetName() << "\" links to item \""
|
|
|
|
<< item << "\" which has leading or trailing whitespace.";
|
|
|
|
cm->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
|
|
|
|
this->GetBacktrace());
|
|
|
|
}
|
|
|
|
case cmPolicies::OLD:
|
|
|
|
break;
|
|
|
|
case cmPolicies::NEW:
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Target \"" << this->GetName() << "\" links to item \""
|
|
|
|
<< item << "\" which has leading or trailing whitespace. "
|
|
|
|
<< "This is now an error according to policy CMP0004.";
|
|
|
|
cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case cmPolicies::REQUIRED_IF_USED:
|
|
|
|
case cmPolicies::REQUIRED_ALWAYS:
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << (this->Makefile->GetPolicies()
|
|
|
|
->GetRequiredPolicyError(cmPolicies::CMP0004)) << "\n"
|
|
|
|
<< "Target \"" << this->GetName() << "\" links to item \""
|
|
|
|
<< item << "\" which has leading or trailing whitespace.";
|
|
|
|
cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lib;
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
template<typename PropertyType>
|
|
|
|
PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
|
|
|
|
const std::string prop,
|
|
|
|
const char *config,
|
|
|
|
PropertyType *);
|
|
|
|
|
|
|
|
template<>
|
|
|
|
bool getLinkInterfaceDependentProperty(cmTarget *tgt,
|
|
|
|
const std::string prop,
|
|
|
|
const char *config, bool *)
|
|
|
|
{
|
|
|
|
return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:20 +04:00
|
|
|
template<>
|
|
|
|
const char * getLinkInterfaceDependentProperty(cmTarget *tgt,
|
|
|
|
const std::string prop,
|
|
|
|
const char *config,
|
|
|
|
const char **)
|
|
|
|
{
|
|
|
|
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
template<typename PropertyType>
|
|
|
|
void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
|
|
|
|
const char *propName,
|
|
|
|
std::set<cmStdString> &emitted,
|
|
|
|
const char *config,
|
|
|
|
PropertyType *)
|
|
|
|
{
|
|
|
|
const char *prop = dependee->GetProperty(propName);
|
|
|
|
if (!prop)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> props;
|
|
|
|
cmSystemTools::ExpandListArgument(prop, props);
|
2013-09-17 17:42:13 +04:00
|
|
|
std::string pdir =
|
|
|
|
dependee->GetMakefile()->GetRequiredDefinition("CMAKE_ROOT");
|
|
|
|
pdir += "/Help/prop_tgt/";
|
2013-01-06 16:49:16 +04:00
|
|
|
|
|
|
|
for(std::vector<std::string>::iterator pi = props.begin();
|
|
|
|
pi != props.end(); ++pi)
|
|
|
|
{
|
2013-09-17 17:42:13 +04:00
|
|
|
std::string pname = cmSystemTools::HelpFileName(*pi);
|
|
|
|
std::string pfile = pdir + pname + ".rst";
|
|
|
|
if(cmSystemTools::FileExists(pfile.c_str(), true))
|
2013-01-06 16:49:16 +04:00
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Target \"" << dependee->GetName() << "\" has property \""
|
|
|
|
<< *pi << "\" listed in its " << propName << " property. "
|
|
|
|
"This is not allowed. Only user-defined properties may appear "
|
|
|
|
"listed in the " << propName << " property.";
|
|
|
|
depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(emitted.insert(*pi).second)
|
|
|
|
{
|
|
|
|
getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
|
|
|
|
0);
|
|
|
|
if (cmSystemTools::GetErrorOccuredFlag())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-05 17:59:39 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
|
|
|
|
const char* config)
|
|
|
|
{
|
|
|
|
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
|
|
|
|
|
2013-02-07 03:47:31 +04:00
|
|
|
std::set<cmStdString> emittedBools;
|
|
|
|
std::set<cmStdString> emittedStrings;
|
2012-12-05 17:59:39 +04:00
|
|
|
|
|
|
|
for(cmComputeLinkInformation::ItemVector::const_iterator li =
|
|
|
|
deps.begin();
|
|
|
|
li != deps.end(); ++li)
|
|
|
|
{
|
|
|
|
if (!li->Target)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-01-06 16:49:16 +04:00
|
|
|
checkPropertyConsistency<bool>(this, li->Target,
|
|
|
|
"COMPATIBLE_INTERFACE_BOOL",
|
2013-02-07 03:47:31 +04:00
|
|
|
emittedBools, config, 0);
|
2013-01-06 16:49:20 +04:00
|
|
|
if (cmSystemTools::GetErrorOccuredFlag())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
checkPropertyConsistency<const char *>(this, li->Target,
|
|
|
|
"COMPATIBLE_INTERFACE_STRING",
|
2013-02-07 03:47:31 +04:00
|
|
|
emittedStrings, config, 0);
|
2013-01-06 16:49:16 +04:00
|
|
|
if (cmSystemTools::GetErrorOccuredFlag())
|
2012-12-05 17:59:39 +04:00
|
|
|
{
|
2013-01-06 16:49:16 +04:00
|
|
|
return;
|
2012-12-05 17:59:39 +04:00
|
|
|
}
|
|
|
|
}
|
2013-02-07 03:47:31 +04:00
|
|
|
|
|
|
|
for(std::set<cmStdString>::const_iterator li = emittedBools.begin();
|
|
|
|
li != emittedBools.end(); ++li)
|
|
|
|
{
|
|
|
|
const std::set<cmStdString>::const_iterator si = emittedStrings.find(*li);
|
|
|
|
if (si != emittedStrings.end())
|
|
|
|
{
|
|
|
|
cmOStringStream e;
|
|
|
|
e << "Property \"" << *li << "\" appears in both the "
|
|
|
|
"COMPATIBLE_INTERFACE_BOOL and the COMPATIBLE_INTERFACE_STRING "
|
|
|
|
"property in the dependencies of target \"" << this->GetName() <<
|
|
|
|
"\". This is not allowed. A property may only require compatibility "
|
|
|
|
"in a boolean interpretation or a string interpretation, but not both.";
|
|
|
|
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2012-12-05 17:59:39 +04:00
|
|
|
}
|
|
|
|
|
2012-11-05 19:14:02 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmComputeLinkInformation*
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget::GetLinkInformation(const char* config, cmTarget *head)
|
2012-11-05 19:14:02 +04:00
|
|
|
{
|
2013-01-04 16:31:01 +04:00
|
|
|
cmTarget *headTarget = head ? head : this;
|
2012-11-05 19:14:02 +04:00
|
|
|
// Lookup any existing information for this configuration.
|
2013-01-04 16:31:01 +04:00
|
|
|
TargetConfigPair key(headTarget,
|
|
|
|
cmSystemTools::UpperCase(config?config:""));
|
|
|
|
cmTargetLinkInformationMap::iterator
|
|
|
|
i = this->LinkInformation.find(key);
|
2012-11-05 19:14:02 +04:00
|
|
|
if(i == this->LinkInformation.end())
|
|
|
|
{
|
|
|
|
// Compute information for this configuration.
|
|
|
|
cmComputeLinkInformation* info =
|
2013-01-04 16:31:01 +04:00
|
|
|
new cmComputeLinkInformation(this, config, headTarget);
|
2012-11-05 19:14:02 +04:00
|
|
|
if(!info || !info->Compute())
|
|
|
|
{
|
|
|
|
delete info;
|
|
|
|
info = 0;
|
|
|
|
}
|
|
|
|
|
2013-01-16 20:54:30 +04:00
|
|
|
// Store the information for this configuration.
|
|
|
|
cmTargetLinkInformationMap::value_type entry(key, info);
|
|
|
|
i = this->LinkInformation.insert(entry).first;
|
|
|
|
|
2012-12-05 17:59:39 +04:00
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
this->CheckPropertyCompatibility(info, config);
|
|
|
|
}
|
2012-11-05 19:14:02 +04:00
|
|
|
}
|
|
|
|
return i->second;
|
|
|
|
}
|
|
|
|
|
2012-07-16 21:44:19 +04:00
|
|
|
//----------------------------------------------------------------------------
|
2013-05-06 06:19:05 +04:00
|
|
|
std::string cmTarget::GetFrameworkDirectory(const char* config,
|
|
|
|
bool rootDir)
|
2012-07-16 21:44:19 +04:00
|
|
|
{
|
|
|
|
std::string fpath;
|
2013-05-06 06:19:05 +04:00
|
|
|
fpath += this->GetOutputName(config, false);
|
|
|
|
fpath += ".framework";
|
|
|
|
if(!rootDir)
|
|
|
|
{
|
|
|
|
fpath += "/Versions/";
|
|
|
|
fpath += this->GetFrameworkVersion();
|
|
|
|
}
|
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetCFBundleDirectory(const char* config,
|
|
|
|
bool contentOnly)
|
|
|
|
{
|
|
|
|
std::string fpath;
|
|
|
|
fpath += this->GetOutputName(config, false);
|
|
|
|
fpath += ".";
|
|
|
|
const char *ext = this->GetProperty("BUNDLE_EXTENSION");
|
|
|
|
if (!ext)
|
|
|
|
{
|
|
|
|
ext = "bundle";
|
|
|
|
}
|
|
|
|
fpath += ext;
|
|
|
|
fpath += "/Contents";
|
|
|
|
if(!contentOnly)
|
|
|
|
fpath += "/MacOS";
|
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetAppBundleDirectory(const char* config,
|
|
|
|
bool contentOnly)
|
|
|
|
{
|
|
|
|
std::string fpath = this->GetFullName(config, false);
|
|
|
|
fpath += ".app/Contents";
|
|
|
|
if(!contentOnly)
|
|
|
|
fpath += "/MacOS";
|
2012-07-16 21:44:19 +04:00
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
2012-07-16 21:42:56 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::BuildMacContentDirectory(const std::string& base,
|
|
|
|
const char* config,
|
2013-05-06 06:19:05 +04:00
|
|
|
bool contentOnly)
|
2012-07-16 21:42:56 +04:00
|
|
|
{
|
|
|
|
std::string fpath = base;
|
|
|
|
if(this->IsAppBundleOnApple())
|
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
fpath += this->GetAppBundleDirectory(config, contentOnly);
|
2012-07-16 21:42:56 +04:00
|
|
|
}
|
|
|
|
if(this->IsFrameworkOnApple())
|
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
fpath += this->GetFrameworkDirectory(config, contentOnly);
|
2012-07-16 21:42:56 +04:00
|
|
|
}
|
|
|
|
if(this->IsCFBundleOnApple())
|
|
|
|
{
|
2013-05-06 06:19:05 +04:00
|
|
|
fpath += this->GetCFBundleDirectory(config, contentOnly);
|
2012-07-16 21:42:56 +04:00
|
|
|
}
|
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
std::string cmTarget::GetMacContentDirectory(const char* config,
|
2013-05-06 06:19:05 +04:00
|
|
|
bool implib)
|
2012-07-16 21:42:56 +04:00
|
|
|
{
|
|
|
|
// Start with the output directory for the target.
|
|
|
|
std::string fpath = this->GetDirectory(config, implib);
|
|
|
|
fpath += "/";
|
2013-05-06 06:19:05 +04:00
|
|
|
bool contentOnly = true;
|
|
|
|
if(this->IsFrameworkOnApple())
|
|
|
|
{
|
|
|
|
// additional files with a framework go into the version specific
|
|
|
|
// directory
|
|
|
|
contentOnly = false;
|
|
|
|
}
|
|
|
|
fpath = this->BuildMacContentDirectory(fpath, config, contentOnly);
|
2012-07-16 21:42:56 +04:00
|
|
|
return fpath;
|
|
|
|
}
|
|
|
|
|
2012-11-05 19:14:02 +04:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetLinkInformationMap
|
|
|
|
::cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r): derived()
|
|
|
|
{
|
|
|
|
// Ideally cmTarget instances should never be copied. However until
|
|
|
|
// we can make a sweep to remove that, this copy constructor avoids
|
|
|
|
// allowing the resources (LinkInformation) from getting copied. In
|
|
|
|
// the worst case this will lead to extra cmComputeLinkInformation
|
|
|
|
// instances. We also enforce in debug mode that the map be emptied
|
|
|
|
// when copied.
|
|
|
|
static_cast<void>(r);
|
|
|
|
assert(r.empty());
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetLinkInformationMap::~cmTargetLinkInformationMap()
|
|
|
|
{
|
|
|
|
for(derived::iterator i = this->begin(); i != this->end(); ++i)
|
|
|
|
{
|
|
|
|
delete i->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-19 00:38:34 +03:00
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetInternalPointer::cmTargetInternalPointer()
|
|
|
|
{
|
|
|
|
this->Pointer = new cmTargetInternals;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetInternalPointer
|
2009-10-06 00:14:17 +04:00
|
|
|
::cmTargetInternalPointer(cmTargetInternalPointer const& r)
|
2008-02-19 00:38:34 +03:00
|
|
|
{
|
|
|
|
// Ideally cmTarget instances should never be copied. However until
|
|
|
|
// we can make a sweep to remove that, this copy constructor avoids
|
|
|
|
// allowing the resources (Internals) to be copied.
|
2009-10-06 00:14:17 +04:00
|
|
|
this->Pointer = new cmTargetInternals(*r.Pointer);
|
2008-02-19 00:38:34 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetInternalPointer::~cmTargetInternalPointer()
|
|
|
|
{
|
2012-11-20 01:47:30 +04:00
|
|
|
deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
|
2013-05-16 17:15:28 +04:00
|
|
|
deleteAndClear(this->Pointer->CompileOptionsEntries);
|
2013-06-12 12:12:51 +04:00
|
|
|
deleteAndClear(this->Pointer->CompileDefinitionsEntries);
|
2008-02-19 00:38:34 +03:00
|
|
|
delete this->Pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
cmTargetInternalPointer&
|
2008-02-19 17:09:46 +03:00
|
|
|
cmTargetInternalPointer::operator=(cmTargetInternalPointer const& r)
|
2008-02-19 00:38:34 +03:00
|
|
|
{
|
2008-02-19 17:09:46 +03:00
|
|
|
if(this == &r) { return *this; } // avoid warning on HP about self check
|
2008-02-19 00:38:34 +03:00
|
|
|
// Ideally cmTarget instances should never be copied. However until
|
|
|
|
// we can make a sweep to remove that, this copy constructor avoids
|
|
|
|
// allowing the resources (Internals) to be copied.
|
2008-03-04 21:51:27 +03:00
|
|
|
cmTargetInternals* oldPointer = this->Pointer;
|
2009-10-06 00:14:17 +04:00
|
|
|
this->Pointer = new cmTargetInternals(*r.Pointer);
|
2008-03-04 21:51:27 +03:00
|
|
|
delete oldPointer;
|
2008-02-19 00:38:34 +03:00
|
|
|
return *this;
|
|
|
|
}
|