|
|
@@ -0,0 +1,351 @@
|
|
|
+function(MapAppend map key value)
|
|
|
+ list(APPEND "${map}_k" "${key}")
|
|
|
+ list(APPEND "${map}_v" "${value}")
|
|
|
+
|
|
|
+ set("${map}_k" "${${map}_k}" PARENT_SCOPE)
|
|
|
+ set("${map}_v" "${${map}_v}" PARENT_SCOPE)
|
|
|
+endfunction()
|
|
|
+
|
|
|
+function(MapLength map out_variable)
|
|
|
+ list(LENGTH "${map}_k" length)
|
|
|
+ set("${out_variable}" "${length}" PARENT_SCOPE)
|
|
|
+endfunction()
|
|
|
+
|
|
|
+function(MapFind map key out_variable)
|
|
|
+ list(FIND "${map}_k" "${key}" index)
|
|
|
+ if("${index}" LESS 0)
|
|
|
+ unset("${out_variable}" PARENT_SCOPE)
|
|
|
+ else()
|
|
|
+ list(GET "${map}_v" "${index}" value)
|
|
|
+ set("${out_variable}" "${value}" PARENT_SCOPE)
|
|
|
+ endif()
|
|
|
+endfunction()
|
|
|
+
|
|
|
+macro(MapPropagateToParentScope map)
|
|
|
+ set("${map}_k" "${${map}_k}" PARENT_SCOPE)
|
|
|
+ set("${map}_v" "${${map}_v}" PARENT_SCOPE)
|
|
|
+endmacro()
|
|
|
+
|
|
|
+
|
|
|
+function(ParseSln vcSlnFile)
|
|
|
+ if(NOT EXISTS "${vcSlnFile}")
|
|
|
+ set(RunCMake_TEST_FAILED "Solution file ${vcSlnFile} does not exist." PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ set(SCOPE "")
|
|
|
+
|
|
|
+ set(IN_SOLUTION_ITEMS FALSE)
|
|
|
+ set(IN_NESTED_PROJECTS FALSE)
|
|
|
+
|
|
|
+ set(REGUID "\\{[0-9A-F-]+\\}")
|
|
|
+
|
|
|
+ file(STRINGS "${vcSlnFile}" lines)
|
|
|
+ foreach(line IN LISTS lines)
|
|
|
+ string(STRIP "${line}" line)
|
|
|
+
|
|
|
+ # Project(...)
|
|
|
+ if(line MATCHES "Project\\(\"(${REGUID})\"\\) = \"([^\"]+)\", \"([^\"]+)\", \"(${REGUID})\"")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of Project" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "Project")
|
|
|
+
|
|
|
+ if("${CMAKE_MATCH_1}" STREQUAL "{2150E333-8FDC-42A3-9474-1A3956D46DE8}")
|
|
|
+ set(GROUP_NAME "${CMAKE_MATCH_2}")
|
|
|
+
|
|
|
+ MapFind(GROUP_PATHS "${GROUP_NAME}" existing_path)
|
|
|
+ if(DEFINED existing_path)
|
|
|
+ set(RunCMake_TEST_FAILED "Duplicate solution items project '${GROUP_NAME}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapAppend(GROUP_PATHS "${GROUP_NAME}" "${CMAKE_MATCH_3}")
|
|
|
+ MapAppend(GROUP_GUIDS "${GROUP_NAME}" "${CMAKE_MATCH_4}")
|
|
|
+ endif()
|
|
|
+
|
|
|
+ # EndProject
|
|
|
+ elseif(line STREQUAL "EndProject")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "Project")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of EndProject" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "")
|
|
|
+
|
|
|
+ unset(GROUP_NAME)
|
|
|
+
|
|
|
+ # ProjectSection
|
|
|
+ elseif(line MATCHES "ProjectSection\\(([a-zA-Z]+)\\) = ([a-zA-Z]+)")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "Project")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of ProjectSection" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "ProjectSection")
|
|
|
+
|
|
|
+ if("${CMAKE_MATCH_1}" STREQUAL "SolutionItems")
|
|
|
+ if(NOT "${CMAKE_MATCH_2}" STREQUAL "preProject")
|
|
|
+ set(RunCMake_TEST_FAILED "SolutionItems must be preProject" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ set(IN_SOLUTION_ITEMS TRUE)
|
|
|
+ endif()
|
|
|
+
|
|
|
+ # EndProjectSection
|
|
|
+ elseif(line STREQUAL "EndProjectSection")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "ProjectSection")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of EndProjectSection" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "Project")
|
|
|
+
|
|
|
+ set(IN_SOLUTION_ITEMS FALSE)
|
|
|
+
|
|
|
+ # Global
|
|
|
+ elseif(line STREQUAL "Global")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of Global" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "Global")
|
|
|
+
|
|
|
+ # EndGlobal
|
|
|
+ elseif(line STREQUAL "EndGlobal")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "Global")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of EndGlobal" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "")
|
|
|
+
|
|
|
+ # GlobalSection
|
|
|
+ elseif(line MATCHES "GlobalSection\\(([a-zA-Z]+)\\) = ([a-zA-Z]+)")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "Global")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of GlobalSection" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "GlobalSection")
|
|
|
+
|
|
|
+ if("${CMAKE_MATCH_1}" STREQUAL "NestedProjects")
|
|
|
+ if(NOT "${CMAKE_MATCH_2}" STREQUAL "preSolution")
|
|
|
+ set(RunCMake_TEST_FAILED "NestedProjects must be preSolution" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ set(IN_NESTED_PROJECTS TRUE)
|
|
|
+ endif()
|
|
|
+
|
|
|
+ # EndGlobalSection
|
|
|
+ elseif(line STREQUAL "EndGlobalSection")
|
|
|
+ if(NOT "${SCOPE}" STREQUAL "GlobalSection")
|
|
|
+ set(RunCMake_TEST_FAILED "Improper nesting of EndGlobalSection" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ set(SCOPE "Global")
|
|
|
+
|
|
|
+ set(IN_NESTED_PROJECTS FALSE)
|
|
|
+
|
|
|
+ # .../solution-item-0-1.txt = .../solution-item-0-1.txt
|
|
|
+ elseif(${IN_SOLUTION_ITEMS})
|
|
|
+ if(NOT line MATCHES "([^=]+)=([^=]+)")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid solution item paths 1" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ string(STRIP "${CMAKE_MATCH_1}" CMAKE_MATCH_1)
|
|
|
+ string(STRIP "${CMAKE_MATCH_2}" CMAKE_MATCH_2)
|
|
|
+
|
|
|
+ if(NOT "${CMAKE_MATCH_1}" STREQUAL "${CMAKE_MATCH_2}")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid solution item paths 2" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ cmake_path(GET CMAKE_MATCH_1 FILENAME filename)
|
|
|
+ MapAppend(SOLUTION_ITEMS "${filename}" "${GROUP_NAME}")
|
|
|
+
|
|
|
+ # {1EB55F5E...} = {A11E84C6...}
|
|
|
+ elseif(${IN_NESTED_PROJECTS})
|
|
|
+ if(NOT line MATCHES "(${REGUID}) = (${REGUID})")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid nested project guids" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(PROJECT_PARENTS "${CMAKE_MATCH_1}" existing_parent)
|
|
|
+ if(DEFINED existing_parent)
|
|
|
+ set(RunCMake_TEST_FAILED "Duplicate nested project: '${CMAKE_MATCH_1}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapAppend(PROJECT_PARENTS "${CMAKE_MATCH_1}" "${CMAKE_MATCH_2}")
|
|
|
+
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapPropagateToParentScope(GROUP_PATHS)
|
|
|
+ MapPropagateToParentScope(GROUP_GUIDS)
|
|
|
+ MapPropagateToParentScope(PROJECT_PARENTS)
|
|
|
+ MapPropagateToParentScope(SOLUTION_ITEMS)
|
|
|
+ endforeach()
|
|
|
+endfunction()
|
|
|
+
|
|
|
+
|
|
|
+# Check the root solution:
|
|
|
+block()
|
|
|
+ ParseSln("${RunCMake_TEST_BINARY_DIR}/SolutionItems.sln")
|
|
|
+
|
|
|
+ if(DEFINED RunCMake_TEST_FAILED)
|
|
|
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+
|
|
|
+ # Check group guids and nesting:
|
|
|
+
|
|
|
+ MapFind(GROUP_GUIDS "Solution Items" root_group_guid)
|
|
|
+ if(NOT DEFINED root_group_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution Items not found" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(GROUP_PATHS "Solution Items" root_group_path)
|
|
|
+ if(NOT "${root_group_path}" STREQUAL "Solution Items")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid Solution Items path: '${root_group_path}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(PROJECT_PARENTS "${root_group_guid}" root_group_parent_guid)
|
|
|
+ if(DEFINED root_group_parent_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution Items is nested" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(GROUP_GUIDS "Outer Group" outer_group_guid)
|
|
|
+ if(NOT DEFINED outer_group_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Outer Group not found" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(GROUP_PATHS "Outer Group" outer_group_path)
|
|
|
+ if(NOT "${outer_group_path}" STREQUAL "Outer Group")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid Outer Group path: '${outer_group_path}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(PROJECT_PARENTS "${outer_group_guid}" outer_group_parent_guid)
|
|
|
+ if(DEFINED outer_group_parent_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Outer Group is nested" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(GROUP_GUIDS "Inner Group" inner_group_guid)
|
|
|
+ if(NOT DEFINED inner_group_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Inner Group not found" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(GROUP_PATHS "Inner Group" inner_group_path)
|
|
|
+ if(NOT "${inner_group_path}" STREQUAL "Outer Group\\Inner Group")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid Inner Group path: '${inner_group_path}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(PROJECT_PARENTS "${inner_group_guid}" inner_group_parent_guid)
|
|
|
+ if(NOT DEFINED inner_group_parent_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Inner Group is not nested" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${inner_group_parent_guid}" STREQUAL "${outer_group_guid}")
|
|
|
+ set(RunCMake_TEST_FAILED "Inner Group is not nested within Outer Group" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+
|
|
|
+ # Check solution items and nesting:
|
|
|
+ MapLength(SOLUTION_ITEMS solution_item_count)
|
|
|
+ if(NOT "${solution_item_count}" EQUAL 4)
|
|
|
+ set(RunCMake_TEST_FAILED "Unexpected number of solution items: ${solution_item_count}")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(SOLUTION_ITEMS "solution-item-0-1.txt" group_name)
|
|
|
+ if(NOT DEFINED group_name)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution item not found: solution-item-0-1.txt")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${group_name}" STREQUAL "Solution Items")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid group for solution-item-0-1.txt: '${group_name}'")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(SOLUTION_ITEMS "solution-item-1-1.txt" group_name)
|
|
|
+ if(NOT DEFINED group_name)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution item not found: solution-item-1-1.txt")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${group_name}" STREQUAL "Outer Group")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid group for solution-item-1-1.txt: '${group_name}'")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(SOLUTION_ITEMS "solution-item-2-1.txt" group_name)
|
|
|
+ if(NOT DEFINED group_name)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution item not found: solution-item-2-1.txt")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${group_name}" STREQUAL "Inner Group")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid group for solution-item-2-1.txt: '${group_name}'")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(SOLUTION_ITEMS "solution-item-2-2.txt" group_name)
|
|
|
+ if(NOT DEFINED group_name)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution item not found: solution-item-2-2.txt")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${group_name}" STREQUAL "Inner Group")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid group for solution-item-2-2.txt: '${group_name}'")
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+endblock()
|
|
|
+
|
|
|
+
|
|
|
+# Check the nested solution:
|
|
|
+block()
|
|
|
+ ParseSln("${RunCMake_TEST_BINARY_DIR}/SolutionItems/SolutionItemsSubproject.sln")
|
|
|
+
|
|
|
+ if(DEFINED RunCMake_TEST_FAILED)
|
|
|
+ set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+
|
|
|
+ # Check group guids and nesting:
|
|
|
+
|
|
|
+ MapFind(GROUP_GUIDS "Extraneous" root_group_guid)
|
|
|
+ if(NOT DEFINED root_group_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Extraneous not found" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(GROUP_PATHS "Extraneous" root_group_path)
|
|
|
+ if(NOT "${root_group_path}" STREQUAL "Extraneous")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid Extraneous path: '${root_group_path}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ MapFind(PROJECT_PARENTS "${root_group_guid}" root_group_parent_guid)
|
|
|
+ if(DEFINED root_group_parent_guid)
|
|
|
+ set(RunCMake_TEST_FAILED "Extraneous is nested" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+
|
|
|
+ # Check solution items and nesting:
|
|
|
+
|
|
|
+ MapLength(SOLUTION_ITEMS solution_item_count)
|
|
|
+ if(NOT "${solution_item_count}" EQUAL 1)
|
|
|
+ set(RunCMake_TEST_FAILED "Unexpected number of solution items: ${solution_item_count}" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ MapFind(SOLUTION_ITEMS "extraneous.txt" group_name)
|
|
|
+ if(NOT DEFINED group_name)
|
|
|
+ set(RunCMake_TEST_FAILED "Solution item not found: extraneous.txt" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+ if(NOT "${group_name}" STREQUAL "Extraneous")
|
|
|
+ set(RunCMake_TEST_FAILED "Invalid group for extraneous.txt: '${group_name}'" PARENT_SCOPE)
|
|
|
+ return()
|
|
|
+ endif()
|
|
|
+endblock()
|