Commit 49c7b649 authored by Brad King's avatar Brad King Committed by Kitware Robot
Browse files

Merge topic 'export-sets'

80112da5 Merge topic 'AutomocUseTargetProperties' into export-sets
955b9662 exports: add a test for exporting dependent targets
6f50a04c exports: define a CMAKE_FIND_PACKAGE_NAME var set by find_package()
0cfd055a exports: move the handling of missing targets into subclasses
190f2c82 exports: fix build with MSVC6
8b5f448b exports: first try at error handling if a target is missing
87f4c019 exports: accept a missing target if it is exported exactly once
999061a4 exports: store pointers to all installations of each export set
64b3a6c9 exports: cmGlobalGenerator::ExportSets destructor will clear it
81cdab5b exports: Hold an ExportSet pointer in cm*Export*Generator
5c898fbd exports: Add cmExportSetMap class
d13ec1ac exports: Create class cmExportSet
4e2347cb exports: Rename cmGlobalGenerator::AddTargetToExport{s,}
e846e703 exports: Remove cmTargetExport constructor
81c66c8b exports: Move cmTargetExport to a dedicated header file
ae4ab625 find_package: add support for a <package>_NOT_FOUND_MESSAGE va...
parents 7dce31f3 80112da5
......@@ -120,6 +120,9 @@ macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
set(configsText "${configsText} ${filename} (version ${version})\n")
endforeach()
if (${_NAME}_NOT_FOUND_MESSAGE)
set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
......
......@@ -18,6 +18,9 @@ XXX_VERSION_YY Expect Version YY if true. Make sure at most one of thes
XXX_WRAP_YY If False, do not try to use the relevent CMake wrapping command.
XXX_YY_FOUND If False, optional YY part of XXX sytem is not available.
XXX_FOUND Set to false, or undefined, if we haven't found, or don't want to use XXX.
XXX_NOT_FOUND_MESSAGE Should be set by config-files in the case that it has set XXX_FOUND to FALSE.
The contained message will be printed by the find_package() command and by
find_package_handle_standard_args() to inform the user about the problem.
XXX_RUNTIME_LIBRARY_DIRS Optionally, the runtime library search path for use when running an executable linked to shared libraries.
The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix.
This should not be a cache entry.
......@@ -124,7 +127,7 @@ If neither the QUIET nor REQUIRED options are given then the
FindXXX.cmake module should look for the package and complain without
error if the module is not found.
A package can be provide sub-components.
A package can provide sub-components.
Those components can be listed after the COMPONENTS (or REQUIRED)
or OPTIONAL_COMPONENTS keywords. The set of all listed components will be
specified in a XXX_FIND_COMPONENTS variable.
......
......@@ -176,6 +176,10 @@ set(SRCS
cmExportFileGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
cmExportSet.h
cmExportSet.cxx
cmExportSetMap.h
cmExportSetMap.cxx
cmExtraCodeBlocksGenerator.cxx
cmExtraCodeBlocksGenerator.h
cmExtraEclipseCDT4Generator.cxx
......@@ -259,6 +263,7 @@ set(SRCS
cmSystemTools.h
cmTarget.cxx
cmTarget.h
cmTargetExport.h
cmTest.cxx
cmTest.h
cmTestGenerator.cxx
......
......@@ -72,8 +72,9 @@ cmExportBuildFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
target, properties);
target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
......@@ -82,6 +83,7 @@ cmExportBuildFileGenerator
// properties);
// Generate code in the export file.
this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, target, properties);
}
}
......@@ -131,6 +133,25 @@ cmExportBuildFileGenerator
}
}
//----------------------------------------------------------------------------
void
cmExportBuildFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>&,
cmMakefile*, cmTarget* depender, cmTarget* dependee)
{
// The target is not in the export.
if(!this->AppendMode)
{
// We are not appending, so all exported targets should be
// known here. This is probably user-error.
this->ComplainAboutMissingTarget(depender, dependee);
}
// Assume the target will be exported by another command.
// Append it with the export namespace.
link_libs += this->Namespace;
link_libs += dependee->GetName();
}
//----------------------------------------------------------------------------
void
cmExportBuildFileGenerator
......
......@@ -45,8 +45,14 @@ protected:
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
std::string const& suffix);
virtual void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee);
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee);
void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee);
/** Fill in properties indicating built file locations. */
void SetImportLocationProperty(const char* config,
......
......@@ -11,10 +11,15 @@
============================================================================*/
#include "cmExportFileGenerator.h"
#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmVersion.h"
#include <cmsys/auto_ptr.hxx>
......@@ -123,7 +128,9 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
void
cmExportFileGenerator
::SetImportDetailProperties(const char* config, std::string const& suffix,
cmTarget* target, ImportPropertyMap& properties)
cmTarget* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets
)
{
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->GetMakefile();
......@@ -159,13 +166,13 @@ cmExportFileGenerator
{
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties);
iface->Languages, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties);
iface->Libraries, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties);
iface->SharedDeps, properties, missingTargets);
if(iface->Multiplicity > 0)
{
std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
......@@ -184,7 +191,9 @@ cmExportFileGenerator
cmTarget* target,
const char* propName,
std::vector<std::string> const& libs,
ImportPropertyMap& properties)
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets
)
{
// Skip the property if there are no libraries.
if(libs.empty())
......@@ -224,17 +233,7 @@ cmExportFileGenerator
}
else
{
// The target is not in the export.
if(!this->AppendMode)
{
// We are not appending, so all exported targets should be
// known here. This is probably user-error.
this->ComplainAboutMissingTarget(target, tgt);
}
// Assume the target will be exported by another command.
// Append it with the export namespace.
link_libs += this->Namespace;
link_libs += *li;
this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
}
}
else
......@@ -250,6 +249,7 @@ cmExportFileGenerator
properties[prop] = link_libs;
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
const char* config)
......@@ -380,6 +380,30 @@ cmExportFileGenerator
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets)
{
os << "# Make sure the targets which have been exported in some other \n"
"# export set exist.\n";
for(unsigned int i=0; i<missingTargets.size(); ++i)
{
os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
<< " IF(CMAKE_FIND_PACKAGE_NAME)\n"
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
<< "\"Required imported target \\\"" << missingTargets[i]
<< "\\\" not found ! \")\n"
<< " ELSE()\n"
<< " MESSAGE(FATAL_ERROR \"Required imported target \\\""
<< missingTargets[i] << "\\\" not found ! \")\n"
<< " ENDIF()\n"
<< "ENDIF()\n";
}
os << "\n";
}
//----------------------------------------------------------------------------
void
cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
......
......@@ -60,17 +60,21 @@ protected:
ImportPropertyMap const& properties,
const std::set<std::string>& importedLocations);
void GenerateImportedFileCheckLoop(std::ostream& os);
void GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets);
// Collect properties with detailed information about targets beyond
// their location on disk.
void SetImportDetailProperties(const char* config,
std::string const& suffix, cmTarget* target,
ImportPropertyMap& properties);
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
void SetImportLinkProperty(std::string const& suffix,
cmTarget* target, const char* propName,
std::vector<std::string> const& libs,
ImportPropertyMap& properties);
ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
/** Each subclass knows how to generate its kind of export file. */
virtual bool GenerateMainFile(std::ostream& os) = 0;
......@@ -80,10 +84,13 @@ protected:
const char* config,
std::string const& suffix) = 0;
/** Each subclass knows how to complain about a target that is
missing from an export set. */
virtual void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee) = 0;
/** Each subclass knows how to deal with a target that is missing from an
* export set. */
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee) = 0;
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
......
......@@ -11,14 +11,19 @@
============================================================================*/
#include "cmExportInstallFileGenerator.h"
#include "cmExportSet.h"
#include "cmExportSetMap.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmTargetExport.h"
//----------------------------------------------------------------------------
cmExportInstallFileGenerator
::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
InstallExportGenerator(iegen)
IEGen(iegen)
{
}
......@@ -36,10 +41,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
// Create all the imported targets.
for(std::vector<cmTargetExport*>::const_iterator
tei = this->ExportSet->begin();
tei != this->ExportSet->end(); ++tei)
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
cmTargetExport* te = *tei;
cmTargetExport const* te = *tei;
if(this->ExportedTargets.insert(te->Target).second)
{
this->GenerateImportTargetCode(os, te->Target);
......@@ -47,8 +52,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
else
{
cmOStringStream e;
e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
<< "includes target \"" << te->Target->GetName()
e << "INSTALL(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) " << "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
cmSystemTools::Error(e.str().c_str());
return false;
......@@ -84,7 +90,7 @@ bool
cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
{
// Skip configurations not enabled for this export.
if(!this->InstallExportGenerator->InstallsForConfig(config))
if(!this->IEGen->InstallsForConfig(config))
{
return true;
}
......@@ -140,7 +146,7 @@ cmExportInstallFileGenerator
{
// Add code to compute the installation prefix relative to the
// import file location.
const char* installDest = this->InstallExportGenerator->GetDestination();
const char* installDest = this->IEGen->GetDestination();
if(!cmSystemTools::FileIsFullPath(installDest))
{
std::string dest = installDest;
......@@ -161,11 +167,11 @@ cmExportInstallFileGenerator
// Add each target in the set to the export.
for(std::vector<cmTargetExport*>::const_iterator
tei = this->ExportSet->begin();
tei != this->ExportSet->end(); ++tei)
tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
// Collect import properties for this target.
cmTargetExport* te = *tei;
cmTargetExport const* te = *tei;
ImportPropertyMap properties;
std::set<std::string> importedLocations;
this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
......@@ -185,8 +191,9 @@ cmExportInstallFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
te->Target, properties);
te->Target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
......@@ -195,6 +202,7 @@ cmExportInstallFileGenerator
// properties);
// Generate code in the export file.
this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, te->Target, properties);
this->GenerateImportedFileChecksCode(os, te->Target, properties,
importedLocations);
......@@ -304,14 +312,82 @@ cmExportInstallFileGenerator
}
}
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator::HandleMissingTarget(
std::string& link_libs, std::vector<std::string>& missingTargets,
cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
{
std::string name = dependee->GetName();
std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
int targetOccurrences = (int)namespaces.size();
if (targetOccurrences == 1)
{
std::string missingTarget = namespaces[0];
missingTarget += name;
link_libs += missingTarget;
missingTargets.push_back(missingTarget);
}
else
{
// We are not appending, so all exported targets should be
// known here. This is probably user-error.
this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
}
}
//----------------------------------------------------------------------------
std::vector<std::string>
cmExportInstallFileGenerator
::FindNamespaces(cmMakefile* mf, const std::string& name)
{
std::vector<std::string> namespaces;
cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
const cmExportSetMap& exportSets = gg->GetExportSets();
for(cmExportSetMap::const_iterator expIt = exportSets.begin();
expIt != exportSets.end();
++expIt)
{
const cmExportSet* exportSet = expIt->second;
std::vector<cmTargetExport*> const* targets =
exportSet->GetTargetExports();
bool containsTarget = false;
for(unsigned int i=0; i<targets->size(); i++)
{
if (name == (*targets)[i]->Target->GetName())
{
containsTarget = true;
break;
}
}
if (containsTarget)
{
std::vector<cmInstallExportGenerator const*> const* installs =
exportSet->GetInstallations();
for(unsigned int i=0; i<installs->size(); i++)
{
namespaces.push_back((*installs)[i]->GetNamespace());
}
}
}
return namespaces;
}
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator
::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
{
const char* installDest = this->InstallExportGenerator->GetDestination();
const char* installDest = this->IEGen->GetDestination();
cmOStringStream e;
e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
e << "INSTALL(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\") given absolute "
<< "DESTINATION \"" << installDest << "\" but the export "
<< "references an installation of target \""
<< itgen->GetTarget()->GetName() << "\" which has relative "
......@@ -322,12 +398,24 @@ cmExportInstallFileGenerator
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator
::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
::ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee,
int occurrences)
{
cmOStringStream e;
e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
e << "INSTALL(EXPORT \""
<< this->IEGen->GetExportSet()->GetName()
<< "\" ...) "
<< "includes target \"" << depender->GetName()
<< "\" which requires target \"" << dependee->GetName()
<< "\" that is not in the export set.";
<< "\" which requires target \"" << dependee->GetName() << "\" ";
if (occurrences == 0)
{
e << "that is not in the export set.";
}
else
{
e << "that is not in this export set, but " << occurrences
<< " times in others.";
}
cmSystemTools::Error(e.str().c_str());
}
......@@ -18,6 +18,7 @@ class cmInstallExportGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
class cmTargetExport;
class cmExportSet;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
......@@ -40,15 +41,6 @@ public:
files. */
cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
/** Set the name of the export associated with the files. This is
the name given to the install(EXPORT) command mode. */
void SetName(const char* name) { this->Name = name; }
/** Set the set of targets to be exported. These are the targets
associated with the export name. */
void SetExportSet(std::vector<cmTargetExport*> const* eSet)
{ this->ExportSet = eSet; }
/** Get the per-config file generated for each configuraiton. This
maps from the configuration name to the file temporary location
for installation. */
......@@ -65,8 +57,19 @@ protected:
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
std::string const& suffix);
virtual void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee);
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
cmTarget* depender,
cmTarget* dependee);
void ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee,
int occurrences);
std::vector<std::string> FindNamespaces(cmMakefile* mf,
const std::string& name);
/** Generate a per-configuration file for the targets. */
bool GenerateImportFileConfig(const char* config);
......@@ -81,9 +84,7 @@ protected:
void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
cmInstallExportGenerator* InstallExportGenerator;
std::string Name;
std::vector<cmTargetExport*> const* ExportSet;
cmInstallExportGenerator* IEGen;
std::string ImportPrefix;
......@@ -91,34 +92,4 @@ protected:
std::map<cmStdString, cmStdString> ConfigImportFiles;
};
/*
cmTargetExport is used in cmGlobalGenerator to collect the install
generators for targets associated with an export.
*/
class cmTargetExport
{
public:
cmTargetExport(cmTarget* tgt,
cmInstallTargetGenerator* archive,
cmInstallTargetGenerator* runtime,
cmInstallTargetGenerator* library,
cmInstallTargetGenerator* framework,
cmInstallTargetGenerator* bundle,
cmInstallFilesGenerator* headers
) : Target(tgt), ArchiveGenerator(archive),
RuntimeGenerator(runtime), LibraryGenerator(library),
FrameworkGenerator(framework), BundleGenerator(bundle),
HeaderGenerator(headers) {}
cmTarget* Target;
cmInstallTargetGenerator* ArchiveGenerator;
cmInstallTargetGenerator* RuntimeGenerator;
cmInstallTargetGenerator* LibraryGenerator;
cmInstallTargetGenerator* FrameworkGenerator;
cmInstallTargetGenerator* BundleGenerator;
cmInstallFilesGenerator* HeaderGenerator;
private:
cmTargetExport();
};
#endif
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
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.
============================================================================*/
#include "cmExportSet.h"
#include "cmTargetExport.h"
cmExportSet::~cmExportSet()
{
for(unsigned int i = 0; i < this->TargetExports.size(); ++ i)
{
delete this->TargetExports[i];
}
}
void cmExportSet::AddTargetExport(cmTargetExport* te)
{
this->TargetExports.push_back(te);
}
void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
{
this->Installations.push_back(installation);
}
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the