summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx14
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h1
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx72
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h2
-rw-r--r--Source/cmMakefile.cxx40
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/MorePost-check.cmake5
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/MorePost.cmake2
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/MorePre-check.cmake5
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/MorePre.cmake2
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/OnePost-check.cmake4
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/OnePost.cmake1
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/OnePre-check.cmake4
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/OnePre.cmake1
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/Override1-check.cmake4
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/Override1.cmake2
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/Override2-check.cmake4
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/Override2.cmake2
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/PrePost-check.cmake6
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/PrePost.cmake4
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/RunCMakeTest.cmake10
-rw-r--r--Tests/RunCMake/SolutionGlobalSections/solution_parsing.cmake60
23 files changed, 232 insertions, 17 deletions
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 736efd5..9f318ec 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -128,6 +128,9 @@ void cmGlobalVisualStudio71Generator
fout << "\tEndGlobalSection\n";
}
+ // Write out global sections
+ this->WriteSLNGlobalSections(fout, root);
+
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
@@ -297,17 +300,6 @@ void cmGlobalVisualStudio71Generator
}
//----------------------------------------------------------------------------
-// Standard end of dsw file
-void cmGlobalVisualStudio71Generator::WriteSLNFooter(std::ostream& fout)
-{
- fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "EndGlobal\n";
-}
-
-//----------------------------------------------------------------------------
// ouput standard header for dsw file
void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
{
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 5dd194c..f96a7d9 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -70,7 +70,6 @@ protected:
const char* path,
const char* typeGuid,
const std::set<cmStdString>& depends);
- virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
std::string ProjectConfigurationSectionName;
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 862f1d3..6f9c028 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -435,6 +435,9 @@ void cmGlobalVisualStudio7Generator
this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
fout << "\tEndGlobalSection\n";
+ // Write out global sections
+ this->WriteSLNGlobalSections(fout, root);
+
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
@@ -631,14 +634,73 @@ void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
+void cmGlobalVisualStudio7Generator
+::WriteSLNGlobalSections(std::ostream& fout,
+ cmLocalGenerator* root)
+{
+ bool extensibilityGlobalsOverridden = false;
+ bool extensibilityAddInsOverridden = false;
+ const cmPropertyMap& props = root->GetMakefile()->GetProperties();
+ for(cmPropertyMap::const_iterator itProp = props.begin();
+ itProp != props.end(); ++itProp)
+ {
+ if(itProp->first.find("VS_GLOBAL_SECTION_") == 0)
+ {
+ std::string sectionType;
+ std::string name = itProp->first.substr(18);
+ if(name.find("PRE_") == 0)
+ {
+ name = name.substr(4);
+ sectionType = "preSolution";
+ }
+ else if(name.find("POST_") == 0)
+ {
+ name = name.substr(5);
+ sectionType = "postSolution";
+ }
+ else
+ continue;
+ if(!name.empty())
+ {
+ if(name == "ExtensibilityGlobals" && sectionType == "postSolution")
+ extensibilityGlobalsOverridden = true;
+ else if(name == "ExtensibilityAddIns" && sectionType == "postSolution")
+ extensibilityAddInsOverridden = true;
+ fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
+ std::vector<std::string> keyValuePairs;
+ cmSystemTools::ExpandListArgument(itProp->second.GetValue(),
+ keyValuePairs);
+ for(std::vector<std::string>::const_iterator itPair =
+ keyValuePairs.begin(); itPair != keyValuePairs.end(); ++itPair)
+ {
+ const std::string::size_type posEqual = itPair->find('=');
+ if(posEqual != std::string::npos)
+ {
+ const std::string key =
+ cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
+ const std::string value =
+ cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
+ fout << "\t\t" << key << " = " << value << "\n";
+ }
+ }
+ fout << "\tEndGlobalSection\n";
+ }
+ }
+ }
+ if(!extensibilityGlobalsOverridden)
+ fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
+ << "\tEndGlobalSection\n";
+ if(!extensibilityAddInsOverridden)
+ fout << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
+ << "\tEndGlobalSection\n";
+}
+
+
+
// Standard end of dsw file
void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
{
- fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
- << "\tEndGlobalSection\n"
- << "EndGlobal\n";
+ fout << "EndGlobal\n";
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index 3775dd4..8ba1f44 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -109,6 +109,8 @@ protected:
std::ostream& fout, const char* name,
const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping = NULL);
+ virtual void WriteSLNGlobalSections(std::ostream& fout,
+ cmLocalGenerator* root);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
virtual std::string WriteUtilityDepend(cmTarget* target);
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index f067da4..8498d72 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -3937,6 +3937,46 @@ void cmMakefile::DefineProperties(cmake *cm)
"See the global property of the same name for details. "
"This overrides the global property for a directory.",
true);
+
+ cm->DefineProperty
+ ("VS_GLOBAL_SECTION_PRE_<section>", cmProperty::DIRECTORY,
+ "Specify a preSolution global section in Visual Studio.",
+ "Setting a property like this generates an entry of the following form "
+ "in the solution file:\n"
+ " GlobalSection(<section>) = preSolution\n"
+ " <contents based on property value>\n"
+ " EndGlobalSection\n"
+ "The property must be set to a semicolon-separated list of key=value "
+ "pairs. Each such pair will be transformed into an entry in the solution "
+ "global section. Whitespace around key and value is ignored. List "
+ "elements which do not contain an equal sign are skipped."
+ "\n"
+ "This property only works for Visual Studio 7 and above; it is ignored "
+ "on other generators. The property only applies when set on a directory "
+ "whose CMakeLists.txt conatins a project() command.");
+ cm->DefineProperty
+ ("VS_GLOBAL_SECTION_POST_<section>", cmProperty::DIRECTORY,
+ "Specify a postSolution global section in Visual Studio.",
+ "Setting a property like this generates an entry of the following form "
+ "in the solution file:\n"
+ " GlobalSection(<section>) = postSolution\n"
+ " <contents based on property value>\n"
+ " EndGlobalSection\n"
+ "The property must be set to a semicolon-separated list of key=value "
+ "pairs. Each such pair will be transformed into an entry in the solution "
+ "global section. Whitespace around key and value is ignored. List "
+ "elements which do not contain an equal sign are skipped."
+ "\n"
+ "This property only works for Visual Studio 7 and above; it is ignored "
+ "on other generators. The property only applies when set on a directory "
+ "whose CMakeLists.txt conatins a project() command."
+ "\n"
+ "Note that CMake generates postSolution sections ExtensibilityGlobals "
+ "and ExtensibilityAddIns by default. If you set the corresponding "
+ "property, it will override the default section. For example, setting "
+ "VS_GLOBAL_SECTION_POST_ExtensibilityGlobals will override the default "
+ "contents of the ExtensibilityGlobals section, while keeping "
+ "ExtensibilityAddIns on its default.");
}
//----------------------------------------------------------------------------
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 360ad78..722d9c3 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -59,4 +59,5 @@ add_RunCMake_test(load_command)
if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
add_RunCMake_test(include_external_msproject)
+ add_RunCMake_test(SolutionGlobalSections)
endif()
diff --git a/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt
new file mode 100644
index 0000000..e8db6b0
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/SolutionGlobalSections/MorePost-check.cmake b/Tests/RunCMake/SolutionGlobalSections/MorePost-check.cmake
new file mode 100644
index 0000000..0f7e370
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/MorePost-check.cmake
@@ -0,0 +1,5 @@
+parseGlobalSections(pre post MorePost)
+testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces")
+testGlobalSection(post TestSec4 Key6=Value1 "Key7=Value with spaces" Key8=ValueWithoutSpaces)
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/MorePost.cmake b/Tests/RunCMake/SolutionGlobalSections/MorePost.cmake
new file mode 100644
index 0000000..2eb3f60
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/MorePost.cmake
@@ -0,0 +1,2 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_TestSec2 Key1=Value1 "Key2=Value with spaces")
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_TestSec4 Key6=Value1 "Key7=Value with spaces" "Key8 =ValueWithoutSpaces")
diff --git a/Tests/RunCMake/SolutionGlobalSections/MorePre-check.cmake b/Tests/RunCMake/SolutionGlobalSections/MorePre-check.cmake
new file mode 100644
index 0000000..45e7419
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/MorePre-check.cmake
@@ -0,0 +1,5 @@
+parseGlobalSections(pre post MorePre)
+testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces")
+testGlobalSection(pre TestSec3 Key3=Value1 "Key4=Value with spaces" Key5=ValueWithoutSpaces)
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/MorePre.cmake b/Tests/RunCMake/SolutionGlobalSections/MorePre.cmake
new file mode 100644
index 0000000..07f4eb8
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/MorePre.cmake
@@ -0,0 +1,2 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_PRE_TestSec1 Key1=Value1 "Key2=Value with spaces")
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_PRE_TestSec3 Key3=Value1 "Key4=Value with spaces" "Key5 = ValueWithoutSpaces")
diff --git a/Tests/RunCMake/SolutionGlobalSections/OnePost-check.cmake b/Tests/RunCMake/SolutionGlobalSections/OnePost-check.cmake
new file mode 100644
index 0000000..6af5156
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/OnePost-check.cmake
@@ -0,0 +1,4 @@
+parseGlobalSections(pre post OnePost)
+testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces")
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/OnePost.cmake b/Tests/RunCMake/SolutionGlobalSections/OnePost.cmake
new file mode 100644
index 0000000..2295cfb
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/OnePost.cmake
@@ -0,0 +1 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_TestSec2 Key1=Value1 "Key2=Value with spaces")
diff --git a/Tests/RunCMake/SolutionGlobalSections/OnePre-check.cmake b/Tests/RunCMake/SolutionGlobalSections/OnePre-check.cmake
new file mode 100644
index 0000000..70b18b2
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/OnePre-check.cmake
@@ -0,0 +1,4 @@
+parseGlobalSections(pre post OnePre)
+testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces")
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/OnePre.cmake b/Tests/RunCMake/SolutionGlobalSections/OnePre.cmake
new file mode 100644
index 0000000..1499b47
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/OnePre.cmake
@@ -0,0 +1 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_PRE_TestSec1 Key1=Value1 "Key2=Value with spaces")
diff --git a/Tests/RunCMake/SolutionGlobalSections/Override1-check.cmake b/Tests/RunCMake/SolutionGlobalSections/Override1-check.cmake
new file mode 100644
index 0000000..a19e2e1
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/Override1-check.cmake
@@ -0,0 +1,4 @@
+parseGlobalSections(pre post Override1)
+testGlobalSection(post TestSec Key2=Value2 Key3=Value3)
+testGlobalSection(post ExtensibilityGlobals Key1=Value1)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/Override1.cmake b/Tests/RunCMake/SolutionGlobalSections/Override1.cmake
new file mode 100644
index 0000000..a726c9f
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/Override1.cmake
@@ -0,0 +1,2 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_ExtensibilityGlobals Key1=Value1)
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_TestSec Key2=Value2 Key3=Value3)
diff --git a/Tests/RunCMake/SolutionGlobalSections/Override2-check.cmake b/Tests/RunCMake/SolutionGlobalSections/Override2-check.cmake
new file mode 100644
index 0000000..d9656e1
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/Override2-check.cmake
@@ -0,0 +1,4 @@
+parseGlobalSections(pre post Override2)
+testGlobalSection(pre TestSec Key2=Value2 Key3=Value3)
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns Key1=Value1)
diff --git a/Tests/RunCMake/SolutionGlobalSections/Override2.cmake b/Tests/RunCMake/SolutionGlobalSections/Override2.cmake
new file mode 100644
index 0000000..0ce43cc
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/Override2.cmake
@@ -0,0 +1,2 @@
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_ExtensibilityAddIns Key1=Value1)
+set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_PRE_TestSec Key2=Value2 Key3=Value3)
diff --git a/Tests/RunCMake/SolutionGlobalSections/PrePost-check.cmake b/Tests/RunCMake/SolutionGlobalSections/PrePost-check.cmake
new file mode 100644
index 0000000..322a689
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/PrePost-check.cmake
@@ -0,0 +1,6 @@
+parseGlobalSections(pre post PrePost)
+testGlobalSection(post Postsec Key1=Value2)
+testGlobalSection(pre Presec Key1=Value1 "Key2=Value with some spaces")
+testGlobalSection(post Emptysec)
+testGlobalSection(post ExtensibilityGlobals)
+testGlobalSection(post ExtensibilityAddIns)
diff --git a/Tests/RunCMake/SolutionGlobalSections/PrePost.cmake b/Tests/RunCMake/SolutionGlobalSections/PrePost.cmake
new file mode 100644
index 0000000..976c341
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/PrePost.cmake
@@ -0,0 +1,4 @@
+set_directory_properties(PROPERTIES
+ VS_GLOBAL_SECTION_POST_Postsec Key1=Value2
+ VS_GLOBAL_SECTION_PRE_Presec "Key1=Value1;Key2= Value with some spaces"
+ VS_GLOBAL_SECTION_POST_Emptysec "")
diff --git a/Tests/RunCMake/SolutionGlobalSections/RunCMakeTest.cmake b/Tests/RunCMake/SolutionGlobalSections/RunCMakeTest.cmake
new file mode 100644
index 0000000..6ae158d
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/RunCMakeTest.cmake
@@ -0,0 +1,10 @@
+include(RunCMake)
+include(${CMAKE_CURRENT_LIST_DIR}/solution_parsing.cmake)
+
+run_cmake(OnePre)
+run_cmake(OnePost)
+run_cmake(MorePre)
+run_cmake(MorePost)
+run_cmake(PrePost)
+run_cmake(Override1)
+run_cmake(Override2)
diff --git a/Tests/RunCMake/SolutionGlobalSections/solution_parsing.cmake b/Tests/RunCMake/SolutionGlobalSections/solution_parsing.cmake
new file mode 100644
index 0000000..dd158ef
--- /dev/null
+++ b/Tests/RunCMake/SolutionGlobalSections/solution_parsing.cmake
@@ -0,0 +1,60 @@
+macro(error text)
+ set(RunCMake_TEST_FAILED "${text}")
+ return()
+endmacro()
+
+
+macro(parseGlobalSections arg_out_pre arg_out_post testName)
+ set(out_pre ${arg_out_pre})
+ set(out_post ${arg_out_post})
+ set(sln "${RunCMake_TEST_BINARY_DIR}/${testName}.sln")
+ if(NOT EXISTS "${sln}")
+ error("Expected solution file ${sln} does not exist")
+ endif()
+ file(STRINGS "${sln}" lines)
+ set(sectionLines "")
+ set(store FALSE)
+ foreach(line IN LISTS lines)
+ if(line MATCHES "^\t*Global\n?$")
+ set(store TRUE)
+ elseif(line MATCHES "^\t*EndGlobal\n?$")
+ set(store FALSE)
+ elseif(store)
+ list(APPEND sectionLines "${line}")
+ endif()
+ endforeach()
+ set(sectionName "")
+ set(sectionType "")
+ foreach(line IN LISTS sectionLines)
+ if(line MATCHES "^\t*GlobalSection\\((.*)\\) *= *(pre|post)Solution\n?$")
+ set(sectionName "${CMAKE_MATCH_1}")
+ set(sectionType ${CMAKE_MATCH_2})
+ list(APPEND ${out_${sectionType}} "${sectionName}")
+ if(DEFINED ${out_${sectionType}}_${sectionName})
+ error("Section ${sectionName} defined twice")
+ endif()
+ set(${out_${sectionType}}_${sectionName} "")
+ elseif(line MATCHES "\t*EndGlobalSection\n?$")
+ set(sectionName "")
+ set(sectionType "")
+ elseif(sectionName)
+ string(REGEX MATCH "^\t*([^=]*)=([^\n]*)\n?$" matches "${line}")
+ if(NOT matches)
+ error("Bad syntax in solution file: '${line}'")
+ endif()
+ string(STRIP "${CMAKE_MATCH_1}" key)
+ string(STRIP "${CMAKE_MATCH_2}" value)
+ list(APPEND ${out_${sectionType}}_${sectionName} "${key}=${value}")
+ endif()
+ endforeach()
+endmacro()
+
+
+macro(testGlobalSection prefix sectionName)
+ if(NOT DEFINED ${prefix}_${sectionName})
+ error("Section ${sectionName} does not exist")
+ endif()
+ if(NOT "${${prefix}_${sectionName}}" STREQUAL "${ARGN}")
+ error("Section ${sectionName} content mismatch\n expected: ${ARGN}\n actual: ${${prefix}_${sectionName}}")
+ endif()
+endmacro()