Merge branch 'improve-variable-help-formatting' into revert-cmake-W-options

Resolve conflicts in

 Help/variable/CMAKE_ERROR_DEPRECATED.rst
 Help/variable/CMAKE_WARN_DEPRECATED.rst

by integrating changes from both sides.
This commit is contained in:
Brad King
2015-09-22 13:57:08 -04:00
604 changed files with 21628 additions and 15518 deletions
+1
View File
@@ -288,6 +288,7 @@ set(SRCS
cmInstallDirectoryGenerator.h
cmInstallDirectoryGenerator.cxx
cmLinkedTree.h
cmLinkItem.h
cmListFileCache.cxx
cmListFileCache.h
cmListFileLexer.c
+1 -1
View File
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 3)
set(CMake_VERSION_PATCH 20150728)
set(CMake_VERSION_PATCH 20150819)
#set(CMake_VERSION_RC 1)
+27 -6
View File
@@ -1474,7 +1474,12 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
<< std::endl, this->Quiet);
std::vector<std::string> files;
this->FindLCovFiles(files);
if (!this->FindLCovFiles(files))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error while finding LCov files.\n");
return 0;
}
std::vector<std::string>::iterator it;
if (files.empty())
@@ -1745,18 +1750,28 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
}
//----------------------------------------------------------------------------
void cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
{
cmsys::Glob gl;
gl.RecurseOff(); // No need of recurse if -prof_dir${BUILD_DIR} flag is
// used while compiling.
gl.RecurseThroughSymlinksOff();
std::string prevBinaryDir;
cmSystemTools::ChangeDirectory(
this->CTest->GetCTestConfiguration("BuildDirectory"));
std::string buildDir = this->CTest->GetCTestConfiguration("BuildDirectory");
if (cmSystemTools::ChangeDirectory(buildDir))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error changing directory to " << buildDir << std::endl);
return false;
}
// Run profmerge to merge all *.dyn files into dpi files
cmSystemTools::RunSingleCommand("profmerge");
if (!cmSystemTools::RunSingleCommand("profmerge"))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error while running profmerge.\n");
return false;
}
prevBinaryDir = cmSystemTools::GetCurrentWorkingDirectory().c_str();
@@ -1766,10 +1781,16 @@ void cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
daGlob += "/*.dpi";
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" looking for dpi files in: " << daGlob << std::endl, this->Quiet);
gl.FindFiles(daGlob);
if (!gl.FindFiles(daGlob))
{
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Error while finding files matching " << daGlob << std::endl);
return false;
}
files.insert(files.end(), gl.GetFiles().begin(), gl.GetFiles().end());
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Now searching in: " << daGlob << std::endl, this->Quiet);
return true;
}
//----------------------------------------------------------------------
+1 -1
View File
@@ -75,7 +75,7 @@ private:
//! Handle coverage using Intel's LCov
int HandleLCovCoverage(cmCTestCoverageHandlerContainer* cont);
void FindLCovFiles(std::vector<std::string>& files);
bool FindLCovFiles(std::vector<std::string>& files);
//! Handle coverage using xdebug php coverage
int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
+2
View File
@@ -28,5 +28,7 @@
<string>public.app-category.developer-tools</string>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<key>NSHighResolutionCapable</key>
<true/>
</dict>
</plist>
+2 -3
View File
@@ -1546,9 +1546,8 @@ void cmCTest::StartXML(cmXMLWriter& xml, bool append)
xml.Attribute("Append", "true");
}
xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler"));
#ifdef _COMPILER_VERSION
xml.Attribute("CompilerVersion", _COMPILER_VERSION);
#endif
xml.Attribute("CompilerVersion",
this->GetCTestConfiguration("CompilerVersion"));
xml.Attribute("OSName", info.GetOSName());
xml.Attribute("Hostname", info.GetHostname());
xml.Attribute("OSRelease", info.GetOSRelease());
+87 -43
View File
@@ -20,8 +20,12 @@
#include "cmSystemTools.h"
#include "cmTarget.h"
cmCommonTargetGenerator::cmCommonTargetGenerator(cmGeneratorTarget* gt)
: GeneratorTarget(gt)
cmCommonTargetGenerator::cmCommonTargetGenerator(
cmOutputConverter::RelativeRoot wd,
cmGeneratorTarget* gt
)
: WorkingDirectory(wd)
, GeneratorTarget(gt)
, Target(gt->Target)
, Makefile(gt->Makefile)
, LocalGenerator(static_cast<cmLocalCommonGenerator*>(gt->LocalGenerator))
@@ -101,47 +105,47 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
}
//----------------------------------------------------------------------------
const char* cmCommonTargetGenerator::GetFortranModuleDirectory()
std::string cmCommonTargetGenerator::ComputeFortranModuleDirectory() const
{
std::string mod_dir;
const char* target_mod_dir =
this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
const char* moddir_flag =
this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
if(target_mod_dir && moddir_flag)
{
// Compute the full path to the module directory.
if(cmSystemTools::FileIsFullPath(target_mod_dir))
{
// Already a full path.
mod_dir = target_mod_dir;
}
else
{
// Interpret relative to the current output directory.
mod_dir = this->Makefile->GetCurrentBinaryDirectory();
mod_dir += "/";
mod_dir += target_mod_dir;
}
// Make sure the module output directory exists.
cmSystemTools::MakeDirectory(mod_dir);
}
return mod_dir;
}
//----------------------------------------------------------------------------
std::string cmCommonTargetGenerator::GetFortranModuleDirectory()
{
// Compute the module directory.
if(!this->FortranModuleDirectoryComputed)
{
const char* target_mod_dir =
this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
const char* moddir_flag =
this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
if(target_mod_dir && moddir_flag)
{
// Compute the full path to the module directory.
if(cmSystemTools::FileIsFullPath(target_mod_dir))
{
// Already a full path.
this->FortranModuleDirectory = target_mod_dir;
}
else
{
// Interpret relative to the current output directory.
this->FortranModuleDirectory =
this->Makefile->GetCurrentBinaryDirectory();
this->FortranModuleDirectory += "/";
this->FortranModuleDirectory += target_mod_dir;
}
// Make sure the module output directory exists.
cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
}
this->FortranModuleDirectoryComputed = true;
this->FortranModuleDirectory = this->ComputeFortranModuleDirectory();
}
// Return the computed directory.
if(this->FortranModuleDirectory.empty())
{
return 0;
}
else
{
return this->FortranModuleDirectory.c_str();
}
return this->FortranModuleDirectory;
}
//----------------------------------------------------------------------------
@@ -155,19 +159,24 @@ void cmCommonTargetGenerator::AddFortranFlags(std::string& flags)
}
// Add a module output directory flag if necessary.
const char* mod_dir = this->GetFortranModuleDirectory();
if(!mod_dir)
std::string mod_dir = this->GetFortranModuleDirectory();
if (!mod_dir.empty())
{
mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
mod_dir = this->Convert(mod_dir,
this->WorkingDirectory,
cmLocalGenerator::SHELL);
}
if(mod_dir)
else
{
mod_dir =
this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
}
if (!mod_dir.empty())
{
const char* moddir_flag =
this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
std::string modflag = moddir_flag;
modflag += this->Convert(mod_dir,
cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::SHELL);
modflag += mod_dir;
this->LocalGenerator->AppendFlags(flags, modflag);
}
@@ -267,7 +276,8 @@ std::string cmCommonTargetGenerator::GetFrameworkFlags(std::string const& l)
std::string flags;
const char* cfg = this->LocalGenerator->GetConfigName().c_str();
if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
if(cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(cfg))
{
std::vector<std::string> const& frameworks = cli->GetFrameworkPaths();
for(std::vector<std::string>::const_iterator i = frameworks.begin();
@@ -368,3 +378,37 @@ std::string cmCommonTargetGenerator::GetIncludes(std::string const& l)
}
return i->second;
}
std::vector<std::string>
cmCommonTargetGenerator::GetLinkedTargetDirectories() const
{
std::vector<std::string> dirs;
std::set<cmTarget const*> emitted;
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(this->ConfigName))
{
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator
i = items.begin(); i != items.end(); ++i)
{
cmTarget const* linkee = i->Target;
if(linkee && !linkee->IsImported()
// We can ignore the INTERFACE_LIBRARY items because
// Target->GetLinkInformation already processed their
// link interface and they don't have any output themselves.
&& linkee->GetType() != cmTarget::INTERFACE_LIBRARY
&& emitted.insert(linkee).second)
{
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(linkee);
cmLocalGenerator* lg = gt->GetLocalGenerator();
cmMakefile* mf = linkee->GetMakefile();
std::string di = mf->GetCurrentBinaryDirectory();
di += "/";
di += lg->GetTargetDirectory(*linkee);
dirs.push_back(di);
}
}
}
return dirs;
}
+7 -2
View File
@@ -29,7 +29,8 @@ class cmTarget;
class cmCommonTargetGenerator
{
public:
cmCommonTargetGenerator(cmGeneratorTarget* gt);
cmCommonTargetGenerator(cmOutputConverter::RelativeRoot wd,
cmGeneratorTarget* gt);
virtual ~cmCommonTargetGenerator();
std::string const& GetConfigName() const;
@@ -46,6 +47,7 @@ protected:
// Helper to add flag for windows .def file.
void AddModuleDefinitionFlag(std::string& flags);
cmOutputConverter::RelativeRoot WorkingDirectory;
cmGeneratorTarget* GeneratorTarget;
cmTarget* Target;
cmMakefile* Makefile;
@@ -59,7 +61,8 @@ protected:
// Target-wide Fortran module output directory.
bool FortranModuleDirectoryComputed;
std::string FortranModuleDirectory;
const char* GetFortranModuleDirectory();
std::string GetFortranModuleDirectory();
virtual std::string ComputeFortranModuleDirectory() const;
// Compute target-specific Fortran language flags.
void AddFortranFlags(std::string& flags);
@@ -85,6 +88,8 @@ protected:
ByLanguageMap DefinesByLanguage;
std::string GetIncludes(std::string const& l);
ByLanguageMap IncludesByLanguage;
std::vector<std::string> GetLinkedTargetDirectories() const;
};
#endif
+9 -8
View File
@@ -173,18 +173,19 @@ items that we know the linker will re-use automatically (shared libs).
//----------------------------------------------------------------------------
cmComputeLinkDepends
::cmComputeLinkDepends(cmTarget const* target, const std::string& config)
::cmComputeLinkDepends(const cmGeneratorTarget* target,
const std::string& config)
{
// Store context information.
this->Target = target;
this->Makefile = this->Target->GetMakefile();
this->Makefile = this->Target->Target->GetMakefile();
this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
// The configuration being linked.
this->HasConfig = !config.empty();
this->Config = (this->HasConfig)? config : std::string();
this->LinkType = this->Target->ComputeLinkType(this->Config);
this->LinkType = this->Target->Target->ComputeLinkType(this->Config);
// Enable debug mode if requested.
this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE");
@@ -363,7 +364,7 @@ void cmComputeLinkDepends::FollowLinkEntry(BFSEntry const& qe)
{
// Follow the target dependencies.
if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config, this->Target))
entry.Target->GetLinkInterface(this->Config, this->Target->Target))
{
const bool isIface =
entry.Target->GetType() == cmTarget::INTERFACE_LIBRARY;
@@ -461,7 +462,7 @@ void cmComputeLinkDepends::HandleSharedDependency(SharedDepEntry const& dep)
if(entry.Target)
{
if(cmTarget::LinkInterface const* iface =
entry.Target->GetLinkInterface(this->Config, this->Target))
entry.Target->GetLinkInterface(this->Config, this->Target->Target))
{
// Follow public and private dependencies transitively.
this->FollowSharedDeps(index, iface, true);
@@ -552,7 +553,7 @@ void cmComputeLinkDepends::AddDirectLinkEntries()
{
// Add direct link dependencies in this configuration.
cmTarget::LinkImplementation const* impl =
this->Target->GetLinkImplementation(this->Config);
this->Target->Target->GetLinkImplementation(this->Config);
this->AddLinkEntries(-1, impl->Libraries);
for(std::vector<cmLinkItem>::const_iterator
wi = impl->WrongConfigLibraries.begin();
@@ -634,7 +635,7 @@ cmTarget const* cmComputeLinkDepends::FindTargetToLink(int depender_index,
const std::string& name)
{
// Look for a target in the scope of the depender.
cmTarget const* from = this->Target;
cmTarget const* from = this->Target->Target;
if(depender_index >= 0)
{
if(cmTarget const* depender = this->EntryList[depender_index].Target)
@@ -932,7 +933,7 @@ int cmComputeLinkDepends::ComputeComponentCount(NodeList const& nl)
if(cmTarget const* target = this->EntryList[*ni].Target)
{
if(cmTarget::LinkInterface const* iface =
target->GetLinkInterface(this->Config, this->Target))
target->GetLinkInterface(this->Config, this->Target->Target))
{
if(iface->Multiplicity > count)
{
+4 -2
View File
@@ -22,6 +22,7 @@
class cmComputeComponentGraph;
class cmGlobalGenerator;
class cmMakefile;
class cmGeneratorTarget;
class cmTarget;
class cmake;
@@ -31,7 +32,8 @@ class cmake;
class cmComputeLinkDepends
{
public:
cmComputeLinkDepends(cmTarget const* target, const std::string& config);
cmComputeLinkDepends(cmGeneratorTarget const* target,
const std::string& config);
~cmComputeLinkDepends();
// Basic information about each link item.
@@ -57,7 +59,7 @@ public:
private:
// Context information.
cmTarget const* Target;
cmGeneratorTarget const* Target;
cmMakefile* Makefile;
cmGlobalGenerator const* GlobalGenerator;
cmake* CMakeInstance;
+54 -44
View File
@@ -14,11 +14,13 @@
#include "cmComputeLinkDepends.h"
#include "cmOrderDirectories.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmState.h"
#include "cmOutputConverter.h"
#include "cmMakefile.h"
#include "cmTarget.h"
#include "cmGeneratorTarget.h"
#include "cmake.h"
#include "cmAlgorithms.h"
@@ -241,12 +243,14 @@ because this need be done only for shared libraries without soname-s.
//----------------------------------------------------------------------------
cmComputeLinkInformation
::cmComputeLinkInformation(cmTarget const* target, const std::string& config)
::cmComputeLinkInformation(const cmGeneratorTarget* target,
const std::string& config)
{
// Store context information.
this->Target = target;
this->Makefile = this->Target->GetMakefile();
this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
this->Makefile = this->Target->Target->GetMakefile();
this->GlobalGenerator =
this->Target->GetLocalGenerator()->GetGlobalGenerator();
this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
// Check whether to recognize OpenBSD-style library versioned names.
@@ -280,14 +284,14 @@ cmComputeLinkInformation
// Check whether we should skip dependencies on shared library files.
this->LinkDependsNoShared =
this->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED");
this->Target->Target->GetPropertyAsBool("LINK_DEPENDS_NO_SHARED");
// On platforms without import libraries there may be a special flag
// to use when creating a plugin (module) that obtains symbols from
// the program that will load it.
this->LoaderFlag = 0;
if(!this->UseImportLibrary &&
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
this->Target->Target->GetType() == cmTarget::MODULE_LIBRARY)
{
std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
loader_flag_var += this->LinkLanguage;
@@ -305,10 +309,10 @@ cmComputeLinkInformation
// Get options needed to specify RPATHs.
this->RuntimeUseChrpath = false;
if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
if(this->Target->Target->GetType() != cmTarget::STATIC_LIBRARY)
{
const char* tType =
((this->Target->GetType() == cmTarget::EXECUTABLE)?
((this->Target->Target->GetType() == cmTarget::EXECUTABLE)?
"EXECUTABLE" : "SHARED_LIBRARY");
std::string rtVar = "CMAKE_";
rtVar += tType;
@@ -321,6 +325,7 @@ cmComputeLinkInformation
this->RuntimeAlways =
(this->Makefile->
GetSafeDefinition("CMAKE_PLATFORM_REQUIRED_RUNTIME_PATH"));
this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config);
// Get options needed to help find dependent libraries.
@@ -373,9 +378,9 @@ cmComputeLinkInformation
// Add the search path entries requested by the user to path ordering.
this->OrderLinkerSearchPath
->AddUserDirectories(this->Target->GetLinkDirectories());
->AddUserDirectories(this->Target->Target->GetLinkDirectories());
this->OrderRuntimeSearchPath
->AddUserDirectories(this->Target->GetLinkDirectories());
->AddUserDirectories(this->Target->Target->GetLinkDirectories());
// Set up the implicit link directories.
this->LoadImplicitLinkInfo();
@@ -403,12 +408,13 @@ cmComputeLinkInformation
// order to support such projects we need to add the directories
// containing libraries linked with a full path to the -L path.
this->OldLinkDirMode =
this->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW;
this->Target->Target->GetPolicyStatusCMP0003() != cmPolicies::NEW;
if(this->OldLinkDirMode)
{
// Construct a mask to not bother with this behavior for link
// directories already specified by the user.
std::vector<std::string> const& dirs = this->Target->GetLinkDirectories();
std::vector<std::string> const& dirs =
this->Target->Target->GetLinkDirectories();
this->OldLinkDirMask.insert(dirs.begin(), dirs.end());
}
@@ -514,10 +520,12 @@ bool cmComputeLinkInformation::Compute()
// Restore the target link type so the correct system runtime
// libraries are found.
const char* lss = this->Target->GetProperty("LINK_SEARCH_END_STATIC");
if(cmSystemTools::IsOn(lss))
const char* lss =
this->Target->Target->GetProperty("LINK_SEARCH_END_STATIC");
if(lss)
{
this->SetCurrentLinkType(LinkStatic);
this->SetCurrentLinkType(
cmSystemTools::IsOn(lss) ? LinkStatic : LinkShared);
}
else
{
@@ -535,9 +543,7 @@ bool cmComputeLinkInformation::Compute()
i != wrongItems.end(); ++i)
{
cmTarget const* tgt = *i;
cmGeneratorTarget *gtgt = tgt->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(tgt);
cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(tgt);
bool implib =
(this->UseImportLibrary &&
(tgt->GetType() == cmTarget::SHARED_LIBRARY));
@@ -567,7 +573,7 @@ bool cmComputeLinkInformation::Compute()
"name."
;
this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
this->Target->Target->GetBacktrace());
}
return true;
@@ -577,7 +583,8 @@ bool cmComputeLinkInformation::Compute()
void cmComputeLinkInformation::AddImplicitLinkInfo()
{
// The link closure lists all languages whose implicit info is needed.
cmTarget::LinkClosure const* lc=this->Target->GetLinkClosure(this->Config);
cmGeneratorTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config);
for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
li != lc->Languages.end(); ++li)
{
@@ -640,9 +647,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
if(tgt && tgt->IsLinkable())
{
cmGeneratorTarget *gtgt = tgt->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(tgt);
cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(tgt);
// This is a CMake target. Ask the target for its real name.
if(impexe && this->LoaderFlag)
{
@@ -756,15 +761,16 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
return;
}
cmGeneratorTarget *gtgt = 0;
// Get a full path to the dependent shared library.
// Add it to the runtime path computation so that the target being
// linked will be able to find it.
std::string lib;
if(tgt)
{
cmGeneratorTarget *gtgt = tgt->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(tgt);
gtgt = tgt->GetMakefile()->GetGlobalGenerator()->GetGeneratorTarget(tgt);
lib = gtgt->GetFullPath(this->Config, this->UseImportLibrary);
this->AddLibraryRuntimeInfo(lib, tgt);
}
@@ -790,9 +796,9 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
}
if(order)
{
if(tgt)
if(gtgt)
{
std::string soName = tgt->GetSOName(this->Config);
std::string soName = gtgt->GetSOName(this->Config);
const char* soname = soName.empty()? 0 : soName.c_str();
order->AddRuntimeLibrary(lib, soname);
}
@@ -854,9 +860,11 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
}
// Lookup the starting link type from the target (linked statically?).
const char* lss = this->Target->GetProperty("LINK_SEARCH_START_STATIC");
const char* lss =
this->Target->Target->GetProperty("LINK_SEARCH_START_STATIC");
this->StartLinkType = cmSystemTools::IsOn(lss)? LinkStatic : LinkShared;
this->CurrentLinkType = this->StartLinkType;
this->CurrentLinkType = LinkUnknown;
this->SetCurrentLinkType(this->StartLinkType);
}
//----------------------------------------------------------------------------
@@ -1140,7 +1148,7 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
// Full path libraries should specify a valid library file name.
// See documentation of CMP0008.
std::string generator = this->GlobalGenerator->GetName();
if(this->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW &&
if(this->Target->Target->GetPolicyStatusCMP0008() != cmPolicies::NEW &&
(generator.find("Visual Studio") != generator.npos ||
generator.find("Xcode") != generator.npos))
{
@@ -1221,7 +1229,7 @@ bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
}
// Check the policy for whether we should use the approach below.
switch (this->Target->GetPolicyStatusCMP0060())
switch (this->Target->Target->GetPolicyStatusCMP0060())
{
case cmPolicies::WARN:
if (this->CMP0060Warn)
@@ -1531,7 +1539,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
this->OrderLinkerSearchPath->AddLinkLibrary(item);
// Produce any needed message.
switch(this->Target->GetPolicyStatusCMP0008())
switch(this->Target->Target->GetPolicyStatusCMP0008())
{
case cmPolicies::WARN:
{
@@ -1548,7 +1556,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
<< " " << item << "\n"
<< "which is a full-path but not a valid library file name.";
this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
this->Target->Target->GetBacktrace());
}
}
case cmPolicies::OLD:
@@ -1566,7 +1574,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
<< " " << item << "\n"
<< "which is a full-path but not a valid library file name.";
this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
this->Target->Target->GetBacktrace());
}
break;
}
@@ -1583,7 +1591,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
}
// Enforce policy constraints.
switch(this->Target->GetPolicyStatusCMP0003())
switch(this->Target->Target->GetPolicyStatusCMP0003())
{
case cmPolicies::WARN:
if(!this->CMakeInstance->GetState()
@@ -1594,7 +1602,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
std::ostringstream w;
this->PrintLinkPolicyDiagnosis(w);
this->CMakeInstance->IssueMessage(cmake::AUTHOR_WARNING, w.str(),
this->Target->GetBacktrace());
this->Target->Target->GetBacktrace());
}
case cmPolicies::OLD:
// OLD behavior is to add the paths containing libraries with
@@ -1610,7 +1618,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories()
e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n";
this->PrintLinkPolicyDiagnosis(e);
this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(),
this->Target->GetBacktrace());
this->Target->Target->GetBacktrace());
return false;
}
}
@@ -1804,7 +1812,8 @@ cmComputeLinkInformation::AddLibraryRuntimeInfo(std::string const& fullPath,
// Try to get the soname of the library. Only files with this name
// could possibly conflict.
std::string soName = target->GetSOName(this->Config);
cmGeneratorTarget *gtgt = this->GlobalGenerator->GetGeneratorTarget(target);
std::string soName = gtgt->GetSOName(this->Config);
const char* soname = soName.empty()? 0 : soName.c_str();
// Include this library in the runtime path ordering.
@@ -1911,23 +1920,24 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// build tree.
bool linking_for_install =
(for_install ||
this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
this->Target->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"));
bool use_install_rpath =
(outputRuntime && this->Target->HaveInstallTreeRPATH() &&
(outputRuntime && this->Target->Target->HaveInstallTreeRPATH() &&
linking_for_install);
bool use_build_rpath =
(outputRuntime && this->Target->HaveBuildTreeRPATH(this->Config) &&
(outputRuntime && this->Target->Target->HaveBuildTreeRPATH(this->Config) &&
!linking_for_install);
bool use_link_rpath =
outputRuntime && linking_for_install &&
!this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH") &&
this->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
this->Target->Target->GetPropertyAsBool("INSTALL_RPATH_USE_LINK_PATH");
// Construct the RPATH.
std::set<std::string> emitted;
if(use_install_rpath)
{
const char* install_rpath = this->Target->GetProperty("INSTALL_RPATH");
const char* install_rpath =
this->Target->Target->GetProperty("INSTALL_RPATH");
cmCLI_ExpandListUnique(install_rpath, runtimeDirs, emitted);
}
if(use_build_rpath || use_link_rpath)
@@ -1999,7 +2009,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
// Add runtime paths required by the languages to always be
// present. This is done even when skipping rpath support.
{
cmTarget::LinkClosure const* lc =
cmGeneratorTarget::LinkClosure const* lc =
this->Target->GetLinkClosure(this->Config);
for(std::vector<std::string>::const_iterator li = lc->Languages.begin();
li != lc->Languages.end(); ++li)
+4 -2
View File
@@ -20,6 +20,7 @@ class cmake;
class cmGlobalGenerator;
class cmMakefile;
class cmTarget;
class cmGeneratorTarget;
class cmOrderDirectories;
/** \class cmComputeLinkInformation
@@ -28,7 +29,8 @@ class cmOrderDirectories;
class cmComputeLinkInformation
{
public:
cmComputeLinkInformation(cmTarget const* target, const std::string& config);
cmComputeLinkInformation(cmGeneratorTarget const* target,
const std::string& config);
~cmComputeLinkInformation();
bool Compute();
@@ -72,7 +74,7 @@ private:
std::set<cmTarget const*> SharedLibrariesLinked;
// Context information.
cmTarget const* Target;
cmGeneratorTarget const* Target;
cmMakefile* Makefile;
cmGlobalGenerator* GlobalGenerator;
cmake* CMakeInstance;
+25 -1
View File
@@ -16,7 +16,8 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile):
Makefile(makefile),
Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)),
Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)),
Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057))
Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)),
Policy64Status(makefile.GetPolicyStatus(cmPolicies::CMP0064))
{
}
@@ -493,6 +494,29 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs,
this->Makefile.FindTargetToUse(argP1->GetValue())?true:false,
reducible, arg, newArgs, argP1, argP2);
}
// does a test exist
if(this->Policy64Status != cmPolicies::OLD &&
this->Policy64Status != cmPolicies::WARN)
{
if (this->IsKeyword("TEST", *arg) && argP1 != newArgs.end())
{
const cmTest* haveTest = this->Makefile.GetTest(argP1->c_str());
this->HandlePredicate(
haveTest?true:false,
reducible, arg, newArgs, argP1, argP2);
}
}
else if(this->Policy64Status == cmPolicies::WARN &&
this->IsKeyword("TEST", *arg))
{
std::ostringstream e;
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0064) << "\n";
e << "TEST will be interpreted as an operator "
"when the policy is set to NEW. "
"Since the policy is not set the OLD behavior will be used.";
this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str());
}
// is a variable defined
if (this->IsKeyword("DEFINED", *arg) && argP1 != newArgs.end())
{
+1
View File
@@ -94,6 +94,7 @@ private:
cmPolicies::PolicyStatus Policy12Status;
cmPolicies::PolicyStatus Policy54Status;
cmPolicies::PolicyStatus Policy57Status;
cmPolicies::PolicyStatus Policy64Status;
};
#endif
+10
View File
@@ -470,6 +470,16 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
{
fprintf(fout, "set(CMAKE_POSITION_INDEPENDENT_CODE \"ON\")\n");
}
if (const char *lssDef = this->Makefile->GetDefinition(
"CMAKE_LINK_SEARCH_START_STATIC"))
{
fprintf(fout, "set(CMAKE_LINK_SEARCH_START_STATIC \"%s\")\n", lssDef);
}
if (const char *lssDef = this->Makefile->GetDefinition(
"CMAKE_LINK_SEARCH_END_STATIC"))
{
fprintf(fout, "set(CMAKE_LINK_SEARCH_END_STATIC \"%s\")\n", lssDef);
}
/* Put the executable at a known location (for COPY_FILE). */
fprintf(fout, "set(CMAKE_RUNTIME_OUTPUT_DIRECTORY \"%s\")\n",
+1 -1
View File
@@ -13,7 +13,7 @@
#include "cmSystemTools.h"
#define check_curl_result(result, errstr) \
if (result != CURLE_OK) \
if (result != CURLE_OK && result != CURLE_NOT_BUILT_IN) \
{ \
e += e.empty()? "" : "\n"; \
e += errstr; \
+5 -8
View File
@@ -154,14 +154,10 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
const char* stamp_dir = this->TargetDirectory.c_str();
// Get the directory in which module files will be created.
const char* mod_dir;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
if(const char* target_mod_dir =
mf->GetDefinition("CMAKE_Fortran_TARGET_MODULE_DIR"))
{
mod_dir = target_mod_dir;
}
else
std::string mod_dir =
mf->GetSafeDefinition("CMAKE_Fortran_TARGET_MODULE_DIR");
if (mod_dir.empty())
{
mod_dir =
this->LocalGenerator->GetMakefile()->GetCurrentBinaryDirectory();
@@ -356,7 +352,8 @@ bool
cmDependsFortran
::WriteDependenciesReal(const char *obj,
cmFortranSourceInfo const& info,
const char* mod_dir, const char* stamp_dir,
std::string const& mod_dir,
const char* stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends)
{
+2 -1
View File
@@ -66,7 +66,8 @@ protected:
// Actually write the depenencies to the streams.
bool WriteDependenciesReal(const char *obj,
cmFortranSourceInfo const& info,
const char* mod_dir, const char* stamp_dir,
std::string const& mod_dir,
const char* stamp_dir,
std::ostream& makeDepends,
std::ostream& internalDepends);
+6 -4
View File
@@ -27,6 +27,7 @@ cmExportBuildFileGenerator::cmExportBuildFileGenerator()
//----------------------------------------------------------------------------
bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
{
std::vector<cmGeneratorTarget*> allTargets;
{
std::string expectedTargets;
std::string sep;
@@ -68,7 +69,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
tei = this->Exports.begin();
tei != this->Exports.end(); ++tei)
{
cmTarget* te = (*tei)->Target;
cmGeneratorTarget* gte = *tei;
cmTarget* te = gte->Target;
this->GenerateImportTargetCode(os, te);
te->AppendBuildInterfaceIncludes();
@@ -104,7 +106,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
}
this->PopulateCompatibleInterfaceProperties(te, properties);
this->PopulateCompatibleInterfaceProperties(gte, properties);
this->GenerateInterfaceProperties(te, os, properties);
}
@@ -331,12 +333,12 @@ cmExportBuildFileGenerator
}
std::string
cmExportBuildFileGenerator::InstallNameDir(cmTarget* target,
cmExportBuildFileGenerator::InstallNameDir(cmGeneratorTarget* target,
const std::string& config)
{
std::string install_name_dir;
cmMakefile* mf = target->GetMakefile();
cmMakefile* mf = target->Target->GetMakefile();
if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
install_name_dir =
+2 -1
View File
@@ -71,7 +71,8 @@ protected:
cmGeneratorTarget* target,
ImportPropertyMap& properties);
std::string InstallNameDir(cmTarget* target, const std::string& config);
std::string InstallNameDir(cmGeneratorTarget* target,
const std::string& config);
std::vector<std::string>
FindNamespaces(cmMakefile* mf, const std::string& name);
+9 -8
View File
@@ -525,7 +525,7 @@ void getPropertyContents(cmTarget const* tgt, const std::string& prop,
}
//----------------------------------------------------------------------------
void getCompatibleInterfaceProperties(cmTarget *target,
void getCompatibleInterfaceProperties(cmGeneratorTarget *target,
std::set<std::string> &ifaceProperties,
const std::string& config)
{
@@ -533,7 +533,7 @@ void getCompatibleInterfaceProperties(cmTarget *target,
if (!info)
{
cmMakefile* mf = target->GetMakefile();
cmMakefile* mf = target->Target->GetMakefile();
std::ostringstream e;
e << "Exporting the target \"" << target->GetName() << "\" is not "
"allowed since its linker language cannot be determined";
@@ -568,9 +568,10 @@ void getCompatibleInterfaceProperties(cmTarget *target,
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
cmTarget *target,
cmGeneratorTarget *gtarget,
ImportPropertyMap &properties)
{
cmTarget *target = gtarget->Target;
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
target, properties);
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING",
@@ -591,7 +592,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
if (target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
getCompatibleInterfaceProperties(target, ifaceProperties, "");
getCompatibleInterfaceProperties(gtarget, ifaceProperties, "");
std::vector<std::string> configNames;
target->GetMakefile()->GetConfigurations(configNames);
@@ -599,7 +600,7 @@ void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
for (std::vector<std::string>::const_iterator ci = configNames.begin();
ci != configNames.end(); ++ci)
{
getCompatibleInterfaceProperties(target, ifaceProperties, *ci);
getCompatibleInterfaceProperties(gtarget, ifaceProperties, *ci);
}
}
@@ -888,14 +889,14 @@ cmExportFileGenerator
{
std::string prop;
std::string value;
if(target->Target->HasSOName(config))
if(target->HasSOName(config))
{
if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
value = this->InstallNameDir(target->Target, config);
value = this->InstallNameDir(target, config);
}
prop = "IMPORTED_SONAME";
value += target->Target->GetSOName(config);
value += target->GetSOName(config);
}
else
{
+2 -2
View File
@@ -132,7 +132,7 @@ protected:
std::vector<std::string> &missingTargets);
void PopulateInterfaceProperty(const std::string& propName, cmTarget *target,
ImportPropertyMap &properties);
void PopulateCompatibleInterfaceProperties(cmTarget *target,
void PopulateCompatibleInterfaceProperties(cmGeneratorTarget *target,
ImportPropertyMap &properties);
void GenerateInterfaceProperties(cmTarget const* target, std::ostream& os,
const ImportPropertyMap &properties);
@@ -200,7 +200,7 @@ private:
virtual void ReplaceInstallPrefix(std::string &input);
virtual std::string InstallNameDir(cmTarget* target,
virtual std::string InstallNameDir(cmGeneratorTarget* target,
const std::string& config) = 0;
};
+9 -5
View File
@@ -193,7 +193,11 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
cmGeneratorTarget *gtgt = te->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(te);
this->PopulateCompatibleInterfaceProperties(gtgt, properties);
this->GenerateInterfaceProperties(te, os, properties);
}
@@ -358,7 +362,7 @@ cmExportInstallFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
cmGeneratorTarget *gtgt = te->Target->GetMakefile()->GetLocalGenerator()
cmGeneratorTarget *gtgt = te->Target->GetMakefile()
->GetGlobalGenerator()->GetGeneratorTarget(te->Target);
this->SetImportDetailProperties(config, suffix,
gtgt, properties, missingTargets);
@@ -398,7 +402,7 @@ cmExportInstallFileGenerator
}
// Get the target to be installed.
cmTarget* target = itgen->GetTarget();
cmTarget* target = itgen->GetTarget()->Target;
// Construct the installed location of the target.
std::string dest = itgen->GetDestination(config);
@@ -542,12 +546,12 @@ cmExportInstallFileGenerator
}
std::string
cmExportInstallFileGenerator::InstallNameDir(cmTarget* target,
cmExportInstallFileGenerator::InstallNameDir(cmGeneratorTarget* target,
const std::string&)
{
std::string install_name_dir;
cmMakefile* mf = target->GetMakefile();
cmMakefile* mf = target->Target->GetMakefile();
if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
install_name_dir =
+2 -1
View File
@@ -83,7 +83,8 @@ protected:
std::set<std::string>& importedLocations
);
std::string InstallNameDir(cmTarget* target, const std::string& config);
std::string InstallNameDir(cmGeneratorTarget* target,
const std::string& config);
cmInstallExportGenerator* IEGen;
@@ -11,7 +11,6 @@
============================================================================*/
#include "cmExportLibraryDependenciesCommand.h"
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmake.h"
#include "cmVersion.h"
@@ -82,15 +81,14 @@ void cmExportLibraryDependenciesCommand::ConstFinalPass() const
// the project.
cmake* cm = this->Makefile->GetCMakeInstance();
cmGlobalGenerator* global = cm->GetGlobalGenerator();
const std::vector<cmLocalGenerator *>& locals = global->GetLocalGenerators();
const std::vector<cmMakefile*>& locals = global->GetMakefiles();
std::map<std::string, std::string> libDepsOld;
std::map<std::string, std::string> libDepsNew;
std::map<std::string, std::string> libTypes;
for(std::vector<cmLocalGenerator *>::const_iterator i = locals.begin();
for(std::vector<cmMakefile*>::const_iterator i = locals.begin();
i != locals.end(); ++i)
{
const cmLocalGenerator* gen = *i;
const cmTargets &tgts = gen->GetMakefile()->GetTargets();
const cmTargets &tgts = (*i)->GetTargets();
for(cmTargets::const_iterator l = tgts.begin();
l != tgts.end(); ++l)
{
+2 -2
View File
@@ -125,12 +125,12 @@ cmExportTryCompileFileGenerator::PopulateProperties(cmTarget const* target,
}
std::string
cmExportTryCompileFileGenerator::InstallNameDir(cmTarget* target,
cmExportTryCompileFileGenerator::InstallNameDir(cmGeneratorTarget* target,
const std::string& config)
{
std::string install_name_dir;
cmMakefile* mf = target->GetMakefile();
cmMakefile* mf = target->Target->GetMakefile();
if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
install_name_dir =
+3 -3
View File
@@ -9,8 +9,8 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef cmExportInstallFileGenerator_h
#define cmExportInstallFileGenerator_h
#ifndef cmExportTryCompileFileGenerator_h
#define cmExportTryCompileFileGenerator_h
#include "cmExportFileGenerator.h"
@@ -45,7 +45,7 @@ protected:
ImportPropertyMap& properties,
std::set<cmTarget const*> &emitted);
std::string InstallNameDir(cmTarget* target,
std::string InstallNameDir(cmGeneratorTarget* target,
const std::string& config);
private:
std::string FindTargets(const std::string& prop, cmTarget const* tgt,
+2 -5
View File
@@ -3573,11 +3573,8 @@ void cmFileCommand::AddEvaluationFile(const std::string &inputName,
cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge
= conditionGe.Parse(condition);
this->Makefile->GetGlobalGenerator()->AddEvaluationFile(inputName,
outputCge,
this->Makefile,
conditionCge,
inputIsContent);
this->Makefile->AddEvaluationFile(inputName, outputCge,
conditionCge, inputIsContent);
}
//----------------------------------------------------------------------------
+21 -19
View File
@@ -25,19 +25,18 @@
cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
const std::string &input,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
cmMakefile *makefile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent)
: Input(input),
OutputFileExpr(outputFileExpr),
Makefile(makefile),
Condition(condition),
InputIsContent(inputIsContent)
{
}
//----------------------------------------------------------------------------
void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg,
const std::string& config,
const std::string& lang,
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string> &outputFiles, mode_t perm)
@@ -45,7 +44,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
std::string rawCondition = this->Condition->GetInput();
if (!rawCondition.empty())
{
std::string condResult = this->Condition->Evaluate(this->Makefile, config,
std::string condResult = this->Condition->Evaluate(lg->GetMakefile(),
config,
false, 0, 0, 0, lang);
if (condResult == "0")
{
@@ -56,16 +56,17 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
std::ostringstream e;
e << "Evaluation file condition \"" << rawCondition << "\" did "
"not evaluate to valid content. Got \"" << condResult << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
}
const std::string outputFileName
= this->OutputFileExpr->Evaluate(this->Makefile, config,
= this->OutputFileExpr->Evaluate(lg->GetMakefile(), config,
false, 0, 0, 0, lang);
const std::string outputContent
= inputExpression->Evaluate(this->Makefile, config,
= inputExpression->Evaluate(lg->GetMakefile(),
config,
false, 0, 0, 0, lang);
std::map<std::string, std::string>::iterator it
@@ -81,11 +82,11 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
e << "Evaluation file to be written multiple times for different "
"configurations or languages with different content:\n "
<< outputFileName;
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
lg->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
this->Makefile->AddCMakeOutputFile(outputFileName.c_str());
lg->GetMakefile()->AddCMakeOutputFile(outputFileName.c_str());
this->Files.push_back(outputFileName);
outputFiles[outputFileName] = outputContent;
@@ -100,18 +101,19 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
//----------------------------------------------------------------------------
void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
std::string const& config)
cmLocalGenerator *lg, std::string const& config)
{
std::vector<std::string> enabledLanguages;
cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator();
cmGlobalGenerator *gg = lg->GetGlobalGenerator();
gg->GetEnabledLanguages(enabledLanguages);
for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
le != enabledLanguages.end(); ++le)
{
std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config,
std::string name = this->OutputFileExpr->Evaluate(lg->GetMakefile(),
config,
false, 0, 0, 0, *le);
cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name);
sf->SetProperty("GENERATED", "1");
gg->SetFilenameTargetDepends(sf,
@@ -120,7 +122,7 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
}
//----------------------------------------------------------------------------
void cmGeneratorExpressionEvaluationFile::Generate()
void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator *lg)
{
mode_t perm = 0;
std::string inputContent;
@@ -130,14 +132,14 @@ void cmGeneratorExpressionEvaluationFile::Generate()
}
else
{
this->Makefile->AddCMakeDependFile(this->Input.c_str());
lg->GetMakefile()->AddCMakeDependFile(this->Input.c_str());
cmSystemTools::GetPermissions(this->Input.c_str(), perm);
cmsys::ifstream fin(this->Input.c_str());
if(!fin)
{
std::ostringstream e;
e << "Evaluation file \"" << this->Input << "\" cannot be read.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
lg->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
@@ -159,7 +161,7 @@ void cmGeneratorExpressionEvaluationFile::Generate()
std::map<std::string, std::string> outputFiles;
std::vector<std::string> allConfigs;
this->Makefile->GetConfigurations(allConfigs);
lg->GetMakefile()->GetConfigurations(allConfigs);
if (allConfigs.empty())
{
@@ -167,7 +169,7 @@ void cmGeneratorExpressionEvaluationFile::Generate()
}
std::vector<std::string> enabledLanguages;
cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator();
cmGlobalGenerator *gg = lg->GetGlobalGenerator();
gg->GetEnabledLanguages(enabledLanguages);
for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
@@ -176,7 +178,7 @@ void cmGeneratorExpressionEvaluationFile::Generate()
for(std::vector<std::string>::const_iterator li = allConfigs.begin();
li != allConfigs.end(); ++li)
{
this->Generate(*li, *le, inputExpression.get(), outputFiles, perm);
this->Generate(lg, *li, *le, inputExpression.get(), outputFiles, perm);
if(cmSystemTools::GetFatalErrorOccured())
{
return;
+8 -7
View File
@@ -18,31 +18,32 @@
#include "cmGeneratorExpression.h"
class cmLocalGenerator;
//----------------------------------------------------------------------------
class cmGeneratorExpressionEvaluationFile
{
public:
cmGeneratorExpressionEvaluationFile(const std::string &input,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputFileExpr,
cmMakefile *makefile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent);
void Generate();
void Generate(cmLocalGenerator* lg);
std::vector<std::string> GetFiles() const { return this->Files; }
void CreateOutputFile(std::string const& config);
void CreateOutputFile(cmLocalGenerator* lg, std::string const& config);
private:
void Generate(const std::string& config, const std::string& lang,
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string> &outputFiles, mode_t perm);
void Generate(cmLocalGenerator* lg, const std::string& config,
const std::string& lang,
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string> &outputFiles, mode_t perm);
private:
const std::string Input;
const cmsys::auto_ptr<cmCompiledGeneratorExpression> OutputFileExpr;
cmMakefile *Makefile;
const cmsys::auto_ptr<cmCompiledGeneratorExpression> Condition;
std::vector<std::string> Files;
const bool InputIsContent;
+33 -25
View File
@@ -990,6 +990,9 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
assert(target);
cmGeneratorTarget* gtgt =
context->Makefile->GetGlobalGenerator()->GetGeneratorTarget(target);
if (propertyName == "LINKER_LANGUAGE")
{
if (target->LinkLanguagePropagatesToDependents() &&
@@ -1001,7 +1004,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"link libraries for a static library");
return std::string();
}
return target->GetLinkerLanguage(context->Config);
return gtgt->GetLinkerLanguage(context->Config);
}
cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
@@ -1117,7 +1120,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
}
else if(!interfacePropertyName.empty())
{
if(cmTarget::LinkImplementationLibraries const* impl =
if(cmLinkImplementationLibraries const* impl =
target->GetLinkImplementationLibraries(context->Config))
{
linkedTargetsContent =
@@ -1135,40 +1138,40 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
return linkedTargetsContent;
}
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
return target->GetLinkInterfaceDependentBoolProperty(
return gtgt->GetLinkInterfaceDependentBoolProperty(
propertyName,
context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentStringProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentStringProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentStringProperty(
gtgt->GetLinkInterfaceDependentStringProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
}
if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentNumberMinProperty(
gtgt->GetLinkInterfaceDependentNumberMinProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
}
if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentNumberMaxProperty(
gtgt->GetLinkInterfaceDependentNumberMaxProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
@@ -1180,22 +1183,22 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
if (!target->IsImported()
&& dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries())
{
if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentNumberMinProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentNumberMinProperty(
gtgt->GetLinkInterfaceDependentNumberMinProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
}
if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config))
if (gtgt->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
context->Config))
{
context->HadContextSensitiveCondition = true;
const char *propContent =
target->GetLinkInterfaceDependentNumberMaxProperty(
gtgt->GetLinkInterfaceDependentNumberMaxProperty(
propertyName,
context->Config);
return propContent ? propContent : "";
@@ -1369,8 +1372,6 @@ static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
std::string result;
for (LangMap::const_iterator lit = testedFeatures.begin();
lit != testedFeatures.end(); ++lit)
{
@@ -1586,7 +1587,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
}
std::string result = target->Target->GetDirectory(context->Config);
result += "/";
result += target->Target->GetSOName(context->Config);
result += target->GetSOName(context->Config);
return result;
}
};
@@ -1599,7 +1600,14 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *content)
{
std::string language = target->Target->GetLinkerLanguage(context->Config);
if (target->IsImported())
{
::reportError(context, content->GetOriginalExpression(),
"TARGET_PDB_FILE not allowed for IMPORTED targets.");
return std::string();
}
std::string language = target->GetLinkerLanguage(context->Config);
std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
@@ -1624,7 +1632,7 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
std::string result = target->Target->GetPDBDirectory(context->Config);
result += "/";
result += target->Target->GetPDBName(context->Config);
result += target->GetPDBName(context->Config);
return result;
}
};
File diff suppressed because it is too large Load Diff
+196 -1
View File
@@ -20,11 +20,13 @@ class cmLocalGenerator;
class cmMakefile;
class cmSourceFile;
class cmTarget;
class cmComputeLinkInformation;
class cmGeneratorTarget
{
public:
cmGeneratorTarget(cmTarget*, cmLocalGenerator* lg);
~cmGeneratorTarget();
cmLocalGenerator* GetLocalGenerator() const;
@@ -36,6 +38,9 @@ public:
location is suitable for use as the LOCATION target property. */
const char* GetLocationForBuild() const;
cmComputeLinkInformation*
GetLinkInformation(const std::string& config) const;
int GetType() const;
std::string GetName() const;
const char *GetProperty(const std::string& prop) const;
@@ -82,6 +87,26 @@ public:
bool GetFeatureAsBool(const std::string& feature,
const std::string& config) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentStringProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
const std::string& config) const;
bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p,
const std::string& config) const;
/** Get the full path to the target according to the settings in its
makefile and the configuration type. */
std::string GetFullPath(const std::string& config="", bool implib = false,
@@ -90,6 +115,53 @@ public:
bool realname) const;
std::string NormalGetRealName(const std::string& config) const;
/** @return the Mac App directory without the base */
std::string GetAppBundleDirectory(const std::string& config,
bool contentOnly) const;
/** Return whether this target is an executable Bundle, a framework
or CFBundle on Apple. */
bool IsBundleOnApple() const;
/** Get the full name of the target according to the settings in its
makefile. */
std::string GetFullName(const std::string& config="",
bool implib = false) const;
/** @return the Mac framework directory without the base. */
std::string GetFrameworkDirectory(const std::string& config,
bool rootDir) const;
/** @return the Mac CFBundle directory without the base */
std::string GetCFBundleDirectory(const std::string& config,
bool contentOnly) const;
/** Return the install name directory for the target in the
* build tree. For example: "\@rpath/", "\@loader_path/",
* or "/full/path/to/library". */
std::string GetInstallNameDirForBuildTree(const std::string& config) const;
/** Return the install name directory for the target in the
* install tree. For example: "\@rpath/" or "\@loader_path/". */
std::string GetInstallNameDirForInstallTree() const;
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const std::string& config) const;
void GetFullNameComponents(std::string& prefix,
std::string& base, std::string& suffix,
const std::string& config="",
bool implib = false) const;
/** Append to @a base the mac content directory and return it. */
std::string BuildMacContentDirectory(const std::string& base,
const std::string& config = "",
bool contentOnly = true) const;
/** @return the mac content directory for this target. */
std::string GetMacContentDirectory(const std::string& config = 0,
bool implib = false) const;
cmTarget* Target;
cmMakefile* Makefile;
cmLocalGenerator* LocalGenerator;
@@ -97,6 +169,20 @@ public:
std::string GetModuleDefinitionFile(const std::string& config) const;
/** Link information from the transitive closure of the link
implementation and the interfaces of its dependencies. */
struct LinkClosure
{
// The preferred linker language.
std::string LinkerLanguage;
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
};
LinkClosure const* GetLinkClosure(const std::string& config) const;
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
/** Full path with trailing slash to the top-level directory
holding object files for this target. Includes the build
time config name placeholder if needed for the generator. */
@@ -128,10 +214,41 @@ public:
*/
void TraceDependencies();
/** Get the directory in which to place the target compiler .pdb file.
If the configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical
compiler pdb output directory is given. */
std::string GetCompilePDBDirectory(const std::string& config = "") const;
/** Get sources that must be built before the given source. */
std::vector<cmSourceFile*> const*
GetSourceDepends(cmSourceFile const* sf) const;
/** Get the name of the pdb file for the target. */
std::string GetPDBName(const std::string& config="") const;
/** Whether this library has soname enabled and platform supports it. */
bool HasSOName(const std::string& config) const;
struct CompileInfo
{
std::string CompilePdbDir;
};
CompileInfo const* GetCompileInfo(const std::string& config) const;
typedef std::map<std::string, CompileInfo> CompileInfoMapType;
mutable CompileInfoMapType CompileInfoMap;
/** Get the name of the compiler pdb file for the target. */
std::string GetCompilePDBName(const std::string& config="") const;
/** Get the path for the MSVC /Fd option for this target. */
std::string GetCompilePDBPath(const std::string& config="") const;
// Get the target base name.
std::string GetOutputName(const std::string& config, bool implib) const;
/**
* Flags for a given source file as used in this target. Typically assigned
* via SET_TARGET_PROPERTIES when the property is a list of source files.
@@ -153,6 +270,33 @@ public:
SourceFileType Type;
const char* MacFolder; // location inside Mac content folders
};
void GetAutoUicOptions(std::vector<std::string> &result,
const std::string& config) const;
/** Get the names of the executable needed to generate a build rule
that takes into account executable version numbers. This should
be called only on an executable target. */
void GetExecutableNames(std::string& name, std::string& realName,
std::string& impName, std::string& pdbName,
const std::string& config) const;
/** Get the names of the library needed to generate a build rule
that takes into account shared library version numbers. This
should be called only on a library target. */
void GetLibraryNames(std::string& name, std::string& soName,
std::string& realName, std::string& impName,
std::string& pdbName, const std::string& config) const;
/**
* Compute whether this target must be relinked before installing.
*/
bool NeedRelinkBeforeInstall(const std::string& config) const;
/** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed(const std::string& config) const;
///! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config = "") const;
struct SourceFileFlags
GetTargetSourceFileFlags(const cmSourceFile* sf) const;
@@ -168,12 +312,16 @@ public:
std::vector<cmSourceFile const*> XamlSources;
};
void ReportPropertyOrigin(const std::string &p,
const std::string &result,
const std::string &report,
const std::string &compatibilityType) const;
private:
friend class cmTargetTraceDependencies;
struct SourceEntry { std::vector<cmSourceFile*> Depends; };
typedef std::map<cmSourceFile const*, SourceEntry> SourceEntriesType;
SourceEntriesType SourceEntries;
mutable std::map<cmSourceFile const*, std::string> Objects;
std::set<cmSourceFile const*> ExplicitObjectName;
mutable std::map<std::string, std::vector<std::string> > SystemIncludesCache;
@@ -182,8 +330,55 @@ private:
mutable bool SourceFileFlagsConstructed;
mutable std::map<cmSourceFile const*, SourceFileFlags> SourceFlagsMap;
mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
std::string GetFullNameInternal(const std::string& config,
bool implib) const;
void GetFullNameInternal(const std::string& config, bool implib,
std::string& outPrefix, std::string& outBase,
std::string& outSuffix) const;
typedef std::map<std::string, LinkClosure> LinkClosureMapType;
mutable LinkClosureMapType LinkClosureMap;
struct CompatibleInterfacesBase
{
std::set<std::string> PropsBool;
std::set<std::string> PropsString;
std::set<std::string> PropsNumberMax;
std::set<std::string> PropsNumberMin;
};
CompatibleInterfacesBase const&
GetCompatibleInterfaces(std::string const& config) const;
struct CompatibleInterfaces: public CompatibleInterfacesBase
{
CompatibleInterfaces(): Done(false) {}
bool Done;
};
mutable std::map<std::string, CompatibleInterfaces> CompatibleInterfacesMap;
typedef std::map<std::string, cmComputeLinkInformation*>
cmTargetLinkInformationMap;
mutable cmTargetLinkInformationMap LinkInformation;
void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const std::string& config) const;
cmGeneratorTarget(cmGeneratorTarget const&);
void operator=(cmGeneratorTarget const&);
struct LinkImplClosure: public std::vector<cmTarget const*>
{
LinkImplClosure(): Done(false) {}
bool Done;
};
mutable std::map<std::string, LinkImplClosure> LinkImplClosureMap;
public:
std::vector<cmTarget const*> const&
GetLinkImplementationClosure(const std::string& config) const;
};
struct cmStrictTargetComparison {
+2 -5
View File
@@ -51,10 +51,8 @@ bool cmGetDirectoryPropertyCommand
sd = cmSystemTools::CollapseFullPath(sd);
// lookup the makefile from the directory name
cmLocalGenerator *lg =
this->Makefile->GetGlobalGenerator()->
FindLocalGenerator(sd);
if (!lg)
dir = this->Makefile->GetGlobalGenerator()->FindMakefile(sd);
if (!dir)
{
this->SetError
("DIRECTORY argument provided but requested directory not found. "
@@ -62,7 +60,6 @@ bool cmGetDirectoryPropertyCommand
"it is valid but has not been processed yet.");
return false;
}
dir = lg->GetMakefile();
++i;
}
+2 -2
View File
@@ -24,7 +24,7 @@ bool cmGetFilenameComponentCommand
// Check and see if the value has been stored in the cache
// already, if so use that value
if(args.size() == 4 && args[3] == "CACHE")
if(args.size() >= 4 && args[args.size() - 1] == "CACHE")
{
const char* cacheValue = this->Makefile->GetDefinition(args[0]);
if(cacheValue && !cmSystemTools::IsNOTFOUND(cacheValue))
@@ -111,7 +111,7 @@ bool cmGetFilenameComponentCommand
return false;
}
if(args.size() == 4 && args[3] == "CACHE")
if(args.size() >= 4 && args[args.size() - 1] == "CACHE")
{
if(!programArgs.empty() && !storeArgs.empty())
{
+2 -7
View File
@@ -262,13 +262,8 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
dir = cmSystemTools::CollapseFullPath(dir);
// Lookup the generator.
if(cmLocalGenerator* lg =
(this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir)))
{
// Use the makefile for the directory found.
mf = lg->GetMakefile();
}
else
mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
if (!mf)
{
// Could not find the directory.
this->SetError
+2 -1
View File
@@ -128,7 +128,8 @@ void cmGhsMultiTargetGenerator::Generate()
{
config = "RELEASE";
}
const std::string language(this->Target->GetLinkerLanguage(config));
const std::string language(
this->GeneratorTarget->GetLinkerLanguage(config));
config = cmSystemTools::UpperCase(config);
this->DynamicDownload = this->DetermineIfDynamicDownload(config, language);
if (this->DynamicDownload)
+127 -102
View File
@@ -14,6 +14,20 @@
#if defined(_MSC_VER) && _MSC_VER >= 1800
# define KWSYS_WINDOWS_DEPRECATED_GetVersionEx
#endif
typedef struct {
ULONG dwOSVersionInfoSize;
ULONG dwMajorVersion;
ULONG dwMinorVersion;
ULONG dwBuildNumber;
ULONG dwPlatformId;
WCHAR szCSDVersion[128];
USHORT wServicePackMajor;
USHORT wServicePackMinor;
USHORT wSuiteMask;
UCHAR wProductType;
UCHAR wReserved;
} CMRTL_OSVERSIONINFOEXW;
#endif
#include "cmGlobalGenerator.h"
@@ -30,10 +44,10 @@
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmExportBuildFileGenerator.h"
#include "cmCPackPropertiesGenerator.h"
#include "cmAlgorithms.h"
#include "cmInstallGenerator.h"
#include <cmsys/Directory.hxx>
#include <cmsys/FStream.hxx>
@@ -432,23 +446,45 @@ cmGlobalGenerator::EnableLanguage(std::vector<std::string>const& languages,
if (!mf->GetDefinition("CMAKE_SYSTEM"))
{
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Windows version number data. */
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
CMRTL_OSVERSIONINFOEXW osviex;
ZeroMemory(&osviex, sizeof(osviex));
osviex.dwOSVersionInfoSize = sizeof(osviex);
typedef LONG (FAR WINAPI *cmRtlGetVersion)(CMRTL_OSVERSIONINFOEXW*);
cmRtlGetVersion rtlGetVersion = reinterpret_cast<cmRtlGetVersion>(
GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetVersion"));
if (rtlGetVersion && rtlGetVersion(&osviex) == 0)
{
std::ostringstream windowsVersionString;
windowsVersionString << osviex.dwMajorVersion << "."
<< osviex.dwMinorVersion << "."
<< osviex.dwBuildNumber;
windowsVersionString.str();
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
windowsVersionString.str().c_str());
}
else
{
// RtlGetVersion failed, so use the deprecated GetVersionEx function.
/* Windows version number data. */
OSVERSIONINFO osvi;
ZeroMemory(&osvi, sizeof(osvi));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# pragma warning (push)
# pragma warning (disable:4996)
#endif
GetVersionEx (&osvi);
GetVersionEx (&osvi);
#ifdef KWSYS_WINDOWS_DEPRECATED_GetVersionEx
# pragma warning (pop)
#endif
std::ostringstream windowsVersionString;
windowsVersionString << osvi.dwMajorVersion << "." << osvi.dwMinorVersion;
windowsVersionString.str();
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
windowsVersionString.str().c_str());
std::ostringstream windowsVersionString;
windowsVersionString << osvi.dwMajorVersion << "."
<< osvi.dwMinorVersion;
windowsVersionString.str();
mf->AddDefinition("CMAKE_HOST_SYSTEM_VERSION",
windowsVersionString.str().c_str());
}
#endif
// Read the DetermineSystem file
std::string systemFile = mf->GetModulesFile("CMakeDetermineSystem.cmake");
@@ -1093,6 +1129,7 @@ void cmGlobalGenerator::Configure()
// start with this directory
cmLocalGenerator *lg = this->MakeLocalGenerator();
this->Makefiles.push_back(lg->GetMakefile());
this->LocalGenerators.push_back(lg);
// set the Start directories
@@ -1111,9 +1148,9 @@ void cmGlobalGenerator::Configure()
// update the cache entry for the number of local generators, this is used
// for progress
char num[100];
sprintf(num,"%d",static_cast<int>(this->LocalGenerators.size()));
sprintf(num,"%d",static_cast<int>(this->Makefiles.size()));
this->GetCMakeInstance()->AddCacheEntry
("CMAKE_NUMBER_OF_LOCAL_GENERATORS", num,
("CMAKE_NUMBER_OF_MAKEFILES", num,
"number of local generators", cmState::INTERNAL);
// check for link libraries and include directories containing "NOTFOUND"
@@ -1156,9 +1193,9 @@ void cmGlobalGenerator::Configure()
cmTargets globalTargets;
this->CreateDefaultGlobalTargets(&globalTargets);
for (i = 0; i < this->LocalGenerators.size(); ++i)
for (i = 0; i < this->Makefiles.size(); ++i)
{
cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
cmMakefile* mf = this->Makefiles[i];
cmTargets* targets = &(mf->GetTargets());
cmTargets::iterator tit;
for ( tit = globalTargets.begin(); tit != globalTargets.end(); ++ tit )
@@ -1212,7 +1249,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const
return false;
}
void cmGlobalGenerator::DoGenerate()
bool cmGlobalGenerator::Compute()
{
// Some generators track files replaced during the Generate.
// Start with an empty vector:
@@ -1221,17 +1258,11 @@ void cmGlobalGenerator::DoGenerate()
// clear targets to issue warning CMP0042 for
this->CMP0042WarnTargets.clear();
this->Generate();
}
void cmGlobalGenerator::Generate()
{
// Check whether this generator is allowed to run.
if(!this->CheckALLOW_DUPLICATE_CUSTOM_TARGETS())
{
return;
return false;
}
this->FinalizeTargetCompileInfo();
this->CreateGenerationObjects();
@@ -1266,6 +1297,24 @@ void cmGlobalGenerator::Generate()
}
#endif
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
cmMakefile* mf = this->LocalGenerators[i]->GetMakefile();
std::vector<cmInstallGenerator*>& gens = mf->GetInstallGenerators();
for (std::vector<cmInstallGenerator*>::const_iterator git = gens.begin();
git != gens.end(); ++git)
{
(*git)->Compute(this->LocalGenerators[i]);
}
}
return true;
}
void cmGlobalGenerator::Generate()
{
unsigned int i;
// Trace the dependencies, after that no custom commands should be added
// because their dependencies might not be handled correctly
for (i = 0; i < this->LocalGenerators.size(); ++i)
@@ -1433,9 +1482,9 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens)
void cmGlobalGenerator::FinalizeTargetCompileInfo()
{
// Construct per-target generator information.
for(unsigned int i=0; i < this->LocalGenerators.size(); ++i)
for(unsigned int i=0; i < this->Makefiles.size(); ++i)
{
cmMakefile *mf = this->LocalGenerators[i]->GetMakefile();
cmMakefile *mf = this->Makefiles[i];
const cmStringRange noconfig_compile_definitions =
mf->GetCompileDefinitionsEntries();
@@ -1501,6 +1550,7 @@ void cmGlobalGenerator::CreateGeneratorTargets(TargetTypes targetTypes,
ti != targets.end(); ++ti)
{
cmTarget* t = &ti->second;
t->Compute();
cmGeneratorTarget* gt = new cmGeneratorTarget(t, lg);
this->GeneratorTargets[t] = gt;
generatorTargets[t] = gt;
@@ -1548,12 +1598,11 @@ void cmGlobalGenerator::ClearGeneratorMembers()
cmDeleteAll(this->GeneratorTargets);
this->GeneratorTargets.clear();
cmDeleteAll(this->EvaluationFiles);
this->EvaluationFiles.clear();
cmDeleteAll(this->BuildExportSets);
this->BuildExportSets.clear();
this->Makefiles.clear();
cmDeleteAll(this->LocalGenerators);
this->LocalGenerators.clear();
@@ -1593,11 +1642,11 @@ void cmGlobalGenerator::CheckLocalGenerators()
// std::set<std::string> notFoundMap;
// after it is all done do a ConfigureFinalPass
cmState* state = this->GetCMakeInstance()->GetState();
for (unsigned int i = 0; i < this->LocalGenerators.size(); ++i)
for (unsigned int i = 0; i < this->Makefiles.size(); ++i)
{
this->LocalGenerators[i]->GetMakefile()->ConfigureFinalPass();
this->Makefiles[i]->ConfigureFinalPass();
cmTargets &targets =
this->LocalGenerators[i]->GetMakefile()->GetTargets();
this->Makefiles[i]->GetTargets();
for (cmTargets::iterator l = targets.begin();
l != targets.end(); l++)
{
@@ -1652,15 +1701,14 @@ void cmGlobalGenerator::CheckLocalGenerators()
}
std::string text = notFoundMap[varName];
text += "\n used as include directory in directory ";
text += this->LocalGenerators[i]
->GetMakefile()->GetCurrentSourceDirectory();
text += this->Makefiles[i]->GetCurrentSourceDirectory();
notFoundMap[varName] = text;
}
}
}
this->CMakeInstance->UpdateProgress
("Configuring", 0.9f+0.1f*(static_cast<float>(i)+1.0f)/
static_cast<float>(this->LocalGenerators.size()));
static_cast<float>(this->Makefiles.size()));
}
if(!notFoundMap.empty())
@@ -1694,9 +1742,9 @@ int cmGlobalGenerator::TryCompile(const std::string& srcdir,
// take the bulk of the time, so try and guess some progress
// by getting closer and closer to 100 without actually getting there.
if (!this->CMakeInstance->GetState()->GetInitializedCacheValue
("CMAKE_NUMBER_OF_LOCAL_GENERATORS"))
("CMAKE_NUMBER_OF_MAKEFILES"))
{
// If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
// If CMAKE_NUMBER_OF_MAKEFILES is not set
// we are in the first time progress and we have no
// idea how long it will be. So, just move 1/10th of the way
// there each time, and don't go over 95%
@@ -1884,19 +1932,19 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
}
//----------------------------------------------------------------------------
void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
void cmGlobalGenerator::AddMakefile(cmMakefile *mf)
{
this->LocalGenerators.push_back(lg);
this->Makefiles.push_back(mf);
// update progress
// estimate how many lg there will be
const char *numGenC =
this->CMakeInstance->GetState()->GetInitializedCacheValue
("CMAKE_NUMBER_OF_LOCAL_GENERATORS");
("CMAKE_NUMBER_OF_MAKEFILES");
if (!numGenC)
{
// If CMAKE_NUMBER_OF_LOCAL_GENERATORS is not set
// If CMAKE_NUMBER_OF_MAKEFILES is not set
// we are in the first time progress and we have no
// idea how long it will be. So, just move half way
// there each time, and don't go over 95%
@@ -1911,7 +1959,7 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
}
int numGen = atoi(numGenC);
float prog = 0.9f*static_cast<float>(this->LocalGenerators.size())/
float prog = 0.9f*static_cast<float>(this->Makefiles.size())/
static_cast<float>(numGen);
if (prog > 0.9f)
{
@@ -1920,6 +1968,12 @@ void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
this->CMakeInstance->UpdateProgress("Configuring", prog);
}
//----------------------------------------------------------------------------
void cmGlobalGenerator::AddLocalGenerator(cmLocalGenerator *lg)
{
this->LocalGenerators.push_back(lg);
}
void cmGlobalGenerator::AddInstallComponent(const char* component)
{
if(component && *component)
@@ -2009,10 +2063,10 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
}
bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
cmTarget const& target) const
cmGeneratorTarget* target) const
{
if(target.GetType() == cmTarget::INTERFACE_LIBRARY
|| target.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
if(target->GetType() == cmTarget::INTERFACE_LIBRARY
|| target->Target->GetPropertyAsBool("EXCLUDE_FROM_ALL"))
{
// This target is excluded from its directory.
return true;
@@ -2021,7 +2075,7 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
{
// This target is included in its directory. Check whether the
// directory is excluded.
return this->IsExcluded(root, target.GetMakefile()->GetLocalGenerator());
return this->IsExcluded(root, target->GetLocalGenerator());
}
}
@@ -2082,15 +2136,16 @@ void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
{
cmTarget const& target = t->second;
cmGeneratorTarget* gt = this->GetGeneratorTarget(&target);
// Consider the directory containing the target and all its
// parents until something excludes the target.
for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, target);
for(cmLocalGenerator* clg = lg; clg && !this->IsExcluded(clg, gt);
clg = clg->GetParent())
{
// This local generator includes the target.
std::set<cmGeneratorTarget const*>& targetSet =
this->LocalGeneratorToTargetMap[clg];
cmGeneratorTarget* gt = this->GetGeneratorTarget(&target);
targetSet.insert(gt);
// Add dependencies of the included target. An excluded
@@ -2107,6 +2162,20 @@ void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
}
}
cmMakefile*
cmGlobalGenerator::FindMakefile(const std::string& start_dir) const
{
for(std::vector<cmMakefile*>::const_iterator it =
this->Makefiles.begin(); it != this->Makefiles.end(); ++it)
{
std::string sd = (*it)->GetCurrentSourceDirectory();
if (sd == start_dir)
{
return *it;
}
}
return 0;
}
///! Find a local generator by its startdirectory
cmLocalGenerator*
@@ -2194,7 +2263,7 @@ inline std::string removeQuotes(const std::string& s)
void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets)
{
cmMakefile* mf = this->LocalGenerators[0]->GetMakefile();
cmMakefile* mf = this->Makefiles[0];
const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
// CPack
@@ -2698,12 +2767,8 @@ void cmGlobalGenerator::AddTargetDepends(cmGeneratorTarget const* target,
//----------------------------------------------------------------------------
void cmGlobalGenerator::AddToManifest(const std::string& config,
std::string const& f)
void cmGlobalGenerator::AddToManifest(std::string const& f)
{
// Add to the main manifest for this configuration.
this->TargetManifest[config].insert(f);
// Add to the content listing for the file's directory.
std::string dir = cmSystemTools::GetFilenamePath(f);
std::string file = cmSystemTools::GetFilenameName(f);
@@ -2771,9 +2836,9 @@ cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
}
// Shorten the output name (in expected use case).
cmLocalGenerator* lg = this->GetLocalGenerators()[0];
std::string fname = lg->Convert(outputs[0],
cmLocalGenerator::HOME_OUTPUT);
cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot());
std::string fname = converter.Convert(
outputs[0], cmLocalGenerator::HOME_OUTPUT);
// Associate the hash with this output.
this->RuleHashes[fname] = hash;
@@ -3023,61 +3088,21 @@ cmGlobalGenerator::GetFilenameTargetDepends(cmSourceFile* sf) const {
void cmGlobalGenerator::CreateEvaluationSourceFiles(
std::string const& config) const
{
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = this->EvaluationFiles.begin();
li != this->EvaluationFiles.end();
++li)
unsigned int i;
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
(*li)->CreateOutputFile(config);
this->LocalGenerators[i]->CreateEvaluationFileOutputs(config);
}
}
//----------------------------------------------------------------------------
void cmGlobalGenerator::AddEvaluationFile(const std::string &inputFile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputExpr,
cmMakefile *makefile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent)
{
this->EvaluationFiles.push_back(
new cmGeneratorExpressionEvaluationFile(inputFile, outputExpr,
makefile, condition,
inputIsContent));
}
//----------------------------------------------------------------------------
void cmGlobalGenerator::ProcessEvaluationFiles()
{
std::vector<std::string> generatedFiles;
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = this->EvaluationFiles.begin();
li != this->EvaluationFiles.end();
++li)
unsigned int i;
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
(*li)->Generate();
if (cmSystemTools::GetFatalErrorOccured())
{
return;
}
std::vector<std::string> files = (*li)->GetFiles();
std::sort(files.begin(), files.end());
std::vector<std::string> intersection;
std::set_intersection(files.begin(), files.end(),
generatedFiles.begin(), generatedFiles.end(),
std::back_inserter(intersection));
if (!intersection.empty())
{
cmSystemTools::Error("Files to be generated by multiple different "
"commands: ", cmWrap('"', intersection, '"', " ").c_str());
return;
}
generatedFiles.insert(generatedFiles.end(),
files.begin(), files.end());
std::vector<std::string>::iterator newIt =
generatedFiles.end() - files.size();
std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end());
this->LocalGenerators[i]->ProcessEvaluationFiles(generatedFiles);
}
}
+11 -24
View File
@@ -34,7 +34,6 @@
class cmake;
class cmGeneratorTarget;
class cmGeneratorExpressionEvaluationFile;
class cmMakefile;
class cmLocalGenerator;
class cmExternalMakefileProjectGenerator;
@@ -86,6 +85,7 @@ public:
*/
virtual void Configure();
virtual bool Compute();
enum TargetTypes {
AllTargets,
@@ -99,7 +99,7 @@ public:
* basically creates a series of LocalGenerators for each directory and
* requests that they Generate.
*/
void DoGenerate();
virtual void Generate();
/**
* Set/Get and Clear the enabled languages.
@@ -173,6 +173,8 @@ public:
cmake *GetCMakeInstance() const { return this->CMakeInstance; }
void SetConfiguredFilesPath(cmGlobalGenerator* gen);
const std::vector<cmMakefile*>& GetMakefiles() const {
return this->Makefiles;}
const std::vector<cmLocalGenerator *>& GetLocalGenerators() const {
return this->LocalGenerators;}
@@ -184,6 +186,7 @@ public:
void SetCurrentMakefile(cmMakefile* mf)
{this->CurrentMakefile = mf;}
void AddMakefile(cmMakefile *mf);
void AddLocalGenerator(cmLocalGenerator *lg);
///! Set an generator for an "external makefile based project"
@@ -200,7 +203,7 @@ public:
cmExportSetMap& GetExportSets() {return this->ExportSets;}
/** Add a file to the manifest of generated targets for a configuration. */
void AddToManifest(const std::string& config, std::string const& f);
void AddToManifest(std::string const& f);
void EnableInstallTarget();
@@ -253,6 +256,7 @@ public:
that is a framework. */
bool NameResolvesToFramework(const std::string& libname) const;
cmMakefile* FindMakefile(const std::string& start_dir) const;
///! Find a local generator by its startdirectory
cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const;
@@ -264,11 +268,6 @@ public:
const std::string& suffix,
std::string& dir);
/** Get the manifest of all targets that will be built for each
configuration. This is valid during generation only. */
cmTargetManifest const& GetTargetManifest() const
{ return this->TargetManifest; }
/** Get the content of a directory. Directory listings are cached
and re-loaded from disk only when modified. During the generation
step the content will include the target files to be built even if
@@ -338,12 +337,6 @@ public:
static std::string EscapeJSON(const std::string& s);
void AddEvaluationFile(const std::string &inputFile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
cmMakefile *makefile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent);
void ProcessEvaluationFiles();
std::map<std::string, cmExportBuildFileGenerator*>& GetBuildExportSets()
@@ -373,8 +366,6 @@ public:
std::string MakeSilentFlag;
protected:
virtual void Generate();
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
// information, and also collect all the targets
@@ -387,6 +378,8 @@ protected:
void SetLanguageEnabledFlag(const std::string& l, cmMakefile* mf);
void SetLanguageEnabledMaps(const std::string& l, cmMakefile* mf);
void FillExtensionToLanguageMap(const std::string& l, cmMakefile* mf);
virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const;
virtual bool ComputeTargetDepends();
@@ -404,7 +397,7 @@ protected:
void FillProjectMap();
void CheckLocalGenerators();
bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
bool IsExcluded(cmLocalGenerator* root, cmTarget const& target) const;
bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
void FillLocalGeneratorToTargetMap();
void CreateDefaultGlobalTargets(cmTargets* targets);
cmTarget CreateGlobalTarget(const std::string& name, const char* message,
@@ -415,6 +408,7 @@ protected:
std::string FindMakeProgramFile;
std::string ConfiguredFilesPath;
cmake *CMakeInstance;
std::vector<cmMakefile*> Makefiles;
std::vector<cmLocalGenerator *> LocalGenerators;
cmMakefile* CurrentMakefile;
// map from project name to vector of local generators in that project
@@ -429,10 +423,6 @@ protected:
std::map<std::string, cmExportBuildFileGenerator*> BuildExportSets;
std::map<std::string, cmExportBuildFileGenerator*> BuildExportExportSets;
// Manifest of all targets that will be built for each configuration.
// This is computed just before local generators generate.
cmTargetManifest TargetManifest;
// All targets in the entire project.
#if defined(CMAKE_BUILD_WITH_CMAKE)
#ifdef CMake_HAVE_CXX11_UNORDERED_MAP
@@ -446,7 +436,6 @@ protected:
TargetMap TotalTargets;
TargetMap AliasTargets;
TargetMap ImportedTargets;
std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
const char* GetPredefinedTargetsFolder();
virtual bool UseFolderProperty();
@@ -480,8 +469,6 @@ private:
virtual void ForceLinkerLanguages();
virtual void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const;
void CheckCompilerIdCompatibility(cmMakefile* mf,
std::string const& lang) const;
+16 -12
View File
@@ -36,18 +36,6 @@ void cmGlobalJOMMakefileGenerator
// pick a default
mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
if(!(cmSystemTools::GetEnv("INCLUDE") &&
cmSystemTools::GetEnv("LIB"))
)
{
std::string message = "To use the JOM generator, cmake must be run "
"from a shell that can use the compiler cl from the command line. "
"This environment does not contain INCLUDE, LIB, or LIBPATH, and "
"these must be set for the cl compiler to work. ";
mf->IssueMessage(cmake::WARNING,
message);
}
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
@@ -58,3 +46,19 @@ void cmGlobalJOMMakefileGenerator
entry.Name = cmGlobalJOMMakefileGenerator::GetActualName();
entry.Brief = "Generates JOM makefiles.";
}
//----------------------------------------------------------------------------
void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(std::ostream& os,
std::string const& lang,
const char* envVar) const
{
if(lang == "CXX" || lang == "C")
{
os <<
"To use the JOM generator with Visual C++, cmake must be run from a "
"shell that can use the compiler cl from the command line. This "
"environment is unable to invoke the cl compiler. To fix this problem, "
"run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+3
View File
@@ -42,6 +42,9 @@ public:
*/
virtual void EnableLanguage(std::vector<std::string>const& languages,
cmMakefile *, bool optional);
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const;
};
#endif
+16 -12
View File
@@ -36,18 +36,6 @@ void cmGlobalNMakeMakefileGenerator
// pick a default
mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
if(!(cmSystemTools::GetEnv("INCLUDE") &&
cmSystemTools::GetEnv("LIB"))
)
{
std::string message = "To use the NMake generator, cmake must be run "
"from a shell that can use the compiler cl from the command line. "
"This environment does not contain INCLUDE, LIB, or LIBPATH, and "
"these must be set for the cl compiler to work. ";
mf->IssueMessage(cmake::WARNING,
message);
}
this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional);
}
@@ -58,3 +46,19 @@ void cmGlobalNMakeMakefileGenerator
entry.Name = cmGlobalNMakeMakefileGenerator::GetActualName();
entry.Brief = "Generates NMake makefiles.";
}
//----------------------------------------------------------------------------
void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(std::ostream& os,
std::string const& lang,
const char* envVar) const
{
if(lang == "CXX" || lang == "C")
{
os <<
"To use the NMake generator with Visual C++, cmake must be run from a "
"shell that can use the compiler cl from the command line. This "
"environment is unable to invoke the cl compiler. To fix this problem, "
"run cmake from the Visual Studio Command Prompt (vcvarsall.bat).\n";
}
this->cmGlobalUnixMakefileGenerator3::PrintCompilerAdvice(os, lang, envVar);
}
+3
View File
@@ -40,6 +40,9 @@ public:
*/
virtual void EnableLanguage(std::vector<std::string>const& languages,
cmMakefile *, bool optional);
private:
void PrintCompilerAdvice(std::ostream& os, std::string const& lang,
const char* envVar) const;
};
#endif
+29 -20
View File
@@ -547,6 +547,18 @@ void cmGlobalNinjaGenerator
// Source/cmake.cxx
void cmGlobalNinjaGenerator::Generate()
{
// Check minimum Ninja version.
if (cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
CurrentNinjaVersion().c_str(),
RequiredNinjaVersion().c_str()))
{
std::ostringstream msg;
msg << "The detected version of Ninja (" << this->CurrentNinjaVersion();
msg << ") is less than the version of Ninja required by CMake (";
msg << this->RequiredNinjaVersion() << ").";
this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, msg.str());
return;
}
this->OpenBuildFileStream();
this->OpenRulesFileStream();
@@ -911,9 +923,7 @@ cmGlobalNinjaGenerator
case cmTarget::STATIC_LIBRARY:
case cmTarget::MODULE_LIBRARY:
{
cmGeneratorTarget *gtgt = target->GetMakefile()->GetLocalGenerator()
->GetGlobalGenerator()
->GetGeneratorTarget(target);
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(target);
outputs.push_back(ng->ConvertToNinjaPath(
gtgt->GetFullPath(configName, false, realname)));
break;
@@ -1055,23 +1065,21 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
{
knownDependencies.insert( ng->ConvertToNinjaPath( *j ) );
}
}
knownDependencies.insert( "CMakeCache.txt" );
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = this->EvaluationFiles.begin();
li != this->EvaluationFiles.end();
++li)
{
//get all the files created by generator expressions and convert them
//to ninja paths
std::vector<std::string> files = (*li)->GetFiles();
typedef std::vector<std::string>::const_iterator vect_it;
for(vect_it j = files.begin(); j != files.end(); ++j)
std::vector<cmGeneratorExpressionEvaluationFile*> const& ef =
(*i)->GetMakefile()->GetEvaluationFiles();
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = ef.begin(); li != ef.end(); ++li)
{
knownDependencies.insert( ng->ConvertToNinjaPath( *j ) );
//get all the files created by generator expressions and convert them
//to ninja paths
std::vector<std::string> evaluationFiles = (*li)->GetFiles();
for(vect_it j = evaluationFiles.begin(); j != evaluationFiles.end(); ++j)
{
knownDependencies.insert( ng->ConvertToNinjaPath( *j ) );
}
}
}
knownDependencies.insert( "CMakeCache.txt" );
for(TargetAliasMap::const_iterator i= this->TargetAliases.begin();
i != this->TargetAliases.end();
@@ -1260,7 +1268,7 @@ std::string cmGlobalNinjaGenerator::ninjaCmd() const
return "ninja";
}
std::string cmGlobalNinjaGenerator::ninjaVersion() const
std::string cmGlobalNinjaGenerator::CurrentNinjaVersion() const
{
std::string version;
std::string command = ninjaCmd() + " --version";
@@ -1268,13 +1276,14 @@ std::string cmGlobalNinjaGenerator::ninjaVersion() const
&version, 0, 0, 0,
cmSystemTools::OUTPUT_NONE);
return version;
return cmSystemTools::TrimWhitespace(version);
}
bool cmGlobalNinjaGenerator::SupportsConsolePool() const
{
return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
ninjaVersion().c_str(), "1.5") == false;
CurrentNinjaVersion().c_str(),
RequiredNinjaVersionForConsolePool().c_str()) == false;
}
void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os)
+5 -3
View File
@@ -289,7 +289,7 @@ public:
const std::vector<cmLocalGenerator*>& GetLocalGenerators() const {
return LocalGenerators; }
bool IsExcluded(cmLocalGenerator* root, cmTarget& target) {
bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) {
return cmGlobalGenerator::IsExcluded(root, target); }
int GetRuleCmdLength(const std::string& name) {
@@ -299,8 +299,10 @@ public:
virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
std::string ninjaVersion() const;
std::string CurrentNinjaVersion() const;
// Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
static std::string RequiredNinjaVersion() { return "1.3"; }
static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; }
bool SupportsConsolePool() const;
protected:
+5 -5
View File
@@ -482,7 +482,7 @@ cmGlobalUnixMakefileGenerator3
// Add this to the list of depends rules in this directory.
if((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
(!check_relink ||
gtarget->Target
gtarget
->NeedRelinkBeforeInstall(lg->GetConfigName())))
{
std::string tname = lg->GetRelativeTargetDirectory(*gtarget->Target);
@@ -691,7 +691,7 @@ cmGlobalUnixMakefileGenerator3
// Add a local name for the rule to relink the target before
// installation.
if(gtarget->Target
if(gtarget
->NeedRelinkBeforeInstall(lg->GetConfigName()))
{
makeTargetName = lg->GetRelativeTargetDirectory(*gtarget->Target);
@@ -821,7 +821,7 @@ cmGlobalUnixMakefileGenerator3
localName, depends, commands, true);
// add the all/all dependency
if(!this->IsExcluded(this->LocalGenerators[0], *gtarget->Target))
if(!this->IsExcluded(this->LocalGenerators[0], gtarget))
{
depends.clear();
depends.push_back(localName);
@@ -876,7 +876,7 @@ cmGlobalUnixMakefileGenerator3
name, depends, commands, true);
// Add rules to prepare the target for installation.
if(gtarget->Target
if(gtarget
->NeedRelinkBeforeInstall(lg->GetConfigName()))
{
localName = lg->GetRelativeTargetDirectory(*gtarget->Target);
@@ -889,7 +889,7 @@ cmGlobalUnixMakefileGenerator3
"Pre-install relink rule for target.",
localName, depends, commands, true);
if(!this->IsExcluded(this->LocalGenerators[0], *gtarget->Target))
if(!this->IsExcluded(this->LocalGenerators[0], gtarget))
{
depends.clear();
depends.push_back(localName);
+10 -1
View File
@@ -314,9 +314,18 @@ cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmLocalGenerator* parent,
}
//----------------------------------------------------------------------------
bool cmGlobalVisualStudio10Generator::Compute()
{
if (!cmGlobalVisualStudio8Generator::Compute())
{
return false;
}
this->LongestSource = LongestSourcePath();
return true;
}
void cmGlobalVisualStudio10Generator::Generate()
{
this->LongestSource = LongestSourcePath();
this->cmGlobalVisualStudio8Generator::Generate();
if(this->LongestSource.Length > 0)
{
+2
View File
@@ -45,6 +45,8 @@ public:
std::vector<std::string> const& makeOptions = std::vector<std::string>()
);
virtual bool Compute();
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent,
cmState::Snapshot snapshot);
+10 -4
View File
@@ -254,6 +254,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
no_working_directory, no_depends,
noCommandLines);
tgt->Compute();
cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg);
mf->AddGeneratorTarget(tgt, gt);
// Organize in the "predefined targets" folder:
//
@@ -345,8 +348,13 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
}
//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Generator::Generate()
bool cmGlobalVisualStudio8Generator::Compute()
{
if (!cmGlobalVisualStudio7Generator::Compute())
{
return false;
}
if(this->AddCheckTarget())
{
// All targets depend on the build-system check target.
@@ -360,9 +368,7 @@ void cmGlobalVisualStudio8Generator::Generate()
}
}
}
// Now perform the main generation.
this->cmGlobalVisualStudio7Generator::Generate();
return true;
}
//----------------------------------------------------------------------------
+1 -1
View File
@@ -67,7 +67,7 @@ public:
return !this->WindowsCEVersion.empty(); }
protected:
virtual void Generate();
virtual bool Compute();
virtual const char* GetIDEVersion() { return "8.0"; }
virtual std::string FindDevEnvCommand();
+19 -7
View File
@@ -64,8 +64,13 @@ std::string cmGlobalVisualStudioGenerator::GetRegistryBase(
}
//----------------------------------------------------------------------------
void cmGlobalVisualStudioGenerator::Generate()
bool cmGlobalVisualStudioGenerator::Compute()
{
if (!cmGlobalGenerator::Compute())
{
return false;
}
// Add a special target that depends on ALL projects for easy build
// of one configuration only.
const char* no_working_dir = 0;
@@ -85,6 +90,9 @@ void cmGlobalVisualStudioGenerator::Generate()
AddUtilityCommand("ALL_BUILD", true, no_working_dir,
no_depends, no_commands, false,
"Build all projects");
allBuild->Compute();
cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]);
allBuild->GetMakefile()->AddGeneratorTarget(allBuild, gt);
#if 0
// Can't activate this code because we want ALL_BUILD
@@ -104,13 +112,19 @@ void cmGlobalVisualStudioGenerator::Generate()
for(std::vector<cmLocalGenerator*>::iterator i = gen.begin();
i != gen.end(); ++i)
{
cmTargets& targets = (*i)->GetMakefile()->GetTargets();
for(cmTargets::iterator t = targets.begin();
cmGeneratorTargetsType targets =
(*i)->GetMakefile()->GetGeneratorTargets();
for(cmGeneratorTargetsType::iterator t = targets.begin();
t != targets.end(); ++t)
{
if (t->second->GetType() == cmTarget::GLOBAL_TARGET
|| t->first->IsImported())
{
continue;
}
if(!this->IsExcluded(gen[0], t->second))
{
allBuild->AddUtility(t->second.GetName());
allBuild->AddUtility(t->second->GetName());
}
}
}
@@ -130,9 +144,7 @@ void cmGlobalVisualStudioGenerator::Generate()
static_cast<cmLocalVisualStudioGenerator*>(*lgi);
lg->AddCMakeListsRules();
}
// Run all the local generators.
this->cmGlobalGenerator::Generate();
return true;
}
//----------------------------------------------------------------------------
+1 -1
View File
@@ -108,7 +108,7 @@ public:
cmGeneratorTarget*, std::vector<cmCustomCommand>& commands,
std::string const& configName);
protected:
virtual void Generate();
virtual bool Compute();
// Does this VS version link targets to each other if there are
// dependencies in the SLN file? This was done for VS versions
+41 -16
View File
@@ -378,8 +378,13 @@ cmGlobalXCodeGenerator::CreateLocalGenerator(cmLocalGenerator* parent,
}
//----------------------------------------------------------------------------
void cmGlobalXCodeGenerator::Generate()
bool cmGlobalXCodeGenerator::Compute()
{
if (!cmGlobalGenerator::Compute())
{
return false;
}
std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
// make sure extra targets are added before calling
// the parent generate which will call trace depends
@@ -390,11 +395,17 @@ void cmGlobalXCodeGenerator::Generate()
// add ALL_BUILD, INSTALL, etc
this->AddExtraTargets(root, it->second);
}
return true;
}
void cmGlobalXCodeGenerator::Generate()
{
this->cmGlobalGenerator::Generate();
if(cmSystemTools::GetErrorOccuredFlag())
{
return;
}
std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it;
for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
{
cmLocalGenerator* root = it->second[0];
@@ -449,10 +460,12 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
// Add ALL_BUILD
const char* no_working_directory = 0;
std::vector<std::string> no_depends;
mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
cmTarget* allbuild = mf->AddUtilityCommand("ALL_BUILD", true, no_depends,
no_working_directory,
"echo", "Build all projects");
cmTarget* allbuild = mf->FindTarget("ALL_BUILD");
allbuild->Compute();
cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
mf->AddGeneratorTarget(allbuild, allBuildGt);
// Refer to the main build configuration file for easy editing.
std::string listfile = mf->GetCurrentSourceDirectory();
@@ -481,9 +494,13 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
std::string file = this->ConvertToRelativeForMake(
this->CurrentReRunCMakeMakefile.c_str());
cmSystemTools::ReplaceString(file, "\\ ", " ");
mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends,
cmTarget* check = mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET,
true, no_depends,
no_working_directory,
"make", "-f", file.c_str());
check->Compute();
cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
mf->AddGeneratorTarget(check, checkGt);
}
// now make the allbuild depend on all the non-utility targets
@@ -502,6 +519,11 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
{
cmTarget& target = l->second;
if (target.GetType() == cmTarget::GLOBAL_TARGET)
{
continue;
}
if (regenerate && (l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET))
{
target.AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
@@ -1356,7 +1378,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmTarget& cmtarget)
return;
}
std::string llang = cmtarget.GetLinkerLanguage("NOCONFIG");
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget);
std::string llang = gtgt->GetLinkerLanguage("NOCONFIG");
if(llang.empty()) { return; }
// If the language is compiled as a source trust Xcode to link with it.
@@ -1804,7 +1827,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
AddCompileOptions(flags, &target, lang, configName);
}
std::string llang = target.GetLinkerLanguage(configName);
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
std::string llang = gtgt->GetLinkerLanguage(configName);
if(binary && llang.empty())
{
cmSystemTools::Error
@@ -1830,7 +1854,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro);
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
std::vector<std::string> targetDefines;
target.GetCompileDefinitions(targetDefines, configName, "C");
this->AppendDefines(ppDefs, targetDefines);
@@ -1920,11 +1943,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
std::string pnprefix;
std::string pnbase;
std::string pnsuffix;
target.GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
gtgt->GetFullNameComponents(pnprefix, pnbase, pnsuffix, configName);
const char* version = target.GetProperty("VERSION");
const char* soversion = target.GetProperty("SOVERSION");
if(!target.HasSOName(configName) || target.IsFrameworkOnApple())
if(!gtgt->HasSOName(configName) || target.IsFrameworkOnApple())
{
version = 0;
soversion = 0;
@@ -2182,7 +2205,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
}
}
// Add framework search paths needed for linking.
if(cmComputeLinkInformation* cli = target.GetLinkInformation(configName))
if(cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName))
{
std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
for(std::vector<std::string>::const_iterator fdi = fwDirs.begin();
@@ -2311,7 +2334,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
if(target.GetType() == cmTarget::SHARED_LIBRARY)
{
// Get the install_name directory for the build tree.
install_name_dir = target.GetInstallNameDirForBuildTree(configName);
install_name_dir = gtgt->GetInstallNameDirForBuildTree(configName);
// Xcode doesn't create the correct install_name in some cases.
// That is, if the INSTALL_PATH is empty, or if we have versioning
// of dylib libraries, we want to specify the install_name.
@@ -2325,7 +2348,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
install_name += install_name_dir;
install_name += "/";
}
install_name += target.GetSOName(configName);
install_name += gtgt->GetSOName(configName);
if((realName != soName) || install_name_dir.empty())
{
@@ -2338,7 +2361,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->CreateString(install_name_dir.c_str()));
// Create the LD_RUNPATH_SEARCH_PATHS
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName);
if(pcli)
{
std::string search_paths;
@@ -2722,7 +2745,8 @@ cmGlobalXCodeGenerator::CreateXCodeTarget(cmTarget& cmtarget,
}
else
{
fullName = cmtarget.GetFullName(defConfig.c_str());
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&cmtarget);
fullName = gtgt->GetFullName(defConfig.c_str());
}
fileRef->AddAttribute("path", this->CreateString(fullName.c_str()));
fileRef->AddAttribute("refType", this->CreateString("0"));
@@ -2944,7 +2968,8 @@ void cmGlobalXCodeGenerator
}
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = cmtarget->GetLinkInformation(configName);
cmGeneratorTarget* gtgt = this->GetGeneratorTarget(cmtarget);
cmComputeLinkInformation* pcli = gtgt->GetLinkInformation(configName);
if(!pcli)
{
continue;
@@ -3667,7 +3692,7 @@ cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
std::string universalFile = universal;
universalFile += *arch;
universalFile += "/";
universalFile += t->GetFullName(configName);
universalFile += gt->GetFullName(configName);
makefileStream << "\t/bin/rm -f "
<<
this->ConvertToRelativeForMake(universalFile.c_str())
+1
View File
@@ -88,6 +88,7 @@ public:
virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
void AppendFlag(std::string& flags, std::string const& flag);
protected:
virtual bool Compute();
virtual void Generate();
private:
cmXCodeObject* CreateOrGetPBXGroup(cmTarget& cmtarget,
+8 -1
View File
@@ -27,7 +27,8 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
{
cmInstallGenerator::MessageLevel message =
cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
return new cmInstallTargetGenerator(target.GetName(),
args.GetDestination().c_str(),
impLib, args.GetPermissions().c_str(),
args.GetConfigurations(), args.GetComponent().c_str(),
message,
@@ -752,6 +753,12 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0;
installsResource = installsResource || resourceGenerator;
if (installsArchive || installsRuntime || installsFramework
|| installsLibrary || installsBundle)
{
target.SetHaveInstallRule(true);
}
this->Makefile->AddInstallGenerator(archiveGenerator);
this->Makefile->AddInstallGenerator(libraryGenerator);
this->Makefile->AddInstallGenerator(runtimeGenerator);
+2
View File
@@ -62,6 +62,8 @@ public:
/** Select message level from CMAKE_INSTALL_MESSAGE or 'never'. */
static MessageLevel SelectMessageLevel(cmMakefile* mf, bool never = false);
virtual void Compute(cmLocalGenerator*) {}
protected:
virtual void GenerateScript(std::ostream& os);
+52 -32
View File
@@ -16,26 +16,30 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmGeneratorTarget.h"
#include "cmake.h"
#include "cmGeneratorTarget.h"
#include <assert.h>
//----------------------------------------------------------------------------
cmInstallTargetGenerator
::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib,
::cmInstallTargetGenerator(const std::string& targetName,
const char* dest, bool implib,
const char* file_permissions,
std::vector<std::string> const& configurations,
const char* component,
MessageLevel message,
bool optional):
cmInstallGenerator(dest, configurations, component, message), Target(&t),
cmInstallGenerator(dest, configurations, component, message),
TargetName(targetName),
Target(0),
FilePermissions(file_permissions),
ImportLibrary(implib),
Optional(optional)
{
this->ActionsPerConfig = true;
this->NamelinkMode = NamelinkModeNone;
this->Target->SetHaveInstallRule(true);
}
//----------------------------------------------------------------------------
@@ -71,13 +75,15 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string fromDirConfig;
if(this->Target->NeedRelinkBeforeInstall(config))
{
fromDirConfig = this->Target->GetMakefile()->GetCurrentBinaryDirectory();
fromDirConfig =
this->Target->Target->GetMakefile()->GetCurrentBinaryDirectory();
fromDirConfig += cmake::GetCMakeFilesDirectory();
fromDirConfig += "/CMakeRelink.dir/";
}
else
{
fromDirConfig = this->Target->GetDirectory(config, this->ImportLibrary);
fromDirConfig =
this->Target->Target->GetDirectory(config, this->ImportLibrary);
fromDirConfig += "/";
}
std::string toDir =
@@ -88,7 +94,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::vector<std::string> filesFrom;
std::vector<std::string> filesTo;
std::string literal_args;
cmTarget::TargetType targetType = this->Target->GetType();
cmTarget::TargetType targetType =
static_cast<cmTarget::TargetType>(this->Target->GetType());
cmInstallType type = cmInstallType();
switch(targetType)
{
@@ -105,7 +112,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
case cmTarget::UNKNOWN_LIBRARY:
this->Target->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR,
this->Target->Target->GetMakefile()->IssueMessage(cmake::INTERNAL_ERROR,
"cmInstallTargetGenerator created with non-installable target.");
return;
}
@@ -128,7 +135,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
filesFrom.push_back(from1);
filesTo.push_back(to1);
std::string targetNameImportLib;
if(this->Target->GetImplibGNUtoMS(targetNameImport,
if(this->Target->Target->GetImplibGNUtoMS(targetNameImport,
targetNameImportLib))
{
filesFrom.push_back(fromDirConfig + targetNameImportLib);
@@ -144,7 +151,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string to1 = toDir + targetName;
// Handle OSX Bundles.
if(this->Target->IsAppBundleOnApple())
if(this->Target->Target->IsAppBundleOnApple())
{
// Install the whole app bundle directory.
type = cmInstallType_DIRECTORY;
@@ -178,7 +185,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
this->Target->GetLibraryNames(targetName, targetNameSO,
targetNameReal,
targetNameImport, targetNamePDB,
config);
if(this->ImportLibrary)
@@ -191,7 +199,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
filesFrom.push_back(from1);
filesTo.push_back(to1);
std::string targetNameImportLib;
if(this->Target->GetImplibGNUtoMS(targetNameImport,
if(this->Target->Target->GetImplibGNUtoMS(targetNameImport,
targetNameImportLib))
{
filesFrom.push_back(fromDirConfig + targetNameImportLib);
@@ -201,7 +209,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
// An import library looks like a static library.
type = cmInstallType_STATIC_LIBRARY;
}
else if(this->Target->IsFrameworkOnApple())
else if(this->Target->Target->IsFrameworkOnApple())
{
// There is a bug in cmInstallCommand if this fails.
assert(this->NamelinkMode == NamelinkModeNone);
@@ -219,7 +227,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(std::ostream& os,
filesFrom.push_back(from1);
filesTo.push_back(to1);
}
else if(this->Target->IsCFBundleOnApple())
else if(this->Target->Target->IsCFBundleOnApple())
{
// Install the whole app bundle directory.
type = cmInstallType_DIRECTORY;
@@ -343,7 +351,7 @@ cmInstallTargetGenerator::GetDestination(std::string const& config) const
{
cmGeneratorExpression ge;
return ge.Parse(this->Destination)
->Evaluate(this->Target->GetMakefile(), config);
->Evaluate(this->Target->Target->GetMakefile(), config);
}
//----------------------------------------------------------------------------
@@ -352,7 +360,7 @@ cmInstallTargetGenerator::GetInstallFilename(const std::string& config) const
{
NameType nameType = this->ImportLibrary? NameImplib : NameNormal;
return
cmInstallTargetGenerator::GetInstallFilename(this->Target, config,
cmInstallTargetGenerator::GetInstallFilename(this->Target->Target, config,
nameType);
}
@@ -364,13 +372,16 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target,
{
std::string fname;
// Compute the name of the library.
cmGeneratorTarget *gtgt = target->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(target);
if(target->GetType() == cmTarget::EXECUTABLE)
{
std::string targetName;
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
target->GetExecutableNames(targetName, targetNameReal,
gtgt->GetExecutableNames(targetName, targetNameReal,
targetNameImport, targetNamePDB,
config);
if(nameType == NameImplib)
@@ -400,7 +411,7 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target,
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
gtgt->GetLibraryNames(targetName, targetNameSO, targetNameReal,
targetNameImport, targetNamePDB, config);
if(nameType == NameImplib)
{
@@ -431,6 +442,12 @@ cmInstallTargetGenerator::GetInstallFilename(cmTarget const* target,
return fname;
}
void cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
{
this->Target = lg->GetGlobalGenerator()->GetGeneratorTarget(
lg->GetMakefile()->FindTarget(this->TargetName));
}
//----------------------------------------------------------------------------
void
cmInstallTargetGenerator
@@ -533,8 +550,8 @@ cmInstallTargetGenerator
}
// Fix the install_name settings in installed binaries.
std::string installNameTool =
this->Target->GetMakefile()->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
std::string installNameTool = this->Target->Target->GetMakefile()
->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");
if(installNameTool.empty())
{
@@ -559,11 +576,14 @@ cmInstallTargetGenerator
continue;
}
cmGeneratorTarget *gtgt = tgt->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(tgt);
// If the build tree and install tree use different path
// components of the install_name field then we need to create a
// mapping to be applied after installation.
std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
std::string for_install = tgt->GetInstallNameDirForInstallTree();
std::string for_build = gtgt->GetInstallNameDirForBuildTree(config);
std::string for_install = gtgt->GetInstallNameDirForInstallTree();
if(for_build != for_install)
{
// The directory portions differ. Append the filename to
@@ -592,7 +612,7 @@ cmInstallTargetGenerator
std::string for_install =
this->Target->GetInstallNameDirForInstallTree();
if(this->Target->IsFrameworkOnApple() && for_install.empty())
if(this->Target->Target->IsFrameworkOnApple() && for_install.empty())
{
// Frameworks seem to have an id corresponding to their own full
// path.
@@ -606,7 +626,7 @@ cmInstallTargetGenerator
{
// Prepare to refer to the install-tree install_name.
new_id = for_install;
new_id += this->GetInstallFilename(this->Target, config, NameSO);
new_id += this->GetInstallFilename(this->Target->Target, config, NameSO);
}
}
@@ -643,9 +663,9 @@ cmInstallTargetGenerator
{
return;
}
// Skip if on Apple
if(this->Target->GetMakefile()->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
if(this->Target->Target->GetMakefile()
->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
return;
}
@@ -690,7 +710,7 @@ cmInstallTargetGenerator
return;
}
cmMakefile* mf = this->Target->GetMakefile();
cmMakefile* mf = this->Target->Target->GetMakefile();
if(mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME"))
{
@@ -802,20 +822,20 @@ cmInstallTargetGenerator::AddStripRule(std::ostream& os,
}
// Don't handle OSX Bundles.
if(this->Target->GetMakefile()->IsOn("APPLE") &&
this->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
if(this->Target->Target->GetMakefile()->IsOn("APPLE") &&
this->Target->Target->GetPropertyAsBool("MACOSX_BUNDLE"))
{
return;
}
if(! this->Target->GetMakefile()->IsSet("CMAKE_STRIP"))
if(! this->Target->Target->GetMakefile()->IsSet("CMAKE_STRIP"))
{
return;
}
os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n";
os << indent << " execute_process(COMMAND \""
<< this->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
<< this->Target->Target->GetMakefile()->GetDefinition("CMAKE_STRIP")
<< "\" \"" << toDestDirPath << "\")\n";
os << indent << "endif()\n";
}
@@ -834,13 +854,13 @@ cmInstallTargetGenerator::AddRanlibRule(std::ostream& os,
// Perform post-installation processing on the file depending
// on its type.
if(!this->Target->GetMakefile()->IsOn("APPLE"))
if(!this->Target->Target->GetMakefile()->IsOn("APPLE"))
{
return;
}
std::string ranlib =
this->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
if(ranlib.empty())
{
return;
+10 -4
View File
@@ -13,7 +13,9 @@
#define cmInstallTargetGenerator_h
#include "cmInstallGenerator.h"
#include "cmTarget.h"
class cmTarget;
class cmGeneratorTarget;
/** \class cmInstallTargetGenerator
* \brief Generate target installation rules.
@@ -22,7 +24,7 @@ class cmInstallTargetGenerator: public cmInstallGenerator
{
public:
cmInstallTargetGenerator(
cmTarget& t, const char* dest, bool implib,
std::string const& targetName, const char* dest, bool implib,
const char* file_permissions,
std::vector<std::string> const& configurations,
const char* component,
@@ -56,7 +58,10 @@ public:
const std::string& config,
NameType nameType = NameNormal);
cmTarget* GetTarget() const { return this->Target; }
void Compute(cmLocalGenerator* lg);
cmGeneratorTarget* GetTarget() const { return this->Target; }
bool IsImportLibrary() const { return this->ImportLibrary; }
std::string GetDestination(std::string const& config) const;
@@ -98,7 +103,8 @@ protected:
void AddRanlibRule(std::ostream& os, Indent const& indent,
const std::string& toDestDirPath);
cmTarget* Target;
std::string TargetName;
cmGeneratorTarget* Target;
std::string FilePermissions;
NamelinkModeType NamelinkMode;
bool ImportLibrary;
+59
View File
@@ -0,0 +1,59 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2015 Kitware, Inc.
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.
============================================================================*/
#ifndef cmLinkItem_h
#define cmLinkItem_h
#include "cmListFileCache.h"
class cmTarget;
// Basic information about each link item.
class cmLinkItem: public std::string
{
typedef std::string std_string;
public:
cmLinkItem(): std_string(), Target(0) {}
cmLinkItem(const std_string& n,
cmTarget const* t): std_string(n), Target(t) {}
cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {}
cmTarget const* Target;
};
class cmLinkImplItem: public cmLinkItem
{
public:
cmLinkImplItem(): cmLinkItem(), Backtrace(), FromGenex(false) {}
cmLinkImplItem(std::string const& n,
cmTarget const* t,
cmListFileBacktrace const& bt,
bool fromGenex):
cmLinkItem(n, t), Backtrace(bt), FromGenex(fromGenex) {}
cmLinkImplItem(cmLinkImplItem const& r):
cmLinkItem(r), Backtrace(r.Backtrace), FromGenex(r.FromGenex) {}
cmListFileBacktrace Backtrace;
bool FromGenex;
};
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
struct cmLinkImplementationLibraries
{
// Libraries linked directly in this configuration.
std::vector<cmLinkImplItem> Libraries;
// Libraries linked directly in other configurations.
// Needed only for OLD behavior of CMP0003.
std::vector<cmLinkItem> WrongConfigLibraries;
};
#endif
+6
View File
@@ -155,6 +155,12 @@ public:
return iterator(this, 1);
}
void Clear()
{
this->UpPositions.clear();
this->Data.clear();
}
private:
T& GetReference(PositionType pos)
{
+64 -10
View File
@@ -16,6 +16,7 @@
#include "cmGlobalGenerator.h"
#include "cmInstallGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmMakefile.h"
@@ -212,6 +213,53 @@ void cmLocalGenerator::GenerateTestFiles()
}
}
void cmLocalGenerator::CreateEvaluationFileOutputs(std::string const& config)
{
std::vector<cmGeneratorExpressionEvaluationFile*> ef =
this->Makefile->GetEvaluationFiles();
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = ef.begin(); li != ef.end(); ++li)
{
(*li)->CreateOutputFile(this, config);
}
}
void cmLocalGenerator::ProcessEvaluationFiles(
std::vector<std::string>& generatedFiles)
{
std::vector<cmGeneratorExpressionEvaluationFile*> ef =
this->Makefile->GetEvaluationFiles();
for(std::vector<cmGeneratorExpressionEvaluationFile*>::const_iterator
li = ef.begin();
li != ef.end();
++li)
{
(*li)->Generate(this);
if (cmSystemTools::GetFatalErrorOccured())
{
return;
}
std::vector<std::string> files = (*li)->GetFiles();
std::sort(files.begin(), files.end());
std::vector<std::string> intersection;
std::set_intersection(files.begin(), files.end(),
generatedFiles.begin(), generatedFiles.end(),
std::back_inserter(intersection));
if (!intersection.empty())
{
cmSystemTools::Error("Files to be generated by multiple different "
"commands: ", cmWrap('"', intersection, '"', " ").c_str());
return;
}
generatedFiles.insert(generatedFiles.end(), files.begin(), files.end());
std::vector<std::string>::iterator newIt =
generatedFiles.end() - files.size();
std::inplace_merge(generatedFiles.begin(), newIt, generatedFiles.end());
}
}
//----------------------------------------------------------------------------
void cmLocalGenerator::GenerateInstallRules()
{
@@ -1353,7 +1401,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
linkFlags += this->Makefile->GetSafeDefinition(build);
linkFlags += " ";
}
std::string linkLanguage = target->Target->GetLinkerLanguage(buildType);
std::string linkLanguage = target->GetLinkerLanguage(buildType);
if(linkLanguage.empty())
{
cmSystemTools::Error
@@ -1468,7 +1516,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries,
bool escapeAllowMakeVars = !forResponseFile;
std::ostringstream fout;
std::string config = this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
cmComputeLinkInformation* pcli = tgt.Target->GetLinkInformation(config);
cmComputeLinkInformation* pcli = tgt.GetLinkInformation(config);
if(!pcli)
{
return;
@@ -2059,7 +2107,9 @@ void cmLocalGenerator::AddCMP0018Flags(std::string &flags,
return;
}
if (target->GetLinkInterfaceDependentBoolProperty(
cmGeneratorTarget* gtgt =
this->GlobalGenerator->GetGeneratorTarget(target);
if (gtgt->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE",
config))
{
@@ -2375,11 +2425,15 @@ cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg,
class cmInstallTargetGeneratorLocal: public cmInstallTargetGenerator
{
public:
cmInstallTargetGeneratorLocal(cmTarget& t, const char* dest, bool implib):
cmInstallTargetGeneratorLocal(cmLocalGenerator* lg, std::string const& t,
const char* dest, bool implib):
cmInstallTargetGenerator(
t, dest, implib, "", std::vector<std::string>(), "Unspecified",
cmInstallGenerator::SelectMessageLevel(t.GetMakefile()),
false) {}
cmInstallGenerator::SelectMessageLevel(lg->GetMakefile()),
false)
{
this->Compute(lg);
}
};
//----------------------------------------------------------------------------
@@ -2428,7 +2482,7 @@ cmLocalGenerator
{
// Use a target install generator.
cmInstallTargetGeneratorLocal
g(l->second, destination.c_str(), false);
g(this, l->first, destination.c_str(), false);
g.Generate(os, config, configurationTypes);
}
break;
@@ -2439,18 +2493,18 @@ cmLocalGenerator
// to the normal destination and the DLL to the runtime
// destination.
cmInstallTargetGeneratorLocal
g1(l->second, destination.c_str(), true);
g1(this, l->first, destination.c_str(), true);
g1.Generate(os, config, configurationTypes);
// We also skip over the leading slash given by the user.
destination = l->second.GetRuntimeInstallPath().substr(1);
cmSystemTools::ConvertToUnixSlashes(destination);
cmInstallTargetGeneratorLocal
g2(l->second, destination.c_str(), false);
g2(this, l->first, destination.c_str(), false);
g2.Generate(os, config, configurationTypes);
#else
// Use a target install generator.
cmInstallTargetGeneratorLocal
g(l->second, destination.c_str(), false);
g(this, l->first, destination.c_str(), false);
g.Generate(os, config, configurationTypes);
#endif
}
+2
View File
@@ -305,6 +305,8 @@ public:
void IssueMessage(cmake::MessageType t, std::string const& text) const;
void CreateEvaluationFileOutputs(const std::string& config);
void ProcessEvaluationFiles(std::vector<std::string>& generatedFiles);
void ComputeObjectMaxPath();
protected:
+6 -8
View File
@@ -90,7 +90,7 @@ void cmLocalNinjaGenerator::Generate()
// Add the target to "all" if required.
if (!this->GetGlobalNinjaGenerator()->IsExcluded(
this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0],
*t->second->Target))
t->second))
this->GetGlobalNinjaGenerator()->AddDependencyToAll(t->second->Target);
delete tg;
}
@@ -193,16 +193,14 @@ void cmLocalNinjaGenerator::WriteProjectHeader(std::ostream& os)
void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os)
{
// Default required version
// Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3
std::string requiredVersion = "1.3";
std::string requiredVersion =
this->GetGlobalNinjaGenerator()->RequiredNinjaVersion();
// Ninja generator uses the 'console' pool if available (>= 1.5)
std::string usedVersion = this->GetGlobalNinjaGenerator()->ninjaVersion();
if(cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
usedVersion.c_str(),
"1.5") == false)
if(this->GetGlobalNinjaGenerator()->SupportsConsolePool())
{
requiredVersion = "1.5";
requiredVersion =
this->GetGlobalNinjaGenerator()->RequiredNinjaVersionForConsolePool();
}
cmGlobalNinjaGenerator::WriteComment(os,
+1 -2
View File
@@ -486,8 +486,7 @@ void cmLocalUnixMakefileGenerator3
// Add a local name for the rule to relink the target before
// installation.
if(t->second->Target
->NeedRelinkBeforeInstall(this->ConfigName))
if(t->second->NeedRelinkBeforeInstall(this->ConfigName))
{
makeTargetName = this->GetRelativeTargetDirectory(*t->second->Target);
makeTargetName += "/preinstall";
+24 -19
View File
@@ -88,7 +88,8 @@ void cmLocalVisualStudio6Generator::AddCMakeListsRules()
for(cmTargets::iterator l = tgts.begin();
l != tgts.end(); l++)
{
if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY)
if (l->second.GetType() == cmTarget::INTERFACE_LIBRARY
|| l->second.GetType() == cmTarget::GLOBAL_TARGET)
{
continue;
}
@@ -1114,10 +1115,12 @@ void cmLocalVisualStudio6Generator
cmTarget* tgt = this->GlobalGenerator->FindTarget(j->first.c_str());
if(tgt)
{
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(tgt);
lib = cmSystemTools::GetFilenameWithoutExtension
(tgt->GetFullName().c_str());
(gt->GetFullName().c_str());
libDebug = cmSystemTools::GetFilenameWithoutExtension
(tgt->GetFullName("Debug").c_str());
(gt->GetFullName("Debug").c_str());
lib += ".lib";
libDebug += ".lib";
}
@@ -1257,8 +1260,8 @@ void cmLocalVisualStudio6Generator
extraLinkOptionsRelWithDebInfo += targetLinkFlags;
}
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
// Get standard libraries for this language.
if(targetBuilds)
@@ -1267,10 +1270,10 @@ void cmLocalVisualStudio6Generator
std::vector<std::string> configs;
target.GetMakefile()->GetConfigurations(configs);
std::vector<std::string>::const_iterator it = configs.begin();
const std::string& linkLanguage = target.GetLinkerLanguage(*it);
const std::string& linkLanguage = gt->GetLinkerLanguage(*it);
for ( ; it != configs.end(); ++it)
{
const std::string& configLinkLanguage = target.GetLinkerLanguage(*it);
const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it);
if (configLinkLanguage != linkLanguage)
{
cmSystemTools::Error
@@ -1327,11 +1330,11 @@ void cmLocalVisualStudio6Generator
target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY)
{
outputName = target.GetFullName();
outputNameDebug = target.GetFullName("Debug");
outputNameRelease = target.GetFullName("Release");
outputNameMinSizeRel = target.GetFullName("MinSizeRel");
outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
outputName = gt->GetFullName();
outputNameDebug = gt->GetFullName("Debug");
outputNameRelease = gt->GetFullName("Release");
outputNameMinSizeRel = gt->GetFullName("MinSizeRel");
outputNameRelWithDebInfo = gt->GetFullName("RelWithDebInfo");
}
else if(target.GetType() == cmTarget::OBJECT_LIBRARY)
{
@@ -1428,10 +1431,10 @@ void cmLocalVisualStudio6Generator
fullPathImpRelease += "/";
fullPathImpMinSizeRel += "/";
fullPathImpRelWithDebInfo += "/";
fullPathImpDebug += target.GetFullName("Debug", true);
fullPathImpRelease += target.GetFullName("Release", true);
fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true);
fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true);
fullPathImpDebug += gt->GetFullName("Debug", true);
fullPathImpRelease += gt->GetFullName("Release", true);
fullPathImpMinSizeRel += gt->GetFullName("MinSizeRel", true);
fullPathImpRelWithDebInfo += gt->GetFullName("RelWithDebInfo", true);
targetImplibFlagDebug = "/implib:";
targetImplibFlagRelease = "/implib:";
@@ -1700,10 +1703,10 @@ void cmLocalVisualStudio6Generator
std::vector<std::string> configs;
target.GetMakefile()->GetConfigurations(configs);
std::vector<std::string>::const_iterator it = configs.begin();
const std::string& linkLanguage = target.GetLinkerLanguage(*it);
const std::string& linkLanguage = gt->GetLinkerLanguage(*it);
for ( ; it != configs.end(); ++it)
{
const std::string& configLinkLanguage = target.GetLinkerLanguage(*it);
const std::string& configLinkLanguage = gt->GetLinkerLanguage(*it);
if (configLinkLanguage != linkLanguage)
{
cmSystemTools::Error
@@ -1845,8 +1848,10 @@ void cmLocalVisualStudio6Generator
const std::string extraOptions,
std::string& options)
{
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
// Compute the link information for this configuration.
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
if(!pcli)
{
return;
+20 -11
View File
@@ -108,6 +108,10 @@ void cmLocalVisualStudio7Generator::AddCMakeListsRules()
// Add the rule to targets that need it.
for(cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
{
if (l->second.GetType() == cmTarget::GLOBAL_TARGET)
{
continue;
}
if(l->first != CMAKE_CHECK_BUILD_SYSTEM_TARGET)
{
l->second.AddSource(sf->GetFullPath());
@@ -660,6 +664,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
const char* configType = "10";
const char* projectType = 0;
bool targetBuilds = true;
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
switch(target.GetType())
{
case cmTarget::OBJECT_LIBRARY:
@@ -692,7 +700,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
{
const std::string& linkLanguage = (this->FortranProject?
std::string("Fortran"):
target.GetLinkerLanguage(configName));
gt->GetLinkerLanguage(configName));
if(linkLanguage.empty())
{
cmSystemTools::Error
@@ -754,8 +762,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
std::vector<std::string> targetDefines;
target.GetCompileDefinitions(targetDefines, configName, "CXX");
targetOptions.AddDefines(targetDefines);
@@ -799,7 +805,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
if (this->FortranProject)
{
// Intel Fortran >= 15.0 uses TargetName property.
std::string targetNameFull = target.GetFullName(configName);
std::string targetNameFull = gt->GetFullName(configName);
std::string targetName =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
std::string targetExt =
@@ -877,7 +883,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
if(target.GetType() <= cmTarget::OBJECT_LIBRARY)
{
// Specify the compiler program database file if configured.
std::string pdb = target.GetCompilePDBPath(configName);
std::string pdb = gt->GetCompilePDBPath(configName);
if(!pdb.empty())
{
fout << "\t\t\t\tProgramDataBaseFileName=\""
@@ -1070,6 +1076,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
this->ConvertToOutputFormat(this->ModuleDefinitionFile, SHELL);
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
}
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
if (target.GetType() == cmTarget::SHARED_LIBRARY &&
this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS"))
{
@@ -1100,7 +1109,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
}
case cmTarget::STATIC_LIBRARY:
{
std::string targetNameFull = target.GetFullName(configName);
std::string targetNameFull = gt->GetFullName(configName);
std::string libpath = target.GetDirectory(configName);
libpath += "/";
libpath += targetNameFull;
@@ -1140,11 +1149,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
std::string targetNameFull;
std::string targetNameImport;
std::string targetNamePDB;
target.GetLibraryNames(targetName, targetNameSO, targetNameFull,
gt->GetLibraryNames(targetName, targetNameSO, targetNameFull,
targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
if(!pcli)
{
return;
@@ -1237,11 +1246,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
std::string targetNameFull;
std::string targetNameImport;
std::string targetNamePDB;
target.GetExecutableNames(targetName, targetNameFull,
gt->GetExecutableNames(targetName, targetNameFull,
targetNameImport, targetNamePDB, configName);
// Compute the link library and directory information.
cmComputeLinkInformation* pcli = target.GetLinkInformation(configName);
cmComputeLinkInformation* pcli = gt->GetLinkInformation(configName);
if(!pcli)
{
return;
@@ -1628,7 +1637,7 @@ cmLocalVisualStudio7GeneratorFCInfo
lg->GlobalGenerator->GetLanguageFromExtension
(sf.GetExtension().c_str());
const std::string& sourceLang = lg->GetSourceFileLanguage(sf);
const std::string& linkLanguage = target.GetLinkerLanguage(i->c_str());
const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str());
bool needForceLang = false;
// source file does not match its extension language
if(lang != sourceLang)
+74 -111
View File
@@ -21,6 +21,7 @@
#include "cmState.h"
#include "cmOutputConverter.h"
#include "cmFunctionBlocker.h"
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmListFileCache.h"
#include "cmCommandArgumentParserHelper.h"
#include "cmGeneratorExpression.h"
@@ -189,12 +190,12 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator)
this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)");
this->cmNamedCurly.compile("^[A-Za-z0-9/_.+-]+{");
this->StateSnapshot = this->StateSnapshot.GetState()
->CreatePolicyScopeSnapshot(this->StateSnapshot);
// Enter a policy level for this directory.
this->PushPolicy();
// Protect the directory-level policies.
this->PushPolicyBarrier();
// push empty loop block
this->PushLoopBlockBarrier();
@@ -235,12 +236,10 @@ cmMakefile::~cmMakefile()
cmDeleteAll(this->ImportedTargetsOwned);
cmDeleteAll(this->FinalPassCommands);
cmDeleteAll(this->FunctionBlockers);
cmDeleteAll(this->EvaluationFiles);
this->EvaluationFiles.clear();
this->FunctionBlockers.clear();
if (this->PolicyStack.size() != 1)
{
cmSystemTools::Error("Internal CMake Error, Policy Stack has not been"
" popped properly");
}
}
//----------------------------------------------------------------------------
@@ -468,6 +467,14 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
Makefile(mf), NoPolicyScope(noPolicyScope),
CheckCMP0011(false), ReportError(true)
{
this->Makefile->PushFunctionBlockerBarrier();
this->Makefile->StateSnapshot =
this->Makefile->GetState()->CreateCallStackSnapshot(
this->Makefile->StateSnapshot,
this->Makefile->ContextStack.back()->Name,
this->Makefile->ContextStack.back()->Line,
filenametoread);
if(!this->NoPolicyScope)
{
// Check CMP0011 to determine the policy scope type.
@@ -496,37 +503,19 @@ cmMakefile::IncludeScope::IncludeScope(cmMakefile* mf,
break;
}
}
// The included file cannot pop our policy scope.
this->Makefile->PushPolicyBarrier();
this->Makefile->PushFunctionBlockerBarrier();
this->Makefile->StateSnapshot =
this->Makefile->GetState()->CreateCallStackSnapshot(
this->Makefile->StateSnapshot,
this->Makefile->ContextStack.back()->Name,
this->Makefile->ContextStack.back()->Line,
filenametoread);
}
//----------------------------------------------------------------------------
cmMakefile::IncludeScope::~IncludeScope()
{
this->Makefile->StateSnapshot =
this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot);
assert(this->Makefile->StateSnapshot.IsValid());
this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
// Enforce matching policy scopes inside the included file.
this->Makefile->PopPolicyBarrier(this->ReportError);
if(!this->NoPolicyScope)
{
// If we need to enforce policy CMP0011 then the top entry is the
// one we pushed above. If the entry is empty, then the included
// script did not set any policies that might affect the includer so
// we do not need to enforce the policy.
if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty())
if(this->CheckCMP0011
&& !this->Makefile->StateSnapshot.HasDefinedPolicyCMP0011())
{
this->CheckCMP0011 = false;
}
@@ -541,6 +530,9 @@ cmMakefile::IncludeScope::~IncludeScope()
this->EnforceCMP0011();
}
}
this->Makefile->PopPolicyBarrier(this->ReportError);
this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
}
//----------------------------------------------------------------------------
@@ -635,8 +627,6 @@ public:
ListFileScope(cmMakefile* mf, std::string const& filenametoread)
: Makefile(mf), ReportError(true)
{
this->Makefile->PushPolicyBarrier();
long line = 0;
std::string name;
if (!this->Makefile->ContextStack.empty())
@@ -648,17 +638,14 @@ public:
this->Makefile->GetState()->CreateInlineListFileSnapshot(
this->Makefile->StateSnapshot, name, line, filenametoread);
assert(this->Makefile->StateSnapshot.IsValid());
this->Makefile->PushFunctionBlockerBarrier();
}
~ListFileScope()
{
this->Makefile->StateSnapshot =
this->Makefile->GetState()->Pop(this->Makefile->StateSnapshot);
assert(this->Makefile->StateSnapshot.IsValid());
this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
this->Makefile->PopPolicyBarrier(this->ReportError);
this->Makefile->PopFunctionBlockerBarrier(this->ReportError);
}
void Quiet() { this->ReportError = false; }
@@ -777,6 +764,23 @@ void cmMakefile::EnforceDirectoryLevelRules() const
}
}
void cmMakefile::AddEvaluationFile(const std::string& inputFile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent)
{
this->EvaluationFiles.push_back(
new cmGeneratorExpressionEvaluationFile(inputFile, outputName,
condition,
inputIsContent));
}
std::vector<cmGeneratorExpressionEvaluationFile*>
cmMakefile::GetEvaluationFiles() const
{
return this->EvaluationFiles;
}
namespace
{
struct file_not_persistent
@@ -1205,15 +1209,16 @@ cmMakefile::AddCustomCommandOldStyle(const std::string& target,
}
//----------------------------------------------------------------------------
void cmMakefile::AddUtilityCommand(const std::string& utilityName,
bool excludeFromAll,
const std::vector<std::string>& depends,
const char* workingDirectory,
const char* command,
const char* arg1,
const char* arg2,
const char* arg3,
const char* arg4)
cmTarget*
cmMakefile::AddUtilityCommand(const std::string& utilityName,
bool excludeFromAll,
const std::vector<std::string>& depends,
const char* workingDirectory,
const char* command,
const char* arg1,
const char* arg2,
const char* arg3,
const char* arg4)
{
// Construct the command line for the custom command.
cmCustomCommandLine commandLine;
@@ -1238,8 +1243,8 @@ void cmMakefile::AddUtilityCommand(const std::string& utilityName,
commandLines.push_back(commandLine);
// Call the real signature of this method.
this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
depends, commandLines);
return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
depends, commandLines);
}
//----------------------------------------------------------------------------
@@ -1640,16 +1645,13 @@ void cmMakefile::PushFunctionScope(std::string const& fileName,
this->PushFunctionBlockerBarrier();
this->PushPolicy(true, pm);
this->PushPolicyBarrier();
}
void cmMakefile::PopFunctionScope(bool reportError)
{
this->PopPolicyBarrier(reportError);
this->PopPolicy();
this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
assert(this->StateSnapshot.IsValid());
this->PopPolicyBarrier(reportError);
this->PopFunctionBlockerBarrier(reportError);
@@ -1677,16 +1679,12 @@ void cmMakefile::PushMacroScope(std::string const& fileName,
this->PushFunctionBlockerBarrier();
this->PushPolicy(true, pm);
this->PushPolicyBarrier();
}
void cmMakefile::PopMacroScope(bool reportError)
{
this->PopPolicyBarrier(reportError);
this->PopPolicy();
this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
assert(this->StateSnapshot.IsValid());
this->PopPolicyBarrier(reportError);
this->PopFunctionBlockerBarrier(reportError);
}
@@ -1706,7 +1704,8 @@ public:
this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource();
currentStart += "/CMakeLists.txt";
this->Makefile->StateSnapshot.SetListFile(currentStart);
this->Makefile->PushPolicyBarrier();
this->Makefile->StateSnapshot = this->Makefile->StateSnapshot.GetState()
->CreatePolicyScopeSnapshot(this->Makefile->StateSnapshot);
this->Makefile->PushFunctionBlockerBarrier();
this->GG = mf->GetGlobalGenerator();
@@ -1795,8 +1794,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile *mf)
cmSystemTools::Message(msg.c_str());
}
currentStart += "/CMakeLists.txt";
if(!cmSystemTools::FileExists(currentStart.c_str(), true))
std::string const currentStartFile = currentStart + "/CMakeLists.txt";
if (!cmSystemTools::FileExists(currentStartFile, true))
{
// The file is missing. Check policy CMP0014.
std::ostringstream e;
@@ -1858,6 +1857,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
// create a new local generator and set its parent
cmLocalGenerator *lg2 = this->GetGlobalGenerator()
->MakeLocalGenerator(newSnapshot, this->LocalGenerator);
this->GetGlobalGenerator()->AddMakefile(lg2->GetMakefile());
this->GetGlobalGenerator()->AddLocalGenerator(lg2);
cmMakefile* subMf = lg2->GetMakefile();
@@ -1905,6 +1905,12 @@ const char* cmMakefile::GetCurrentBinaryDirectory() const
return this->StateSnapshot.GetDirectory().GetCurrentBinary();
}
void cmMakefile::AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt)
{
this->GeneratorTargets[t] = gt;
this->GetGlobalGenerator()->AddGeneratorTarget(t, gt);
}
//----------------------------------------------------------------------------
void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs,
bool before)
@@ -4747,30 +4753,7 @@ const char* cmMakefile::GetDefineFlagsCMP0059() const
cmPolicies::PolicyStatus
cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const
{
cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
if(status == cmPolicies::REQUIRED_ALWAYS ||
status == cmPolicies::REQUIRED_IF_USED)
{
return status;
}
cmLocalGenerator* lg = this->LocalGenerator;
while(lg)
{
cmMakefile const* mf = lg->GetMakefile();
for(PolicyStackType::const_reverse_iterator psi =
mf->PolicyStack.rbegin(); psi != mf->PolicyStack.rend(); ++psi)
{
if(psi->IsDefined(id))
{
status = psi->Get(id);
return status;
}
}
lg = lg->GetParent();
}
return status;
return this->StateSnapshot.GetPolicy(id);
}
//----------------------------------------------------------------------------
@@ -4819,15 +4802,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
return false;
}
// Update the policy stack from the top to the top-most strong entry.
bool previous_was_weak = true;
for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin();
previous_was_weak && psi != this->PolicyStack.rend(); ++psi)
{
psi->Set(id, status);
previous_was_weak = psi->Weak;
}
this->StateSnapshot.SetPolicy(id, status);
return true;
}
@@ -4836,50 +4811,38 @@ cmMakefile::PolicyPushPop::PolicyPushPop(cmMakefile* m, bool weak,
cmPolicies::PolicyMap const& pm):
Makefile(m), ReportError(true)
{
this->Makefile->StateSnapshot = this->Makefile->StateSnapshot.GetState()
->CreatePolicyScopeSnapshot(this->Makefile->StateSnapshot);
this->Makefile->PushPolicy(weak, pm);
this->Makefile->PushPolicyBarrier();
}
//----------------------------------------------------------------------------
cmMakefile::PolicyPushPop::~PolicyPushPop()
{
this->Makefile->PopPolicyBarrier(this->ReportError);
this->Makefile->PopPolicy();
this->Makefile->PopPolicyBarrier(this->ReportError);
}
//----------------------------------------------------------------------------
void cmMakefile::PushPolicy(bool weak, cmPolicies::PolicyMap const& pm)
{
// Allocate a new stack entry.
this->PolicyStack.push_back(PolicyStackEntry(pm, weak));
this->StateSnapshot.PushPolicy(pm, weak);
}
//----------------------------------------------------------------------------
void cmMakefile::PopPolicy()
{
if(this->PolicyStack.size() > this->PolicyBarriers.back())
{
this->PolicyStack.pop_back();
}
else
if (!this->StateSnapshot.PopPolicy())
{
this->IssueMessage(cmake::FATAL_ERROR,
"cmake_policy POP without matching PUSH");
}
}
//----------------------------------------------------------------------------
void cmMakefile::PushPolicyBarrier()
{
this->PolicyBarriers.push_back(this->PolicyStack.size());
}
//----------------------------------------------------------------------------
void cmMakefile::PopPolicyBarrier(bool reportError)
{
// Remove any extra entries pushed on the barrier.
PolicyStackType::size_type barrier = this->PolicyBarriers.back();
while(this->PolicyStack.size() > barrier)
while (!this->StateSnapshot.CanPopPolicyScope())
{
if(reportError)
{
@@ -4890,8 +4853,8 @@ void cmMakefile::PopPolicyBarrier(bool reportError)
this->PopPolicy();
}
// Remove the barrier.
this->PolicyBarriers.pop_back();
this->StateSnapshot = this->GetState()->Pop(this->StateSnapshot);
assert(this->StateSnapshot.IsValid());
}
//----------------------------------------------------------------------------
+19 -29
View File
@@ -52,6 +52,7 @@ class cmVariableWatch;
class cmake;
class cmMakefileCall;
class cmCMakePolicyCommand;
class cmGeneratorExpressionEvaluationFile;
/** \class cmMakefile
* \brief Process the input CMakeLists.txt file.
@@ -113,10 +114,6 @@ public:
bool GetIsSourceFileTryCompile() const;
///! Get the current makefile generator.
cmLocalGenerator* GetLocalGenerator() const
{ return this->LocalGenerator;}
/**
* Help enforce global target name uniqueness.
*/
@@ -194,14 +191,15 @@ public:
* Add a utility to the build. A utiltity target is a command that
* is run every time the target is built.
*/
void AddUtilityCommand(const std::string& utilityName, bool excludeFromAll,
const std::vector<std::string>& depends,
const char* workingDirectory,
const char* command,
const char* arg1=0,
const char* arg2=0,
const char* arg3=0,
const char* arg4=0);
cmTarget* AddUtilityCommand(const std::string& utilityName,
bool excludeFromAll,
const std::vector<std::string>& depends,
const char* workingDirectory,
const char* command,
const char* arg1=0,
const char* arg2=0,
const char* arg3=0,
const char* arg4=0);
cmTarget* AddUtilityCommand(const std::string& utilityName,
bool excludeFromAll,
const char* workingDirectory,
@@ -416,10 +414,7 @@ public:
{
this->GeneratorTargets = targets;
}
void AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt)
{
this->GeneratorTargets[t] = gt;
}
void AddGeneratorTarget(cmTarget* t, cmGeneratorTarget* gt);
cmTarget* FindTarget(const std::string& name,
bool excludeAliases = false) const;
@@ -801,6 +796,12 @@ public:
void EnforceDirectoryLevelRules() const;
void AddEvaluationFile(const std::string &inputFile,
cmsys::auto_ptr<cmCompiledGeneratorExpression> outputName,
cmsys::auto_ptr<cmCompiledGeneratorExpression> condition,
bool inputIsContent);
std::vector<cmGeneratorExpressionEvaluationFile*> GetEvaluationFiles() const;
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const std::string& name, cmTarget& target);
@@ -897,6 +898,8 @@ private:
std::vector<cmMakefile*> UnConfiguredDirectories;
std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles;
cmPropertyMap Properties;
std::vector<cmCommandContext const*> ContextStack;
@@ -911,7 +914,6 @@ private:
void PushPolicy(bool weak = false,
cmPolicies::PolicyMap const& pm = cmPolicies::PolicyMap());
void PopPolicy();
void PushPolicyBarrier();
void PopPolicyBarrier(bool reportError = true);
friend class cmCMakePolicyCommand;
class IncludeScope;
@@ -921,18 +923,6 @@ private:
class BuildsystemFileScope;
friend class BuildsystemFileScope;
// stack of policy settings
struct PolicyStackEntry: public cmPolicies::PolicyMap
{
typedef cmPolicies::PolicyMap derived;
PolicyStackEntry(bool w = false): derived(), Weak(w) {}
PolicyStackEntry(derived const& d, bool w = false): derived(d), Weak(w) {}
PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {}
bool Weak;
};
typedef std::vector<PolicyStackEntry> PolicyStackType;
PolicyStackType PolicyStack;
std::vector<PolicyStackType::size_type> PolicyBarriers;
// CMP0053 == old
cmake::MessageType ExpandVariablesInStringOld(
@@ -25,7 +25,7 @@ cmMakefileExecutableTargetGenerator
cmMakefileTargetGenerator(target)
{
this->CustomCommandDriver = OnDepends;
this->Target->GetExecutableNames(
this->GeneratorTarget->GetExecutableNames(
this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
this->TargetNamePDB, this->ConfigName);
@@ -58,7 +58,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
// write the link rules
this->WriteExecutableRule(false);
if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName))
{
// Write rules to link an installable version of the target.
this->WriteExecutableRule(true);
@@ -94,7 +94,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetExecutableNames
this->GeneratorTarget->GetExecutableNames
(targetName, targetNameReal, targetNameImport, targetNamePDB,
this->ConfigName);
@@ -130,7 +130,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
}
std::string compilePdbOutputPath =
this->Target->GetCompilePDBDirectory(this->ConfigName);
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName);
@@ -161,7 +161,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Get the language to use for linking this executable.
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
// Make sure we have a link language.
if(linkLanguage.empty())
+12 -12
View File
@@ -28,7 +28,7 @@ cmMakefileLibraryTargetGenerator
this->CustomCommandDriver = OnDepends;
if (this->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{
this->Target->GetLibraryNames(
this->GeneratorTarget->GetLibraryNames(
this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
}
@@ -69,7 +69,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
break;
case cmTarget::SHARED_LIBRARY:
this->WriteSharedLibraryRules(false);
if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName))
{
// Write rules to link an installable version of the target.
this->WriteSharedLibraryRules(true);
@@ -77,7 +77,7 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
break;
case cmTarget::MODULE_LIBRARY:
this->WriteModuleLibraryRules(false);
if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
if(this->GeneratorTarget->NeedRelinkBeforeInstall(this->ConfigName))
{
// Write rules to link an installable version of the target.
this->WriteModuleLibraryRules(true);
@@ -133,7 +133,7 @@ void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
{
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_STATIC_LIBRARY";
@@ -159,7 +159,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
return;
}
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_SHARED_LIBRARY";
@@ -183,7 +183,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_SHARED_MODULE";
@@ -206,7 +206,7 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
{
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
std::string linkRuleVar = "CMAKE_";
linkRuleVar += linkLanguage;
linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
@@ -238,7 +238,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
// Get the language to use for linking this library.
std::string linkLanguage =
this->Target->GetLinkerLanguage(this->ConfigName);
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
// Make sure we have a link language.
if(linkLanguage.empty())
@@ -266,7 +266,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
std::string targetNameReal;
std::string targetNameImport;
std::string targetNamePDB;
this->Target->GetLibraryNames(
this->GeneratorTarget->GetLibraryNames(
targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
this->ConfigName);
@@ -311,7 +311,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
std::string compilePdbOutputPath =
this->Target->GetCompilePDBDirectory(this->ConfigName);
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
std::string pdbOutputPath = this->Target->GetPDBDirectory(this->ConfigName);
@@ -653,7 +653,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
vars.Target = target.c_str();
vars.LinkLibraries = linkLibs.c_str();
vars.ObjectsQuoted = buildObjs.c_str();
if (this->Target->HasSOName(this->ConfigName))
if (this->GeneratorTarget->HasSOName(this->ConfigName))
{
vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
vars.TargetSOName= targetNameSO.c_str();
@@ -666,7 +666,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
{
// Get the install_name directory for the build tree.
install_name_dir =
this->Target->GetInstallNameDirForBuildTree(this->ConfigName);
this->GeneratorTarget->GetInstallNameDirForBuildTree(this->ConfigName);
// Set the rule variable replacement value.
if(install_name_dir.empty())
+20 -43
View File
@@ -33,7 +33,7 @@
#include <ctype.h>
cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target)
: cmCommonTargetGenerator(cmOutputConverter::START_OUTPUT, target)
, OSXBundleGenerator(0)
, MacOSXContentGenerator(0)
{
@@ -313,7 +313,7 @@ cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
(cmSourceFile const& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
if(!this->Generator->GetTarget()->IsBundleOnApple())
if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple())
{
return;
}
@@ -414,7 +414,6 @@ void cmMakefileTargetGenerator
// we compute some depends when writing the depend.make that we will also
// use in the build.make, same with depMakeFile
std::vector<std::string> depends;
std::string depMakeFile;
// generate the build rule file
this->WriteObjectBuildFile(obj, lang, source, depends);
@@ -549,12 +548,12 @@ cmMakefileTargetGenerator
this->GeneratorTarget->GetFullPath(this->ConfigName, false, true);
targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
targetFullPathPDB += "/";
targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName);
}
if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
{
targetFullPathCompilePDB =
this->Target->GetCompilePDBPath(this->ConfigName);
this->GeneratorTarget->GetCompilePDBPath(this->ConfigName);
if(targetFullPathCompilePDB.empty())
{
targetFullPathCompilePDB = this->Target->GetSupportDirectory() + "/";
@@ -1059,46 +1058,21 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "\n"
<< "# Targets to which this target links.\n"
<< "set(CMAKE_TARGET_LINKED_INFO_FILES\n";
std::set<cmTarget const*> emitted;
const char* cfg = this->LocalGenerator->GetConfigName().c_str();
if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
std::vector<std::string> dirs = this->GetLinkedTargetDirectories();
for (std::vector<std::string>::iterator i = dirs.begin();
i != dirs.end(); ++i)
{
cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator
i = items.begin(); i != items.end(); ++i)
{
cmTarget const* linkee = i->Target;
if(linkee && !linkee->IsImported()
// We can ignore the INTERFACE_LIBRARY items because
// Target->GetLinkInformation already processed their
// link interface and they don't have any output themselves.
&& linkee->GetType() != cmTarget::INTERFACE_LIBRARY
&& emitted.insert(linkee).second)
{
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(linkee);
cmLocalGenerator* lg = gt->GetLocalGenerator();
cmMakefile* mf = linkee->GetMakefile();
std::string di = mf->GetCurrentBinaryDirectory();
di += "/";
di += lg->GetTargetDirectory(*linkee);
di += "/DependInfo.cmake";
*this->InfoFileStream << " \"" << di << "\"\n";
}
}
*this->InfoFileStream << " \"" << *i << "/DependInfo.cmake\"\n";
}
*this->InfoFileStream
<< " )\n";
}
// Check for a target-specific module output directory.
if(const char* mdir = this->GetFortranModuleDirectory())
{
*this->InfoFileStream
<< "\n"
<< "# Fortran module output directory.\n"
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
}
*this->InfoFileStream
<< "\n"
<< "# Fortran module output directory.\n"
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \""
<< this->GetFortranModuleDirectory() << "\")\n";
// and now write the rule to use it
std::vector<std::string> depends;
@@ -1472,7 +1446,8 @@ void cmMakefileTargetGenerator
// Loop over all library dependencies.
const char* cfg = this->LocalGenerator->GetConfigName().c_str();
if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
if(cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(cfg))
{
std::vector<std::string> const& libDeps = cli->GetDepends();
depends.insert(depends.end(), libDeps.begin(), libDeps.end());
@@ -1534,7 +1509,7 @@ std::string cmMakefileTargetGenerator::GetLinkRule(
if(this->Target->HasImplibGNUtoMS())
{
std::string ruleVar = "CMAKE_";
ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
ruleVar += "_GNUtoMS_RULE";
if(const char* rule = this->Makefile->GetDefinition(ruleVar))
{
@@ -1688,7 +1663,8 @@ cmMakefileTargetGenerator
{
// Lookup the response file reference flag.
std::string responseFlagVar = "CMAKE_";
responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
responseFlagVar += this->GeneratorTarget
->GetLinkerLanguage(this->ConfigName);
responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
const char* responseFlag =
this->Makefile->GetDefinition(responseFlagVar);
@@ -1732,7 +1708,8 @@ cmMakefileTargetGenerator
// Lookup the response file reference flag.
std::string responseFlagVar = "CMAKE_";
responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
responseFlagVar += this->GeneratorTarget
->GetLinkerLanguage(this->ConfigName);
responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
const char* responseFlag =
this->Makefile->GetDefinition(responseFlagVar);
+1
View File
@@ -53,6 +53,7 @@ public:
{ return this->ProgressFileNameFull; }
cmTarget* GetTarget() { return this->Target;}
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget;}
protected:
+10 -9
View File
@@ -40,16 +40,15 @@ cmNinjaNormalTargetGenerator(cmGeneratorTarget* target)
, TargetNamePDB()
, TargetLinkLanguage("")
{
this->TargetLinkLanguage = target->Target
->GetLinkerLanguage(this->GetConfigName());
this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
if (target->GetType() == cmTarget::EXECUTABLE)
target->Target->GetExecutableNames(this->TargetNameOut,
this->GetGeneratorTarget()->GetExecutableNames(this->TargetNameOut,
this->TargetNameReal,
this->TargetNameImport,
this->TargetNamePDB,
GetLocalGenerator()->GetConfigName());
else
target->Target->GetLibraryNames(this->TargetNameOut,
this->GetGeneratorTarget()->GetLibraryNames(this->TargetNameOut,
this->TargetNameSO,
this->TargetNameReal,
this->TargetNameImport,
@@ -531,13 +530,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
vars["LANGUAGE_COMPILE_FLAGS"] = t;
}
if (target.HasSOName(cfgName))
if (this->GetGeneratorTarget()->HasSOName(cfgName))
{
vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
vars["SONAME"] = this->TargetNameSO;
if (targetType == cmTarget::SHARED_LIBRARY)
{
std::string install_dir = target.GetInstallNameDirForBuildTree(cfgName);
std::string install_dir =
this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
if (!install_dir.empty())
{
vars["INSTALLNAME_DIR"] = localGen.Convert(install_dir,
@@ -547,6 +547,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
}
}
cmNinjaDeps byproducts;
if (!this->TargetNameImport.empty())
{
const std::string impLibPath = localGen.ConvertToOutputFormat(
@@ -556,7 +558,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
EnsureParentDirectoryExists(impLibPath);
if(target.HasImportLibrary())
{
outputs.push_back(targetOutputImplib);
byproducts.push_back(targetOutputImplib);
}
}
@@ -567,7 +569,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string prefix;
std::string base;
std::string suffix;
target.GetFullNameComponents(prefix, base, suffix);
this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix);
std::string dbg_suffix = ".dbg";
// TODO: Where to document?
if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX"))
@@ -602,7 +604,6 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
&postBuildCmdLines
};
cmNinjaDeps byproducts;
for (unsigned i = 0; i != 3; ++i)
{
for (std::vector<cmCustomCommand>::const_iterator
+15 -5
View File
@@ -58,7 +58,7 @@ cmNinjaTargetGenerator::New(cmGeneratorTarget* target)
}
cmNinjaTargetGenerator::cmNinjaTargetGenerator(cmGeneratorTarget* target)
: cmCommonTargetGenerator(target),
: cmCommonTargetGenerator(cmOutputConverter::HOME_OUTPUT, target),
MacOSXContentGenerator(0),
OSXBundleGenerator(0),
MacContentFolders(),
@@ -195,7 +195,7 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
return cmNinjaDeps();
cmComputeLinkInformation* cli =
this->Target->GetLinkInformation(this->GetConfigName());
this->GeneratorTarget->GetLinkInformation(this->GetConfigName());
if(!cli)
return cmNinjaDeps();
@@ -209,6 +209,15 @@ cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
result.push_back(this->ConvertToNinjaPath(this->ModuleDefinitionFile));
}
// Add user-specified dependencies.
if (const char* linkDepends = this->Target->GetProperty("LINK_DEPENDS"))
{
std::vector<std::string> linkDeps;
cmSystemTools::ExpandListArgument(linkDepends, linkDeps);
std::transform(linkDeps.begin(), linkDeps.end(),
std::back_inserter(result), MapToNinjaPath());
}
return result;
}
@@ -273,11 +282,12 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
{
pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
pdbPath += "/";
pdbPath += this->Target->GetPDBName(this->GetConfigName());
pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName());
}
if(this->Target->GetType() <= cmTarget::OBJECT_LIBRARY)
{
compilePdbPath = this->Target->GetCompilePDBPath(this->GetConfigName());
compilePdbPath =
this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName());
if(compilePdbPath.empty())
{
compilePdbPath = this->Target->GetSupportDirectory() + "/";
@@ -741,7 +751,7 @@ cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
cmSourceFile const& source, const char* pkgloc)
{
// Skip OS X content when not building a Framework or Bundle.
if(!this->Generator->GetTarget()->IsBundleOnApple())
if(!this->Generator->GetGeneratorTarget()->IsBundleOnApple())
{
return;
}
+7 -7
View File
@@ -47,7 +47,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
// Compute bundle directory names.
std::string out = outpath;
out += "/";
out += this->GT->Target->GetAppBundleDirectory(this->ConfigName, false);
out += this->GT->GetAppBundleDirectory(this->ConfigName, false);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
@@ -57,7 +57,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
// to be set.
std::string plist = outpath;
plist += "/";
plist += this->GT->Target->GetAppBundleDirectory(this->ConfigName, true);
plist += this->GT->GetAppBundleDirectory(this->ConfigName, true);
plist += "/Info.plist";
this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target,
targetName,
@@ -77,11 +77,11 @@ void cmOSXBundleGenerator::CreateFramework(
// Compute the location of the top-level foo.framework directory.
std::string contentdir = outpath + "/" +
this->GT->Target->GetFrameworkDirectory(this->ConfigName, true);
this->GT->GetFrameworkDirectory(this->ConfigName, true);
contentdir += "/";
std::string newoutpath = outpath + "/" +
this->GT->Target->GetFrameworkDirectory(this->ConfigName, false);
this->GT->GetFrameworkDirectory(this->ConfigName, false);
std::string frameworkVersion = this->GT->Target->GetFrameworkVersion();
@@ -172,14 +172,14 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
// Compute bundle directory names.
std::string out = root;
out += "/";
out += this->GT->Target->GetCFBundleDirectory(this->ConfigName, false);
out += this->GT->GetCFBundleDirectory(this->ConfigName, false);
cmSystemTools::MakeDirectory(out.c_str());
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
// to be set.
std::string plist = root + "/" +
this->GT->Target->GetCFBundleDirectory(this->ConfigName, true);
this->GT->GetCFBundleDirectory(this->ConfigName, true);
plist += "/Info.plist";
std::string name = cmSystemTools::GetFilenameName(targetName);
this->LocalGenerator->GenerateAppleInfoPList(this->GT->Target,
@@ -217,7 +217,7 @@ cmOSXBundleGenerator::InitMacOSXContentDirectory(const char* pkgloc)
// Construct the full path to the content subdirectory.
std::string macdir =
this->GT->Target->GetMacContentDirectory(this->ConfigName,
this->GT->GetMacContentDirectory(this->ConfigName,
/*implib*/ false);
macdir += "/";
macdir += pkgloc;
+5 -3
View File
@@ -280,7 +280,7 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
//----------------------------------------------------------------------------
cmOrderDirectories::cmOrderDirectories(cmGlobalGenerator* gg,
cmTarget const* target,
const cmGeneratorTarget* target,
const char* purpose)
{
this->GlobalGenerator = gg;
@@ -554,7 +554,8 @@ void cmOrderDirectories::FindImplicitConflicts()
<< text
<< "Some of these libraries may not be found correctly.";
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::WARNING, w.str(), this->Target->GetBacktrace());
->IssueMessage(cmake::WARNING, w.str(),
this->Target->Target->GetBacktrace());
}
//----------------------------------------------------------------------------
@@ -635,5 +636,6 @@ void cmOrderDirectories::DiagnoseCycle()
}
e << "Some of these libraries may not be found correctly.";
this->GlobalGenerator->GetCMakeInstance()
->IssueMessage(cmake::WARNING, e.str(), this->Target->GetBacktrace());
->IssueMessage(cmake::WARNING, e.str(),
this->Target->Target->GetBacktrace());
}
+3 -3
View File
@@ -19,7 +19,7 @@
class cmGlobalGenerator;
class cmOrderDirectoriesConstraint;
class cmOrderDirectoriesConstraintLibrary;
class cmTarget;
class cmGeneratorTarget;
/** \class cmOrderDirectories
* \brief Compute a safe runtime path order for a set of shared libraries.
@@ -27,7 +27,7 @@ class cmTarget;
class cmOrderDirectories
{
public:
cmOrderDirectories(cmGlobalGenerator* gg, cmTarget const* target,
cmOrderDirectories(cmGlobalGenerator* gg, cmGeneratorTarget const* target,
const char* purpose);
~cmOrderDirectories();
void AddRuntimeLibrary(std::string const& fullPath, const char* soname = 0);
@@ -41,7 +41,7 @@ public:
std::vector<std::string> const& GetOrderedDirectories();
private:
cmGlobalGenerator* GlobalGenerator;
cmTarget const* Target;
cmGeneratorTarget const* Target;
std::string Purpose;
std::vector<std::string> OrderedDirectories;
+3
View File
@@ -217,6 +217,9 @@ class cmPolicy;
3, 3, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0063, \
"Honor visibility properties for all target types.", \
3, 3, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0064, \
"Support new TEST if() operator.", \
3, 3, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
+16 -7
View File
@@ -369,7 +369,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg,
#if defined(_WIN32) && !defined(__CYGWIN__)
bool usePRE_BUILD = false;
cmGlobalGenerator* gg = makefile->GetGlobalGenerator();
cmGlobalGenerator* gg = lg->GetGlobalGenerator();
if(gg->GetName().find("Visual Studio") != std::string::npos)
{
cmGlobalVisualStudioGenerator* vsgg =
@@ -396,7 +396,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg,
std::vector<std::string> rcc_output;
bool const isNinja =
makefile->GetGlobalGenerator()->GetName() == "Ninja";
lg->GetGlobalGenerator()->GetName() == "Ninja";
if(isNinja
#if defined(_WIN32) && !defined(__CYGWIN__)
|| usePRE_BUILD
@@ -475,8 +475,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmLocalGenerator* lg,
/*byproducts=*/rcc_output, depends,
commandLines, false, autogenComment.c_str());
autogenTarget->Compute();
cmGeneratorTarget* gt = new cmGeneratorTarget(autogenTarget, lg);
lg->GetGlobalGenerator()->AddGeneratorTarget(autogenTarget, gt);
makefile->AddGeneratorTarget(autogenTarget, gt);
// Set target folder
@@ -548,8 +549,11 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
{
qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
}
cmGeneratorTarget *gtgt = target->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(target);
if (const char *targetQtVersion =
target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
{
qtVersion = targetQtVersion;
}
@@ -879,8 +883,11 @@ void cmQtAutoGenerators::MergeUicOptions(std::vector<std::string> &opts,
static void GetUicOpts(cmTarget const* target, const std::string& config,
std::string &optString)
{
cmGeneratorTarget *gtgt = target->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(target);
std::vector<std::string> opts;
target->GetAutoUicOptions(opts, config);
gtgt->GetAutoUicOptions(opts, config);
optString = cmJoin(opts, ";");
}
@@ -1148,6 +1155,9 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target)
{
cmGeneratorTarget *gtgt = target->GetMakefile()
->GetGlobalGenerator()
->GetGeneratorTarget(target);
cmMakefile *makefile = target->GetMakefile();
const char *qtVersion = makefile->GetDefinition("_target_qt_version");
if (!qtVersion)
@@ -1158,8 +1168,7 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target)
qtVersion = makefile->GetDefinition("QT_VERSION_MAJOR");
}
if (const char *targetQtVersion =
target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION",
""))
gtgt->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""))
{
qtVersion = targetQtVersion;
}
-3
View File
@@ -54,9 +54,6 @@ public:
void Generate(std::ostream& os, const std::string& config,
std::vector<std::string> const& configurationTypes);
const std::vector<std::string>& GetConfigurations() const
{ return this->Configurations; }
protected:
typedef cmScriptGeneratorIndent Indent;
virtual void GenerateScript(std::ostream& os);
+2 -8
View File
@@ -205,14 +205,8 @@ bool cmSetPropertyCommand::HandleDirectoryMode()
// The local generators are associated with collapsed paths.
dir = cmSystemTools::CollapseFullPath(dir);
// Lookup the generator.
if(cmLocalGenerator* lg =
this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir))
{
// Use the makefile for the directory found.
mf = lg->GetMakefile();
}
else
mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
if (!mf)
{
// Could not find the directory.
this->SetError
+156 -15
View File
@@ -20,8 +20,10 @@
struct cmState::SnapshotDataType
{
cmState::PositionType CallStackParent;
cmState::PositionType DirectoryParent;
cmLinkedTree<cmState::PolicyStackEntry>::iterator Policies;
cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyRoot;
cmLinkedTree<cmState::PolicyStackEntry>::iterator PolicyScope;
cmState::SnapshotType SnapshotType;
cmLinkedTree<std::string>::iterator ExecutionListFile;
cmLinkedTree<cmState::BuildsystemDirectoryStateType>::iterator
@@ -33,8 +35,19 @@ struct cmState::SnapshotDataType
std::vector<std::string>::size_type CompileOptionsPosition;
};
struct cmState::PolicyStackEntry: public cmPolicies::PolicyMap
{
typedef cmPolicies::PolicyMap derived;
PolicyStackEntry(bool w = false): derived(), Weak(w) {}
PolicyStackEntry(derived const& d, bool w): derived(d), Weak(w) {}
PolicyStackEntry(PolicyStackEntry const& r): derived(r), Weak(r.Weak) {}
bool Weak;
};
struct cmState::BuildsystemDirectoryStateType
{
cmState::PositionType DirectoryEnd;
std::string Location;
std::string OutputLocation;
@@ -240,6 +253,9 @@ cmState::Snapshot cmState::Reset()
this->GlobalProperties.clear();
this->PropertyDefinitions.clear();
PositionType pos = this->SnapshotData.Truncate();
this->ExecutionListFiles.Truncate();
{
cmLinkedTree<BuildsystemDirectoryStateType>::iterator it =
this->BuildsystemDirectory.Truncate();
@@ -249,9 +265,15 @@ cmState::Snapshot cmState::Reset()
it->CompileDefinitionsBacktraces.clear();
it->CompileOptions.clear();
it->CompileOptionsBacktraces.clear();
it->DirectoryEnd = pos;
}
PositionType pos = this->SnapshotData.Truncate();
this->ExecutionListFiles.Truncate();
this->PolicyStack.Clear();
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
pos->PolicyScope = this->PolicyStack.Root();
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
this->DefineProperty
("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY,
@@ -722,6 +744,12 @@ cmState::Snapshot cmState::CreateBaseSnapshot()
pos->IncludeDirectoryPosition = 0;
pos->CompileDefinitionsPosition = 0;
pos->CompileOptionsPosition = 0;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->Policies = this->PolicyStack.Root();
pos->PolicyRoot = this->PolicyStack.Root();
pos->PolicyScope = this->PolicyStack.Root();
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
return cmState::Snapshot(this, pos);
}
@@ -732,7 +760,6 @@ cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot,
{
assert(originSnapshot.IsValid());
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position);
pos->CallStackParent = originSnapshot.Position;
pos->EntryPointLine = entryPointLine;
pos->EntryPointCommand = entryPointCommand;
pos->DirectoryParent = originSnapshot.Position;
@@ -743,6 +770,12 @@ cmState::CreateBuildsystemDirectorySnapshot(Snapshot originSnapshot,
pos->ExecutionListFile =
this->ExecutionListFiles.Extend(
originSnapshot.Position->ExecutionListFile);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->Policies = originSnapshot.Position->Policies;
pos->PolicyRoot = originSnapshot.Position->Policies;
pos->PolicyScope = originSnapshot.Position->Policies;
assert(pos->Policies.IsValid());
assert(pos->PolicyRoot.IsValid());
return cmState::Snapshot(this, pos);
}
@@ -754,12 +787,13 @@ cmState::CreateFunctionCallSnapshot(cmState::Snapshot originSnapshot,
{
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
*originSnapshot.Position);
pos->CallStackParent = originSnapshot.Position;
pos->EntryPointLine = entryPointLine;
pos->EntryPointCommand = entryPointCommand;
pos->SnapshotType = FunctionCallType;
pos->ExecutionListFile = this->ExecutionListFiles.Extend(
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return cmState::Snapshot(this, pos);
}
@@ -772,12 +806,13 @@ cmState::CreateMacroCallSnapshot(cmState::Snapshot originSnapshot,
{
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
*originSnapshot.Position);
pos->CallStackParent = originSnapshot.Position;
pos->EntryPointLine = entryPointLine;
pos->EntryPointCommand = entryPointCommand;
pos->SnapshotType = MacroCallType;
pos->ExecutionListFile = this->ExecutionListFiles.Extend(
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return cmState::Snapshot(this, pos);
}
@@ -789,12 +824,13 @@ cmState::CreateCallStackSnapshot(cmState::Snapshot originSnapshot,
{
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
*originSnapshot.Position);
pos->CallStackParent = originSnapshot.Position;
pos->EntryPointLine = entryPointLine;
pos->EntryPointCommand = entryPointCommand;
pos->SnapshotType = CallStackType;
pos->ExecutionListFile = this->ExecutionListFiles.Extend(
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return cmState::Snapshot(this, pos);
}
@@ -806,12 +842,24 @@ cmState::CreateInlineListFileSnapshot(cmState::Snapshot originSnapshot,
{
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
*originSnapshot.Position);
pos->CallStackParent = originSnapshot.Position;
pos->EntryPointLine = entryPointLine;
pos->EntryPointCommand = entryPointCommand;
pos->SnapshotType = InlineListFileType;
pos->ExecutionListFile = this->ExecutionListFiles.Extend(
originSnapshot.Position->ExecutionListFile, fileName);
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return cmState::Snapshot(this, pos);
}
cmState::Snapshot
cmState::CreatePolicyScopeSnapshot(cmState::Snapshot originSnapshot)
{
PositionType pos = this->SnapshotData.Extend(originSnapshot.Position,
*originSnapshot.Position);
pos->SnapshotType = PolicyScopeType;
pos->BuildSystemDirectory->DirectoryEnd = pos;
pos->PolicyScope = originSnapshot.Position->Policies;
return cmState::Snapshot(this, pos);
}
@@ -826,12 +874,9 @@ cmState::Snapshot cmState::Pop(cmState::Snapshot originSnapshot)
prevPos->BuildSystemDirectory->CompileDefinitions.size();
prevPos->CompileOptionsPosition =
prevPos->BuildSystemDirectory->CompileOptions.size();
prevPos->BuildSystemDirectory->DirectoryEnd = prevPos;
if (prevPos == this->SnapshotData.Root())
{
return Snapshot(this, prevPos);
}
return Snapshot(this, originSnapshot.Position->CallStackParent);
return Snapshot(this, prevPos);
}
cmState::Snapshot::Snapshot(cmState* state)
@@ -847,6 +892,11 @@ cmState::Snapshot::Snapshot(cmState* state, PositionType position)
}
cmState::SnapshotType cmState::Snapshot::GetType() const
{
return this->Position->SnapshotType;
}
const char* cmState::Directory::GetCurrentSource() const
{
return this->DirectoryState->Location.c_str();
@@ -964,13 +1014,22 @@ cmState::Snapshot cmState::Snapshot::GetCallStackParent() const
assert(this->Position != this->State->SnapshotData.Root());
Snapshot snapshot;
if (this->Position->SnapshotType == cmState::BuildsystemDirectoryType)
PositionType parentPos = this->Position;
while(parentPos->SnapshotType == cmState::PolicyScopeType)
{
++parentPos;
}
if (parentPos->SnapshotType == cmState::BuildsystemDirectoryType)
{
return snapshot;
}
PositionType parentPos = this->Position;
++parentPos;
while(parentPos->SnapshotType == cmState::PolicyScopeType)
{
++parentPos;
}
if (parentPos == this->State->SnapshotData.Root())
{
return snapshot;
@@ -980,6 +1039,88 @@ cmState::Snapshot cmState::Snapshot::GetCallStackParent() const
return snapshot;
}
void cmState::Snapshot::PushPolicy(cmPolicies::PolicyMap entry, bool weak)
{
PositionType pos = this->Position;
pos->Policies =
this->State->PolicyStack.Extend(pos->Policies,
PolicyStackEntry(entry, weak));
}
bool cmState::Snapshot::PopPolicy()
{
PositionType pos = this->Position;
if (pos->Policies == pos->PolicyScope)
{
return false;
}
++pos->Policies;
return true;
}
bool cmState::Snapshot::CanPopPolicyScope()
{
return this->Position->Policies == this->Position->PolicyScope;
}
void cmState::Snapshot::SetPolicy(cmPolicies::PolicyID id,
cmPolicies::PolicyStatus status)
{
// Update the policy stack from the top to the top-most strong entry.
bool previous_was_weak = true;
for(cmLinkedTree<PolicyStackEntry>::iterator psi = this->Position->Policies;
previous_was_weak && psi != this->Position->PolicyRoot; ++psi)
{
psi->Set(id, status);
previous_was_weak = psi->Weak;
}
}
cmPolicies::PolicyStatus
cmState::Snapshot::GetPolicy(cmPolicies::PolicyID id) const
{
cmPolicies::PolicyStatus status = cmPolicies::GetPolicyStatus(id);
if(status == cmPolicies::REQUIRED_ALWAYS ||
status == cmPolicies::REQUIRED_IF_USED)
{
return status;
}
cmLinkedTree<BuildsystemDirectoryStateType>::iterator dir =
this->Position->BuildSystemDirectory;
while (true)
{
assert(dir.IsValid());
cmLinkedTree<PolicyStackEntry>::iterator leaf =
dir->DirectoryEnd->Policies;
cmLinkedTree<PolicyStackEntry>::iterator root =
dir->DirectoryEnd->PolicyRoot;
for( ; leaf != root; ++leaf)
{
if(leaf->IsDefined(id))
{
status = leaf->Get(id);
return status;
}
}
cmState::PositionType e = dir->DirectoryEnd;
cmState::PositionType p = e->DirectoryParent;
if (p == this->State->SnapshotData.Root())
{
break;
}
dir = p->BuildSystemDirectory;
}
return status;
}
bool cmState::Snapshot::HasDefinedPolicyCMP0011()
{
return !this->Position->Policies->IsEmpty();
}
static const std::string cmPropertySentinal = std::string();
template<typename T, typename U, typename V>
+14 -1
View File
@@ -17,6 +17,7 @@
#include "cmPropertyMap.h"
#include "cmLinkedTree.h"
#include "cmAlgorithms.h"
#include "cmPolicies.h"
class cmake;
class cmCommand;
@@ -24,6 +25,7 @@ class cmCommand;
class cmState
{
struct SnapshotDataType;
struct PolicyStackEntry;
struct BuildsystemDirectoryStateType;
typedef cmLinkedTree<SnapshotDataType>::iterator PositionType;
friend class Snapshot;
@@ -37,7 +39,8 @@ public:
FunctionCallType,
MacroCallType,
CallStackType,
InlineListFileType
InlineListFileType,
PolicyScopeType
};
class Directory;
@@ -56,9 +59,17 @@ public:
bool IsValid() const;
Snapshot GetBuildsystemDirectoryParent() const;
Snapshot GetCallStackParent() const;
SnapshotType GetType() const;
void InitializeFromParent();
void SetPolicy(cmPolicies::PolicyID id, cmPolicies::PolicyStatus status);
cmPolicies::PolicyStatus GetPolicy(cmPolicies::PolicyID id) const;
bool HasDefinedPolicyCMP0011();
void PushPolicy(cmPolicies::PolicyMap entry, bool weak);
bool PopPolicy();
bool CanPopPolicyScope();
cmState* GetState() const;
Directory GetDirectory() const;
@@ -147,6 +158,7 @@ public:
const std::string& entryPointCommand,
long entryPointLine,
std::string const& fileName);
Snapshot CreatePolicyScopeSnapshot(Snapshot originSnapshot);
Snapshot Pop(Snapshot originSnapshot);
enum CacheEntryType{ BOOL=0, PATH, FILEPATH, STRING, INTERNAL,STATIC,
@@ -254,6 +266,7 @@ private:
cmLinkedTree<std::string> ExecutionListFiles;
cmLinkedTree<PolicyStackEntry> PolicyStack;
cmLinkedTree<SnapshotDataType> SnapshotData;
std::vector<std::string> SourceDirectoryComponents;
+11 -8
View File
@@ -950,8 +950,9 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
Try multiple times since we may be racing against another process
creating/opening the destination file just before our MoveFileEx. */
WindowsFileRetry retry = cmSystemTools::GetWindowsFileRetry();
while(!MoveFileExW(cmsys::Encoding::ToWide(oldname).c_str(),
cmsys::Encoding::ToWide(newname).c_str(),
while(!MoveFileExW(
SystemTools::ConvertToWindowsExtendedPath(oldname).c_str(),
SystemTools::ConvertToWindowsExtendedPath(newname).c_str(),
MOVEFILE_REPLACE_EXISTING) && --retry.Count)
{
DWORD last_error = GetLastError();
@@ -962,12 +963,14 @@ bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
return false;
}
DWORD attrs =
GetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str());
GetFileAttributesW(
SystemTools::ConvertToWindowsExtendedPath(newname).c_str());
if((attrs != INVALID_FILE_ATTRIBUTES) &&
(attrs & FILE_ATTRIBUTE_READONLY))
{
// Remove the read-only attribute from the destination file.
SetFileAttributesW(cmsys::Encoding::ToWide(newname).c_str(),
SetFileAttributesW(
SystemTools::ConvertToWindowsExtendedPath(newname).c_str(),
attrs & ~FILE_ATTRIBUTE_READONLY);
}
else
@@ -1956,11 +1959,11 @@ bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle hFrom =
CreateFileW(cmsys::Encoding::ToWide(fromFile).c_str(),
CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fromFile).c_str(),
GENERIC_READ, FILE_SHARE_READ, 0,
OPEN_EXISTING, 0, 0);
cmSystemToolsWindowsHandle hTo =
CreateFileW(cmsys::Encoding::ToWide(toFile).c_str(),
CreateFileW(SystemTools::ConvertToWindowsExtendedPath(toFile).c_str(),
GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(!hFrom || !hTo)
{
@@ -2012,7 +2015,7 @@ bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle h =
CreateFileW(cmsys::Encoding::ToWide(fname).c_str(),
CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(),
GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(!h)
{
@@ -2039,7 +2042,7 @@ bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
cmSystemToolsWindowsHandle h =
CreateFileW(cmsys::Encoding::ToWide(fname).c_str(),
CreateFileW(SystemTools::ConvertToWindowsExtendedPath(fname).c_str(),
GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
if(!h)
{
+165 -2110
View File
File diff suppressed because it is too large Load Diff
+20 -210
View File
@@ -16,6 +16,7 @@
#include "cmPropertyMap.h"
#include "cmPolicies.h"
#include "cmListFileCache.h"
#include "cmLinkItem.h"
#include <cmsys/auto_ptr.hxx>
#if defined(CMAKE_BUILD_WITH_CMAKE)
@@ -52,41 +53,6 @@ class cmTarget;
class cmGeneratorTarget;
class cmTargetTraceDependencies;
// Basic information about each link item.
class cmLinkItem: public std::string
{
typedef std::string std_string;
public:
cmLinkItem(): std_string(), Target(0) {}
cmLinkItem(const std_string& n,
cmTarget const* t): std_string(n), Target(t) {}
cmLinkItem(cmLinkItem const& r): std_string(r), Target(r.Target) {}
cmTarget const* Target;
};
class cmLinkImplItem: public cmLinkItem
{
public:
cmLinkImplItem(): cmLinkItem(), Backtrace(), FromGenex(false) {}
cmLinkImplItem(std::string const& n,
cmTarget const* t,
cmListFileBacktrace const& bt,
bool fromGenex):
cmLinkItem(n, t), Backtrace(bt), FromGenex(fromGenex) {}
cmLinkImplItem(cmLinkImplItem const& r):
cmLinkItem(r), Backtrace(r.Backtrace), FromGenex(r.FromGenex) {}
cmListFileBacktrace Backtrace;
bool FromGenex;
};
struct cmTargetLinkInformationMap:
public std::map<std::string, cmComputeLinkInformation*>
{
typedef std::map<std::string, cmComputeLinkInformation*> derived;
cmTargetLinkInformationMap() {}
cmTargetLinkInformationMap(cmTargetLinkInformationMap const& r);
~cmTargetLinkInformationMap();
};
class cmTargetInternals;
class cmTargetInternalPointer
{
@@ -166,6 +132,8 @@ public:
void AddPostBuildCommand(cmCustomCommand const &cmd)
{this->PostBuildCommands.push_back(cmd);}
void Compute();
/**
* Get the list of the source files used by this target
*/
@@ -302,31 +270,7 @@ public:
cmTarget const* headTarget,
bool usage_requirements_only) const;
std::vector<cmTarget const*> const&
GetLinkImplementationClosure(const std::string& config) const;
struct CompatibleInterfaces
{
std::set<std::string> PropsBool;
std::set<std::string> PropsString;
std::set<std::string> PropsNumberMax;
std::set<std::string> PropsNumberMin;
};
CompatibleInterfaces const&
GetCompatibleInterfaces(std::string const& config) const;
/** The link implementation specifies the direct library
dependencies needed by the object files of the target. */
struct LinkImplementationLibraries
{
// Libraries linked directly in this configuration.
std::vector<cmLinkImplItem> Libraries;
// Libraries linked directly in other configurations.
// Needed only for OLD behavior of CMP0003.
std::vector<cmLinkItem> WrongConfigLibraries;
};
struct LinkImplementation: public LinkImplementationLibraries
struct LinkImplementation: public cmLinkImplementationLibraries
{
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
@@ -334,21 +278,9 @@ public:
LinkImplementation const*
GetLinkImplementation(const std::string& config) const;
LinkImplementationLibraries const*
cmLinkImplementationLibraries const*
GetLinkImplementationLibraries(const std::string& config) const;
/** Link information from the transitive closure of the link
implementation and the interfaces of its dependencies. */
struct LinkClosure
{
// The preferred linker language.
std::string LinkerLanguage;
// Languages whose runtime libraries must be linked.
std::vector<std::string> Languages;
};
LinkClosure const* GetLinkClosure(const std::string& config) const;
cmTarget const* FindTargetToLink(std::string const& name) const;
/** Strip off leading and trailing whitespace from an item named in
@@ -368,12 +300,6 @@ public:
pdb output directory is given. */
std::string GetPDBDirectory(const std::string& config) const;
/** Get the directory in which to place the target compiler .pdb file.
If the configuration name is given then the generator will add its
subdirectory for that configuration. Otherwise just the canonical
compiler pdb output directory is given. */
std::string GetCompilePDBDirectory(const std::string& config = "") const;
const char* ImportedGetLocation(const std::string& config) const;
/** Get the target major and minor version numbers interpreted from
@@ -387,33 +313,6 @@ public:
void
GetTargetVersion(bool soversion, int& major, int& minor, int& patch) const;
///! Return the preferred linker language for this target
std::string GetLinkerLanguage(const std::string& config = "") const;
/** Get the full name of the target according to the settings in its
makefile. */
std::string GetFullName(const std::string& config="",
bool implib = false) const;
void GetFullNameComponents(std::string& prefix,
std::string& base, std::string& suffix,
const std::string& config="",
bool implib = false) const;
/** Get the name of the pdb file for the target. */
std::string GetPDBName(const std::string& config) const;
/** Get the name of the compiler pdb file for the target. */
std::string GetCompilePDBName(const std::string& config="") const;
/** Get the path for the MSVC /Fd option for this target. */
std::string GetCompilePDBPath(const std::string& config="") const;
/** Whether this library has soname enabled and platform supports it. */
bool HasSOName(const std::string& config) const;
/** Get the soname of the target. Allowed only for a shared library. */
std::string GetSOName(const std::string& config) const;
/** Whether this library has \@rpath and platform supports it. */
bool HasMacOSXRpathInstallNameDir(const std::string& config) const;
@@ -424,21 +323,6 @@ public:
no soname at all. */
bool IsImportedSharedLibWithoutSOName(const std::string& config) const;
/** Get the names of the library needed to generate a build rule
that takes into account shared library version numbers. This
should be called only on a library target. */
void GetLibraryNames(std::string& name, std::string& soName,
std::string& realName, std::string& impName,
std::string& pdbName, const std::string& config) const;
/** Get the names of the executable needed to generate a build rule
that takes into account executable version numbers. This should
be called only on an executable target. */
void GetExecutableNames(std::string& name, std::string& realName,
std::string& impName,
std::string& pdbName,
const std::string& config) const;
/** Does this target have a GNU implib to convert to MS format? */
bool HasImplibGNUtoMS() const;
@@ -447,29 +331,9 @@ public:
bool GetImplibGNUtoMS(std::string const& gnuName, std::string& out,
const char* newExt = 0) const;
/**
* Compute whether this target must be relinked before installing.
*/
bool NeedRelinkBeforeInstall(const std::string& config) const;
bool HaveBuildTreeRPATH(const std::string& config) const;
bool HaveInstallTreeRPATH() const;
/** Return true if builtin chrpath will work for this target */
bool IsChrpathUsed(const std::string& config) const;
/** Return the install name directory for the target in the
* build tree. For example: "\@rpath/", "\@loader_path/",
* or "/full/path/to/library". */
std::string GetInstallNameDirForBuildTree(const std::string& config) const;
/** Return the install name directory for the target in the
* install tree. For example: "\@rpath/" or "\@loader_path/". */
std::string GetInstallNameDirForInstallTree() const;
cmComputeLinkInformation*
GetLinkInformation(const std::string& config) const;
// Get the properties
cmPropertyMap &GetProperties() const { return this->Properties; }
@@ -520,10 +384,6 @@ public:
/** Return whether this target is an executable Bundle on Apple. */
bool IsAppBundleOnApple() const;
/** Return whether this target is an executable Bundle, a framework
or CFBundle on Apple. */
bool IsBundleOnApple() const;
/** Return the framework version string. Undefined if
IsFrameworkOnApple returns false. */
std::string GetFrameworkVersion() const;
@@ -538,25 +398,9 @@ public:
directory. */
bool UsesDefaultOutputDir(const std::string& config, bool implib) const;
/** @return the mac content directory for this target. */
std::string GetMacContentDirectory(const std::string& config,
bool implib) const;
/** @return whether this target have a well defined output file name. */
bool HaveWellDefinedOutputFiles() const;
/** @return the Mac framework directory without the base. */
std::string GetFrameworkDirectory(const std::string& config,
bool rootDir) const;
/** @return the Mac CFBundle directory without the base */
std::string GetCFBundleDirectory(const std::string& config,
bool contentOnly) const;
/** @return the Mac App directory without the base */
std::string GetAppBundleDirectory(const std::string& config,
bool contentOnly) const;
std::vector<std::string> GetIncludeDirectories(
const std::string& config,
const std::string& language) const;
@@ -574,47 +418,21 @@ public:
void GetCompileOptions(std::vector<std::string> &result,
const std::string& config,
const std::string& language) const;
void GetAutoUicOptions(std::vector<std::string> &result,
const std::string& config) const;
void GetCompileFeatures(std::vector<std::string> &features,
const std::string& config) const;
bool IsNullImpliedByLinkLibraries(const std::string &p) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentStringProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentNumberMinProperty(const std::string &p,
const std::string& config) const;
bool IsLinkInterfaceDependentNumberMaxProperty(const std::string &p,
const std::string& config) const;
bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentNumberMinProperty(const std::string &p,
const std::string& config) const;
const char *GetLinkInterfaceDependentNumberMaxProperty(const std::string &p,
const std::string& config) const;
std::string GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt) const;
void AddSystemIncludeDirectories(const std::set<std::string> &incs);
void AddSystemIncludeDirectories(const std::vector<std::string> &incs);
std::set<std::string> const & GetSystemIncludeDirectories() const
{ return this->SystemIncludeDirectories; }
bool LinkLanguagePropagatesToDependents() const
{ return this->TargetTypeValue == STATIC_LIBRARY; }
void ReportPropertyOrigin(const std::string &p,
const std::string &result,
const std::string &report,
const std::string &compatibilityType) const;
std::map<std::string, std::string> const&
GetMaxLanguageStandards() const
{
@@ -684,11 +502,6 @@ private:
const char* GetSuffixVariableInternal(bool implib) const;
const char* GetPrefixVariableInternal(bool implib) const;
std::string GetFullNameInternal(const std::string& config,
bool implib) const;
void GetFullNameInternal(const std::string& config, bool implib,
std::string& outPrefix, std::string& outBase,
std::string& outSuffix) const;
// Use a makefile variable to set a default for the given property.
// If the variable is not defined use the given default instead.
@@ -698,19 +511,12 @@ private:
// Returns ARCHIVE, LIBRARY, or RUNTIME based on platform and type.
const char* GetOutputTargetType(bool implib) const;
// Get the target base name.
std::string GetOutputName(const std::string& config, bool implib) const;
std::string GetFullNameImported(const std::string& config,
bool implib) const;
std::string ImportedGetFullPath(const std::string& config,
bool implib) const;
/** Append to @a base the mac content directory and return it. */
std::string BuildMacContentDirectory(const std::string& base,
const std::string& config,
bool contentOnly) const;
void GetSourceFiles(std::vector<std::string> &files,
const std::string& config) const;
@@ -721,7 +527,6 @@ private:
std::set<std::string> Utilities;
mutable std::set<std::string> LinkImplicitNullProperties;
std::map<std::string, cmListFileBacktrace> UtilityBacktraces;
mutable std::map<std::string, bool> DebugCompatiblePropertiesDone;
mutable std::map<std::string, std::string> MaxLanguageStandards;
cmPolicies::PolicyMap PolicyMap;
std::string Name;
@@ -768,27 +573,32 @@ private:
std::string& out) const;
// Cache import information from properties for each configuration.
struct ImportInfo;
struct ImportInfo
{
ImportInfo(): NoSOName(false), Multiplicity(0) {}
bool NoSOName;
int Multiplicity;
std::string Location;
std::string SOName;
std::string ImportLibrary;
std::string Languages;
std::string Libraries;
std::string LibrariesProp;
std::string SharedDeps;
};
ImportInfo const* GetImportInfo(const std::string& config) const;
void ComputeImportInfo(std::string const& desired_config,
ImportInfo& info) const;
// Cache target compile paths for each configuration.
struct CompileInfo;
CompileInfo const* GetCompileInfo(const std::string& config) const;
mutable cmTargetLinkInformationMap LinkInformation;
void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const std::string& config) const;
LinkInterface const*
GetImportLinkInterface(const std::string& config, cmTarget const* head,
bool usage_requirements_only) const;
LinkImplementationLibraries const*
cmLinkImplementationLibraries const*
GetLinkImplementationLibrariesInternal(const std::string& config,
cmTarget const* head) const;
void ComputeLinkClosure(const std::string& config, LinkClosure& lc) const;
void ExpandLinkItems(std::string const& prop, std::string const& value,
std::string const& config, cmTarget const* headTarget,
+18 -2
View File
@@ -75,7 +75,23 @@ bool cmTargetIncludeDirectoriesCommand
tgt->InsertInclude(this->Join(content), lfbt, prepend);
if (system)
{
tgt->AddSystemIncludeDirectories(content);
std::string prefix =
this->Makefile->GetCurrentSourceDirectory() + std::string("/");
std::set<std::string> sdirs;
for (std::vector<std::string>::const_iterator it = content.begin();
it != content.end(); ++it)
{
if (cmSystemTools::FileIsFullPath(it->c_str())
|| cmGeneratorExpression::Find(*it) == 0)
{
sdirs.insert(*it);
}
else
{
sdirs.insert(prefix + *it);
}
}
tgt->AddSystemIncludeDirectories(sdirs);
}
return true;
}
@@ -91,7 +107,7 @@ void cmTargetIncludeDirectoriesCommand
if (system)
{
std::string joined = cmJoin(content, ";");
std::string joined = this->Join(content);
tgt->AppendProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES",
joined.c_str());
}
+10 -8
View File
@@ -1627,7 +1627,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
this->GlobalGenerator->GetLanguageFromExtension
(sf.GetExtension().c_str());
std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
const std::string& linkLanguage = this->Target->GetLinkerLanguage();
const std::string& linkLanguage = this->GeneratorTarget->GetLinkerLanguage();
bool needForceLang = false;
// source file does not match its extension language
if(lang != sourceLang)
@@ -1774,7 +1774,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
else
{
outDir = this->Target->GetDirectory(config->c_str()) + "/";
targetNameFull = this->Target->GetFullName(config->c_str());
targetNameFull = this->GeneratorTarget->GetFullName(config->c_str());
}
this->ConvertToWindowsSlash(intermediateDir);
this->ConvertToWindowsSlash(outDir);
@@ -1888,7 +1888,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
std::string flags;
const std::string& linkLanguage =
this->Target->GetLinkerLanguage(configName.c_str());
this->GeneratorTarget->GetLinkerLanguage(configName.c_str());
if(linkLanguage.empty())
{
cmSystemTools::Error
@@ -2026,7 +2026,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
}
// Specify the compiler program database file if configured.
std::string pdb = this->Target->GetCompilePDBPath(configName.c_str());
std::string pdb =
this->GeneratorTarget->GetCompilePDBPath(configName.c_str());
if(!pdb.empty())
{
this->ConvertToWindowsSlash(pdb);
@@ -2370,7 +2371,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
Options& linkOptions = *pOptions;
const std::string& linkLanguage =
this->Target->GetLinkerLanguage(config.c_str());
this->GeneratorTarget->GetLinkerLanguage(config.c_str());
if(linkLanguage.empty())
{
cmSystemTools::Error
@@ -2438,7 +2439,7 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
cmSystemTools::ExpandListArgument(libs, libVec);
cmComputeLinkInformation* pcli =
this->Target->GetLinkInformation(config.c_str());
this->GeneratorTarget->GetLinkInformation(config.c_str());
if(!pcli)
{
cmSystemTools::Error
@@ -2471,13 +2472,14 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
std::string targetNamePDB;
if(this->Target->GetType() == cmTarget::EXECUTABLE)
{
this->Target->GetExecutableNames(targetName, targetNameFull,
this->GeneratorTarget->GetExecutableNames(targetName, targetNameFull,
targetNameImport, targetNamePDB,
config.c_str());
}
else
{
this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull,
this->GeneratorTarget->GetLibraryNames(targetName, targetNameSO,
targetNameFull,
targetNameImport, targetNamePDB,
config.c_str());
}
+5 -1
View File
@@ -243,7 +243,11 @@ void cmXCodeObject::PrintString(std::ostream& os,std::string String)
bool needQuote =
(String.empty() ||
String.find("//") != String.npos ||
String.find_first_of(" <>+-*=@[](){},") != String.npos);
String.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
"$_./") != String.npos);
const char* quote = needQuote? "\"" : "";
// Print the string, quoted and escaped as necessary.
+30 -3
View File
@@ -75,7 +75,9 @@
# include "cmGlobalWatcomWMakeGenerator.h"
#endif
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmGlobalNinjaGenerator.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmGlobalNinjaGenerator.h"
#endif
#include "cmExtraCodeLiteGenerator.h"
#if !defined(CMAKE_BOOT_MINGW)
@@ -1447,7 +1449,7 @@ int cmake::ActualConfigure()
}
}
cmMakefile* mf=this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
cmMakefile* mf=this->GlobalGenerator->GetMakefiles()[0];
if (mf->IsOn("CTEST_USE_LAUNCHERS")
&& !this->State->GetGlobalProperty("RULE_LAUNCH_COMPILE"))
{
@@ -1607,7 +1609,11 @@ int cmake::Generate()
{
return -1;
}
this->GlobalGenerator->DoGenerate();
if (!this->GlobalGenerator->Compute())
{
return -1;
}
this->GlobalGenerator->Generate();
if ( !this->GraphVizFile.empty() )
{
std::cout << "Generate graphviz: " << this->GraphVizFile << std::endl;
@@ -1696,8 +1702,10 @@ void cmake::AddDefaultGenerators()
#endif
this->Generators.push_back(
cmGlobalUnixMakefileGenerator3::NewFactory());
#if defined(CMAKE_BUILD_WITH_CMAKE)
this->Generators.push_back(
cmGlobalNinjaGenerator::NewFactory());
#endif
#if defined(CMAKE_USE_WMAKE)
this->Generators.push_back(
cmGlobalWatcomWMakeGenerator::NewFactory());
@@ -2576,6 +2584,25 @@ int cmake::Build(const std::string& dir,
}
std::string cachePath = dir;
cmSystemTools::ConvertToUnixSlashes(cachePath);
std::string cacheFile = cachePath;
cacheFile += "/CMakeCache.txt";
if(!cmSystemTools::FileExists(cacheFile.c_str()))
{
// search in parent directories for cache
std::string cmakeFiles = cachePath;
cmakeFiles += "/CMakeFiles";
if(cmSystemTools::FileExists(cmakeFiles.c_str()))
{
std::string cachePathFound =
cmSystemTools::FileExistsInParentDirectories(
"CMakeCache.txt", cachePath.c_str(), "/");
if(!cachePathFound.empty())
{
cachePath = cmSystemTools::GetFilenamePath(cachePathFound);
}
}
}
if(!this->LoadCache(cachePath))
{
std::cerr << "Error: could not load cache\n";
+14 -5
View File
@@ -1468,18 +1468,24 @@ bool cmcmd::RunCommand(const char* comment,
std::string output;
int retCode =0;
// use rc command to create .res file
cmSystemTools::RunSingleCommand(command,
&output, &output,
&retCode, 0, cmSystemTools::OUTPUT_NONE);
bool res = cmSystemTools::RunSingleCommand(command,
&output, &output,
&retCode, 0,
cmSystemTools::OUTPUT_NONE);
// always print the output of the command, unless
// it is the dumb rc command banner, but if the command
// returned an error code then print the output anyway as
// the banner may be mixed with some other important information.
if(output.find("Resource Compiler Version") == output.npos
|| retCode !=0)
|| !res || retCode)
{
std::cout << output;
}
if (!res)
{
std::cout << comment << " failed to run." << std::endl;
return false;
}
// if retCodeOut is requested then always return true
// and set the retCodeOut to retCode
if(retCodeOut)
@@ -1593,7 +1599,10 @@ int cmcmd::VisualStudioLinkIncremental(std::vector<std::string>& args,
mtCommand.push_back(tempManifest);
// now run mt.exe to create the final manifest file
int mtRet =0;
cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet);
if(!cmcmd::RunCommand("MT", mtCommand, verbose, &mtRet))
{
return -1;
}
// if mt returns 0, then the manifest was not changed and
// we do not need to do another link step
if(mtRet == 0)
+5 -1
View File
@@ -1237,7 +1237,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
IF(NOT CYGWIN)
SET(KWSYS_TEST_PROCESS_7 7)
ENDIF()
FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7})
FOREACH(n 1 2 3 4 5 6 ${KWSYS_TEST_PROCESS_7} 9 10)
ADD_TEST(kwsys.testProcess-${n} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestProcess ${n})
SET_PROPERTY(TEST kwsys.testProcess-${n} PROPERTY LABELS ${KWSYS_LABELS_TEST})
SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120)
@@ -1270,6 +1270,10 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
MESSAGE(STATUS "GET_TEST_PROPERTY returned: ${wfv}")
ENDIF()
# Set up ctest custom configuration file.
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/CTestCustom.cmake.in
${PROJECT_BINARY_DIR}/CTestCustom.cmake @ONLY)
# Suppress known consistent failures on buggy systems.
IF(KWSYS_TEST_BOGUS_FAILURES)
SET_TESTS_PROPERTIES(${KWSYS_TEST_BOGUS_FAILURES} PROPERTIES WILL_FAIL ON)
+15
View File
@@ -0,0 +1,15 @@
# kwsys.testProcess-10 involves sending SIGINT to a child process, which then
# exits abnormally via a call to _exit(). (On Windows, a call to ExitProcess).
# Naturally, this results in plenty of memory being "leaked" by this child
# process - the memory check results are not meaningful in this case.
#
# kwsys.testProcess-9 also tests sending SIGINT to a child process. However,
# normal operation of that test involves the child process timing out, and the
# host process kills (SIGKILL) it as a result. Since it was SIGKILL'ed, the
# resulting memory leaks are not logged by valgrind anyway. Therefore, we
# don't have to exclude it.
set(CTEST_CUSTOM_MEMCHECK_IGNORE
${CTEST_CUSTOM_MEMCHECK_IGNORE}
kwsys.testProcess-10
)
+10 -4
View File
@@ -45,8 +45,11 @@ wchar_t* kwsysEncoding_DupToWide(const char* str)
if(length > 0)
{
ret = (wchar_t*)malloc((length)*sizeof(wchar_t));
ret[0] = 0;
kwsysEncoding_mbstowcs(ret, str, length);
if(ret)
{
ret[0] = 0;
kwsysEncoding_mbstowcs(ret, str, length);
}
}
return ret;
}
@@ -72,8 +75,11 @@ char* kwsysEncoding_DupToNarrow(const wchar_t* str)
if(length > 0)
{
ret = (char*)malloc(length);
ret[0] = 0;
kwsysEncoding_wcstombs(ret, str, length);
if(ret)
{
ret[0] = 0;
kwsysEncoding_wcstombs(ret, str, length);
}
}
return ret;
}
+78 -53
View File
@@ -23,58 +23,60 @@
# define kwsysEXPORT @KWSYS_NAMESPACE@_EXPORT
#endif
#if !@KWSYS_NAMESPACE@_NAME_IS_KWSYS
# define kwsysProcess kwsys_ns(Process)
# define kwsysProcess_s kwsys_ns(Process_s)
# define kwsysProcess_New kwsys_ns(Process_New)
# define kwsysProcess_Delete kwsys_ns(Process_Delete)
# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
# define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
# define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
# define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
# define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
# define kwsysProcess_GetState kwsys_ns(Process_GetState)
# define kwsysProcess_State_e kwsys_ns(Process_State_e)
# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
# define kwsysProcess_Execute kwsys_ns(Process_Execute)
# define kwsysProcess_Disown kwsys_ns(Process_Disown)
# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
# define kwsysProcess_Kill kwsys_ns(Process_Kill)
# define kwsysProcess kwsys_ns(Process)
# define kwsysProcess_s kwsys_ns(Process_s)
# define kwsysProcess_New kwsys_ns(Process_New)
# define kwsysProcess_Delete kwsys_ns(Process_Delete)
# define kwsysProcess_SetCommand kwsys_ns(Process_SetCommand)
# define kwsysProcess_AddCommand kwsys_ns(Process_AddCommand)
# define kwsysProcess_SetTimeout kwsys_ns(Process_SetTimeout)
# define kwsysProcess_SetWorkingDirectory kwsys_ns(Process_SetWorkingDirectory)
# define kwsysProcess_SetPipeFile kwsys_ns(Process_SetPipeFile)
# define kwsysProcess_SetPipeNative kwsys_ns(Process_SetPipeNative)
# define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared)
# define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach)
# define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow)
# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput)
# define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim)
# define kwsysProcess_Option_CreateProcessGroup kwsys_ns(Process_Option_CreateProcessGroup)
# define kwsysProcess_GetOption kwsys_ns(Process_GetOption)
# define kwsysProcess_SetOption kwsys_ns(Process_SetOption)
# define kwsysProcess_Option_e kwsys_ns(Process_Option_e)
# define kwsysProcess_State_Starting kwsys_ns(Process_State_Starting)
# define kwsysProcess_State_Error kwsys_ns(Process_State_Error)
# define kwsysProcess_State_Exception kwsys_ns(Process_State_Exception)
# define kwsysProcess_State_Executing kwsys_ns(Process_State_Executing)
# define kwsysProcess_State_Exited kwsys_ns(Process_State_Exited)
# define kwsysProcess_State_Expired kwsys_ns(Process_State_Expired)
# define kwsysProcess_State_Killed kwsys_ns(Process_State_Killed)
# define kwsysProcess_State_Disowned kwsys_ns(Process_State_Disowned)
# define kwsysProcess_GetState kwsys_ns(Process_GetState)
# define kwsysProcess_State_e kwsys_ns(Process_State_e)
# define kwsysProcess_Exception_None kwsys_ns(Process_Exception_None)
# define kwsysProcess_Exception_Fault kwsys_ns(Process_Exception_Fault)
# define kwsysProcess_Exception_Illegal kwsys_ns(Process_Exception_Illegal)
# define kwsysProcess_Exception_Interrupt kwsys_ns(Process_Exception_Interrupt)
# define kwsysProcess_Exception_Numerical kwsys_ns(Process_Exception_Numerical)
# define kwsysProcess_Exception_Other kwsys_ns(Process_Exception_Other)
# define kwsysProcess_GetExitException kwsys_ns(Process_GetExitException)
# define kwsysProcess_Exception_e kwsys_ns(Process_Exception_e)
# define kwsysProcess_GetExitCode kwsys_ns(Process_GetExitCode)
# define kwsysProcess_GetExitValue kwsys_ns(Process_GetExitValue)
# define kwsysProcess_GetErrorString kwsys_ns(Process_GetErrorString)
# define kwsysProcess_GetExceptionString kwsys_ns(Process_GetExceptionString)
# define kwsysProcess_Execute kwsys_ns(Process_Execute)
# define kwsysProcess_Disown kwsys_ns(Process_Disown)
# define kwsysProcess_WaitForData kwsys_ns(Process_WaitForData)
# define kwsysProcess_Pipes_e kwsys_ns(Process_Pipes_e)
# define kwsysProcess_Pipe_None kwsys_ns(Process_Pipe_None)
# define kwsysProcess_Pipe_STDIN kwsys_ns(Process_Pipe_STDIN)
# define kwsysProcess_Pipe_STDOUT kwsys_ns(Process_Pipe_STDOUT)
# define kwsysProcess_Pipe_STDERR kwsys_ns(Process_Pipe_STDERR)
# define kwsysProcess_Pipe_Timeout kwsys_ns(Process_Pipe_Timeout)
# define kwsysProcess_Pipe_Handle kwsys_ns(Process_Pipe_Handle)
# define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
# define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
# define kwsysProcess_Kill kwsys_ns(Process_Kill)
#endif
#if defined(__cplusplus)
@@ -199,6 +201,15 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe,
* and ignore the rest of the arguments.
* 0 = No (default)
* 1 = Yes
*
* kwsysProcess_Option_CreateProcessGroup = Whether to place the process in a
* new process group. This is
* useful if you want to send Ctrl+C
* to the process. On UNIX, also
* places the process in a new
* session.
* 0 = No (default)
* 1 = Yes
*/
kwsysEXPORT int kwsysProcess_GetOption(kwsysProcess* cp, int optionId);
kwsysEXPORT void kwsysProcess_SetOption(kwsysProcess* cp, int optionId,
@@ -208,7 +219,8 @@ enum kwsysProcess_Option_e
kwsysProcess_Option_HideWindow,
kwsysProcess_Option_Detach,
kwsysProcess_Option_MergeOutput,
kwsysProcess_Option_Verbatim
kwsysProcess_Option_Verbatim,
kwsysProcess_Option_CreateProcessGroup
};
/**
@@ -362,6 +374,17 @@ enum kwsysProcess_Pipes_e
*/
kwsysEXPORT int kwsysProcess_WaitForExit(kwsysProcess* cp, double* timeout);
/**
* Interrupt the process group for the child process that is currently
* running by sending it the appropriate operating-system specific signal.
* The caller should call WaitForExit after this returns to wait for the
* child to terminate.
*
* WARNING: If you didn't specify kwsysProcess_Option_CreateProcessGroup,
* you will interrupt your own process group.
*/
kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp);
/**
* Forcefully terminate the child process that is currently running.
* The caller should call WaitForExit after this returns to wait for
@@ -394,6 +417,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
# undef kwsysProcess_Option_HideWindow
# undef kwsysProcess_Option_MergeOutput
# undef kwsysProcess_Option_Verbatim
# undef kwsysProcess_Option_CreateProcessGroup
# undef kwsysProcess_GetOption
# undef kwsysProcess_SetOption
# undef kwsysProcess_Option_e
@@ -430,6 +454,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
# undef kwsysProcess_Pipe_Timeout
# undef kwsysProcess_Pipe_Handle
# undef kwsysProcess_WaitForExit
# undef kwsysProcess_Interrupt
# undef kwsysProcess_Kill
# endif
#endif
+307 -50
View File
@@ -88,7 +88,7 @@ typedef ssize_t kwsysProcess_ssize_t;
typedef int kwsysProcess_ssize_t;
#endif
#if defined(__BEOS__) && !defined(__ZETA__)
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
# include <be/kernel/OS.h>
static inline void kwsysProcess_usleep(unsigned int msec)
@@ -151,6 +151,7 @@ typedef struct kwsysProcessCreateInformation_s
} kwsysProcessCreateInformation;
/*--------------------------------------------------------------------------*/
static void kwsysProcessVolatileFree(volatile void* p);
static int kwsysProcessInitialize(kwsysProcess* cp);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanupDescriptor(int* pfd);
@@ -197,7 +198,7 @@ struct kwsysProcess_s
{
/* The command lines to execute. */
char*** Commands;
int NumberOfCommands;
volatile int NumberOfCommands;
/* Descriptors for the read ends of the child's output pipes and
the signal pipe. */
@@ -213,8 +214,10 @@ struct kwsysProcess_s
/* Buffer for pipe data. */
char PipeBuffer[KWSYSPE_PIPE_BUFFER_SIZE];
/* Process IDs returned by the calls to fork. */
pid_t* ForkPIDs;
/* Process IDs returned by the calls to fork. Everything is volatile
because the signal handler accesses them. You must be very careful
when reaping PIDs or modifying this array to avoid race conditions. */
volatile pid_t* volatile ForkPIDs;
/* Flag for whether the children were terminated by a faild select. */
int SelectError;
@@ -237,6 +240,9 @@ struct kwsysProcess_s
/* Whether to merge stdout/stderr of the child. */
int MergeOutput;
/* Whether to create the process in a new process group. */
volatile sig_atomic_t CreateProcessGroup;
/* Time at which the child started. Negative for no timeout. */
kwsysProcessTime StartTime;
@@ -257,8 +263,9 @@ struct kwsysProcess_s
/* The number of children still executing. */
int CommandsLeft;
/* The current status of the child process. */
int State;
/* The current status of the child process. Must be atomic because
the signal handler checks this to avoid a race. */
volatile sig_atomic_t State;
/* The exceptional behavior that terminated the child process, if
* any. */
@@ -271,7 +278,7 @@ struct kwsysProcess_s
int ExitValue;
/* Whether the process was killed. */
int Killed;
volatile sig_atomic_t Killed;
/* Buffer for error message in case of failure. */
char ErrorMessage[KWSYSPE_PIPE_BUFFER_SIZE+1];
@@ -649,6 +656,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
case kwsysProcess_Option_Detach: return cp->OptionDetach;
case kwsysProcess_Option_MergeOutput: return cp->MergeOutput;
case kwsysProcess_Option_Verbatim: return cp->Verbatim;
case kwsysProcess_Option_CreateProcessGroup:
return cp->CreateProcessGroup;
default: return 0;
}
}
@@ -666,6 +675,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break;
case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
case kwsysProcess_Option_CreateProcessGroup:
cp->CreateProcessGroup = value; break;
default: break;
}
}
@@ -1489,6 +1500,45 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
return 1;
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_Interrupt(kwsysProcess* cp)
{
int i;
/* Make sure we are executing a process. */
if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
cp->Killed)
{
return;
}
/* Interrupt the children. */
if (cp->CreateProcessGroup)
{
if(cp->ForkPIDs)
{
for(i=0; i < cp->NumberOfCommands; ++i)
{
/* Make sure the PID is still valid. */
if(cp->ForkPIDs[i])
{
/* The user created a process group for this process. The group ID
is the process ID for the original process in the group. */
kill(-cp->ForkPIDs[i], SIGINT);
}
}
}
}
else
{
/* No process group was created. Kill our own process group.
NOTE: While one could argue that we could call kill(cp->ForkPIDs[i],
SIGINT) as a way to still interrupt the process even though it's not in
a special group, this is not an option on Windows. Therefore, we kill
the current process group for consistency with Windows. */
kill(0, SIGINT);
}
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_Kill(kwsysProcess* cp)
{
@@ -1538,11 +1588,29 @@ void kwsysProcess_Kill(kwsysProcess* cp)
cp->CommandsLeft = 0;
}
/*--------------------------------------------------------------------------*/
/* Call the free() function with a pointer to volatile without causing
compiler warnings. */
static void kwsysProcessVolatileFree(volatile void* p)
{
/* clang has made it impossible to free memory that points to volatile
without first using special pragmas to disable a warning... */
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wcast-qual"
#endif
free((void*)p); /* The cast will silence most compilers, but not clang. */
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
}
/*--------------------------------------------------------------------------*/
/* Initialize a process control structure for kwsysProcess_Execute. */
static int kwsysProcessInitialize(kwsysProcess* cp)
{
int i;
volatile pid_t* oldForkPIDs;
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
{
cp->PipeReadEnds[i] = -1;
@@ -1571,16 +1639,21 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
cp->ErrorMessage[0] = 0;
strcpy(cp->ExitExceptionString, "No exception");
if(cp->ForkPIDs)
oldForkPIDs = cp->ForkPIDs;
cp->ForkPIDs = (volatile pid_t*)malloc(
sizeof(volatile pid_t)*(size_t)(cp->NumberOfCommands));
if(oldForkPIDs)
{
free(cp->ForkPIDs);
kwsysProcessVolatileFree(oldForkPIDs);
}
cp->ForkPIDs = (pid_t*)malloc(sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
if(!cp->ForkPIDs)
{
return 0;
}
memset(cp->ForkPIDs, 0, sizeof(pid_t)*(size_t)(cp->NumberOfCommands));
for(i=0; i < cp->NumberOfCommands; ++i)
{
cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */
}
if(cp->CommandExitCodes)
{
@@ -1671,7 +1744,7 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error)
/* Free memory. */
if(cp->ForkPIDs)
{
free(cp->ForkPIDs);
kwsysProcessVolatileFree(cp->ForkPIDs);
cp->ForkPIDs = 0;
}
if(cp->RealWorkingDirectory)
@@ -1758,15 +1831,49 @@ int decc$set_child_standard_streams(int fd1, int fd2, int fd3);
static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
kwsysProcessCreateInformation* si)
{
sigset_t mask, old_mask;
int pgidPipe[2];
char tmp;
ssize_t readRes;
/* Create the error reporting pipe. */
if(pipe(si->ErrorPipe) < 0)
{
return 0;
}
/* Set close-on-exec flag on the error pipe's write end. */
if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0)
/* Create a pipe for detecting that the child process has created a process
group and session. */
if(pipe(pgidPipe) < 0)
{
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
return 0;
}
/* Set close-on-exec flag on the pipe's write end. */
if(fcntl(si->ErrorPipe[1], F_SETFD, FD_CLOEXEC) < 0 ||
fcntl(pgidPipe[1], F_SETFD, FD_CLOEXEC) < 0)
{
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
kwsysProcessCleanupDescriptor(&pgidPipe[0]);
kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
}
/* Block SIGINT / SIGTERM while we start. The purpose is so that our signal
handler doesn't get called from the child process after the fork and
before the exec, and subsequently start kill()'ing PIDs from ForkPIDs. */
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0)
{
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
kwsysProcessCleanupDescriptor(&pgidPipe[0]);
kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
}
@@ -1774,13 +1881,19 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
#if defined(__VMS)
/* VMS needs vfork and execvp to be in the same function because
they use setjmp/longjmp to run the child startup code in the
parent! TODO: OptionDetach. */
parent! TODO: OptionDetach. Also
TODO: CreateProcessGroup. */
cp->ForkPIDs[prIndex] = vfork();
#else
cp->ForkPIDs[prIndex] = kwsysProcessFork(cp, si);
#endif
if(cp->ForkPIDs[prIndex] < 0)
{
sigprocmask(SIG_SETMASK, &old_mask, 0);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
kwsysProcessCleanupDescriptor(&pgidPipe[0]);
kwsysProcessCleanupDescriptor(&pgidPipe[1]);
return 0;
}
@@ -1790,8 +1903,10 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
/* Specify standard pipes for child process. */
decc$set_child_standard_streams(si->StdIn, si->StdOut, si->StdErr);
#else
/* Close the read end of the error reporting pipe. */
/* Close the read end of the error reporting / process group
setup pipe. */
close(si->ErrorPipe[0]);
close(pgidPipe[0]);
/* Setup the stdin, stdout, and stderr pipes. */
if(si->StdIn > 0)
@@ -1819,11 +1934,25 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
/* Restore all default signal handlers. */
kwsysProcessRestoreDefaultSignalHandlers();
/* Now that we have restored default signal handling and created the
process group, restore mask. */
sigprocmask(SIG_SETMASK, &old_mask, 0);
/* Create new process group. We use setsid instead of setpgid to avoid
the child getting hung up on signals like SIGTTOU. (In the real world,
this has been observed where "git svn" ends up calling the "resize"
program which opens /dev/tty. */
if(cp->CreateProcessGroup && setsid() < 0)
{
kwsysProcessChildErrorExit(si->ErrorPipe[1]);
}
#endif
/* Execute the real process. If successful, this does not return. */
execvp(cp->Commands[prIndex][0], cp->Commands[prIndex]);
/* TODO: What does VMS do if the child fails to start? */
/* TODO: On VMS, how do we put the process in a new group? */
/* Failure. Report error to parent and terminate. */
kwsysProcessChildErrorExit(si->ErrorPipe[1]);
@@ -1834,12 +1963,34 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex,
decc$set_child_standard_streams(0, 1, 2);
#endif
/* We are done with the error reporting pipe and process group setup pipe
write end. */
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
kwsysProcessCleanupDescriptor(&pgidPipe[1]);
/* Make sure the child is in the process group before we proceed. This
avoids race conditions with calls to the kill function that we make for
signalling process groups. */
while((readRes = read(pgidPipe[0], &tmp, 1)) > 0);
if(readRes < 0)
{
sigprocmask(SIG_SETMASK, &old_mask, 0);
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
kwsysProcessCleanupDescriptor(&pgidPipe[0]);
return 0;
}
kwsysProcessCleanupDescriptor(&pgidPipe[0]);
/* Unmask signals. */
if(sigprocmask(SIG_SETMASK, &old_mask, 0) < 0)
{
kwsysProcessCleanupDescriptor(&si->ErrorPipe[0]);
return 0;
}
/* A child has been created. */
++cp->CommandsLeft;
/* We are done with the error reporting pipe write end. */
kwsysProcessCleanupDescriptor(&si->ErrorPipe[1]);
/* Block until the child's exec call succeeds and closes the error
pipe or writes data to the pipe to report an error. */
{
@@ -1877,6 +2028,17 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
/* A child process has terminated. Reap it if it is one handled by
this object. */
int i;
/* Temporarily disable signals that access ForkPIDs. We don't want them to
read a reaped PID, and writes to ForkPIDs are not atomic. */
sigset_t mask, old_mask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGTERM);
if(sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0)
{
return;
}
for(i=0; i < cp->NumberOfCommands; ++i)
{
if(cp->ForkPIDs[i])
@@ -1910,6 +2072,9 @@ static void kwsysProcessDestroy(kwsysProcess* cp)
}
}
}
/* Re-enable signals. */
sigprocmask(SIG_SETMASK, &old_mask, 0);
}
/*--------------------------------------------------------------------------*/
@@ -1938,7 +2103,7 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
/* Assign the replacement descriptor. */
*p = fout;
return 1;
return 1;
}
/*--------------------------------------------------------------------------*/
@@ -2582,19 +2747,23 @@ typedef struct kwsysProcessInstances_s
} kwsysProcessInstances;
static kwsysProcessInstances kwsysProcesses;
/* The old SIGCHLD handler. */
/* The old SIGCHLD / SIGINT / SIGTERM handlers. */
static struct sigaction kwsysProcessesOldSigChldAction;
static struct sigaction kwsysProcessesOldSigIntAction;
static struct sigaction kwsysProcessesOldSigTermAction;
/*--------------------------------------------------------------------------*/
static void kwsysProcessesUpdate(kwsysProcessInstances* newProcesses)
{
/* Block SIGCHLD while we update the set of pipes to check.
/* Block signals while we update the set of pipes to check.
TODO: sigprocmask is undefined for threaded apps. See
pthread_sigmask. */
sigset_t newset;
sigset_t oldset;
sigemptyset(&newset);
sigaddset(&newset, SIGCHLD);
sigaddset(&newset, SIGINT);
sigaddset(&newset, SIGTERM);
sigprocmask(SIG_BLOCK, &newset, &oldset);
/* Store the new set in that seen by the signal handler. */
@@ -2686,21 +2855,36 @@ static int kwsysProcessesAdd(kwsysProcess* cp)
{
/* Install our handler for SIGCHLD. Repeat call until it is not
interrupted. */
struct sigaction newSigChldAction;
memset(&newSigChldAction, 0, sizeof(struct sigaction));
struct sigaction newSigAction;
memset(&newSigAction, 0, sizeof(struct sigaction));
#if KWSYSPE_USE_SIGINFO
newSigChldAction.sa_sigaction = kwsysProcessesSignalHandler;
newSigChldAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
newSigAction.sa_sigaction = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
# ifdef SA_RESTART
newSigChldAction.sa_flags |= SA_RESTART;
newSigAction.sa_flags |= SA_RESTART;
# endif
#else
newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
newSigChldAction.sa_flags = SA_NOCLDSTOP;
newSigAction.sa_handler = kwsysProcessesSignalHandler;
newSigAction.sa_flags = SA_NOCLDSTOP;
#endif
while((sigaction(SIGCHLD, &newSigChldAction,
sigemptyset(&newSigAction.sa_mask);
while((sigaction(SIGCHLD, &newSigAction,
&kwsysProcessesOldSigChldAction) < 0) &&
(errno == EINTR));
/* Install our handler for SIGINT / SIGTERM. Repeat call until
it is not interrupted. */
sigemptyset(&newSigAction.sa_mask);
sigaddset(&newSigAction.sa_mask, SIGTERM);
while((sigaction(SIGINT, &newSigAction,
&kwsysProcessesOldSigIntAction) < 0) &&
(errno == EINTR));
sigemptyset(&newSigAction.sa_mask);
sigaddset(&newSigAction.sa_mask, SIGINT);
while((sigaction(SIGTERM, &newSigAction,
&kwsysProcessesOldSigIntAction) < 0) &&
(errno == EINTR));
}
}
@@ -2734,10 +2918,14 @@ static void kwsysProcessesRemove(kwsysProcess* cp)
/* If this was the last process, disable the signal handler. */
if(newProcesses.Count == 0)
{
/* Restore the SIGCHLD handler. Repeat call until it is not
/* Restore the signal handlers. Repeat call until it is not
interrupted. */
while((sigaction(SIGCHLD, &kwsysProcessesOldSigChldAction, 0) < 0) &&
(errno == EINTR));
while((sigaction(SIGINT, &kwsysProcessesOldSigIntAction, 0) < 0) &&
(errno == EINTR));
while((sigaction(SIGTERM, &kwsysProcessesOldSigTermAction, 0) < 0) &&
(errno == EINTR));
/* Free the table of process pointers since it is now empty.
This is safe because the signal handler has been removed. */
@@ -2763,39 +2951,108 @@ static void kwsysProcessesSignalHandler(int signum
#endif
)
{
(void)signum;
int i, j, procStatus, old_errno = errno;
#if KWSYSPE_USE_SIGINFO
(void)info;
(void)ucontext;
#endif
/* Signal all process objects that a child has terminated. */
{
int i;
for(i=0; i < kwsysProcesses.Count; ++i)
switch(signum)
{
/* Set the pipe in a signalled state. */
char buf = 1;
kwsysProcess* cp = kwsysProcesses.Processes[i];
kwsysProcess_ssize_t status=
read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
(void)status;
status=write(cp->SignalPipe, &buf, 1);
(void)status;
case SIGCHLD:
for(i=0; i < kwsysProcesses.Count; ++i)
{
/* Set the pipe in a signalled state. */
char buf = 1;
kwsysProcess* cp = kwsysProcesses.Processes[i];
kwsysProcess_ssize_t pipeStatus=
read(cp->PipeReadEnds[KWSYSPE_PIPE_SIGNAL], &buf, 1);
(void)pipeStatus;
pipeStatus=write(cp->SignalPipe, &buf, 1);
(void)pipeStatus;
}
break;
case SIGINT:
case SIGTERM:
/* Signal child processes that are running in new process groups. */
for(i=0; i < kwsysProcesses.Count; ++i)
{
kwsysProcess* cp = kwsysProcesses.Processes[i];
/* Check Killed to avoid data race condition when killing.
Check State to avoid data race condition in kwsysProcessCleanup
when there is an error (it leaves a reaped PID). */
if(cp->CreateProcessGroup && !cp->Killed &&
cp->State != kwsysProcess_State_Error && cp->ForkPIDs)
{
for(j=0; j < cp->NumberOfCommands; ++j)
{
/* Make sure the PID is still valid. */
if(cp->ForkPIDs[j])
{
/* The user created a process group for this process. The group ID
is the process ID for the original process in the group. */
kill(-cp->ForkPIDs[j], SIGINT);
}
}
}
}
/* Wait for all processes to terminate. */
while(wait(&procStatus) >= 0 || errno != ECHILD)
{
}
/* Terminate the process, which is now in an inconsistent state
because we reaped all the PIDs that it may have been reaping
or may have reaped in the future. Reraise the signal so that
the proper exit code is returned. */
{
/* Install default signal handler. */
struct sigaction defSigAction;
sigset_t unblockSet;
memset(&defSigAction, 0, sizeof(defSigAction));
defSigAction.sa_handler = SIG_DFL;
sigemptyset(&defSigAction.sa_mask);
while((sigaction(signum, &defSigAction, 0) < 0) &&
(errno == EINTR));
/* Unmask the signal. */
sigemptyset(&unblockSet);
sigaddset(&unblockSet, signum);
sigprocmask(SIG_UNBLOCK, &unblockSet, 0);
/* Raise the signal again. */
raise(signum);
/* We shouldn't get here... but if we do... */
_exit(1);
}
/* break omitted to silence unreachable code clang compiler warning. */
}
}
#if !KWSYSPE_USE_SIGINFO
/* Re-Install our handler for SIGCHLD. Repeat call until it is not
interrupted. */
/* Re-Install our handler. Repeat call until it is not interrupted. */
{
struct sigaction newSigChldAction;
memset(&newSigChldAction, 0, sizeof(struct sigaction));
struct sigaction newSigAction;
struct sigaction &oldSigAction;
memset(&newSigAction, 0, sizeof(struct sigaction));
newSigChldAction.sa_handler = kwsysProcessesSignalHandler;
newSigChldAction.sa_flags = SA_NOCLDSTOP;
while((sigaction(SIGCHLD, &newSigChldAction,
&kwsysProcessesOldSigChldAction) < 0) &&
sigemptyset(&newSigAction.sa_mask);
switch(signum)
{
case SIGCHLD: oldSigAction = &kwsysProcessesOldSigChldAction; break;
case SIGINT:
sigaddset(&newSigAction.sa_mask, SIGTERM);
oldSigAction = &kwsysProcessesOldSigIntAction; break;
case SIGTERM:
sigaddset(&newSigAction.sa_mask, SIGINT);
oldSigAction = &kwsysProcessesOldSigTermAction; break;
default: return 0;
}
while((sigaction(signum, &newSigAction,
oldSigAction) < 0) &&
(errno == EINTR));
}
#endif
errno = old_errno;
}
+409 -53
View File
@@ -109,14 +109,15 @@ static DWORD WINAPI kwsysProcessPipeThreadWake(LPVOID ptd);
static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp,
kwsysProcessPipeData* td);
static int kwsysProcessInitialize(kwsysProcess* cp);
static int kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCreateInformation* si);
static DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCreateInformation* si);
static void kwsysProcessDestroy(kwsysProcess* cp, int event);
static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
static DWORD kwsysProcessSetupOutputPipeFile(PHANDLE handle,
const char* name);
static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle);
static void kwsysProcessCleanupHandle(PHANDLE h);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanup(kwsysProcess* cp, DWORD error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
kwsysProcessTime* timeoutTime);
@@ -133,6 +134,13 @@ static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProc
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
static void kwsysProcessKillTree(int pid);
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
static int kwsysProcessesInitialize(void);
static int kwsysTryEnterCreateProcessSection(void);
static void kwsysLeaveCreateProcessSection(void);
static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessId,
int newProcessGroup);
static void kwsysProcessesRemove(HANDLE hProcess);
static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType);
/*--------------------------------------------------------------------------*/
/* A structure containing synchronization data for each thread. */
@@ -222,6 +230,9 @@ struct kwsysProcess_s
/* Whether to merge stdout/stderr of the child. */
int MergeOutput;
/* Whether to create the process in a new process group. */
int CreateProcessGroup;
/* Mutex to protect the shared index used by threads to report data. */
HANDLE SharedIndexMutex;
@@ -321,6 +332,16 @@ kwsysProcess* kwsysProcess_New(void)
/* Windows version number data. */
OSVERSIONINFO osv;
/* Initialize list of processes before we get any farther. It's especially
important that the console Ctrl handler be added BEFORE starting the
first process. This prevents the risk of an orphaned process being
started by the main thread while the default Ctrl handler is in
progress. */
if(!kwsysProcessesInitialize())
{
return 0;
}
/* Allocate a process control structure. */
cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
if(!cp)
@@ -836,6 +857,8 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
case kwsysProcess_Option_HideWindow: return cp->HideWindow;
case kwsysProcess_Option_MergeOutput: return cp->MergeOutput;
case kwsysProcess_Option_Verbatim: return cp->Verbatim;
case kwsysProcess_Option_CreateProcessGroup:
return cp->CreateProcessGroup;
default: return 0;
}
}
@@ -854,6 +877,8 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break;
case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break;
case kwsysProcess_Option_CreateProcessGroup:
cp->CreateProcessGroup = value; break;
default: break;
}
}
@@ -945,7 +970,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
if(!GetCurrentDirectoryW(cp->RealWorkingDirectoryLength,
cp->RealWorkingDirectory))
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, GetLastError());
return;
}
SetCurrentDirectoryW(cp->WorkingDirectory);
@@ -957,14 +982,16 @@ void kwsysProcess_Execute(kwsysProcess* cp)
{
/* Create a handle to read a file for stdin. */
wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN);
DWORD error;
cp->PipeChildStd[0] =
CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
0, OPEN_EXISTING, 0, 0);
error = GetLastError(); /* Check now in case free changes this. */
free(wstdin);
if(cp->PipeChildStd[0] == INVALID_HANDLE_VALUE)
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, error);
return;
}
}
@@ -990,17 +1017,18 @@ void kwsysProcess_Execute(kwsysProcess* cp)
if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read,
&cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0))
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, GetLastError());
return;
}
if(cp->PipeFileSTDOUT)
{
/* Use a file for stdout. */
if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1],
cp->PipeFileSTDOUT))
DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1],
cp->PipeFileSTDOUT);
if(error)
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, error);
return;
}
}
@@ -1023,7 +1051,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
GetCurrentProcess(), &cp->PipeChildStd[1],
0, FALSE, DUPLICATE_SAME_ACCESS))
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, GetLastError());
return;
}
}
@@ -1034,17 +1062,18 @@ void kwsysProcess_Execute(kwsysProcess* cp)
if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read,
&cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0))
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, GetLastError());
return;
}
if(cp->PipeFileSTDERR)
{
/* Use a file for stderr. */
if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2],
cp->PipeFileSTDERR))
DWORD error = kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2],
cp->PipeFileSTDERR);
if(error)
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, error);
return;
}
}
@@ -1067,7 +1096,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
GetCurrentProcess(), &cp->PipeChildStd[2],
0, FALSE, DUPLICATE_SAME_ACCESS))
{
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, GetLastError());
return;
}
}
@@ -1106,11 +1135,12 @@ void kwsysProcess_Execute(kwsysProcess* cp)
HANDLE p[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
if (!CreatePipe(&p[0], &p[1], 0, 0))
{
DWORD error = GetLastError();
if (nextStdInput != cp->PipeChildStd[0])
{
kwsysProcessCleanupHandle(&nextStdInput);
}
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, error);
return;
}
nextStdInput = p[0];
@@ -1119,7 +1149,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
si.hStdError = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2];
{
int res = kwsysProcessCreate(cp, i, &si);
DWORD error = kwsysProcessCreate(cp, i, &si);
/* Close our copies of pipes used between children. */
if (si.hStdInput != cp->PipeChildStd[0])
@@ -1134,7 +1164,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
{
kwsysProcessCleanupHandle(&si.hStdError);
}
if (res)
if (!error)
{
cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess;
}
@@ -1144,7 +1174,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
{
kwsysProcessCleanupHandle(&nextStdInput);
}
kwsysProcessCleanup(cp, 1);
kwsysProcessCleanup(cp, error);
return;
}
}
@@ -1459,6 +1489,52 @@ int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
return 1;
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_Interrupt(kwsysProcess* cp)
{
int i;
/* Make sure we are executing a process. */
if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
cp->Killed)
{
KWSYSPE_DEBUG((stderr, "interrupt: child not executing\n"));
return;
}
/* Skip actually interrupting the child if it has already terminated. */
if(cp->Terminated)
{
KWSYSPE_DEBUG((stderr, "interrupt: child already terminated\n"));
return;
}
/* Interrupt the children. */
if (cp->CreateProcessGroup)
{
if(cp->ProcessInformation)
{
for(i=0; i < cp->NumberOfCommands; ++i)
{
/* Make sure the process handle isn't closed (e.g. from disowning). */
if(cp->ProcessInformation[i].hProcess)
{
/* The user created a process group for this process. The group ID
is the process ID for the original process in the group. Note
that we have to use Ctrl+Break: Ctrl+C is not allowed for process
groups. */
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT,
cp->ProcessInformation[i].dwProcessId);
}
}
}
}
else
{
/* No process group was created. Kill our own process group... */
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
}
}
/*--------------------------------------------------------------------------*/
void kwsysProcess_Kill(kwsysProcess* cp)
{
@@ -1487,7 +1563,8 @@ void kwsysProcess_Kill(kwsysProcess* cp)
for(i=0; i < cp->NumberOfCommands; ++i)
{
kwsysProcessKillTree(cp->ProcessInformation[i].dwProcessId);
// close the handle if we kill it
/* Remove from global list of processes and close handles. */
kwsysProcessesRemove(cp->ProcessInformation[i].hProcess);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
@@ -1686,7 +1763,7 @@ int kwsysProcessInitialize(kwsysProcess* cp)
}
/*--------------------------------------------------------------------------*/
static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
static DWORD kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
{
DWORD flags;
@@ -1697,13 +1774,19 @@ static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
if (flags & HANDLE_FLAG_INHERIT)
{
*out = in;
return 1;
return ERROR_SUCCESS;
}
/* Create an inherited copy of this handle. */
return DuplicateHandle(GetCurrentProcess(), in,
GetCurrentProcess(), out,
0, TRUE, DUPLICATE_SAME_ACCESS);
if (DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), out,
0, TRUE, DUPLICATE_SAME_ACCESS))
{
return ERROR_SUCCESS;
}
else
{
return GetLastError();
}
}
else
{
@@ -1719,29 +1802,46 @@ static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn)
(GENERIC_WRITE | FILE_READ_ATTRIBUTES)),
FILE_SHARE_READ|FILE_SHARE_WRITE,
&sa, OPEN_EXISTING, 0, 0);
return *out != INVALID_HANDLE_VALUE;
return (*out != INVALID_HANDLE_VALUE) ? ERROR_SUCCESS : GetLastError();
}
}
/*--------------------------------------------------------------------------*/
int kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCreateInformation* si)
DWORD kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCreateInformation* si)
{
int res =
DWORD creationFlags;
DWORD error = ERROR_SUCCESS;
/* Create inherited copies the handles. */
kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput,
si->hStdInput, 1) &&
kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput,
si->hStdOutput, 0) &&
kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError,
si->hStdError, 0) &&
/* Check if we are currently exiting. */
if (!kwsysTryEnterCreateProcessSection())
{
/* The Ctrl handler is currently working on exiting our process. Rather
than return an error code, which could cause incorrect conclusions to be
reached by the caller, we simply hang. (For example, a CMake try_run
configure step might cause the project to configure wrong.) */
Sleep(INFINITE);
}
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0,
0, &si->StartupInfo, &cp->ProcessInformation[index]);
/* Create the child in a suspended state so we can wait until all
children have been created before running any one. */
creationFlags = CREATE_SUSPENDED;
if (cp->CreateProcessGroup)
{
creationFlags |= CREATE_NEW_PROCESS_GROUP;
}
/* Create inherited copies of the handles. */
(error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput,
si->hStdInput, 1)) ||
(error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput,
si->hStdOutput, 0)) ||
(error = kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError,
si->hStdError, 0)) ||
/* Create the process. */
(!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, creationFlags, 0,
0, &si->StartupInfo, &cp->ProcessInformation[index]) &&
(error = GetLastError()));
/* Close the inherited copies of the handles. */
if (si->StartupInfo.hStdInput != si->hStdInput)
@@ -1757,7 +1857,23 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
kwsysProcessCleanupHandle(&si->StartupInfo.hStdError);
}
return res;
/* Add the process to the global list of processes. */
if (!error &&
!kwsysProcessesAdd(cp->ProcessInformation[index].hProcess,
cp->ProcessInformation[index].dwProcessId, cp->CreateProcessGroup))
{
/* This failed for some reason. Kill the suspended process. */
TerminateProcess(cp->ProcessInformation[index].hProcess, 1);
/* And clean up... */
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hThread);
strcpy(cp->ErrorMessage, "kwsysProcessesAdd function failed");
error = ERROR_NOT_ENOUGH_MEMORY; /* Most likely reason. */
}
/* If the console Ctrl handler is waiting for us, this will release it... */
kwsysLeaveCreateProcessSection();
return error;
}
/*--------------------------------------------------------------------------*/
@@ -1779,6 +1895,9 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
GetExitCodeProcess(cp->ProcessInformation[index].hProcess,
&cp->CommandExitCodes[index]);
/* Remove from global list of processes. */
kwsysProcessesRemove(cp->ProcessInformation[index].hProcess);
/* Close the process handle for the terminated process. */
kwsysProcessCleanupHandle(&cp->ProcessInformation[index].hProcess);
@@ -1813,13 +1932,14 @@ void kwsysProcessDestroy(kwsysProcess* cp, int event)
}
/*--------------------------------------------------------------------------*/
int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
DWORD kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
{
HANDLE fout;
wchar_t* wname;
DWORD error;
if(!name)
{
return 1;
return ERROR_INVALID_PARAMETER;
}
/* Close the existing handle. */
@@ -1829,15 +1949,16 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
wname = kwsysEncoding_DupToWide(name);
fout = CreateFileW(wname, GENERIC_WRITE, FILE_SHARE_READ, 0,
CREATE_ALWAYS, 0, 0);
error = GetLastError();
free(wname);
if(fout == INVALID_HANDLE_VALUE)
{
return 0;
return error;
}
/* Assign the replacement handle. */
*phandle = fout;
return 1;
return ERROR_SUCCESS;
}
/*--------------------------------------------------------------------------*/
@@ -1876,7 +1997,7 @@ void kwsysProcessCleanupHandle(PHANDLE h)
/*--------------------------------------------------------------------------*/
/* Close all handles created by kwsysProcess_Execute. */
void kwsysProcessCleanup(kwsysProcess* cp, int error)
void kwsysProcessCleanup(kwsysProcess* cp, DWORD error)
{
int i;
/* If this is an error case, report the error. */
@@ -1886,21 +2007,27 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
if(cp->ErrorMessage[0] == 0)
{
/* Format the error message. */
DWORD original = GetLastError();
wchar_t err_msg[KWSYSPE_PIPE_BUFFER_SIZE];
DWORD length = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
FORMAT_MESSAGE_IGNORE_INSERTS, 0, error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_msg, KWSYSPE_PIPE_BUFFER_SIZE, 0);
WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage,
KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL);
if(length < 1)
{
/* FormatMessage failed. Use a default message. */
_snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
"Process execution failed with error 0x%X. "
"FormatMessage failed with error 0x%X",
original, GetLastError());
error, GetLastError());
}
if(!WideCharToMultiByte(CP_UTF8, 0, err_msg, -1, cp->ErrorMessage,
KWSYSPE_PIPE_BUFFER_SIZE, NULL, NULL))
{
/* WideCharToMultiByte failed. Use a default message. */
_snprintf(cp->ErrorMessage, KWSYSPE_PIPE_BUFFER_SIZE,
"Process execution failed with error 0x%X. "
"WideCharToMultiByte failed with error 0x%X",
error, GetLastError());
}
}
@@ -1923,6 +2050,8 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error)
}
for(i=0; i < cp->NumberOfCommands; ++i)
{
/* Remove from global list of processes and close handles. */
kwsysProcessesRemove(cp->ProcessInformation[i].hProcess);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hThread);
kwsysProcessCleanupHandle(&cp->ProcessInformation[i].hProcess);
}
@@ -2659,3 +2788,230 @@ static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Reader.Go, 1, 0);
}
}
/*--------------------------------------------------------------------------*/
/* Global set of executing processes for use by the Ctrl handler.
This global instance will be zero-initialized by the compiler.
Note that the console Ctrl handler runs on a background thread and so
everything it does must be thread safe. Here, we track the hProcess
HANDLEs directly instead of kwsysProcess instances, so that we don't have
to make kwsysProcess thread safe. */
typedef struct kwsysProcessInstance_s
{
HANDLE hProcess;
DWORD dwProcessId;
int NewProcessGroup; /* Whether the process was created in a new group. */
} kwsysProcessInstance;
typedef struct kwsysProcessInstances_s
{
/* Whether we have initialized key fields below, like critical sections. */
int Initialized;
/* Ctrl handler runs on a different thread, so we must sync access. */
CRITICAL_SECTION Lock;
int Exiting;
size_t Count;
size_t Size;
kwsysProcessInstance* Processes;
} kwsysProcessInstances;
static kwsysProcessInstances kwsysProcesses;
/*--------------------------------------------------------------------------*/
/* Initialize critial section and set up console Ctrl handler. You MUST call
this before using any other kwsysProcesses* functions below. */
static int kwsysProcessesInitialize(void)
{
/* Initialize everything if not done already. */
if(!kwsysProcesses.Initialized)
{
InitializeCriticalSection(&kwsysProcesses.Lock);
/* Set up console ctrl handler. */
if(!SetConsoleCtrlHandler(kwsysCtrlHandler, TRUE))
{
return 0;
}
kwsysProcesses.Initialized = 1;
}
return 1;
}
/*--------------------------------------------------------------------------*/
/* The Ctrl handler waits on the global list of processes. To prevent an
orphaned process, do not create a new process if the Ctrl handler is
already running. Do so by using this function to check if it is ok to
create a process. */
static int kwsysTryEnterCreateProcessSection(void)
{
/* Enter main critical section; this means creating a process and the Ctrl
handler are mutually exclusive. */
EnterCriticalSection(&kwsysProcesses.Lock);
/* Indicate to the caller if they can create a process. */
if(kwsysProcesses.Exiting)
{
LeaveCriticalSection(&kwsysProcesses.Lock);
return 0;
}
else
{
return 1;
}
}
/*--------------------------------------------------------------------------*/
/* Matching function on successful kwsysTryEnterCreateProcessSection return.
Make sure you called kwsysProcessesAdd if applicable before calling this.*/
static void kwsysLeaveCreateProcessSection(void)
{
LeaveCriticalSection(&kwsysProcesses.Lock);
}
/*--------------------------------------------------------------------------*/
/* Add new process to global process list. The Ctrl handler will wait for
the process to exit before it returns. Do not close the process handle
until after calling kwsysProcessesRemove. The newProcessGroup parameter
must be set if the process was created with CREATE_NEW_PROCESS_GROUP. */
static int kwsysProcessesAdd(HANDLE hProcess, DWORD dwProcessid,
int newProcessGroup)
{
if(!kwsysProcessesInitialize() || !hProcess ||
hProcess == INVALID_HANDLE_VALUE)
{
return 0;
}
/* Enter the critical section. */
EnterCriticalSection(&kwsysProcesses.Lock);
/* Make sure there is enough space for the new process handle. */
if(kwsysProcesses.Count == kwsysProcesses.Size)
{
size_t newSize;
kwsysProcessInstance *newArray;
/* Start with enough space for a small number of process handles
and double the size each time more is needed. */
newSize = kwsysProcesses.Size? kwsysProcesses.Size*2 : 4;
/* Try allocating the new block of memory. */
if(newArray = (kwsysProcessInstance*)malloc(
newSize*sizeof(kwsysProcessInstance)))
{
/* Copy the old process handles to the new memory. */
if(kwsysProcesses.Count > 0)
{
memcpy(newArray, kwsysProcesses.Processes,
kwsysProcesses.Count * sizeof(kwsysProcessInstance));
}
}
else
{
/* Failed to allocate memory for the new process handle set. */
LeaveCriticalSection(&kwsysProcesses.Lock);
return 0;
}
/* Free original array. */
free(kwsysProcesses.Processes);
/* Update original structure with new allocation. */
kwsysProcesses.Size = newSize;
kwsysProcesses.Processes = newArray;
}
/* Append the new process information to the set. */
kwsysProcesses.Processes[kwsysProcesses.Count].hProcess = hProcess;
kwsysProcesses.Processes[kwsysProcesses.Count].dwProcessId = dwProcessid;
kwsysProcesses.Processes[kwsysProcesses.Count++].NewProcessGroup =
newProcessGroup;
/* Leave critical section and return success. */
LeaveCriticalSection(&kwsysProcesses.Lock);
return 1;
}
/*--------------------------------------------------------------------------*/
/* Removes process to global process list. */
static void kwsysProcessesRemove(HANDLE hProcess)
{
size_t i;
if (!hProcess || hProcess == INVALID_HANDLE_VALUE)
{
return;
}
EnterCriticalSection(&kwsysProcesses.Lock);
/* Find the given process in the set. */
for(i=0; i < kwsysProcesses.Count; ++i)
{
if(kwsysProcesses.Processes[i].hProcess == hProcess)
{
break;
}
}
if(i < kwsysProcesses.Count)
{
/* Found it! Remove the process from the set. */
--kwsysProcesses.Count;
for(; i < kwsysProcesses.Count; ++i)
{
kwsysProcesses.Processes[i] = kwsysProcesses.Processes[i+1];
}
/* If this was the last process, free the array. */
if(kwsysProcesses.Count == 0)
{
kwsysProcesses.Size = 0;
free(kwsysProcesses.Processes);
kwsysProcesses.Processes = 0;
}
}
LeaveCriticalSection(&kwsysProcesses.Lock);
}
/*--------------------------------------------------------------------------*/
static BOOL WINAPI kwsysCtrlHandler(DWORD dwCtrlType)
{
size_t i;
(void)dwCtrlType;
/* Enter critical section. */
EnterCriticalSection(&kwsysProcesses.Lock);
/* Set flag indicating that we are exiting. */
kwsysProcesses.Exiting = 1;
/* If some of our processes were created in a new process group, we must
manually interrupt them. They won't otherwise receive a Ctrl+C/Break. */
for(i=0; i < kwsysProcesses.Count; ++i)
{
if(kwsysProcesses.Processes[i].NewProcessGroup)
{
DWORD groupId = kwsysProcesses.Processes[i].dwProcessId;
if(groupId)
{
GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, groupId);
}
}
}
/* Wait for each child process to exit. This is the key step that prevents
us from leaving several orphaned children processes running in the
background when the user presses Ctrl+C. */
for(i=0; i < kwsysProcesses.Count; ++i)
{
WaitForSingleObject(kwsysProcesses.Processes[i].hProcess, INFINITE);
}
/* Leave critical section. */
LeaveCriticalSection(&kwsysProcesses.Lock);
/* Continue on to default Ctrl handler (which calls ExitProcess). */
return FALSE;
}
+16 -2
View File
@@ -3198,8 +3198,16 @@ bool SystemTools::FileIsDirectory(const kwsys_stl::string& inName)
bool SystemTools::FileIsSymlink(const kwsys_stl::string& name)
{
#if defined( _WIN32 )
(void)name;
return false;
DWORD attr = GetFileAttributesW(
SystemTools::ConvertToWindowsExtendedPath(name).c_str());
if (attr != INVALID_FILE_ATTRIBUTES)
{
return (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
}
else
{
return false;
}
#else
struct stat fs;
if(lstat(name.c_str(), &fs) == 0)
@@ -4230,6 +4238,11 @@ SystemTools::DetectFileType(const char *filename,
return SystemTools::FileTypeUnknown;
}
if (SystemTools::FileIsDirectory(filename))
{
return SystemTools::FileTypeUnknown;
}
FILE *fp = Fopen(filename, "rb");
if (!fp)
{
@@ -4243,6 +4256,7 @@ SystemTools::DetectFileType(const char *filename,
fclose(fp);
if (read_length == 0)
{
delete [] buffer;
return SystemTools::FileTypeUnknown;
}
+225 -44
View File
@@ -29,26 +29,48 @@
# include <windows.h>
#else
# include <unistd.h>
# include <signal.h>
#endif
#if defined(__BORLANDC__)
# pragma warn -8060 /* possibly incorrect assignment */
#endif
/* Platform-specific sleep functions. */
#if defined(__BEOS__) && !defined(__ZETA__)
/* BeOS 5 doesn't have usleep(), but it has snooze(), which is identical. */
# include <be/kernel/OS.h>
static inline void testProcess_usleep(unsigned int msec)
static inline void testProcess_usleep(unsigned int usec)
{
snooze(msec);
snooze(usec);
}
#elif defined(_WIN32)
/* Windows can only sleep in millisecond intervals. */
static void testProcess_usleep(unsigned int usec)
{
Sleep(usec / 1000);
}
#else
# define testProcess_usleep usleep
#endif
#if defined(_WIN32)
static void testProcess_sleep(unsigned int sec)
{
Sleep(sec*1000);
}
#else
static void testProcess_sleep(unsigned int sec)
{
sleep(sec);
}
#endif
int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout, int poll,
int repeat, int disown);
int repeat, int disown, int createNewGroup,
unsigned int interruptDelay);
static int test1(int argc, const char* argv[])
{
@@ -73,11 +95,7 @@ static int test3(int argc, const char* argv[])
fprintf(stderr, "Output before sleep on stderr from timeout test.\n");
fflush(stdout);
fflush(stderr);
#if defined(_WIN32)
Sleep(15000);
#else
sleep(15);
#endif
testProcess_sleep(15);
fprintf(stdout, "Output after sleep on stdout from timeout test.\n");
fprintf(stderr, "Output after sleep on stderr from timeout test.\n");
return 0;
@@ -102,7 +120,7 @@ static int test4(int argc, const char* argv[])
#endif
(void)argc; (void)argv;
fprintf(stdout, "Output before crash on stdout from crash test.\n");
fprintf(stderr, "Output before crash on stderr from crash test.\n");
fprintf(stderr, "Output before crash on stderr from crash test.\n");
fflush(stdout);
fflush(stderr);
assert(invalidAddress); /* Quiet Clang scan-build. */
@@ -127,7 +145,7 @@ static int test5(int argc, const char* argv[])
fflush(stdout);
fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Exception,
kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1, 0);
kwsysProcess_Exception_Fault, 1, 1, 1, 0, 15, 0, 1, 0, 0, 0);
fprintf(stdout, "Output on stdout after recursive test.\n");
fprintf(stderr, "Output on stderr after recursive test.\n");
fflush(stdout);
@@ -168,11 +186,7 @@ static int test7(int argc, const char* argv[])
fflush(stdout);
fflush(stderr);
/* Sleep for 1 second. */
#if defined(_WIN32)
Sleep(1000);
#else
sleep(1);
#endif
testProcess_sleep(1);
fprintf(stdout, "Output on stdout after sleep.\n");
fprintf(stderr, "Output on stderr after sleep.\n");
fflush(stdout);
@@ -196,7 +210,7 @@ static int test8(int argc, const char* argv[])
fflush(stdout);
fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Disowned, kwsysProcess_Exception_None,
1, 1, 1, 0, 10, 0, 1, 1);
1, 1, 1, 0, 10, 0, 1, 1, 0, 0);
fprintf(stdout, "Output on stdout after grandchild test.\n");
fprintf(stderr, "Output on stderr after grandchild test.\n");
fflush(stdout);
@@ -217,18 +231,137 @@ static int test8_grandchild(int argc, const char* argv[])
implemented. */
fclose(stdout);
fclose(stderr);
testProcess_sleep(15);
return 0;
}
static int test9(int argc, const char* argv[])
{
/* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
process. Here, we start a child process that sleeps for a long time
while ignoring signals. The test is successful if this process waits
for the child to return before exiting from the Ctrl+C handler.
WARNING: This test will falsely pass if the share parameter of runChild
was set to 0 when invoking the test9 process. */
int r;
const char* cmd[4];
(void)argc;
cmd[0] = argv[0];
cmd[1] = "run";
cmd[2] = "109";
cmd[3] = 0;
fprintf(stdout, "Output on stdout before grandchild test.\n");
fprintf(stderr, "Output on stderr before grandchild test.\n");
fflush(stdout);
fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Exited,
kwsysProcess_Exception_None,
0, 1, 1, 0, 30, 0, 1, 0, 0, 0);
/* This sleep will avoid a race condition between this function exiting
normally and our Ctrl+C handler exiting abnormally after the process
exits. */
testProcess_sleep(1);
fprintf(stdout, "Output on stdout after grandchild test.\n");
fprintf(stderr, "Output on stderr after grandchild test.\n");
fflush(stdout);
fflush(stderr);
return r;
}
#if defined(_WIN32)
Sleep(15000);
#else
sleep(15);
static BOOL WINAPI test9_grandchild_handler(DWORD dwCtrlType)
{
/* Ignore all Ctrl+C/Break signals. We must use an actual handler function
instead of using SetConsoleCtrlHandler(NULL, TRUE) so that we can also
ignore Ctrl+Break in addition to Ctrl+C. */
(void)dwCtrlType;
return TRUE;
}
#endif
static int test9_grandchild(int argc, const char* argv[])
{
/* The grandchild just sleeps for a few seconds while ignoring signals. */
(void)argc; (void)argv;
#if defined(_WIN32)
if(!SetConsoleCtrlHandler(test9_grandchild_handler, TRUE))
{
return 1;
}
#else
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
if(sigaction(SIGINT, &sa, 0) < 0)
{
return 1;
}
#endif
fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
fflush(stdout);
fflush(stderr);
/* Sleep for 9 seconds. */
testProcess_sleep(9);
fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
fflush(stdout);
fflush(stderr);
return 0;
}
static int test10(int argc, const char* argv[])
{
/* Test Ctrl+C behavior: the root test program will send a Ctrl+C to this
process. Here, we start a child process that sleeps for a long time and
processes signals normally. However, this grandchild is created in a new
process group - ensuring that Ctrl+C we receive is sent to our process
groups. We make sure it exits anyway. */
int r;
const char* cmd[4];
(void)argc;
cmd[0] = argv[0];
cmd[1] = "run";
cmd[2] = "110";
cmd[3] = 0;
fprintf(stdout, "Output on stdout before grandchild test.\n");
fprintf(stderr, "Output on stderr before grandchild test.\n");
fflush(stdout);
fflush(stderr);
r = runChild(cmd, kwsysProcess_State_Exception,
kwsysProcess_Exception_Interrupt,
0, 1, 1, 0, 30, 0, 1, 0, 1, 0);
fprintf(stdout, "Output on stdout after grandchild test.\n");
fprintf(stderr, "Output on stderr after grandchild test.\n");
fflush(stdout);
fflush(stderr);
return r;
}
static int test10_grandchild(int argc, const char* argv[])
{
/* The grandchild just sleeps for a few seconds and handles signals. */
(void)argc; (void)argv;
fprintf(stdout, "Output on stdout from grandchild before sleep.\n");
fprintf(stderr, "Output on stderr from grandchild before sleep.\n");
fflush(stdout);
fflush(stderr);
/* Sleep for 6 seconds. */
testProcess_sleep(6);
fprintf(stdout, "Output on stdout from grandchild after sleep.\n");
fprintf(stderr, "Output on stderr from grandchild after sleep.\n");
fflush(stdout);
fflush(stderr);
return 0;
}
static int runChild2(kwsysProcess* kp,
const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout,
int poll, int disown)
int poll, int disown, int createNewGroup,
unsigned int interruptDelay)
{
int result = 0;
char* data = 0;
@@ -249,6 +382,10 @@ static int runChild2(kwsysProcess* kp,
{
kwsysProcess_SetOption(kp, kwsysProcess_Option_Detach, 1);
}
if(createNewGroup)
{
kwsysProcess_SetOption(kp, kwsysProcess_Option_CreateProcessGroup, 1);
}
kwsysProcess_Execute(kp);
if(poll)
@@ -256,6 +393,12 @@ static int runChild2(kwsysProcess* kp,
pUserTimeout = &userTimeout;
}
if(interruptDelay)
{
testProcess_sleep(interruptDelay);
kwsysProcess_Interrupt(kp);
}
if(!share && !disown)
{
int p;
@@ -286,17 +429,13 @@ static int runChild2(kwsysProcess* kp,
if(poll)
{
/* Delay to avoid busy loop during polling. */
#if defined(_WIN32)
Sleep(100);
#else
testProcess_usleep(100000);
#endif
}
if(delay)
{
/* Purposely sleeping only on Win32 to let pipe fill up. */
#if defined(_WIN32)
Sleep(100);
testProcess_usleep(100000);
#endif
}
}
@@ -337,7 +476,7 @@ static int runChild2(kwsysProcess* kp,
printf("Error in administrating child process: [%s]\n",
kwsysProcess_GetErrorString(kp)); break;
};
if(result)
{
if(exception != kwsysProcess_GetExitException(kp))
@@ -353,7 +492,7 @@ static int runChild2(kwsysProcess* kp,
value, kwsysProcess_GetExitValue(kp));
}
}
if(kwsysProcess_GetState(kp) != state)
{
fprintf(stderr, "Mismatch in state. "
@@ -374,9 +513,37 @@ static int runChild2(kwsysProcess* kp,
return result;
}
/**
* Runs a child process and blocks until it returns. Arguments as follows:
*
* cmd = Command line to run.
* state = Expected return value of kwsysProcess_GetState after exit.
* exception = Expected return value of kwsysProcess_GetExitException.
* value = Expected return value of kwsysProcess_GetExitValue.
* share = Whether to share stdout/stderr child pipes with our pipes
* by way of kwsysProcess_SetPipeShared. If false, new pipes
* are created.
* output = If !share && !disown, whether to write the child's stdout
* and stderr output to our stdout.
* delay = If !share && !disown, adds an additional short delay to
* the pipe loop to allow the pipes to fill up; Windows only.
* timeout = Non-zero to sets a timeout in seconds via
* kwsysProcess_SetTimeout.
* poll = If !share && !disown, we count the number of 0.1 second
* intervals where the child pipes had no new data. We fail
* if not in the bounds of MINPOLL/MAXPOLL.
* repeat = Number of times to run the process.
* disown = If set, the process is disowned.
* createNewGroup = If set, the process is created in a new process group.
* interruptDelay = If non-zero, number of seconds to delay before
* interrupting the process. Note that this delay will occur
* BEFORE any reading/polling of pipes occurs and before any
* detachment occurs.
*/
int runChild(const char* cmd[], int state, int exception, int value,
int share, int output, int delay, double timeout,
int poll, int repeat, int disown)
int poll, int repeat, int disown, int createNewGroup,
unsigned int interruptDelay)
{
int result = 1;
kwsysProcess* kp = kwsysProcess_New();
@@ -388,7 +555,8 @@ int runChild(const char* cmd[], int state, int exception, int value,
while(repeat-- > 0)
{
result = runChild2(kp, cmd, state, exception, value, share,
output, delay, timeout, poll, disown);
output, delay, timeout, poll, disown, createNewGroup,
interruptDelay);
}
kwsysProcess_Delete(kp);
return result;
@@ -435,7 +603,7 @@ int main(int argc, const char* argv[])
n = atoi(argv[2]);
}
/* Check arguments. */
if(((n >= 1 && n <= 8) || n == 108) && argc == 3)
if(((n >= 1 && n <= 10) || n == 108 || n == 109 || n == 110) && argc == 3)
{
/* This is the child process for a requested test number. */
switch (n)
@@ -448,15 +616,19 @@ int main(int argc, const char* argv[])
case 6: test6(argc, argv); return 0;
case 7: return test7(argc, argv);
case 8: return test8(argc, argv);
case 9: return test9(argc, argv);
case 10: return test10(argc, argv);
case 108: return test8_grandchild(argc, argv);
case 109: return test9_grandchild(argc, argv);
case 110: return test10_grandchild(argc, argv);
}
fprintf(stderr, "Invalid test number %d.\n", n);
return 1;
}
else if(n >= 1 && n <= 8)
else if(n >= 1 && n <= 10)
{
/* This is the parent process for a requested test number. */
int states[8] =
int states[10] =
{
kwsysProcess_State_Exited,
kwsysProcess_State_Exited,
@@ -465,9 +637,11 @@ int main(int argc, const char* argv[])
kwsysProcess_State_Exited,
kwsysProcess_State_Expired,
kwsysProcess_State_Exited,
kwsysProcess_State_Exited
kwsysProcess_State_Exited,
kwsysProcess_State_Expired, /* Ctrl+C handler test */
kwsysProcess_State_Exception /* Process group test */
};
int exceptions[8] =
int exceptions[10] =
{
kwsysProcess_Exception_None,
kwsysProcess_Exception_None,
@@ -476,14 +650,19 @@ int main(int argc, const char* argv[])
kwsysProcess_Exception_None,
kwsysProcess_Exception_None,
kwsysProcess_Exception_None,
kwsysProcess_Exception_None
kwsysProcess_Exception_None,
kwsysProcess_Exception_None,
kwsysProcess_Exception_Interrupt
};
int values[8] = {0, 123, 1, 1, 0, 0, 0, 0};
int outputs[8] = {1, 1, 1, 1, 1, 0, 1, 1};
int delays[8] = {0, 0, 0, 0, 0, 1, 0, 0};
double timeouts[8] = {10, 10, 10, 30, 30, 10, -1, 10};
int polls[8] = {0, 0, 0, 0, 0, 0, 1, 0};
int repeat[8] = {2, 1, 1, 1, 1, 1, 1, 1};
int values[10] = {0, 123, 1, 1, 0, 0, 0, 0, 1, 1};
int shares[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1};
int outputs[10] = {1, 1, 1, 1, 1, 0, 1, 1, 1, 1};
int delays[10] = {0, 0, 0, 0, 0, 1, 0, 0, 0, 0};
double timeouts[10] = {10, 10, 10, 30, 30, 10, -1, 10, 6, 4};
int polls[10] = {0, 0, 0, 0, 0, 0, 1, 0, 0, 0};
int repeat[10] = {2, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int createNewGroups[10] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1};
unsigned int interruptDelays[10] = {0, 0, 0, 0, 0, 0, 0, 0, 3, 2};
int r;
const char* cmd[4];
#ifdef _WIN32
@@ -515,9 +694,10 @@ int main(int argc, const char* argv[])
fprintf(stderr, "Output on stderr before test %d.\n", n);
fflush(stdout);
fflush(stderr);
r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], 0,
r = runChild(cmd, states[n-1], exceptions[n-1], values[n-1], shares[n-1],
outputs[n-1], delays[n-1], timeouts[n-1],
polls[n-1], repeat[n-1], 0);
polls[n-1], repeat[n-1], 0, createNewGroups[n-1],
interruptDelays[n-1]);
fprintf(stdout, "Output on stdout after test %d.\n", n);
fprintf(stderr, "Output on stderr after test %d.\n", n);
fflush(stdout);
@@ -536,7 +716,8 @@ int main(int argc, const char* argv[])
int exception = kwsysProcess_Exception_None;
int value = 0;
double timeout = 0;
int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout, 0, 1, 0);
int r = runChild(cmd, state, exception, value, 0, 1, 0, timeout,
0, 1, 0, 0, 0);
return r;
}
else
+22
View File
@@ -98,6 +98,10 @@ static bool CheckEscapeChars(kwsys_stl::string input,
static bool CheckFileOperations()
{
bool res = true;
const kwsys_stl::string testNonExistingFile(TEST_SYSTEMTOOLS_SOURCE_DIR
"/testSystemToolsNonExistingFile");
const kwsys_stl::string testDotFile(TEST_SYSTEMTOOLS_SOURCE_DIR
"/.");
const kwsys_stl::string testBinFile(TEST_SYSTEMTOOLS_SOURCE_DIR
"/testSystemTools.bin");
const kwsys_stl::string testTxtFile(TEST_SYSTEMTOOLS_SOURCE_DIR
@@ -106,6 +110,24 @@ static bool CheckFileOperations()
"/testSystemToolsNewDir");
const kwsys_stl::string testNewFile(testNewDir + "/testNewFile.txt");
if (kwsys::SystemTools::DetectFileType(testNonExistingFile.c_str()) !=
kwsys::SystemTools::FileTypeUnknown)
{
kwsys_ios::cerr
<< "Problem with DetectFileType - failed to detect type of: "
<< testNonExistingFile << kwsys_ios::endl;
res = false;
}
if (kwsys::SystemTools::DetectFileType(testDotFile.c_str()) !=
kwsys::SystemTools::FileTypeUnknown)
{
kwsys_ios::cerr
<< "Problem with DetectFileType - failed to detect type of: "
<< testDotFile << kwsys_ios::endl;
res = false;
}
if (kwsys::SystemTools::DetectFileType(testBinFile.c_str()) !=
kwsys::SystemTools::FileTypeBinary)
{