cmGeneratorTarget: Move output info from cmTarget.

This commit is contained in:
Stephen Kelly 2015-08-05 18:55:14 +02:00
parent 1abc20d81d
commit 0bae4a416f
4 changed files with 175 additions and 176 deletions

View File

@ -4464,8 +4464,7 @@ std::string cmGeneratorTarget::GetDirectory(const std::string& config,
cmSystemTools::GetFilenamePath(
this->Target->ImportedGetFullPath(config, implib));
}
else if(cmTarget::OutputInfo const* info =
this->Target->GetOutputInfo(config))
else if(OutputInfo const* info = this->GetOutputInfo(config))
{
// Return the directory in which the target will be built.
return implib? info->ImpDir : info->OutDir;
@ -4478,7 +4477,161 @@ bool cmGeneratorTarget::UsesDefaultOutputDir(const std::string& config,
bool implib) const
{
std::string dir;
return this->Target->ComputeOutputDir(config, implib, dir);
return this->ComputeOutputDir(config, implib, dir);
}
//----------------------------------------------------------------------------
cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
const std::string& config) const
{
// There is no output information for imported targets.
if(this->IsImported())
{
return 0;
}
// Only libraries and executables have well-defined output files.
if(!this->Target->HaveWellDefinedOutputFiles())
{
std::string msg = "cmGeneratorTarget::GetOutputInfo called for ";
msg += this->GetName();
msg += " which has type ";
msg += cmTarget::GetTargetTypeName(cmTarget::TargetType(this->GetType()));
this->LocalGenerator->IssueMessage(cmake::INTERNAL_ERROR, msg);
return 0;
}
// Lookup/compute/cache the output information for this configuration.
std::string config_upper;
if(!config.empty())
{
config_upper = cmSystemTools::UpperCase(config);
}
OutputInfoMapType::iterator i =
this->OutputInfoMap.find(config_upper);
if(i == this->OutputInfoMap.end())
{
// Add empty info in map to detect potential recursion.
OutputInfo info;
OutputInfoMapType::value_type entry(config_upper, info);
i = this->OutputInfoMap.insert(entry).first;
// Compute output directories.
this->ComputeOutputDir(config, false, info.OutDir);
this->ComputeOutputDir(config, true, info.ImpDir);
if(!this->Target->ComputePDBOutputDir("PDB", config, info.PdbDir))
{
info.PdbDir = info.OutDir;
}
// Now update the previously-prepared map entry.
i->second = info;
}
else if(i->second.empty())
{
// An empty map entry indicates we have been called recursively
// from the above block.
this->LocalGenerator->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
"Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
this->Target->GetBacktrace());
return 0;
}
return &i->second;
}
//----------------------------------------------------------------------------
bool cmGeneratorTarget::ComputeOutputDir(const std::string& config,
bool implib, std::string& out) const
{
bool usesDefaultOutputDir = false;
std::string conf = config;
// Look for a target property defining the target output directory
// based on the target type.
std::string targetTypeName = this->Target->GetOutputTargetType(implib);
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(conf);
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.
cmGeneratorExpression ge;
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(config_outdir);
out = cge->Evaluate(this->Makefile, config);
// Skip per-configuration subdirectory.
conf = "";
}
else if(const char* outdir = this->Target->GetProperty(propertyName))
{
// Use the user-specified output directory.
cmGeneratorExpression ge;
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(outdir);
out = cge->Evaluate(this->Makefile, config);
// Skip per-configuration subdirectory if the value contained a
// generator expression.
if (out != outdir)
{
conf = "";
}
}
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.
usesDefaultOutputDir = true;
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, this->Makefile->GetCurrentBinaryDirectory()));
// The generator may add the configuration's subdirectory.
if(!conf.empty())
{
bool iosPlatform = this->Makefile->PlatformIsAppleIos();
std::string suffix =
usesDefaultOutputDir && iosPlatform ? "${EFFECTIVE_PLATFORM_NAME}" : "";
this->LocalGenerator->GetGlobalGenerator()->
AppendDirectoryForConfig("/", conf, suffix, out);
}
return usesDefaultOutputDir;
}
//----------------------------------------------------------------------------
@ -5008,7 +5161,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
std::string
cmGeneratorTarget::GetPDBDirectory(const std::string& config) const
{
if(cmTarget::OutputInfo const* info = this->Target->GetOutputInfo(config))
if(OutputInfo const* info = this->GetOutputInfo(config))
{
// Return the directory in which the target will be built.
return info->PdbDir;

View File

@ -289,6 +289,18 @@ public:
directory. */
bool UsesDefaultOutputDir(const std::string& config, bool implib) const;
// Cache target output paths for each configuration.
struct OutputInfo
{
std::string OutDir;
std::string ImpDir;
std::string PdbDir;
bool empty() const
{ return OutDir.empty() && ImpDir.empty() && PdbDir.empty(); }
};
OutputInfo const* GetOutputInfo(const std::string& config) const;
/** Get the name of the pdb file for the target. */
std::string GetPDBName(const std::string& config="") const;
@ -495,6 +507,12 @@ private:
cmLinkImplementationLibraries const*
GetLinkImplementationLibrariesInternal(const std::string& config,
cmTarget const* head) const;
bool
ComputeOutputDir(const std::string& config,
bool implib, std::string& out) const;
typedef std::map<std::string, OutputInfo> OutputInfoMapType;
mutable OutputInfoMapType OutputInfoMap;
typedef std::pair<std::string, bool> OutputNameKey;
typedef std::map<OutputNameKey, std::string> OutputNameMapType;

View File

@ -79,9 +79,6 @@ public:
// The backtrace when the target was created.
cmListFileBacktrace Backtrace;
typedef std::map<std::string, cmTarget::OutputInfo> OutputInfoMapType;
OutputInfoMapType OutputInfoMap;
typedef std::map<std::string, cmTarget::ImportInfo> ImportInfoMapType;
ImportInfoMapType ImportInfoMap;
@ -1709,67 +1706,6 @@ bool cmTarget::HaveWellDefinedOutputFiles() const
this->GetType() == cmTarget::EXECUTABLE;
}
//----------------------------------------------------------------------------
cmTarget::OutputInfo const* cmTarget::GetOutputInfo(
const std::string& config) const
{
// There is no output information for imported targets.
if(this->IsImported())
{
return 0;
}
// Only libraries and executables have well-defined output files.
if(!this->HaveWellDefinedOutputFiles())
{
std::string msg = "cmTarget::GetOutputInfo called for ";
msg += this->GetName();
msg += " which has type ";
msg += cmTarget::GetTargetTypeName(this->GetType());
this->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR, msg);
return 0;
}
// Lookup/compute/cache the output information for this configuration.
std::string config_upper;
if(!config.empty())
{
config_upper = cmSystemTools::UpperCase(config);
}
typedef cmTargetInternals::OutputInfoMapType OutputInfoMapType;
OutputInfoMapType::iterator i =
this->Internal->OutputInfoMap.find(config_upper);
if(i == this->Internal->OutputInfoMap.end())
{
// Add empty info in map to detect potential recursion.
OutputInfo info;
OutputInfoMapType::value_type entry(config_upper, info);
i = this->Internal->OutputInfoMap.insert(entry).first;
// Compute output directories.
this->ComputeOutputDir(config, false, info.OutDir);
this->ComputeOutputDir(config, true, info.ImpDir);
if(!this->ComputePDBOutputDir("PDB", config, info.PdbDir))
{
info.PdbDir = info.OutDir;
}
// Now update the previously-prepared map entry.
i->second = info;
}
else if(i->second.empty())
{
// An empty map entry indicates we have been called recursively
// from the above block.
this->Makefile->GetCMakeInstance()->IssueMessage(
cmake::FATAL_ERROR,
"Target '" + this->GetName() + "' OUTPUT_DIRECTORY depends on itself.",
this->GetBacktrace());
return 0;
}
return &i->second;
}
//----------------------------------------------------------------------------
const char* cmTarget::ImportedGetLocation(const std::string& config) const
{
@ -2511,100 +2447,6 @@ const char* cmTarget::GetOutputTargetType(bool implib) const
return "";
}
//----------------------------------------------------------------------------
bool cmTarget::ComputeOutputDir(const std::string& config,
bool implib, std::string& out) const
{
bool usesDefaultOutputDir = false;
std::string conf = config;
// Look for a target property defining the target output directory
// based on the target type.
std::string targetTypeName = this->GetOutputTargetType(implib);
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(conf);
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.
cmGeneratorExpression ge;
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(config_outdir);
out = cge->Evaluate(this->Makefile, config);
// Skip per-configuration subdirectory.
conf = "";
}
else if(const char* outdir = this->GetProperty(propertyName))
{
// Use the user-specified output directory.
cmGeneratorExpression ge;
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(outdir);
out = cge->Evaluate(this->Makefile, config);
// Skip per-configuration subdirectory if the value contained a
// generator expression.
if (out != outdir)
{
conf = "";
}
}
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.
usesDefaultOutputDir = true;
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, this->Makefile->GetCurrentBinaryDirectory()));
// The generator may add the configuration's subdirectory.
if(!conf.empty())
{
bool iosPlatform = this->Makefile->PlatformIsAppleIos();
std::string suffix =
usesDefaultOutputDir && iosPlatform ? "${EFFECTIVE_PLATFORM_NAME}" : "";
this->Makefile->GetGlobalGenerator()->
AppendDirectoryForConfig("/", conf, suffix, out);
}
return usesDefaultOutputDir;
}
//----------------------------------------------------------------------------
bool cmTarget::ComputePDBOutputDir(const std::string& kind,
const std::string& config,

View File

@ -470,20 +470,6 @@ private:
bool LinkLibrariesForVS6Analyzed;
#endif
// Cache target output paths for each configuration.
struct OutputInfo
{
std::string OutDir;
std::string ImpDir;
std::string PdbDir;
bool empty() const
{ return OutDir.empty() && ImpDir.empty() && PdbDir.empty(); }
};
OutputInfo const* GetOutputInfo(const std::string& config) const;
bool
ComputeOutputDir(const std::string& config,
bool implib, std::string& out) const;
bool ComputePDBOutputDir(const std::string& kind, const std::string& config,
std::string& out) const;