Merge topic 'vs-global-sections'

45d4f81 Merge topic 'per-config-EXCLUDE_FROM_DEFAULT_BUILD' into vs-global-sections
694322e Define properties VS_GLOBAL_SECTION_*
2c91962 Implement properties VS_GLOBAL_SECTION_*
57cadc1 Add tests for VS_SOLUTION_GLOBAL_SECTIONS
This commit is contained in:
Brad King 2012-11-20 11:47:43 -05:00 committed by CMake Topic Stage
commit 53b7e71e88
23 changed files with 232 additions and 17 deletions

View File

@ -128,6 +128,9 @@ void cmGlobalVisualStudio71Generator
fout << "\tEndGlobalSection\n"; fout << "\tEndGlobalSection\n";
} }
// Write out global sections
this->WriteSLNGlobalSections(fout, root);
// Write the footer for the SLN file // Write the footer for the SLN file
this->WriteSLNFooter(fout); this->WriteSLNFooter(fout);
} }
@ -296,17 +299,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 // ouput standard header for dsw file
void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout) void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)

View File

@ -70,7 +70,6 @@ protected:
const char* path, const char* path,
const char* typeGuid, const char* typeGuid,
const std::set<cmStdString>& depends); const std::set<cmStdString>& depends);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout); virtual void WriteSLNHeader(std::ostream& fout);
std::string ProjectConfigurationSectionName; std::string ProjectConfigurationSectionName;

View File

@ -435,6 +435,9 @@ void cmGlobalVisualStudio7Generator
this->WriteTargetConfigurations(fout, root, orderedProjectTargets); this->WriteTargetConfigurations(fout, root, orderedProjectTargets);
fout << "\tEndGlobalSection\n"; fout << "\tEndGlobalSection\n";
// Write out global sections
this->WriteSLNGlobalSections(fout, root);
// Write the footer for the SLN file // Write the footer for the SLN file
this->WriteSLNFooter(fout); 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 // Standard end of dsw file
void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout) void cmGlobalVisualStudio7Generator::WriteSLNFooter(std::ostream& fout)
{ {
fout << "\tGlobalSection(ExtensibilityGlobals) = postSolution\n" fout << "EndGlobal\n";
<< "\tEndGlobalSection\n"
<< "\tGlobalSection(ExtensibilityAddIns) = postSolution\n"
<< "\tEndGlobalSection\n"
<< "EndGlobal\n";
} }

View File

@ -109,6 +109,8 @@ protected:
std::ostream& fout, const char* name, std::ostream& fout, const char* name,
const std::set<std::string>& configsPartOfDefaultBuild, const std::set<std::string>& configsPartOfDefaultBuild,
const char* platformMapping = NULL); const char* platformMapping = NULL);
virtual void WriteSLNGlobalSections(std::ostream& fout,
cmLocalGenerator* root);
virtual void WriteSLNFooter(std::ostream& fout); virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout); virtual void WriteSLNHeader(std::ostream& fout);
virtual std::string WriteUtilityDepend(cmTarget* target); virtual std::string WriteUtilityDepend(cmTarget* target);

View File

@ -3937,6 +3937,46 @@ void cmMakefile::DefineProperties(cmake *cm)
"See the global property of the same name for details. " "See the global property of the same name for details. "
"This overrides the global property for a directory.", "This overrides the global property for a directory.",
true); 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.");
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -59,4 +59,5 @@ add_RunCMake_test(load_command)
if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
add_RunCMake_test(include_external_msproject) add_RunCMake_test(include_external_msproject)
add_RunCMake_test(SolutionGlobalSections)
endif() endif()

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -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)

View File

@ -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")

View File

@ -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)

View File

@ -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")

View File

@ -0,0 +1,4 @@
parseGlobalSections(pre post OnePost)
testGlobalSection(post TestSec2 Key1=Value1 "Key2=Value with spaces")
testGlobalSection(post ExtensibilityGlobals)
testGlobalSection(post ExtensibilityAddIns)

View File

@ -0,0 +1 @@
set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_POST_TestSec2 Key1=Value1 "Key2=Value with spaces")

View File

@ -0,0 +1,4 @@
parseGlobalSections(pre post OnePre)
testGlobalSection(pre TestSec1 Key1=Value1 "Key2=Value with spaces")
testGlobalSection(post ExtensibilityGlobals)
testGlobalSection(post ExtensibilityAddIns)

View File

@ -0,0 +1 @@
set_property(DIRECTORY PROPERTY VS_GLOBAL_SECTION_PRE_TestSec1 Key1=Value1 "Key2=Value with spaces")

View File

@ -0,0 +1,4 @@
parseGlobalSections(pre post Override1)
testGlobalSection(post TestSec Key2=Value2 Key3=Value3)
testGlobalSection(post ExtensibilityGlobals Key1=Value1)
testGlobalSection(post ExtensibilityAddIns)

View File

@ -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)

View File

@ -0,0 +1,4 @@
parseGlobalSections(pre post Override2)
testGlobalSection(pre TestSec Key2=Value2 Key3=Value3)
testGlobalSection(post ExtensibilityGlobals)
testGlobalSection(post ExtensibilityAddIns Key1=Value1)

View File

@ -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)

View File

@ -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)

View File

@ -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 "")

View File

@ -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)

View File

@ -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()