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")
|
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
|
||||||
|
|
||||||
# basically all general purpose OSs support shared libs
|
# 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
|
SET (CMAKE_SKIP_RPATH "NO" CACHE BOOL
|
||||||
"If set, runtime paths are not added when using shared libraries.")
|
"If set, runtime paths are not added when using shared libraries.")
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
MACRO(SET_FEATURE_INFO _name _desc)
|
MACRO(SET_FEATURE_INFO _name _desc)
|
||||||
SET(_url "${ARGV2}")
|
SET(_url "${ARGV2}")
|
||||||
SET(_comment "${ARGV3}")
|
SET(_comment "${ARGV3}")
|
||||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_DESCRIPTION "${_desc}" )
|
SET_PROPERTY(GLOBAL PROPERTY ${_name}_DESCRIPTION "${_desc}" )
|
||||||
IF(_url MATCHES ".+")
|
IF(_url MATCHES ".+")
|
||||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_URL "${_url}" )
|
SET_PROPERTY(GLOBAL PROPERTY ${_name}_URL "${_url}" )
|
||||||
ENDIF(_url MATCHES ".+")
|
ENDIF(_url MATCHES ".+")
|
||||||
IF(_comment MATCHES ".+")
|
IF(_comment MATCHES ".+")
|
||||||
SET_PROPERTIES(GLOBAL PROPERTIES ${_name}_COMMENT "${_comment}" )
|
SET_PROPERTY(GLOBAL PROPERTY ${_name}_COMMENT "${_comment}" )
|
||||||
ENDIF(_comment MATCHES ".+")
|
ENDIF(_comment MATCHES ".+")
|
||||||
ENDMACRO(SET_FEATURE_INFO)
|
ENDMACRO(SET_FEATURE_INFO)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#the compute nodes on BlueGene/L don't support shared libs
|
#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_C_FLAGS "") # -pic
|
||||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
|
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
|
#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_C_FLAGS "") # -pic
|
||||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
|
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "") # -shared
|
||||||
|
|
|
@ -8,5 +8,4 @@
|
||||||
# and/or ${CMAKE_SYSTEM_NAME}-<compiler_basename>-${CMAKE_SYSTEM_PROCESSOR}.cmake
|
# and/or ${CMAKE_SYSTEM_NAME}-<compiler_basename>-${CMAKE_SYSTEM_PROCESSOR}.cmake
|
||||||
|
|
||||||
# (embedded) targets without operating system usually don't support shared libraries
|
# (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
|
# Debian has lib64 paths only for compatibility so they should not be
|
||||||
# searched.
|
# searched.
|
||||||
IF(EXISTS "/etc/debian_version")
|
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")
|
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.
|
# 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>")
|
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
|
# 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_SHARED_LIBRARY )
|
||||||
SET(CMAKE_CXX_LINK_MODULE_LIBRARY )
|
SET(CMAKE_CXX_LINK_MODULE_LIBRARY )
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
#include "cmProjectCommand.cxx"
|
#include "cmProjectCommand.cxx"
|
||||||
#include "cmRaiseScopeCommand.cxx"
|
#include "cmRaiseScopeCommand.cxx"
|
||||||
#include "cmSetCommand.cxx"
|
#include "cmSetCommand.cxx"
|
||||||
#include "cmSetPropertiesCommand.cxx"
|
#include "cmSetPropertyCommand.cxx"
|
||||||
#include "cmSetSourceFilesPropertiesCommand.cxx"
|
#include "cmSetSourceFilesPropertiesCommand.cxx"
|
||||||
#include "cmSetTargetPropertiesCommand.cxx"
|
#include "cmSetTargetPropertiesCommand.cxx"
|
||||||
#include "cmSetTestsPropertiesCommand.cxx"
|
#include "cmSetTestsPropertiesCommand.cxx"
|
||||||
|
@ -132,7 +132,7 @@ void GetBootstrapCommands(std::list<cmCommand*>& commands)
|
||||||
commands.push_back(new cmProjectCommand);
|
commands.push_back(new cmProjectCommand);
|
||||||
commands.push_back(new cmRaiseScopeCommand);
|
commands.push_back(new cmRaiseScopeCommand);
|
||||||
commands.push_back(new cmSetCommand);
|
commands.push_back(new cmSetCommand);
|
||||||
commands.push_back(new cmSetPropertiesCommand);
|
commands.push_back(new cmSetPropertyCommand);
|
||||||
commands.push_back(new cmSetSourceFilesPropertiesCommand);
|
commands.push_back(new cmSetSourceFilesPropertiesCommand);
|
||||||
commands.push_back(new cmSetTargetPropertiesCommand);
|
commands.push_back(new cmSetTargetPropertiesCommand);
|
||||||
commands.push_back(new cmSetTestsPropertiesCommand);
|
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)
|
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")
|
"${CMAKE_CURRENT_BINARY_DIR}/UndefinedProperties.txt")
|
||||||
|
|
|
@ -24,10 +24,9 @@ include_directories("${Properties_SOURCE_DIR}" "${Properties_BINARY_DIR}")
|
||||||
# test generic property interfaces
|
# test generic property interfaces
|
||||||
define_property(GLOBALTEST GLOBAL "A test property"
|
define_property(GLOBALTEST GLOBAL "A test property"
|
||||||
"A long description of this test property" 0)
|
"A long description of this test property" 0)
|
||||||
set_properties(GLOBAL PROPERTIES GLOBALTEST 1)
|
set_property(GLOBAL PROPERTY GLOBALTEST 1)
|
||||||
set_properties(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
set_property(DIRECTORY PROPERTY DIRECTORYTEST 1)
|
||||||
PROPERTIES DIRECTORYTEST 1)
|
set_property(SOURCE SubDir/properties3.cxx PROPERTY SOURCETEST 1)
|
||||||
set_properties(SOURCE_FILE SubDir/properties3.cxx PROPERTIES SOURCETEST 1)
|
|
||||||
get_property(GLOBALRESULT GLOBAL GLOBALTEST)
|
get_property(GLOBALRESULT GLOBAL GLOBALTEST)
|
||||||
get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
get_property(DIRECTORYRESULT DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||||
DIRECTORYTEST)
|
DIRECTORYTEST)
|
||||||
|
@ -46,7 +45,7 @@ endif (RESULT1 AND RESULT2 AND RESULT3 AND GLOBALRESULT AND
|
||||||
DIRECTORYRESULT AND SOURCE_FILERESULT)
|
DIRECTORYRESULT AND SOURCE_FILERESULT)
|
||||||
|
|
||||||
# test the target property
|
# test the target property
|
||||||
set_properties(TARGET Properties PROPERTIES TARGETTEST 1)
|
set_property(TARGET Properties PROPERTY TARGETTEST 1)
|
||||||
get_property(TARGETRESULT TARGET Properties TARGETTEST)
|
get_property(TARGETRESULT TARGET Properties TARGETTEST)
|
||||||
if (NOT TARGETRESULT)
|
if (NOT TARGETRESULT)
|
||||||
message("Error: target result is TARGETRESULT=${TARGETRESULT}")
|
message("Error: target result is TARGETRESULT=${TARGETRESULT}")
|
||||||
|
|
Loading…
Reference in New Issue