mirror of
https://github.com/Kitware/CMake.git
synced 2026-05-04 21:30:01 -05:00
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:
@@ -288,6 +288,7 @@ set(SRCS
|
||||
cmInstallDirectoryGenerator.h
|
||||
cmInstallDirectoryGenerator.cxx
|
||||
cmLinkedTree.h
|
||||
cmLinkItem.h
|
||||
cmListFileCache.cxx
|
||||
cmListFileCache.h
|
||||
cmListFileLexer.c
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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());
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -94,6 +94,7 @@ private:
|
||||
cmPolicies::PolicyStatus Policy12Status;
|
||||
cmPolicies::PolicyStatus Policy54Status;
|
||||
cmPolicies::PolicyStatus Policy57Status;
|
||||
cmPolicies::PolicyStatus Policy64Status;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
@@ -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; \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
+1982
-27
File diff suppressed because it is too large
Load Diff
+196
-1
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
@@ -155,6 +155,12 @@ public:
|
||||
return iterator(this, 1);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
this->UpPositions.clear();
|
||||
this->Data.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
T& GetReference(PositionType pos)
|
||||
{
|
||||
|
||||
+64
-10
@@ -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
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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())
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
{ return this->ProgressFileNameFull; }
|
||||
|
||||
cmTarget* GetTarget() { return this->Target;}
|
||||
cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget;}
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+20
-210
@@ -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,
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user