ENH: Rename SET_PROPERITES command to SET_PROPERTY and give it a more powerful signature.
This commit is contained in:
parent
456631225b
commit
b8357db11d
|
@ -21,7 +21,7 @@ SET(CMAKE_FIND_LIBRARY_PREFIXES "lib")
|
|||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
|
||||
|
||||
# basically all general purpose OSs support shared libs
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS TRUE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
|
||||
|
||||
SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL
|
||||
"If set, runtime paths are not added when using shared libraries.")
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
MACRO(SET_FEATURE_INFO _name _desc)
|
||||
SET(_url "${ARGV2}")
|
||||
SET(_comment "${ARGV3}")
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_DESCRIPTION "${_desc}" )
|
||||
SET_PROPERTY(GLOBAL PROPERTY ${_name}_DESCRIPTION "${_desc}" )
|
||||
IF(_url MATCHES ".+")
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_URL "${_url}" )
|
||||
SET_PROPERTY(GLOBAL PROPERTY ${_name}_URL "${_url}" )
|
||||
ENDIF(_url MATCHES ".+")
|
||||
IF(_comment MATCHES ".+")
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_COMMENT "${_comment}" )
|
||||
SET_PROPERTY(GLOBAL PROPERTY ${_name}_COMMENT "${_comment}" )
|
||||
ENDIF(_comment MATCHES ".+")
|
||||
ENDMACRO(SET_FEATURE_INFO)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#the compute nodes on BlueGene/L don't support shared libs
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#Catamount, which runs on the compute nodes of Cray machines, e.g. RedStorm, doesn't support shared libs
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
|
||||
SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -pic
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
|
||||
|
|
|
@ -8,5 +8,4 @@
|
|||
# and/or ${CMAKE_SYSTEM_NAME}-<compiler_basename>-${CMAKE_SYSTEM_PROCESSOR}.cmake
|
||||
|
||||
# (embedded) targets without operating system usually don't support shared libraries
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
|
||||
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
|
|
|
@ -52,5 +52,5 @@ INCLUDE(Platform/UnixPaths)
|
|||
# Debian has lib64 paths only for compatibility so they should not be
|
||||
# searched.
|
||||
IF(EXISTS "/etc/debian_version")
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS FALSE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS FALSE)
|
||||
ENDIF(EXISTS "/etc/debian_version")
|
||||
|
|
|
@ -54,4 +54,4 @@ LIST(APPEND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
|
|||
)
|
||||
|
||||
# Enable use of lib64 search path variants by default.
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS TRUE)
|
||||
|
|
|
@ -47,7 +47,7 @@ SET(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLA
|
|||
SET(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -nostdlib -nostartfiles -L${ECOS_LIBTARGET_DIRECTORY} -Ttarget.ld <LINK_LIBRARIES>")
|
||||
|
||||
# eCos doesn't support shared libs
|
||||
SET_PROPERTIES(GLOBAL PROPERTIES TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
|
||||
|
||||
SET(CMAKE_CXX_LINK_SHARED_LIBRARY )
|
||||
SET(CMAKE_CXX_LINK_MODULE_LIBRARY )
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
#include "cmProjectCommand.cxx"
|
||||
#include "cmRaiseScopeCommand.cxx"
|
||||
#include "cmSetCommand.cxx"
|
||||
#include "cmSetPropertiesCommand.cxx"
|
||||
#include "cmSetPropertyCommand.cxx"
|
||||
#include "cmSetSourceFilesPropertiesCommand.cxx"
|
||||
#include "cmSetTargetPropertiesCommand.cxx"
|
||||
#include "cmSetTestsPropertiesCommand.cxx"
|
||||
|
@ -132,7 +132,7 @@ void GetBootstrapCommands(std::list<cmCommand*>& commands)
|
|||
commands.push_back(new cmProjectCommand);
|
||||
commands.push_back(new cmRaiseScopeCommand);
|
||||
commands.push_back(new cmSetCommand);
|
||||
commands.push_back(new cmSetPropertiesCommand);
|
||||
commands.push_back(new cmSetPropertyCommand);
|
||||
commands.push_back(new cmSetSourceFilesPropertiesCommand);
|
||||
commands.push_back(new cmSetTargetPropertiesCommand);
|
||||
commands.push_back(new cmSetTestsPropertiesCommand);
|
||||
|
|
|
@ -1,210 +0,0 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmSetPropertiesCommand.h"
|
||||
#include "cmSetTargetPropertiesCommand.h"
|
||||
#include "cmSetTestsPropertiesCommand.h"
|
||||
#include "cmSetSourceFilesPropertiesCommand.h"
|
||||
|
||||
// cmSetPropertiesCommand
|
||||
bool cmSetPropertiesCommand::InitialPass(
|
||||
std::vector<std::string> const& args)
|
||||
{
|
||||
if(args.size() < 2 )
|
||||
{
|
||||
this->SetError("called with incorrect number of arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
// first collect up the list of files
|
||||
std::vector<std::string> propertyPairs;
|
||||
bool doingFiles = true;
|
||||
int numFiles = 0;
|
||||
std::vector<std::string>::const_iterator j;
|
||||
for(j= args.begin(); j != args.end();++j)
|
||||
{
|
||||
if(*j == "PROPERTIES")
|
||||
{
|
||||
doingFiles = false;
|
||||
// now loop through the rest of the arguments, new style
|
||||
++j;
|
||||
while (j != args.end())
|
||||
{
|
||||
propertyPairs.push_back(*j);
|
||||
++j;
|
||||
if(j == args.end())
|
||||
{
|
||||
this->SetError("called with incorrect number of arguments.");
|
||||
return false;
|
||||
}
|
||||
propertyPairs.push_back(*j);
|
||||
++j;
|
||||
}
|
||||
// break out of the loop because j is already == end
|
||||
break;
|
||||
}
|
||||
else if (doingFiles)
|
||||
{
|
||||
numFiles++;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetError("called with illegal arguments, maybe missing "
|
||||
"a PROPERTIES specifier?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(propertyPairs.size() == 0)
|
||||
{
|
||||
this->SetError("called with illegal arguments, maybe missing "
|
||||
"a PROPERTIES specifier?");
|
||||
return false;
|
||||
}
|
||||
|
||||
cmProperty::ScopeType scope;
|
||||
const char *scopeName = 0;
|
||||
if (args[0] == "GLOBAL" && numFiles == 1)
|
||||
{
|
||||
scope = cmProperty::GLOBAL;
|
||||
}
|
||||
else if (args[0] == "DIRECTORY" && numFiles >= 1)
|
||||
{
|
||||
scope = cmProperty::DIRECTORY;
|
||||
if (numFiles == 2)
|
||||
{
|
||||
scopeName = args[1].c_str();
|
||||
}
|
||||
}
|
||||
else if (args[0] == "TARGET" && numFiles == 2)
|
||||
{
|
||||
scope = cmProperty::TARGET;
|
||||
scopeName = args[1].c_str();
|
||||
}
|
||||
else if (args[0] == "TEST" && numFiles == 2)
|
||||
{
|
||||
scope = cmProperty::TEST;
|
||||
scopeName = args[1].c_str();
|
||||
}
|
||||
else if (args[0] == "SOURCE_FILE" && numFiles == 2)
|
||||
{
|
||||
scope = cmProperty::SOURCE_FILE;
|
||||
scopeName = args[1].c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SetError("called with illegal arguments.");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (scope)
|
||||
{
|
||||
case cmProperty::TARGET:
|
||||
{
|
||||
bool ret = cmSetTargetPropertiesCommand::
|
||||
SetOneTarget(scopeName,propertyPairs, this->Makefile);
|
||||
if (!ret)
|
||||
{
|
||||
std::string message = "Can not find target to add properties to: ";
|
||||
message += scopeName;
|
||||
this->SetError(message.c_str());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmProperty::DIRECTORY:
|
||||
{
|
||||
// lookup the makefile from the directory name
|
||||
cmLocalGenerator *lg = this->Makefile->GetLocalGenerator();
|
||||
if (numFiles == 2)
|
||||
{
|
||||
std::string sd = scopeName;
|
||||
// make sure the start dir is a full path
|
||||
if (!cmSystemTools::FileIsFullPath(sd.c_str()))
|
||||
{
|
||||
sd = this->Makefile->GetStartDirectory();
|
||||
sd += "/";
|
||||
sd += scopeName;
|
||||
}
|
||||
|
||||
// The local generators are associated with collapsed paths.
|
||||
sd = cmSystemTools::CollapseFullPath(sd.c_str());
|
||||
|
||||
lg = this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
FindLocalGenerator(sd.c_str());
|
||||
}
|
||||
if (!lg)
|
||||
{
|
||||
this->SetError
|
||||
("DIRECTORY argument provided but requested directory not found. "
|
||||
"This could be because the directory argument was invalid or, "
|
||||
"it is valid but has not been processed yet.");
|
||||
return false;
|
||||
}
|
||||
|
||||
for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j)
|
||||
{
|
||||
const char *pn = j->c_str();
|
||||
++j;
|
||||
lg->GetMakefile()->SetProperty(pn,j->c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmProperty::GLOBAL:
|
||||
{
|
||||
for(j= propertyPairs.begin(); j != propertyPairs.end(); ++j)
|
||||
{
|
||||
const char *pn = j->c_str();
|
||||
++j;
|
||||
this->Makefile->GetCMakeInstance()->SetProperty(pn, j->c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmProperty::TEST:
|
||||
{
|
||||
std::string errors;
|
||||
bool ret = cmSetTestsPropertiesCommand::
|
||||
SetOneTest(scopeName,propertyPairs, this->Makefile, errors);
|
||||
if (!ret)
|
||||
{
|
||||
this->SetError(errors.c_str());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmProperty::SOURCE_FILE:
|
||||
{
|
||||
std::string errors;
|
||||
bool ret = cmSetSourceFilesPropertiesCommand::
|
||||
RunCommand(this->Makefile,
|
||||
args.begin()+1, args.begin()+2,
|
||||
args.begin() + 2, args.end(),
|
||||
errors);
|
||||
if (!ret)
|
||||
{
|
||||
this->SetError(errors.c_str());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case cmProperty::VARIABLE:
|
||||
case cmProperty::CACHED_VARIABLE:
|
||||
// not handled by SetProperty
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmSetsPropertiesCommand_h
|
||||
#define cmSetsPropertiesCommand_h
|
||||
|
||||
#include "cmCommand.h"
|
||||
|
||||
class cmSetPropertiesCommand : public cmCommand
|
||||
{
|
||||
public:
|
||||
virtual cmCommand* Clone()
|
||||
{
|
||||
return new cmSetPropertiesCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the command is first encountered in
|
||||
* the input file.
|
||||
*/
|
||||
virtual bool InitialPass(std::vector<std::string> const& args);
|
||||
|
||||
/**
|
||||
* The name of the command as specified in CMakeList.txt.
|
||||
*/
|
||||
virtual const char* GetName() { return "set_properties";}
|
||||
|
||||
/**
|
||||
* Succinct documentation.
|
||||
*/
|
||||
virtual const char* GetTerseDocumentation()
|
||||
{
|
||||
return "Set properties used by CMake.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Longer documentation.
|
||||
*/
|
||||
virtual const char* GetFullDocumentation()
|
||||
{
|
||||
return
|
||||
" set_properties(scope_value\n"
|
||||
" PROPERTIES prop1 value1\n"
|
||||
" prop2 value2 ...)\n"
|
||||
"Set properties on something. The scope_value is either GLOBAL, "
|
||||
"DIRECTORY dir_name, TARGET tgt_name, SOURCE_FILE src_name, "
|
||||
"or TEST test_name."
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* This determines if the command is invoked when in script mode.
|
||||
*/
|
||||
virtual bool IsScriptable() { return true; }
|
||||
|
||||
cmTypeMacro(cmSetPropertiesCommand, cmCommand);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,408 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#include "cmSetPropertyCommand.h"
|
||||
#include "cmSetTargetPropertiesCommand.h"
|
||||
#include "cmSetTestsPropertiesCommand.h"
|
||||
#include "cmSetSourceFilesPropertiesCommand.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
cmSetPropertyCommand::cmSetPropertyCommand()
|
||||
{
|
||||
this->AppendMode = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::InitialPass(std::vector<std::string> const& args)
|
||||
{
|
||||
if(args.size() < 2 )
|
||||
{
|
||||
this->SetError("called with incorrect number of arguments");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the scope on which to set the property.
|
||||
std::vector<std::string>::const_iterator arg = args.begin();
|
||||
cmProperty::ScopeType scope;
|
||||
if(*arg == "GLOBAL")
|
||||
{
|
||||
scope = cmProperty::GLOBAL;
|
||||
}
|
||||
else if(*arg == "DIRECTORY")
|
||||
{
|
||||
scope = cmProperty::DIRECTORY;
|
||||
}
|
||||
else if(*arg == "TARGET")
|
||||
{
|
||||
scope = cmProperty::TARGET;
|
||||
}
|
||||
else if(*arg == "SOURCE")
|
||||
{
|
||||
scope = cmProperty::SOURCE_FILE;
|
||||
}
|
||||
else if(*arg == "TEST")
|
||||
{
|
||||
scope = cmProperty::TEST;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given invalid scope " << *arg << ". "
|
||||
<< "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse the rest of the arguments up to the values.
|
||||
enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
|
||||
Doing doing = DoingNames;
|
||||
const char* sep = "";
|
||||
for(++arg; arg != args.end(); ++arg)
|
||||
{
|
||||
if(*arg == "PROPERTY")
|
||||
{
|
||||
doing = DoingProperty;
|
||||
}
|
||||
else if(*arg == "APPEND")
|
||||
{
|
||||
doing = DoingNone;
|
||||
this->AppendMode = true;
|
||||
}
|
||||
else if(doing == DoingNames)
|
||||
{
|
||||
this->Names.insert(*arg);
|
||||
}
|
||||
else if(doing == DoingProperty)
|
||||
{
|
||||
this->PropertyName = *arg;
|
||||
doing = DoingValues;
|
||||
}
|
||||
else if(doing == DoingValues)
|
||||
{
|
||||
this->PropertyValue += sep;
|
||||
sep = ";";
|
||||
this->PropertyValue += *arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given invalid argument \"" << *arg << "\".";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure a property name was found.
|
||||
if(this->PropertyName.empty())
|
||||
{
|
||||
this->SetError("not given a PROPERTY <name> argument.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Dispatch property setting.
|
||||
switch(scope)
|
||||
{
|
||||
case cmProperty::GLOBAL: return this->HandleGlobalMode();
|
||||
case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
|
||||
case cmProperty::TARGET: return this->HandleTargetMode();
|
||||
case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
|
||||
case cmProperty::TEST: return this->HandleTestMode();
|
||||
|
||||
case cmProperty::VARIABLE:
|
||||
case cmProperty::CACHED_VARIABLE:
|
||||
break; // should never happen
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::ConstructValue(std::string& value,
|
||||
const char* old)
|
||||
{
|
||||
if(this->AppendMode)
|
||||
{
|
||||
// This is an append. Start with the original value.
|
||||
if(old)
|
||||
{
|
||||
value = old;
|
||||
}
|
||||
}
|
||||
else if(this->PropertyValue.empty())
|
||||
{
|
||||
// This is a set to no values. Remove the property.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the new value.
|
||||
if(!this->PropertyValue.empty())
|
||||
{
|
||||
if(!value.empty())
|
||||
{
|
||||
value += ";";
|
||||
}
|
||||
value += this->PropertyValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleGlobalMode()
|
||||
{
|
||||
if(!this->Names.empty())
|
||||
{
|
||||
this->SetError("given names for GLOBAL scope.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set or append the property.
|
||||
cmake* cm = this->Makefile->GetCMakeInstance();
|
||||
const char* name = this->PropertyName.c_str();
|
||||
std::string value;
|
||||
if(this->ConstructValue(value, cm->GetProperty(name)))
|
||||
{
|
||||
// Set the new property.
|
||||
cm->SetProperty(name, value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the property.
|
||||
cm->SetProperty(name, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleDirectoryMode()
|
||||
{
|
||||
if(this->Names.size() > 1)
|
||||
{
|
||||
this->SetError("allows at most one name for DIRECTORY scope.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Default to the current directory.
|
||||
cmMakefile* mf = this->Makefile;
|
||||
|
||||
// Lookup the directory if given.
|
||||
if(!this->Names.empty())
|
||||
{
|
||||
// Construct the directory name. Interpret relative paths with
|
||||
// respect to the current directory.
|
||||
std::string dir = *this->Names.begin();
|
||||
if(!cmSystemTools::FileIsFullPath(dir.c_str()))
|
||||
{
|
||||
dir = this->Makefile->GetCurrentDirectory();
|
||||
dir += "/";
|
||||
dir += *this->Names.begin();
|
||||
}
|
||||
|
||||
// The local generators are associated with collapsed paths.
|
||||
dir = cmSystemTools::CollapseFullPath(dir.c_str());
|
||||
|
||||
// Lookup the generator.
|
||||
if(cmLocalGenerator* lg =
|
||||
(this->Makefile->GetLocalGenerator()
|
||||
->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
|
||||
{
|
||||
// Use the makefile for the directory found.
|
||||
mf = lg->GetMakefile();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could not find the directory.
|
||||
this->SetError
|
||||
("DIRECTORY scope provided but requested directory was not found. "
|
||||
"This could be because the directory argument was invalid or, "
|
||||
"it is valid but has not been processed yet.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set or append the property.
|
||||
const char* name = this->PropertyName.c_str();
|
||||
std::string value;
|
||||
if(this->ConstructValue(value, mf->GetProperty(name)))
|
||||
{
|
||||
// Set the new property.
|
||||
mf->SetProperty(name, value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the property.
|
||||
mf->SetProperty(name, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleTargetMode()
|
||||
{
|
||||
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end(); ++ni)
|
||||
{
|
||||
if(cmTarget* target =
|
||||
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
|
||||
->FindTarget(0, ni->c_str(), true))
|
||||
{
|
||||
// Handle the current target.
|
||||
if(!this->HandleTarget(target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "could not find TARGET " << *ni
|
||||
<< ". Perhaps it has not yet been created.";
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
|
||||
{
|
||||
// Set or append the property.
|
||||
const char* name = this->PropertyName.c_str();
|
||||
std::string value;
|
||||
if(this->ConstructValue(value, target->GetProperty(name)))
|
||||
{
|
||||
// Set the new property.
|
||||
target->SetProperty(name, value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the property.
|
||||
target->SetProperty(name, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleSourceMode()
|
||||
{
|
||||
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end(); ++ni)
|
||||
{
|
||||
// Get the source file.
|
||||
if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
|
||||
{
|
||||
if(!this->HandleSource(sf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given SOURCE name that could not be found or created: " << *ni;
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
|
||||
{
|
||||
// Set or append the property.
|
||||
const char* name = this->PropertyName.c_str();
|
||||
std::string value;
|
||||
if(this->ConstructValue(value, sf->GetProperty(name)))
|
||||
{
|
||||
// Set the new property.
|
||||
sf->SetProperty(name, value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the property.
|
||||
sf->SetProperty(name, 0);
|
||||
}
|
||||
|
||||
// TODO: MACOSX_PACKAGE_LOCATION special case in
|
||||
// cmSetSourceFilesPropertiesCommand
|
||||
// The logic should be moved to cmSourceFile.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleTestMode()
|
||||
{
|
||||
// Loop over all tests looking for matching names.
|
||||
std::vector<cmTest*> const& tests = *this->Makefile->GetTests();
|
||||
for(std::vector<cmTest*>::const_iterator ti = tests.begin();
|
||||
ti != tests.end(); ++ti)
|
||||
{
|
||||
cmTest* test = *ti;
|
||||
std::set<cmStdString>::const_iterator ni =
|
||||
this->Names.find(test->GetName());
|
||||
if(ni != this->Names.end())
|
||||
{
|
||||
if(this->HandleTest(test))
|
||||
{
|
||||
this->Names.erase(ni);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Names that are still left were not found.
|
||||
if(!this->Names.empty())
|
||||
{
|
||||
cmOStringStream e;
|
||||
e << "given TEST names that do not exist:\n";
|
||||
for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
|
||||
ni != this->Names.end(); ++ni)
|
||||
{
|
||||
e << " " << *ni << "\n";
|
||||
}
|
||||
this->SetError(e.str().c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool cmSetPropertyCommand::HandleTest(cmTest* test)
|
||||
{
|
||||
// Set or append the property.
|
||||
const char* name = this->PropertyName.c_str();
|
||||
std::string value;
|
||||
if(this->ConstructValue(value, test->GetProperty(name)))
|
||||
{
|
||||
// Set the new property.
|
||||
test->SetProperty(name, value.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the property.
|
||||
test->SetProperty(name, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*=========================================================================
|
||||
|
||||
Program: CMake - Cross-Platform Makefile Generator
|
||||
Module: $RCSfile$
|
||||
Language: C++
|
||||
Date: $Date$
|
||||
Version: $Revision$
|
||||
|
||||
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
|
||||
See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
|
||||
|
||||
This software is distributed WITHOUT ANY WARRANTY; without even
|
||||
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. See the above copyright notices for more information.
|
||||
|
||||
=========================================================================*/
|
||||
#ifndef cmSetsPropertiesCommand_h
|
||||
#define cmSetsPropertiesCommand_h
|
||||
|
||||
#include "cmCommand.h"
|
||||
|
||||
class cmSetPropertyCommand : public cmCommand
|
||||
{
|
||||
public:
|
||||
cmSetPropertyCommand();
|
||||
|
||||
virtual cmCommand* Clone()
|
||||
{
|
||||
return new cmSetPropertyCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the command is first encountered in
|
||||
* the input file.
|
||||
*/
|
||||
virtual bool InitialPass(std::vector<std::string> const& args);
|
||||
|
||||
/**
|
||||
* The name of the command as specified in CMakeList.txt.
|
||||
*/
|
||||
virtual const char* GetName() { return "set_property";}
|
||||
|
||||
/**
|
||||
* Succinct documentation.
|
||||
*/
|
||||
virtual const char* GetTerseDocumentation()
|
||||
{
|
||||
return "Set a named property in a given scope.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Longer documentation.
|
||||
*/
|
||||
virtual const char* GetFullDocumentation()
|
||||
{
|
||||
return
|
||||
" set_property(<GLOBAL |\n"
|
||||
" DIRECTORY [dir] |\n"
|
||||
" TARGET [target1 [target2 ...]] |\n"
|
||||
" SOURCE [src1 [src2 ...]] |\n"
|
||||
" TEST [test1 [test2 ...]]>\n"
|
||||
" [APPEND]\n"
|
||||
" PROPERTY <name> [value1 [value2 ...]])\n"
|
||||
"Set one property on zero or more objects of a scope. "
|
||||
"The first argument determines the scope in which the property "
|
||||
"is set. It must be one of the following:\n"
|
||||
"GLOBAL scope is unique and does not accept a name.\n"
|
||||
"DIRECTORY scope defaults to the current directory but another "
|
||||
"directory (already processed by CMake) may be named by full or "
|
||||
"relative path.\n"
|
||||
"TARGET scope may name zero or more existing targets.\n"
|
||||
"SOURCE scope may name zero or more source files.\n"
|
||||
"TEST scope may name zero or more existing tests.\n"
|
||||
"The required PROPERTY option is immediately followed by the name "
|
||||
"of the property to set. Remaining arguments are used to "
|
||||
"compose the property value in the form of a semicolon-separated "
|
||||
"list. "
|
||||
"If the APPEND option is given the list is appended to any "
|
||||
"existing property value."
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* This determines if the command is invoked when in script mode.
|
||||
*/
|
||||
virtual bool IsScriptable() { return true; }
|
||||
|
||||
cmTypeMacro(cmSetPropertyCommand, cmCommand);
|
||||
|
||||
private:
|
||||
std::set<cmStdString> Names;
|
||||
std::string PropertyName;
|
||||
std::string PropertyValue;
|
||||
bool AppendMode;
|
||||
|
||||
// Implementation of value construction.
|
||||
bool ConstructValue(std::string& value, const char* old);
|
||||
|
||||
// Implementation of each property type.
|
||||
bool HandleGlobalMode();
|
||||
bool HandleDirectoryMode();
|
||||
bool HandleTargetMode();
|
||||
bool HandleTarget(cmTarget* target);
|
||||
bool HandleSourceMode();
|
||||
bool HandleSource(cmSourceFile* sf);
|
||||
bool HandleTestMode();
|
||||
bool HandleTest(cmTest* test);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -2,5 +2,5 @@ project (DocTest)
|
|||
|
||||
add_executable (DocTest DocTest.cxx)
|
||||
|
||||
set_properties(GLOBAL PROPERTIES REPORT_UNDEFINED_PROPERTIES
|
||||
set_property(GLOBAL PROPERTY REPORT_UNDEFINED_PROPERTIES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/UndefinedProperties.txt")
|
||||
|
|
|
@ -24,10 +24,9 @@ include_directories("${Properties_SOURCE_DIR}" "${Properties_BINARY_DIR}")
|
|||
# test generic property interfaces
|
||||
define_property(GLOBALTEST GLOBAL "A test property"
|
||||
"A long description of this test property" 0)
|
||||
set_properties(GLOBAL PROPERTIES GLOBALTEST 1)
|
||||
set_properties(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
PROPERTIES DIRECTORYTEST 1)
|
||||
set_properties(SOURCE_FILE SubDir/properties3.cxx PROPERTIES SOURCETEST 1)
|
||||
set_property(GLOBAL PROPERTY GLOBALTEST 1)
|
||||
set_property(DIRECTORY PROPERTY DIRECTORYTEST 1)
|
||||
set_property(SOURCE SubDir/properties3.cxx PROPERTY SOURCETEST 1)
|
||||
get_property(GLOBALRESULT GLOBAL GLOBALTEST)
|
||||
get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
DIRECTORYTEST)
|
||||
|
@ -46,7 +45,7 @@ endif (RESULT1 AND RESULT2 AND RESULT3 AND GLOBALRESULT AND
|
|||
DIRECTORYRESULT AND SOURCE_FILERESULT)
|
||||
|
||||
# test the target property
|
||||
set_properties(TARGET Properties PROPERTIES TARGETTEST 1)
|
||||
set_property(TARGET Properties PROPERTY TARGETTEST 1)
|
||||
get_property(TARGETRESULT TARGET Properties TARGETTEST)
|
||||
if (NOT TARGETRESULT)
|
||||
message("Error: target result is TARGETRESULT=${TARGETRESULT}")
|
||||
|
|
Loading…
Reference in New Issue