summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt8
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/QtDialog/CMakeLists.txt210
-rw-r--r--Source/QtDialog/QCMake.cxx4
-rw-r--r--Source/cmCustomCommandGenerator.cxx7
-rw-r--r--Source/cmDocumentVariables.cxx36
-rw-r--r--Source/cmFileCommand.cxx58
-rw-r--r--Source/cmFileCommand.h12
-rw-r--r--Source/cmGeneratorExpression.cxx265
-rw-r--r--Source/cmGeneratorExpression.h59
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx568
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h118
-rw-r--r--Source/cmGeneratorExpressionLexer.cxx85
-rw-r--r--Source/cmGeneratorExpressionLexer.h58
-rw-r--r--Source/cmGeneratorExpressionParser.cxx235
-rw-r--r--Source/cmGeneratorExpressionParser.h45
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx5
-rw-r--r--Source/cmGlobalVisualStudio8Win64Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio8Win64Generator.h3
-rw-r--r--Source/cmGlobalVisualStudio9IA64Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio9IA64Generator.h3
-rw-r--r--Source/cmGlobalVisualStudio9Win64Generator.cxx11
-rw-r--r--Source/cmGlobalVisualStudio9Win64Generator.h3
-rw-r--r--Source/cmIfCommand.cxx16
-rw-r--r--Source/cmNinjaTargetGenerator.cxx40
-rw-r--r--Source/cmTarget.cxx17
-rw-r--r--Source/cmTestGenerator.cxx8
-rw-r--r--Source/cmake.cxx7
29 files changed, 1478 insertions, 429 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index e79689b..354f123 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -183,6 +183,12 @@ set(SRCS
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmGeneratedFileStream.cxx
+ cmGeneratorExpressionEvaluator.cxx
+ cmGeneratorExpressionEvaluator.h
+ cmGeneratorExpressionLexer.cxx
+ cmGeneratorExpressionLexer.h
+ cmGeneratorExpressionParser.cxx
+ cmGeneratorExpressionParser.h
cmGeneratorExpression.cxx
cmGeneratorExpression.h
cmGeneratorTarget.cxx
@@ -548,7 +554,7 @@ endif()
# Qt GUI
option(BUILD_QtDialog "Build Qt dialog for CMake" FALSE)
if(BUILD_QtDialog)
- subdirs(QtDialog)
+ add_subdirectory(QtDialog)
endif()
include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 4f37280..7b6af1e 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -2,5 +2,5 @@
set(CMake_VERSION_MAJOR 2)
set(CMake_VERSION_MINOR 8)
set(CMake_VERSION_PATCH 9)
-set(CMake_VERSION_TWEAK 20120917)
+set(CMake_VERSION_TWEAK 20120919)
#set(CMake_VERSION_RC 1)
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index 0969aea..a1ffa20 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -9,115 +9,129 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
-project(QtDialog)
-set(QT_MIN_VERSION "4.4.0")
-find_package(Qt4 REQUIRED)
-if(NOT QT4_FOUND)
- message(SEND_ERROR "Failed to find Qt 4.4 or greater.")
+project(QtDialog)
+find_package(Qt5Widgets QUIET)
+if (Qt5Widgets_FOUND)
+ include_directories(${Qt5Widgets_INCLUDE_DIRS})
+ add_definitions(${Qt5Widgets_DEFINITONS})
+ macro(qt4_wrap_ui)
+ qt5_wrap_ui(${ARGN})
+ endmacro()
+ macro(qt4_wrap_cpp)
+ qt5_wrap_cpp(${ARGN})
+ endmacro()
+ macro(qt4_add_resources)
+ qt5_add_resources(${ARGN})
+ endmacro()
+ set(QT_LIBRARIES ${Qt5Widgets_LIBRARIES})
else()
+ set(QT_MIN_VERSION "4.4.0")
+ find_package(Qt4 REQUIRED)
+ if(NOT QT4_FOUND)
+ message(SEND_ERROR "Failed to find Qt 4.4 or greater.")
+ return()
+ endif()
include(${QT_USE_FILE})
- set(CMAKE_PACKAGE_QTGUI TRUE)
- set(SRCS
- AddCacheEntry.cxx
- AddCacheEntry.h
- CMakeSetup.cxx
- CMakeSetupDialog.cxx
- CMakeSetupDialog.h
- FirstConfigure.cxx
- FirstConfigure.h
- QCMake.cxx
- QCMake.h
- QCMakeCacheView.cxx
- QCMakeCacheView.h
- QCMakeWidgets.cxx
- QCMakeWidgets.h
- QMacInstallDialog.cxx
- QMacInstallDialog.h
- )
- QT4_WRAP_UI(UI_SRCS
- CMakeSetupDialog.ui
- Compilers.ui
- CrossCompiler.ui
- AddCacheEntry.ui
- MacInstallDialog.ui
- )
- QT4_WRAP_CPP(MOC_SRCS
- AddCacheEntry.h
- Compilers.h
- CMakeSetupDialog.h
- FirstConfigure.h
- QCMake.h
- QCMakeCacheView.h
- QCMakeWidgets.h
- QMacInstallDialog.h
- )
- QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
+endif()
- set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS})
- if(Q_WS_WIN)
- set(SRCS ${SRCS} CMakeSetup.rc)
- endif()
- if(Q_WS_MAC)
- set(SRCS ${SRCS} CMakeSetup.icns)
- set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns)
- set_source_files_properties(CMakeSetup.icns PROPERTIES
- MACOSX_PACKAGE_LOCATION Resources)
- endif()
+set(SRCS
+ AddCacheEntry.cxx
+ AddCacheEntry.h
+ CMakeSetup.cxx
+ CMakeSetupDialog.cxx
+ CMakeSetupDialog.h
+ FirstConfigure.cxx
+ FirstConfigure.h
+ QCMake.cxx
+ QCMake.h
+ QCMakeCacheView.cxx
+ QCMakeCacheView.h
+ QCMakeWidgets.cxx
+ QCMakeWidgets.h
+ QMacInstallDialog.cxx
+ QMacInstallDialog.h
+ )
+QT4_WRAP_UI(UI_SRCS
+ CMakeSetupDialog.ui
+ Compilers.ui
+ CrossCompiler.ui
+ AddCacheEntry.ui
+ MacInstallDialog.ui
+ )
+QT4_WRAP_CPP(MOC_SRCS
+ AddCacheEntry.h
+ Compilers.h
+ CMakeSetupDialog.h
+ FirstConfigure.h
+ QCMake.h
+ QCMakeCacheView.h
+ QCMakeWidgets.h
+ QMacInstallDialog.h
+ )
+QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc)
- include_directories(${CMAKE_CURRENT_BINARY_DIR})
- include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+set(SRCS ${SRCS} ${UI_SRCS} ${MOC_SRCS} ${RC_SRCS})
+if(WIN32)
+ set(SRCS ${SRCS} CMakeSetup.rc)
+endif()
+if(APPLE)
+ set(SRCS ${SRCS} CMakeSetup.icns)
+ set(MACOSX_BUNDLE_ICON_FILE CMakeSetup.icns)
+ set_source_files_properties(CMakeSetup.icns PROPERTIES
+ MACOSX_PACKAGE_LOCATION Resources)
+endif()
- add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS})
- target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
- if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 2.4)
- if(APPLE)
- set_target_properties(cmake-gui PROPERTIES
- OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
- endif()
- set(CMAKE_INSTALL_DESTINATION_ARGS
- BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}")
- endif()
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
- install(TARGETS cmake-gui RUNTIME DESTINATION bin ${CMAKE_INSTALL_DESTINATION_ARGS})
+add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS})
+target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${QT_LIBRARIES})
- if(UNIX)
- # install a desktop file so CMake appears in the application start menu
- # with an icon
- install(FILES CMake.desktop DESTINATION share/applications )
- install(FILES CMakeSetup32.png DESTINATION share/pixmaps )
- install(FILES cmakecache.xml DESTINATION share/mime/packages )
- endif()
+if(APPLE)
+ set_target_properties(cmake-gui PROPERTIES
+ OUTPUT_NAME ${CMAKE_BUNDLE_NAME})
+endif()
+set(CMAKE_INSTALL_DESTINATION_ARGS
+ BUNDLE DESTINATION "${CMAKE_BUNDLE_LOCATION}")
- if(APPLE)
- set(CMAKE_POSTFLIGHT_SCRIPT
- "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
- set(CMAKE_POSTUPGRADE_SCRIPT
- "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
- configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postflight.sh.in"
- "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
- configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postupgrade.sh.in"
- "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
- install(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" cmake-gui
- WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
- endif()
+install(TARGETS cmake-gui RUNTIME DESTINATION bin ${CMAKE_INSTALL_DESTINATION_ARGS})
- if(APPLE OR WIN32)
- # install rules for including 3rd party libs such as Qt
- # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation
- set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}")
- if(APPLE)
- set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
- endif()
- install(CODE "
- include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\")
- set(BU_CHMOD_BUNDLE_ITEMS ON)
- fixup_bundle(\"${fixup_exe}\" \"\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\")
- ")
- endif()
+if(UNIX)
+ # install a desktop file so CMake appears in the application start menu
+ # with an icon
+ install(FILES CMake.desktop DESTINATION share/applications )
+ install(FILES CMakeSetup32.png DESTINATION share/pixmaps )
+ install(FILES cmakecache.xml DESTINATION share/mime/packages )
+endif()
- configure_file("${QtDialog_SOURCE_DIR}/QtDialogCPack.cmake.in"
- "${QtDialog_BINARY_DIR}/QtDialogCPack.cmake" @ONLY)
+if(APPLE)
+ set(CMAKE_POSTFLIGHT_SCRIPT
+ "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
+ set(CMAKE_POSTUPGRADE_SCRIPT
+ "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
+ configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postflight.sh.in"
+ "${CMake_BINARY_DIR}/Source/QtDialog/postflight.sh")
+ configure_file("${CMake_SOURCE_DIR}/Source/QtDialog/postupgrade.sh.in"
+ "${CMake_BINARY_DIR}/Source/QtDialog/postupgrade.sh")
+ install(CODE "execute_process(COMMAND ln -s \"../MacOS/${CMAKE_BUNDLE_NAME}\" cmake-gui
+ WORKING_DIRECTORY \$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin)")
+endif()
+
+if(APPLE OR WIN32)
+ # install rules for including 3rd party libs such as Qt
+ # if a system Qt is used (e.g. installed in /usr/lib/), it will not be included in the installation
+ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/bin/cmake-gui${CMAKE_EXECUTABLE_SUFFIX}")
+ if(APPLE)
+ set(fixup_exe "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/MacOS/${CMAKE_BUNDLE_NAME}")
+ endif()
+ install(CODE "
+ include(\"${CMake_SOURCE_DIR}/Modules/BundleUtilities.cmake\")
+ set(BU_CHMOD_BUNDLE_ITEMS ON)
+ fixup_bundle(\"${fixup_exe}\" \"\" \"${QT_LIBRARY_DIR};${QT_BINARY_DIR}\")
+ ")
endif()
+set(CMAKE_PACKAGE_QTGUI TRUE)
+configure_file("${QtDialog_SOURCE_DIR}/QtDialogCPack.cmake.in"
+ "${QtDialog_BINARY_DIR}/QtDialogCPack.cmake" @ONLY)
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index a2b1567..0d01181 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -348,7 +348,11 @@ void QCMake::interrupt()
bool QCMake::interruptCallback(void* cd)
{
QCMake* self = reinterpret_cast<QCMake*>(cd);
+#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
return self->InterruptFlag;
+#else
+ return self->InterruptFlag.load();
+#endif
}
void QCMake::progressCallback(const char* msg, float percent, void* cd)
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index a650129..07df7d5 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -21,7 +21,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
cmCustomCommand const& cc, const char* config, cmMakefile* mf):
CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()),
OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()),
- GE(new cmGeneratorExpression(mf, config, cc.GetBacktrace()))
+ GE(new cmGeneratorExpression(cc.GetBacktrace()))
{
}
@@ -47,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{
return target->GetLocation(this->Config);
}
- return this->GE->Process(argv0);
+ return this->GE->Parse(argv0).Evaluate(this->Makefile, this->Config);
}
//----------------------------------------------------------------------------
@@ -58,7 +58,8 @@ cmCustomCommandGenerator
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for(unsigned int j=1;j < commandLine.size(); ++j)
{
- std::string arg = this->GE->Process(commandLine[j]);
+ std::string arg = this->GE->Parse(commandLine[j]).Evaluate(this->Makefile,
+ this->Config);
cmd += " ";
if(this->OldStyle)
{
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 94cd5c2..5e7e081 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -1,6 +1,8 @@
#include "cmDocumentVariables.h"
#include "cmake.h"
+#include <cmsys/ios/sstream>
+
void cmDocumentVariables::DefineVariables(cmake* cm)
{
// Subsection: variables defined by cmake, that give
@@ -992,12 +994,33 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
false,
"Variables That Describe the System");
- cm->DefineProperty
- ("MSVC80", cmProperty::VARIABLE,
- "True when using Microsoft Visual C 8.0",
- "Set to true when the compiler is version 8.0 of Microsoft Visual C.",
- false,
- "Variables That Describe the System");
+ int msvc_versions[] = { 60, 70, 71, 80, 90, 100, 110, 0 };
+ for (int i = 0; msvc_versions[i] != 0; i ++)
+ {
+ const char minor = (char)('0' + (msvc_versions[i] % 10));
+ cmStdString varName = "MSVC";
+ cmsys_ios::ostringstream majorStr;
+
+ majorStr << (msvc_versions[i] / 10);
+ varName += majorStr.str();
+ if (msvc_versions[i] < 100)
+ {
+ varName += minor;
+ }
+
+ cmStdString verString = majorStr.str() + "." + minor;
+
+ cmStdString shortStr = "True when using Microsoft Visual C " + verString;
+ cmStdString fullStr = "Set to true when the compiler is version " +
+ verString +
+ " of Microsoft Visual C.";
+ cm->DefineProperty
+ (varName.c_str(), cmProperty::VARIABLE,
+ shortStr.c_str(),
+ fullStr.c_str(),
+ false,
+ "Variables That Describe the System");
+ }
cm->DefineProperty
("MSVC_IDE", cmProperty::VARIABLE,
@@ -1017,6 +1040,7 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
" 1400 = VS 8.0\n"
" 1500 = VS 9.0\n"
" 1600 = VS 10.0\n"
+ " 1700 = VS 11.0\n"
"",
false,
"Variables That Describe the System");
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 4ac58a4..2bc4290 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -2667,9 +2667,8 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
long inactivity_timeout = 0;
std::string verboseLog;
std::string statusVar;
- std::string caFile;
- bool checkSSL = false;
- bool verifySSL = false;
+ bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY");
+ const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO");
std::string expectedHash;
std::string hashMatchMSG;
cmsys::auto_ptr<cmCryptoHash> hash;
@@ -2723,30 +2722,29 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
}
statusVar = *i;
}
- else if(*i == "SSL_VERIFY")
+ else if(*i == "TLS_VERIFY")
{
++i;
if(i != args.end())
{
- verifySSL = cmSystemTools::IsOn(i->c_str());
- checkSSL = true;
+ tls_verify = cmSystemTools::IsOn(i->c_str());
}
else
{
- this->SetError("SSL_VERIFY missing bool value.");
+ this->SetError("TLS_VERIFY missing bool value.");
return false;
}
}
- else if(*i == "SSL_CAINFO_FILE")
+ else if(*i == "TLS_CAINFO")
{
++i;
if(i != args.end())
{
- caFile = *i;
+ cainfo = i->c_str();
}
else
{
- this->SetError("SSL_CAFILE missing file value.");
+ this->SetError("TLS_CAFILE missing file value.");
return false;
}
}
@@ -2868,41 +2866,23 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
cmFileCommandCurlDebugCallback);
check_curl_result(res, "DOWNLOAD cannot set debug function: ");
- // check to see if SSL verification is requested
- const char* verifyValue =
- this->Makefile->GetDefinition("CMAKE_CURLOPT_SSL_VERIFYPEER");
- // if there is a cmake variable or if the command has SSL_VERIFY requested
- if(verifyValue || checkSSL)
+ // check to see if TLS verification is requested
+ if(tls_verify)
{
- // the args to the command come first
- bool verify = verifySSL;
- if(!verify && verifyValue)
- {
- verify = cmSystemTools::IsOn(verifyValue);
- }
- if(verify)
- {
- res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
- check_curl_result(res, "Unable to set SSL Verify on: ");
- }
- else
- {
- res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
- check_curl_result(res, "Unable to set SSL Verify off: ");
- }
+ res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
+ check_curl_result(res, "Unable to set TLS/SSL Verify on: ");
}
- // check to see if a CAINFO file has been specified
- const char* cainfo =
- this->Makefile->GetDefinition("CMAKE_CURLOPT_CAINFO_FILE");
- // command arg comes first
- if(caFile.size())
+ else
{
- cainfo = caFile.c_str();
+ res = ::curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+ check_curl_result(res, "Unable to set TLS/SSL Verify off: ");
}
- if(cainfo)
+ // check to see if a CAINFO file has been specified
+ // command arg comes first
+ if(cainfo && *cainfo)
{
res = ::curl_easy_setopt(curl, CURLOPT_CAINFO, cainfo);
- check_curl_result(res, "Unable to set SSL Verify CAINFO: ");
+ check_curl_result(res, "Unable to set TLS/SSL Verify CAINFO: ");
}
cmFileCommandVectorOfChar chunkDebug;
diff --git a/Source/cmFileCommand.h b/Source/cmFileCommand.h
index 413e2f4..bd6f612 100644
--- a/Source/cmFileCommand.h
+++ b/Source/cmFileCommand.h
@@ -85,7 +85,7 @@ public:
" [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS]\n"
" [EXPECTED_HASH MD5|SHA1|SHA224|SHA256|SHA384|SHA512 hash]\n"
" [EXPECTED_MD5 sum]\n"
- " [SSL_VERIFY on|off] [SSL_CAINFO_FILE file])\n"
+ " [TLS_VERIFY on|off] [TLS_CAINFO file])\n"
" file(UPLOAD filename url [INACTIVITY_TIMEOUT timeout]\n"
" [TIMEOUT timeout] [STATUS status] [LOG log] [SHOW_PROGRESS])\n"
"WRITE will write a message into a file called 'filename'. It "
@@ -177,12 +177,12 @@ public:
"If SHOW_PROGRESS is specified, progress information will be printed "
"as status messages until the operation is complete. "
"For https URLs CMake must be built with OpenSSL. "
- "SSL certificates are not checked by default. "
- "Set SSL_VERIFY to ON to check certificates and/or use "
+ "TLS/SSL certificates are not checked by default. "
+ "Set TLS_VERIFY to ON to check certificates and/or use "
"EXPECTED_HASH to verify downloaded content. "
- "Set SSL_CAINFO_FILE to specify a custom Certificate Authority file. "
- "If either SSL option is not given CMake will check variables "
- "CMAKE_CURLOPT_SSL_VERIFYPEER and CMAKE_CURLOPT_CAINFO_FILE, "
+ "Set TLS_CAINFO to specify a custom Certificate Authority file. "
+ "If either TLS option is not given CMake will check variables "
+ "CMAKE_TLS_VERIFY and CMAKE_TLS_CAINFO, "
"respectively."
"\n"
"UPLOAD will upload the given file to the given URL. "
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 92bbf1d..0885616 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -16,233 +16,112 @@
#include <cmsys/String.h>
+#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorExpressionLexer.h"
+#include "cmGeneratorExpressionParser.h"
+
//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
- cmMakefile* mf, const char* config,
- cmListFileBacktrace const& backtrace, bool quiet):
- Makefile(mf), Config(config), Backtrace(backtrace), Quiet(quiet)
+ cmListFileBacktrace const& backtrace):
+ Backtrace(backtrace), CompiledExpression(0)
{
- this->TargetInfo.compile("^\\$<TARGET"
- "(|_SONAME|_LINKER)" // File with what purpose?
- "_FILE(|_NAME|_DIR):" // Filename component.
- "([A-Za-z0-9_.-]+)" // Target name.
- ">$");
- this->TestConfig.compile("^\\$<CONFIG:([A-Za-z0-9_]*)>$");
}
//----------------------------------------------------------------------------
-const char* cmGeneratorExpression::Process(std::string const& input)
+const cmCompiledGeneratorExpression &
+cmGeneratorExpression::Parse(std::string const& input)
{
- return this->Process(input.c_str());
+ return this->Parse(input.c_str());
}
//----------------------------------------------------------------------------
-const char* cmGeneratorExpression::Process(const char* input)
+const cmCompiledGeneratorExpression &
+cmGeneratorExpression::Parse(const char* input)
{
- this->Data.clear();
+ cmGeneratorExpressionLexer l;
+ std::vector<cmGeneratorExpressionToken> tokens = l.Tokenize(input);
+ bool needsParsing = l.GetSawGeneratorExpression();
+ std::vector<cmGeneratorExpressionEvaluator*> evaluators;
- // We construct and evaluate expressions directly in the output
- // buffer. Each expression is replaced by its own output value
- // after evaluation. A stack of barriers records the starting
- // indices of open (pending) expressions.
- for(const char* c = input; *c; ++c)
+ if (needsParsing)
{
- if(c[0] == '$' && c[1] == '<')
- {
- this->Barriers.push(this->Data.size());
- this->Data.push_back('$');
- this->Data.push_back('<');
- c += 1;
- }
- else if(c[0] == '>' && !this->Barriers.empty())
- {
- this->Data.push_back('>');
- if(!this->Evaluate()) { break; }
- this->Barriers.pop();
- }
- else
- {
- this->Data.push_back(c[0]);
- }
+ cmGeneratorExpressionParser p(tokens);
+ p.Parse(evaluators);
}
- // Return a null-terminated output value.
- this->Data.push_back('\0');
- return &*this->Data.begin();
+ delete this->CompiledExpression;
+ this->CompiledExpression = new cmCompiledGeneratorExpression(
+ this->Backtrace,
+ evaluators,
+ input,
+ needsParsing);
+ return *this->CompiledExpression;
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpression::Evaluate()
+cmGeneratorExpression::~cmGeneratorExpression()
{
- // The top-most barrier points at the beginning of the expression.
- size_t barrier = this->Barriers.top();
-
- // Construct a null-terminated representation of the expression.
- this->Data.push_back('\0');
- const char* expr = &*(this->Data.begin()+barrier);
-
- // Evaluate the expression.
- std::string result;
- if(this->Evaluate(expr, result))
- {
- // Success. Replace the expression with its evaluation result.
- this->Data.erase(this->Data.begin()+barrier, this->Data.end());
- this->Data.insert(this->Data.end(), result.begin(), result.end());
- return true;
- }
- else if(!this->Quiet)
- {
- // Failure. Report the error message.
- cmOStringStream e;
- e << "Error evaluating generator expression:\n"
- << " " << expr << "\n"
- << result;
- this->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
- this->Backtrace);
- return false;
- }
- return true;
+ delete this->CompiledExpression;
}
//----------------------------------------------------------------------------
-static bool cmGeneratorExpressionBool(const char* c, std::string& result,
- const char* name,
- const char* a, const char* b)
+const char *cmCompiledGeneratorExpression::Evaluate(
+ cmMakefile* mf, const char* config, bool quiet) const
{
- result = a;
- while((c[0] == '0' || c[0] == '1') && (c[1] == ',' || c[1] == '>'))
- {
- if(c[0] == b[0]) { result = b; }
- c += 2;
- }
- if(c[0])
+ if (!this->NeedsParsing)
{
- result = name;
- result += " requires one or more comma-separated '0' or '1' values.";
- return false;
+ return this->Input;
}
- return true;
-}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpression::Evaluate(const char* expr, std::string& result)
-{
- if(this->TargetInfo.find(expr))
- {
- if(!this->EvaluateTargetInfo(result))
- {
- return false;
- }
- }
- else if(strcmp(expr, "$<CONFIGURATION>") == 0)
- {
- result = this->Config? this->Config : "";
- }
- else if(strncmp(expr, "$<0:",4) == 0)
- {
- result = "";
- }
- else if(strncmp(expr, "$<1:",4) == 0)
- {
- result = std::string(expr+4, strlen(expr)-5);
- }
- else if(strncmp(expr, "$<NOT:",6) == 0)
+ this->Output = "";
+
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = this->Evaluators.begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = this->Evaluators.end();
+
+ cmGeneratorExpressionContext context;
+ context.Makefile = mf;
+ context.Config = config;
+ context.Quiet = quiet;
+ context.HadError = false;
+ context.Backtrace = this->Backtrace;
+
+ for ( ; it != end; ++it)
{
- const char* c = expr+6;
- if((c[0] != '0' && c[0] != '1') || c[1] != '>' || c[2])
+ this->Output += (*it)->Evaluate(&context);
+ if (context.HadError)
{
- result = "NOT requires exactly one '0' or '1' value.";
- return false;
+ this->Output = "";
+ break;
}
- result = c[0] == '1'? "0" : "1";
}
- else if(strncmp(expr, "$<AND:",6) == 0)
- {
- return cmGeneratorExpressionBool(expr+6, result, "AND", "1", "0");
- }
- else if(strncmp(expr, "$<OR:",5) == 0)
- {
- return cmGeneratorExpressionBool(expr+5, result, "OR", "0", "1");
- }
- else if(this->TestConfig.find(expr))
- {
- result = cmsysString_strcasecmp(this->TestConfig.match(1).c_str(),
- this->Config? this->Config:"") == 0
- ? "1":"0";
- }
- else
- {
- result = "Expression syntax not recognized.";
- return false;
- }
- return true;
+
+ this->Targets = context.Targets;
+ // TODO: Return a std::string from here instead?
+ return this->Output.c_str();
}
-//----------------------------------------------------------------------------
-bool cmGeneratorExpression::EvaluateTargetInfo(std::string& result)
+cmCompiledGeneratorExpression::cmCompiledGeneratorExpression(
+ cmListFileBacktrace const& backtrace,
+ const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
+ const char *input, bool needsParsing)
+ : Backtrace(backtrace), Evaluators(evaluators), Input(input),
+ NeedsParsing(needsParsing)
{
- // Lookup the referenced target.
- std::string name = this->TargetInfo.match(3);
- cmTarget* target = this->Makefile->FindTargetToUse(name.c_str());
- if(!target)
- {
- result = "No target \"" + name + "\"";
- return false;
- }
- if(target->GetType() >= cmTarget::UTILITY &&
- target->GetType() != cmTarget::UNKNOWN_LIBRARY)
- {
- result = "Target \"" + name + "\" is not an executable or library.";
- return false;
- }
- this->Targets.insert(target);
- // Lookup the target file with the given purpose.
- std::string purpose = this->TargetInfo.match(1);
- if(purpose == "")
- {
- // The target implementation file (.so.1.2, .dll, .exe, .a).
- result = target->GetFullPath(this->Config, false, true);
- }
- else if(purpose == "_LINKER")
- {
- // The file used to link to the target (.so, .lib, .a).
- if(!target->IsLinkable())
- {
- result = ("TARGET_LINKER_FILE is allowed only for libraries and "
- "executables with ENABLE_EXPORTS.");
- return false;
- }
- result = target->GetFullPath(this->Config, target->HasImportLibrary());
- }
- else if(purpose == "_SONAME")
- {
- // The target soname file (.so.1).
- if(target->IsDLLPlatform())
- {
- result = "TARGET_SONAME_FILE is not allowed for DLL target platforms.";
- return false;
- }
- if(target->GetType() != cmTarget::SHARED_LIBRARY)
- {
- result = "TARGET_SONAME_FILE is allowed only for SHARED libraries.";
- return false;
- }
- result = target->GetDirectory(this->Config);
- result += "/";
- result += target->GetSOName(this->Config);
- }
+}
- // Extract the requested portion of the full path.
- std::string part = this->TargetInfo.match(2);
- if(part == "_NAME")
- {
- result = cmSystemTools::GetFilenameName(result);
- }
- else if(part == "_DIR")
+
+//----------------------------------------------------------------------------
+cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
+{
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = this->Evaluators.begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = this->Evaluators.end();
+
+ for ( ; it != end; ++it)
{
- result = cmSystemTools::GetFilenamePath(result);
+ delete *it;
}
- return true;
}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index a023eb0..b8467c2 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -19,6 +19,10 @@ class cmTarget;
class cmMakefile;
class cmListFileBacktrace;
+struct cmGeneratorExpressionEvaluator;
+
+class cmCompiledGeneratorExpression;
+
/** \class cmGeneratorExpression
* \brief Evaluate generate-time query expression syntax.
*
@@ -31,29 +35,48 @@ class cmListFileBacktrace;
class cmGeneratorExpression
{
public:
- /** Construct with an evaluation context and configuration. */
- cmGeneratorExpression(cmMakefile* mf, const char* config,
- cmListFileBacktrace const& backtrace,
- bool quiet = false);
+ /** Construct. */
+ cmGeneratorExpression(cmListFileBacktrace const& backtrace);
+ ~cmGeneratorExpression();
+
+ const cmCompiledGeneratorExpression& Parse(std::string const& input);
+ const cmCompiledGeneratorExpression& Parse(const char* input);
+
+private:
+ cmGeneratorExpression(const cmGeneratorExpression &);
+ void operator=(const cmGeneratorExpression &);
+
+ cmListFileBacktrace const& Backtrace;
+ cmCompiledGeneratorExpression *CompiledExpression;
+};
- /** Evaluate generator expressions in a string. */
- const char* Process(std::string const& input);
- const char* Process(const char* input);
+class cmCompiledGeneratorExpression
+{
+public:
+ const char* Evaluate(cmMakefile* mf, const char* config,
+ bool quiet = false) const;
/** Get set of targets found during evaluations. */
std::set<cmTarget*> const& GetTargets() const
{ return this->Targets; }
+
+ ~cmCompiledGeneratorExpression();
+
private:
- cmMakefile* Makefile;
- const char* Config;
+ cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
+ const std::vector<cmGeneratorExpressionEvaluator*> &evaluators,
+ const char *input, bool needsParsing);
+
+ friend class cmGeneratorExpression;
+
+ cmCompiledGeneratorExpression(const cmCompiledGeneratorExpression &);
+ void operator=(const cmCompiledGeneratorExpression &);
+
cmListFileBacktrace const& Backtrace;
- bool Quiet;
- std::vector<char> Data;
- std::stack<size_t> Barriers;
- cmsys::RegularExpression TargetInfo;
- cmsys::RegularExpression TestConfig;
- std::set<cmTarget*> Targets;
- bool Evaluate();
- bool Evaluate(const char* expr, std::string& result);
- bool EvaluateTargetInfo(std::string& result);
+ const std::vector<cmGeneratorExpressionEvaluator*> Evaluators;
+ const char* const Input;
+ const bool NeedsParsing;
+
+ mutable std::set<cmTarget*> Targets;
+ mutable std::string Output;
};
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
new file mode 100644
index 0000000..acc844a
--- /dev/null
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -0,0 +1,568 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmMakefile.h"
+
+#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorExpressionParser.h"
+
+//----------------------------------------------------------------------------
+static void reportError(cmGeneratorExpressionContext *context,
+ const std::string &expr, const std::string &result)
+{
+ context->HadError = true;
+ if (context->Quiet)
+ {
+ return;
+ }
+
+ cmOStringStream e;
+ e << "Error evaluating generator expression:\n"
+ << " " << expr << "\n"
+ << result;
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+ context->Backtrace);
+}
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionNode
+{
+ virtual ~cmGeneratorExpressionNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+
+ virtual bool AcceptsSingleArbitraryContentParameter() const
+ { return false; }
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ virtual std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content
+ ) const = 0;
+};
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode : public cmGeneratorExpressionNode
+{
+ ZeroNode() {}
+
+ virtual bool GeneratesContent() const { return false; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *) const
+ {
+ // Unreachable
+ return std::string();
+ }
+} zeroNode;
+
+//----------------------------------------------------------------------------
+static const struct OneNode : public cmGeneratorExpressionNode
+{
+ OneNode() {}
+
+ virtual bool AcceptsSingleArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *) const
+ {
+ // Unreachable
+ return std::string();
+ }
+} oneNode;
+
+//----------------------------------------------------------------------------
+#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
+static const struct OP ## Node : public cmGeneratorExpressionNode \
+{ \
+ OP ## Node () {} \
+/* We let -1 carry the meaning 'at least one' */ \
+ virtual int NumExpectedParameters() const { return -1; } \
+ \
+ std::string Evaluate(const std::vector<std::string> &parameters, \
+ cmGeneratorExpressionContext *context, \
+ const GeneratorExpressionContent *content) const \
+ { \
+ std::vector<std::string>::const_iterator it = parameters.begin(); \
+ const std::vector<std::string>::const_iterator end = parameters.end(); \
+ for ( ; it != end; ++it) \
+ { \
+ if (*it == #FAILURE_VALUE) \
+ { \
+ return #FAILURE_VALUE; \
+ } \
+ else if (*it != #SUCCESS_VALUE) \
+ { \
+ reportError(context, content->GetOriginalExpression(), \
+ "Parameters to $<" #OP "> must resolve to either '0' or '1'."); \
+ return std::string(); \
+ } \
+ } \
+ return #SUCCESS_VALUE; \
+ } \
+} OPNAME;
+
+BOOLEAN_OP_NODE(andNode, AND, 1, 0)
+BOOLEAN_OP_NODE(orNode, OR, 0, 1)
+
+#undef BOOLEAN_OP_NODE
+
+//----------------------------------------------------------------------------
+static const struct NotNode : public cmGeneratorExpressionNode
+{
+ NotNode() {}
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content) const
+ {
+ if (*parameters.begin() != "0" && *parameters.begin() != "1")
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
+ return std::string();
+ }
+ return *parameters.begin() == "0" ? "1" : "0";
+ }
+} notNode;
+
+//----------------------------------------------------------------------------
+static const struct ConfigurationNode : public cmGeneratorExpressionNode
+{
+ ConfigurationNode() {}
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *) const
+ {
+ return context->Config ? context->Config : "";
+ }
+} configurationNode;
+
+//----------------------------------------------------------------------------
+static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
+{
+ ConfigurationTestNode() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content) const
+ {
+ if (!context->Config)
+ {
+ return std::string();
+ }
+
+ cmsys::RegularExpression configValidator;
+ configValidator.compile("^[A-Za-z0-9_]*$");
+ if (!configValidator.find(parameters.begin()->c_str()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ return *parameters.begin() == context->Config ? "1" : "0";
+ }
+} configurationTestNode;
+
+//----------------------------------------------------------------------------
+template<bool linker, bool soname>
+struct TargetFilesystemArtifactResultCreator
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content);
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<false, true>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content)
+ {
+ // The target soname file (.so.1).
+ if(target->IsDLLPlatform())
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is not allowed "
+ "for DLL target platforms.");
+ return std::string();
+ }
+ if(target->GetType() != cmTarget::SHARED_LIBRARY)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is allowed only for "
+ "SHARED libraries.");
+ return std::string();
+ }
+ std::string result = target->GetDirectory(context->Config);
+ result += "/";
+ result += target->GetSOName(context->Config);
+ return result;
+ }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<true, false>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content)
+ {
+ // The file used to link to the target (.so, .lib, .a).
+ if(!target->IsLinkable())
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_FILE is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+ return target->GetFullPath(context->Config,
+ target->HasImportLibrary());
+ }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<false, false>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *)
+ {
+ return target->GetFullPath(context->Config, false, true);
+ }
+};
+
+
+//----------------------------------------------------------------------------
+template<bool dirQual, bool nameQual>
+struct TargetFilesystemArtifactResultGetter
+{
+ static std::string Get(const std::string &result);
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<false, true>
+{
+ static std::string Get(const std::string &result)
+ { return cmSystemTools::GetFilenameName(result); }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<true, false>
+{
+ static std::string Get(const std::string &result)
+ { return cmSystemTools::GetFilenamePath(result); }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<false, false>
+{
+ static std::string Get(const std::string &result)
+ { return result; }
+};
+
+//----------------------------------------------------------------------------
+template<bool linker, bool soname, bool dirQual, bool nameQual>
+struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
+{
+ TargetFilesystemArtifact() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content) const
+ {
+ // Lookup the referenced target.
+ std::string name = *parameters.begin();
+
+ cmsys::RegularExpression targetValidator;
+ targetValidator.compile("^[A-Za-z0-9_]+$");
+ if (!targetValidator.find(name.c_str()))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ cmTarget* target = context->Makefile->FindTargetToUse(name.c_str());
+ if(!target)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "No target \"" + name + "\"");
+ return std::string();
+ }
+ if(target->GetType() >= cmTarget::UTILITY &&
+ target->GetType() != cmTarget::UNKNOWN_LIBRARY)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target \"" + name + "\" is not an executable or library.");
+ return std::string();
+ }
+ context->Targets.insert(target);
+
+ std::string result =
+ TargetFilesystemArtifactResultCreator<linker, soname>::Create(
+ target,
+ context,
+ content);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ return
+ TargetFilesystemArtifactResultGetter<dirQual, nameQual>::Get(result);
+ }
+};
+
+//----------------------------------------------------------------------------
+static const
+TargetFilesystemArtifact<false, false, false, false> targetFileNode;
+static const
+TargetFilesystemArtifact<true, false, false, false> targetLinkerFileNode;
+static const
+TargetFilesystemArtifact<false, true, false, false> targetSoNameFileNode;
+static const
+TargetFilesystemArtifact<false, false, false, true> targetFileNameNode;
+static const
+TargetFilesystemArtifact<true, false, false, true> targetLinkerFileNameNode;
+static const
+TargetFilesystemArtifact<false, true, false, true> targetSoNameFileNameNode;
+static const
+TargetFilesystemArtifact<false, false, true, false> targetFileDirNode;
+static const
+TargetFilesystemArtifact<true, false, true, false> targetLinkerFileDirNode;
+static const
+TargetFilesystemArtifact<false, true, true, false> targetSoNameFileDirNode;
+
+//----------------------------------------------------------------------------
+static const
+cmGeneratorExpressionNode* GetNode(const std::string &identifier)
+{
+ if (identifier == "0")
+ return &zeroNode;
+ if (identifier == "1")
+ return &oneNode;
+ if (identifier == "AND")
+ return &andNode;
+ if (identifier == "OR")
+ return &orNode;
+ if (identifier == "NOT")
+ return &notNode;
+ else if (identifier == "CONFIGURATION")
+ return &configurationNode;
+ else if (identifier == "CONFIG")
+ return &configurationTestNode;
+ else if (identifier == "TARGET_FILE")
+ return &targetFileNode;
+ else if (identifier == "TARGET_LINKER_FILE")
+ return &targetLinkerFileNode;
+ else if (identifier == "TARGET_SONAME_FILE")
+ return &targetSoNameFileNode;
+ else if (identifier == "TARGET_FILE_NAME")
+ return &targetFileNameNode;
+ else if (identifier == "TARGET_LINKER_FILE_NAME")
+ return &targetLinkerFileNameNode;
+ else if (identifier == "TARGET_SONAME_FILE_NAME")
+ return &targetSoNameFileNameNode;
+ else if (identifier == "TARGET_FILE_DIR")
+ return &targetFileDirNode;
+ else if (identifier == "TARGET_LINKER_FILE_DIR")
+ return &targetLinkerFileDirNode;
+ else if (identifier == "TARGET_SONAME_FILE_DIR")
+ return &targetSoNameFileDirNode;
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+GeneratorExpressionContent::GeneratorExpressionContent(
+ const char *startContent,
+ unsigned int length)
+ : StartContent(startContent), ContentLength(length)
+{
+
+}
+
+//----------------------------------------------------------------------------
+std::string GeneratorExpressionContent::GetOriginalExpression() const
+{
+ return std::string(this->StartContent, this->ContentLength);
+}
+
+//----------------------------------------------------------------------------
+std::string GeneratorExpressionContent::Evaluate(
+ cmGeneratorExpressionContext *context) const
+{
+ std::string identifier;
+ {
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = this->IdentifierChildren.begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = this->IdentifierChildren.end();
+ for ( ; it != end; ++it)
+ {
+ identifier += (*it)->Evaluate(context);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ }
+ }
+
+ const cmGeneratorExpressionNode *node = GetNode(identifier);
+
+ if (!node)
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "Expression did not evaluate to a known generator expression");
+ return std::string();
+ }
+
+ if (!node->GeneratesContent())
+ {
+ return std::string();
+ }
+
+ if (node->AcceptsSingleArbitraryContentParameter())
+ {
+ std::string result;
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit = this->ParamChildren.begin();
+ const
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pend = this->ParamChildren.end();
+ for ( ; pit != pend; ++pit)
+ {
+ if (!result.empty())
+ {
+ result += ",";
+ }
+
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = pit->begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = pit->end();
+ for ( ; it != end; ++it)
+ {
+ result += (*it)->Evaluate(context);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ }
+ }
+ return result;
+ }
+
+ std::vector<std::string> parameters;
+ {
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pit = this->ParamChildren.begin();
+ const
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> >::const_iterator
+ pend = this->ParamChildren.end();
+ for ( ; pit != pend; ++pit)
+ {
+ std::string parameter;
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it =
+ pit->begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end =
+ pit->end();
+ for ( ; it != end; ++it)
+ {
+ parameter += (*it)->Evaluate(context);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ }
+ parameters.push_back(parameter);
+ }
+ }
+
+ int numExpected = node->NumExpectedParameters();
+ if ((numExpected != -1 && (unsigned int)numExpected != parameters.size()))
+ {
+ if (numExpected == 0)
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier + "> expression requires no parameters.");
+ }
+ else if (numExpected == 1)
+ {
+ reportError(context, this->GetOriginalExpression(),
+ "$<" + identifier + "> expression requires "
+ "exactly one parameter.");
+ }
+ else
+ {
+ cmOStringStream e;
+ e << "$<" + identifier + "> expression requires "
+ << numExpected
+ << " comma separated parameters, but got "
+ << parameters.size() << " instead.";
+ reportError(context, this->GetOriginalExpression(), e.str());
+ }
+ return std::string();
+ }
+
+ if (numExpected == -1 && parameters.empty())
+ {
+ reportError(context, this->GetOriginalExpression(), "$<" + identifier
+ + "> expression requires at least one parameter.");
+ return std::string();
+ }
+
+ return node->Evaluate(parameters, context, this);
+}
+
+//----------------------------------------------------------------------------
+static void deleteAll(const std::vector<cmGeneratorExpressionEvaluator*> &c)
+{
+ std::vector<cmGeneratorExpressionEvaluator*>::const_iterator it
+ = c.begin();
+ const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
+ = c.end();
+ for ( ; it != end; ++it)
+ {
+ delete *it;
+ }
+}
+
+//----------------------------------------------------------------------------
+GeneratorExpressionContent::~GeneratorExpressionContent()
+{
+ deleteAll(this->IdentifierChildren);
+
+ typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
+ typedef std::vector<cmGeneratorExpressionToken> TokenVector;
+ std::vector<EvaluatorVector>::const_iterator pit =
+ this->ParamChildren.begin();
+ const std::vector<EvaluatorVector>::const_iterator pend =
+ this->ParamChildren.end();
+ for ( ; pit != pend; ++pit)
+ {
+ deleteAll(*pit);
+ }
+}
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
new file mode 100644
index 0000000..5163ca0
--- /dev/null
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -0,0 +1,118 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ 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 cmGeneratorExpressionEvaluator_h
+#define cmGeneratorExpressionEvaluator_h
+
+#include <vector>
+#include <string>
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionContext
+{
+ cmListFileBacktrace Backtrace;
+ std::set<cmTarget*> Targets;
+ cmMakefile *Makefile;
+ const char *Config;
+ cmTarget *Target;
+ bool Quiet;
+ bool HadError;
+};
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionEvaluator
+{
+ cmGeneratorExpressionEvaluator() {}
+ virtual ~cmGeneratorExpressionEvaluator() {}
+
+ enum Type
+ {
+ Text,
+ Generator
+ };
+
+ virtual Type GetType() const = 0;
+
+ virtual std::string Evaluate(cmGeneratorExpressionContext *context
+ ) const = 0;
+
+private:
+ cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator &);
+ void operator=(const cmGeneratorExpressionEvaluator &);
+};
+
+struct TextContent : public cmGeneratorExpressionEvaluator
+{
+ TextContent(const char *start, unsigned int length)
+ : Content(start), Length(length)
+ {
+
+ }
+
+ std::string Evaluate(cmGeneratorExpressionContext *) const
+ {
+ return std::string(this->Content, this->Length);
+ }
+
+ Type GetType() const
+ {
+ return cmGeneratorExpressionEvaluator::Text;
+ }
+
+ void Extend(unsigned int length)
+ {
+ this->Length += length;
+ }
+
+ unsigned int GetLength()
+ {
+ return this->Length;
+ }
+
+private:
+ const char *Content;
+ unsigned int Length;
+};
+
+//----------------------------------------------------------------------------
+struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
+{
+ GeneratorExpressionContent(const char *startContent, unsigned int length);
+ void SetIdentifier(std::vector<cmGeneratorExpressionEvaluator*> identifier)
+ {
+ this->IdentifierChildren = identifier;
+ }
+
+ void SetParameters(
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters)
+ {
+ this->ParamChildren = parameters;
+ }
+
+ Type GetType() const
+ {
+ return cmGeneratorExpressionEvaluator::Generator;
+ }
+
+ std::string Evaluate(cmGeneratorExpressionContext *context) const;
+
+ std::string GetOriginalExpression() const;
+
+ ~GeneratorExpressionContent();
+
+private:
+ std::vector<cmGeneratorExpressionEvaluator*> IdentifierChildren;
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> > ParamChildren;
+ const char *StartContent;
+ unsigned int ContentLength;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx
new file mode 100644
index 0000000..cd71ec0
--- /dev/null
+++ b/Source/cmGeneratorExpressionLexer.cxx
@@ -0,0 +1,85 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmGeneratorExpressionLexer.h"
+
+
+//----------------------------------------------------------------------------
+cmGeneratorExpressionLexer::cmGeneratorExpressionLexer()
+ : SawBeginExpression(false), SawGeneratorExpression(false)
+{
+
+}
+
+//----------------------------------------------------------------------------
+static void InsertText(const char *upto, const char *c,
+ std::vector<cmGeneratorExpressionToken> &result)
+{
+ if (upto != c)
+ {
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::Text, upto, c - upto));
+ }
+}
+
+//----------------------------------------------------------------------------
+std::vector<cmGeneratorExpressionToken>
+cmGeneratorExpressionLexer::Tokenize(const char *input)
+{
+ std::vector<cmGeneratorExpressionToken> result;
+ if (!input)
+ return result;
+
+ const char *c = input;
+ const char *upto = c;
+
+ for ( ; *c; ++c)
+ {
+ if(c[0] == '$' && c[1] == '<')
+ {
+ InsertText(upto, c, result);
+ upto = c;
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::BeginExpression, upto, 2));
+ upto = c + 2;
+ ++c;
+ SawBeginExpression = true;
+ }
+ else if(c[0] == '>')
+ {
+ InsertText(upto, c, result);
+ upto = c;
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::EndExpression, upto, 1));
+ upto = c + 1;
+ SawGeneratorExpression = SawBeginExpression;
+ }
+ else if(c[0] == ':')
+ {
+ InsertText(upto, c, result);
+ upto = c;
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::ColonSeparator, upto, 1));
+ upto = c + 1;
+ }
+ else if(c[0] == ',')
+ {
+ InsertText(upto, c, result);
+ upto = c;
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::CommaSeparator, upto, 1));
+ upto = c + 1;
+ }
+ }
+ InsertText(upto, c, result);
+
+ return result;
+}
diff --git a/Source/cmGeneratorExpressionLexer.h b/Source/cmGeneratorExpressionLexer.h
new file mode 100644
index 0000000..5f16712
--- /dev/null
+++ b/Source/cmGeneratorExpressionLexer.h
@@ -0,0 +1,58 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ 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 cmGeneratorExpressionLexer_h
+#define cmGeneratorExpressionLexer_h
+
+#include "cmStandardIncludes.h"
+
+#include <vector>
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionToken
+{
+ cmGeneratorExpressionToken(unsigned type, const char *c, unsigned l)
+ : TokenType(type), Content(c), Length(l)
+ {
+ }
+ enum {
+ Text,
+ BeginExpression,
+ EndExpression,
+ ColonSeparator,
+ CommaSeparator
+ };
+ unsigned TokenType;
+ const char *Content;
+ unsigned Length;
+};
+
+/** \class cmGeneratorExpressionLexer
+ *
+ */
+class cmGeneratorExpressionLexer
+{
+public:
+ cmGeneratorExpressionLexer();
+
+ std::vector<cmGeneratorExpressionToken> Tokenize(const char *input);
+
+ bool GetSawGeneratorExpression() const
+ {
+ return this->SawGeneratorExpression;
+ }
+
+private:
+ bool SawBeginExpression;
+ bool SawGeneratorExpression;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionParser.cxx b/Source/cmGeneratorExpressionParser.cxx
new file mode 100644
index 0000000..2a5cc7a
--- /dev/null
+++ b/Source/cmGeneratorExpressionParser.cxx
@@ -0,0 +1,235 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+
+#include "cmGeneratorExpressionParser.h"
+
+#include "cmGeneratorExpressionEvaluator.h"
+
+//----------------------------------------------------------------------------
+cmGeneratorExpressionParser::cmGeneratorExpressionParser(
+ const std::vector<cmGeneratorExpressionToken> &tokens)
+ : Tokens(tokens), NestingLevel(0)
+{
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionParser::Parse(
+ std::vector<cmGeneratorExpressionEvaluator*> &result)
+{
+ it = this->Tokens.begin();
+
+ while (this->it != this->Tokens.end())
+ {
+ this->ParseContent(result);
+ }
+}
+
+//----------------------------------------------------------------------------
+static void extendText(std::vector<cmGeneratorExpressionEvaluator*> &result,
+ std::vector<cmGeneratorExpressionToken>::const_iterator it)
+{
+ if (result.size() > 0
+ && (*(result.end() - 1))->GetType()
+ == cmGeneratorExpressionEvaluator::Text)
+ {
+ TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
+ textContent->Extend(it->Length);
+ }
+ else
+ {
+ TextContent *textContent = new TextContent(it->Content, it->Length);
+ result.push_back(textContent);
+ }
+}
+
+//----------------------------------------------------------------------------
+static void extendResult(std::vector<cmGeneratorExpressionEvaluator*> &result,
+ const std::vector<cmGeneratorExpressionEvaluator*> &contents)
+{
+ if (result.size() > 0
+ && (*(result.end() - 1))->GetType()
+ == cmGeneratorExpressionEvaluator::Text
+ && (*contents.begin())->GetType()
+ == cmGeneratorExpressionEvaluator::Text)
+ {
+ TextContent *textContent = static_cast<TextContent*>(*(result.end() - 1));
+ textContent->Extend(
+ static_cast<TextContent*>(*contents.begin())->GetLength());
+ delete *contents.begin();
+ result.insert(result.end(), contents.begin() + 1, contents.end());
+ } else {
+ result.insert(result.end(), contents.begin(), contents.end());
+ }
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionParser::ParseGeneratorExpression(
+ std::vector<cmGeneratorExpressionEvaluator*> &result)
+{
+ unsigned int nestedLevel = this->NestingLevel;
+ ++this->NestingLevel;
+
+ std::vector<cmGeneratorExpressionToken>::const_iterator startToken
+ = this->it - 1;
+
+ std::vector<cmGeneratorExpressionEvaluator*> identifier;
+ while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression
+ && this->it->TokenType != cmGeneratorExpressionToken::ColonSeparator)
+ {
+ this->ParseContent(identifier);
+ if (this->it == this->Tokens.end())
+ {
+ break;
+ }
+ }
+ if (identifier.empty())
+ {
+ // ERROR
+ }
+
+ if (this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
+ {
+ GeneratorExpressionContent *content = new GeneratorExpressionContent(
+ startToken->Content, this->it->Content
+ - startToken->Content
+ + this->it->Length);
+ ++this->it;
+ --this->NestingLevel;
+ content->SetIdentifier(identifier);
+ result.push_back(content);
+ return;
+ }
+
+ std::vector<std::vector<cmGeneratorExpressionEvaluator*> > parameters;
+ std::vector<std::vector<cmGeneratorExpressionToken>::const_iterator>
+ commaTokens;
+ std::vector<cmGeneratorExpressionToken>::const_iterator colonToken;
+ if (this->it->TokenType == cmGeneratorExpressionToken::ColonSeparator)
+ {
+ colonToken = this->it;
+ parameters.resize(parameters.size() + 1);
+ ++this->it;
+ while(this->it->TokenType != cmGeneratorExpressionToken::EndExpression)
+ {
+ this->ParseContent(*(parameters.end() - 1));
+ if (this->it->TokenType == cmGeneratorExpressionToken::CommaSeparator)
+ {
+ commaTokens.push_back(this->it);
+ parameters.resize(parameters.size() + 1);
+ ++this->it;
+ }
+ if (this->it == this->Tokens.end())
+ {
+ break;
+ }
+ }
+ if(this->it->TokenType == cmGeneratorExpressionToken::EndExpression)
+ {
+ --this->NestingLevel;
+ ++this->it;
+ }
+ if (parameters.empty())
+ {
+ // ERROR
+ }
+ }
+
+ if (nestedLevel != this->NestingLevel)
+ {
+ // There was a '$<' in the text, but no corresponding '>'. Rebuild to
+ // treat the '$<' as having been plain text, along with the
+ // corresponding : and , tokens that might have been found.
+ extendText(result, startToken);
+ extendResult(result, identifier);
+ if (!parameters.empty())
+ {
+ extendText(result, colonToken);
+
+ typedef std::vector<cmGeneratorExpressionEvaluator*> EvaluatorVector;
+ typedef std::vector<cmGeneratorExpressionToken> TokenVector;
+ std::vector<EvaluatorVector>::const_iterator pit = parameters.begin();
+ const std::vector<EvaluatorVector>::const_iterator pend =
+ parameters.end();
+ std::vector<TokenVector::const_iterator>::const_iterator commaIt =
+ commaTokens.begin();
+ for ( ; pit != pend; ++pit, ++commaIt)
+ {
+ extendResult(result, *pit);
+ if (commaIt != commaTokens.end())
+ {
+ extendText(result, *commaIt);
+ }
+ }
+ }
+ return;
+ }
+
+ int contentLength = ((this->it - 1)->Content
+ - startToken->Content)
+ + (this->it - 1)->Length;
+ GeneratorExpressionContent *content = new GeneratorExpressionContent(
+ startToken->Content, contentLength);
+ content->SetIdentifier(identifier);
+ content->SetParameters(parameters);
+ result.push_back(content);
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionParser::ParseContent(
+ std::vector<cmGeneratorExpressionEvaluator*> &result)
+{
+ switch(this->it->TokenType)
+ {
+ case cmGeneratorExpressionToken::Text:
+ {
+ if (this->NestingLevel == 0)
+ {
+ if (result.size() > 0
+ && (*(result.end() - 1))->GetType()
+ == cmGeneratorExpressionEvaluator::Text)
+ {
+ // A comma in 'plain text' could have split text that should
+ // otherwise be continuous. Extend the last text content instead of
+ // creating a new one.
+ TextContent *textContent =
+ static_cast<TextContent*>(*(result.end() - 1));
+ textContent->Extend(this->it->Length);
+ ++this->it;
+ return;
+ }
+ }
+ cmGeneratorExpressionEvaluator* n = new TextContent(this->it->Content,
+ this->it->Length);
+ result.push_back(n);
+ ++this->it;
+ return ;
+ }
+ case cmGeneratorExpressionToken::BeginExpression:
+ ++this->it;
+ this->ParseGeneratorExpression(result);
+ return;
+ case cmGeneratorExpressionToken::EndExpression:
+ case cmGeneratorExpressionToken::ColonSeparator:
+ case cmGeneratorExpressionToken::CommaSeparator:
+ if (this->NestingLevel == 0)
+ {
+ extendText(result, this->it);
+ }
+ else
+ {
+ // TODO: Unreachable. Assert?
+ }
+ ++this->it;
+ return;
+ }
+ // Unreachable. Assert?
+}
diff --git a/Source/cmGeneratorExpressionParser.h b/Source/cmGeneratorExpressionParser.h
new file mode 100644
index 0000000..28f1441
--- /dev/null
+++ b/Source/cmGeneratorExpressionParser.h
@@ -0,0 +1,45 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 Stephen Kelly <steveire@gmail.com>
+
+ 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 cmGeneratorExpressionParser_h
+#define cmGeneratorExpressionParser_h
+
+#include "cmGeneratorExpressionLexer.h"
+
+#include <set>
+#include <vector>
+
+#include "cmListFileCache.h"
+
+class cmMakefile;
+class cmTarget;
+struct cmGeneratorExpressionEvaluator;
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionParser
+{
+ cmGeneratorExpressionParser(
+ const std::vector<cmGeneratorExpressionToken> &tokens);
+
+ void Parse(std::vector<cmGeneratorExpressionEvaluator*> &result);
+
+private:
+ void ParseContent(std::vector<cmGeneratorExpressionEvaluator*> &);
+ void ParseGeneratorExpression(
+ std::vector<cmGeneratorExpressionEvaluator*> &);
+
+private:
+ std::vector<cmGeneratorExpressionToken>::const_iterator it;
+ const std::vector<cmGeneratorExpressionToken> Tokens;
+ unsigned int NestingLevel;
+};
+
+#endif
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index d188980..480c577 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -205,6 +205,8 @@ std::string cmGlobalVisualStudio10Generator
{
makeCommand += "Debug";
}
+ makeCommand += " /p:VisualStudioVersion=";
+ makeCommand += this->GetIDEVersion();
if ( additionalOptions )
{
makeCommand += " ";
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 7bb4d0c..23a1204 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -17,7 +17,10 @@
cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator()
{
this->FindMakeProgramFile = "CMakeVS11FindMake.cmake";
- this->ExpressEdition = false; // TODO: VS 11 Express support
+ std::string vc11Express;
+ this->ExpressEdition = cmSystemTools::ReadRegistryValue(
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\11.0\\Setup\\VC;"
+ "ProductDir", vc11Express, cmSystemTools::KeyWOW64_32);
this->PlatformToolset = "v110";
}
diff --git a/Source/cmGlobalVisualStudio8Win64Generator.cxx b/Source/cmGlobalVisualStudio8Win64Generator.cxx
index 60e45b8..164d116 100644
--- a/Source/cmGlobalVisualStudio8Win64Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Win64Generator.cxx
@@ -22,17 +22,6 @@ cmGlobalVisualStudio8Win64Generator::cmGlobalVisualStudio8Win64Generator()
this->ArchitectureId = "x64";
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio8Win64Generator::CreateLocalGenerator()
-{
- cmLocalVisualStudio7Generator *lg
- = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS8);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
//----------------------------------------------------------------------------
void cmGlobalVisualStudio8Win64Generator
::GetDocumentation(cmDocumentationEntry& entry) const
diff --git a/Source/cmGlobalVisualStudio8Win64Generator.h b/Source/cmGlobalVisualStudio8Win64Generator.h
index 136cdb8..12f8012 100644
--- a/Source/cmGlobalVisualStudio8Win64Generator.h
+++ b/Source/cmGlobalVisualStudio8Win64Generator.h
@@ -38,9 +38,6 @@ public:
/** Get the documentation entry for this generator. */
virtual void GetDocumentation(cmDocumentationEntry& entry) const;
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
diff --git a/Source/cmGlobalVisualStudio9IA64Generator.cxx b/Source/cmGlobalVisualStudio9IA64Generator.cxx
index 993340a..38dbfac 100644
--- a/Source/cmGlobalVisualStudio9IA64Generator.cxx
+++ b/Source/cmGlobalVisualStudio9IA64Generator.cxx
@@ -19,17 +19,6 @@ cmGlobalVisualStudio9IA64Generator::cmGlobalVisualStudio9IA64Generator()
this->ArchitectureId = "Itanium";
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio9IA64Generator::CreateLocalGenerator()
-{
- cmLocalVisualStudio7Generator *lg =
- new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
//----------------------------------------------------------------------------
void cmGlobalVisualStudio9IA64Generator
::GetDocumentation(cmDocumentationEntry& entry) const
diff --git a/Source/cmGlobalVisualStudio9IA64Generator.h b/Source/cmGlobalVisualStudio9IA64Generator.h
index e33ee15..989b0d1 100644
--- a/Source/cmGlobalVisualStudio9IA64Generator.h
+++ b/Source/cmGlobalVisualStudio9IA64Generator.h
@@ -38,9 +38,6 @@ public:
/** Get the documentation entry for this generator. */
virtual void GetDocumentation(cmDocumentationEntry& entry) const;
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
diff --git a/Source/cmGlobalVisualStudio9Win64Generator.cxx b/Source/cmGlobalVisualStudio9Win64Generator.cxx
index 08f537d..4d8a646 100644
--- a/Source/cmGlobalVisualStudio9Win64Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Win64Generator.cxx
@@ -19,17 +19,6 @@ cmGlobalVisualStudio9Win64Generator::cmGlobalVisualStudio9Win64Generator()
this->ArchitectureId = "x64";
}
-///! Create a local generator appropriate to this Global Generator
-cmLocalGenerator *cmGlobalVisualStudio9Win64Generator::CreateLocalGenerator()
-{
- cmLocalVisualStudio7Generator *lg =
- new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9);
- lg->SetPlatformName(this->GetPlatformName());
- lg->SetExtraFlagTable(this->GetExtraFlagTableVS8());
- lg->SetGlobalGenerator(this);
- return lg;
-}
-
//----------------------------------------------------------------------------
void cmGlobalVisualStudio9Win64Generator
::GetDocumentation(cmDocumentationEntry& entry) const
diff --git a/Source/cmGlobalVisualStudio9Win64Generator.h b/Source/cmGlobalVisualStudio9Win64Generator.h
index 0ce1afe..7c20cf4 100644
--- a/Source/cmGlobalVisualStudio9Win64Generator.h
+++ b/Source/cmGlobalVisualStudio9Win64Generator.h
@@ -38,9 +38,6 @@ public:
/** Get the documentation entry for this generator. */
virtual void GetDocumentation(cmDocumentationEntry& entry) const;
- ///! create the correct local generator
- virtual cmLocalGenerator *CreateLocalGenerator();
-
/**
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index ffc0f35..56d7170 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -409,14 +409,18 @@ namespace
enum Op { OpLess, OpEqual, OpGreater };
bool HandleVersionCompare(Op op, const char* lhs_str, const char* rhs_str)
{
- // Parse out up to 4 components.
- unsigned int lhs[4] = {0,0,0,0};
- unsigned int rhs[4] = {0,0,0,0};
- sscanf(lhs_str, "%u.%u.%u.%u", &lhs[0], &lhs[1], &lhs[2], &lhs[3]);
- sscanf(rhs_str, "%u.%u.%u.%u", &rhs[0], &rhs[1], &rhs[2], &rhs[3]);
+ // Parse out up to 8 components.
+ unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
+ unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
+ sscanf(lhs_str, "%u.%u.%u.%u.%u.%u.%u.%u",
+ &lhs[0], &lhs[1], &lhs[2], &lhs[3],
+ &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
+ sscanf(rhs_str, "%u.%u.%u.%u.%u.%u.%u.%u",
+ &rhs[0], &rhs[1], &rhs[2], &rhs[3],
+ &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
// Do component-wise comparison.
- for(unsigned int i=0; i < 4; ++i)
+ for(unsigned int i=0; i < 8; ++i)
{
if(lhs[i] < rhs[i])
{
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 4cc23ca..385b4a0 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -167,11 +167,41 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile *source,
// Append old-style preprocessor definition flags.
this->LocalGenerator->AppendFlags(flags, this->Makefile->GetDefineFlags());
- // Add target-specific and source-specific flags.
- this->LocalGenerator->AppendFlags(flags,
- this->Target->GetProperty("COMPILE_FLAGS"));
- this->LocalGenerator->AppendFlags(flags,
- source->GetProperty("COMPILE_FLAGS"));
+ // Add target-specific flags.
+ if(this->Target->GetProperty("COMPILE_FLAGS"))
+ {
+ std::string langIncludeExpr = "CMAKE_";
+ langIncludeExpr += language;
+ langIncludeExpr += "_FLAG_REGEX";
+ const char* regex = this->Makefile->
+ GetDefinition(langIncludeExpr.c_str());
+ if(regex)
+ {
+ cmsys::RegularExpression r(regex);
+ std::vector<std::string> args;
+ cmSystemTools::ParseWindowsCommandLine(
+ this->Target->GetProperty("COMPILE_FLAGS"),
+ args);
+ for(std::vector<std::string>::iterator i = args.begin();
+ i != args.end(); ++i)
+ {
+ if(r.find(i->c_str()))
+ {
+ this->LocalGenerator->AppendFlags
+ (flags, i->c_str());
+ }
+ }
+ }
+ else
+ {
+ this->LocalGenerator->AppendFlags
+ (flags, this->Target->GetProperty("COMPILE_FLAGS"));
+ }
+ }
+
+ // Add source file specific flags.
+ this->LocalGenerator->AppendFlags(flags,
+ source->GetProperty("COMPILE_FLAGS"));
// TODO: Handle Apple frameworks.
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 789713f..9a3812c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1623,7 +1623,11 @@ cmTargetTraceDependencies
{
// Transform command names that reference targets built in this
// project to corresponding target-level dependencies.
- cmGeneratorExpression ge(this->Makefile, 0, cc.GetBacktrace(), true);
+ cmGeneratorExpression ge(cc.GetBacktrace());
+
+ // Add target-level dependencies referenced by generator expressions.
+ std::set<cmTarget*> targets;
+
for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
cit != cc.GetCommandLines().end(); ++cit)
{
@@ -1645,12 +1649,17 @@ cmTargetTraceDependencies
for(cmCustomCommandLine::const_iterator cli = cit->begin();
cli != cit->end(); ++cli)
{
- ge.Process(*cli);
+ const cmCompiledGeneratorExpression &cge = ge.Parse(*cli);
+ cge.Evaluate(this->Makefile, 0, true);
+ std::set<cmTarget*> geTargets = cge.GetTargets();
+ for(std::set<cmTarget*>::const_iterator it = geTargets.begin();
+ it != geTargets.end(); ++it)
+ {
+ targets.insert(*it);
+ }
}
}
- // Add target-level dependencies referenced by generator expressions.
- std::set<cmTarget*> targets = ge.GetTargets();
for(std::set<cmTarget*>::iterator ti = targets.begin();
ti != targets.end(); ++ti)
{
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index e0892b2..2f650e7 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -91,8 +91,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
this->TestGenerated = true;
// Set up generator expression evaluation context.
- cmMakefile* mf = this->Test->GetMakefile();
- cmGeneratorExpression ge(mf, config, this->Test->GetBacktrace());
+ cmGeneratorExpression ge(this->Test->GetBacktrace());
// Start the test command.
os << indent << "ADD_TEST(" << this->Test->GetName() << " ";
@@ -103,6 +102,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
// Check whether the command executable is a target whose name is to
// be translated.
std::string exe = command[0];
+ cmMakefile* mf = this->Test->GetMakefile();
cmTarget* target = mf->FindTargetToUse(exe.c_str());
if(target && target->GetType() == cmTarget::EXECUTABLE)
{
@@ -112,7 +112,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
else
{
// Use the command name given.
- exe = ge.Process(exe.c_str());
+ exe = ge.Parse(exe.c_str()).Evaluate(mf, config);
cmSystemTools::ConvertToUnixSlashes(exe);
}
@@ -122,7 +122,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
for(std::vector<std::string>::const_iterator ci = command.begin()+1;
ci != command.end(); ++ci)
{
- os << " " << lg->EscapeForCMake(ge.Process(*ci));
+ os << " " << lg->EscapeForCMake(ge.Parse(*ci).Evaluate(mf, config));
}
// Finish the test command.
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index c6787b9..079ea36 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2184,6 +2184,7 @@ int cmake::ActualConfigure()
std::vector<std::string> vsVerions;
vsVerions.push_back("VisualStudio\\");
vsVerions.push_back("VCExpress\\");
+ vsVerions.push_back("WDExpress\\");
struct VSRegistryEntryName
{
const char* MSVersion;
@@ -2196,10 +2197,11 @@ int cmake::ActualConfigure()
{"8.0", "Visual Studio 8 2005"},
{"9.0", "Visual Studio 9 2008"},
{"10.0", "Visual Studio 10"},
+ {"11.0", "Visual Studio 11"},
{0, 0}};
- for(size_t b=0; b < vsVerions.size() && installedCompiler.empty(); b++)
+ for(int i=0; version[i].MSVersion != 0; i++)
{
- for(int i =0; version[i].MSVersion != 0; i++)
+ for(size_t b=0; b < vsVerions.size(); b++)
{
std::string reg = vsregBase + vsVerions[b] + version[i].MSVersion;
reg += ";InstallDir]";
@@ -2208,6 +2210,7 @@ int cmake::ActualConfigure()
if (!(reg == "/registry"))
{
installedCompiler = version[i].GeneratorName;
+ break;
}
}
}