diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/cmConvertMSBuildXMLToJSON.py | 453 | ||||
-rw-r--r-- | Source/cmMakefileExecutableTargetGenerator.cxx | 4 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 21 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 50 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmNinjaNormalTargetGenerator.cxx | 10 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmVS140CLFlagTable.h | 237 | ||||
-rw-r--r-- | Source/cmVS141CLFlagTable.h (renamed from Source/cmVS14CLFlagTable.h) | 2 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 11 | ||||
-rw-r--r-- | Source/cmake.cxx | 108 | ||||
-rw-r--r-- | Source/cmake.h | 2 |
13 files changed, 774 insertions, 130 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index e298fc3..662ba9f 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 7) -set(CMake_VERSION_PATCH 20161012) +set(CMake_VERSION_PATCH 20161014) #set(CMake_VERSION_RC 1) diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py new file mode 100644 index 0000000..93ab8a8 --- /dev/null +++ b/Source/cmConvertMSBuildXMLToJSON.py @@ -0,0 +1,453 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +import argparse +import codecs +import copy +import logging +import json +import os + +from collections import OrderedDict +from xml.dom.minidom import parse, parseString, Element + + +class VSFlags: + """Flags corresponding to cmIDEFlagTable.""" + UserValue = "UserValue" # (1 << 0) + UserIgnored = "UserIgnored" # (1 << 1) + UserRequired = "UserRequired" # (1 << 2) + Continue = "Continue" #(1 << 3) + SemicolonAppendable = "SemicolonAppendable" # (1 << 4) + UserFollowing = "UserFollowing" # (1 << 5) + CaseInsensitive = "CaseInsensitive" # (1 << 6) + UserValueIgnored = [UserValue, UserIgnored] + UserValueRequired = [UserValue, UserRequired] + + +def vsflags(*args): + """Combines the flags.""" + values = [] + + for arg in args: + __append_list(values, arg) + + return values + + +def read_msbuild_xml(path, values={}): + """Reads the MS Build XML file at the path and returns its contents. + + Keyword arguments: + values -- The map to append the contents to (default {}) + """ + + # Attempt to read the file contents + try: + document = parse(path) + except Exception as e: + logging.exception('Could not read MS Build XML file at %s', path) + return values + + # Convert the XML to JSON format + logging.info('Processing MS Build XML file at %s', path) + + # Get the rule node + rule = document.getElementsByTagName('Rule')[0] + + rule_name = rule.attributes['Name'].value + + logging.info('Found rules for %s', rule_name) + + # Proprocess Argument values + __preprocess_arguments(rule) + + # Get all the values + converted_values = [] + __convert(rule, 'EnumProperty', converted_values, __convert_enum) + __convert(rule, 'BoolProperty', converted_values, __convert_bool) + __convert(rule, 'StringListProperty', converted_values, + __convert_string_list) + __convert(rule, 'StringProperty', converted_values, __convert_string) + __convert(rule, 'IntProperty', converted_values, __convert_string) + + values[rule_name] = converted_values + + return values + + +def read_msbuild_json(path, values=[]): + """Reads the MS Build JSON file at the path and returns its contents. + + Keyword arguments: + values -- The list to append the contents to (default []) + """ + if not os.path.exists(path): + logging.info('Could not find MS Build JSON file at %s', path) + return values + + try: + values.extend(__read_json_file(path)) + except Exception as e: + logging.exception('Could not read MS Build JSON file at %s', path) + return values + + logging.info('Processing MS Build JSON file at %s', path) + + return values + + +def main(): + """Script entrypoint.""" + # Parse the arguments + parser = argparse.ArgumentParser( + description='Convert MSBuild XML to JSON format') + + parser.add_argument( + '-t', '--toolchain', help='The name of the toolchain', required=True) + parser.add_argument( + '-o', '--output', help='The output directory', default='') + parser.add_argument( + '-r', + '--overwrite', + help='Whether previously output should be overwritten', + dest='overwrite', + action='store_true') + parser.set_defaults(overwrite=False) + parser.add_argument( + '-d', + '--debug', + help="Debug tool output", + action="store_const", + dest="loglevel", + const=logging.DEBUG, + default=logging.WARNING) + parser.add_argument( + '-v', + '--verbose', + help="Verbose output", + action="store_const", + dest="loglevel", + const=logging.INFO) + parser.add_argument('input', help='The input files', nargs='+') + + args = parser.parse_args() + + toolchain = args.toolchain + + logging.basicConfig(level=args.loglevel) + logging.info('Creating %s toolchain files', toolchain) + + values = {} + + # Iterate through the inputs + for input in args.input: + input = __get_path(input) + + read_msbuild_xml(input, values) + + # Determine if the output directory needs to be created + output_dir = __get_path(args.output) + + if not os.path.exists(output_dir): + os.mkdir(output_dir) + logging.info('Created output directory %s', output_dir) + + for key, value in values.items(): + output_path = __output_path(toolchain, key, output_dir) + + if os.path.exists(output_path) and not args.overwrite: + logging.info('Comparing previous output to current') + + __merge_json_values(value, read_msbuild_json(output_path)) + else: + logging.info('Original output will be overwritten') + + logging.info('Writing MS Build JSON file at %s', output_path) + + __write_json_file(output_path, value) + + +########################################################################################### +# private joining functions +def __merge_json_values(current, previous): + """Merges the values between the current and previous run of the script.""" + for value in current: + name = value['name'] + + # Find the previous value + previous_value = __find_and_remove_value(previous, value) + + if previous_value is not None: + flags = value['flags'] + previous_flags = previous_value['flags'] + + if flags != previous_flags: + logging.warning( + 'Flags for %s are different. Using previous value.', name) + + value['flags'] = previous_flags + else: + logging.warning('Value %s is a new value', name) + + for value in previous: + name = value['name'] + logging.warning( + 'Value %s not present in current run. Appending value.', name) + + current.append(value) + + +def __find_and_remove_value(list, compare): + """Finds the value in the list that corresponds with the value of compare.""" + # next throws if there are no matches + try: + found = next(value for value in list + if value['name'] == compare['name'] and value['switch'] == + compare['switch']) + except: + return None + + list.remove(found) + + return found + + +########################################################################################### +# private xml functions +def __convert(root, tag, values, func): + """Converts the tag type found in the root and converts them using the func + and appends them to the values. + """ + elements = root.getElementsByTagName(tag) + + for element in elements: + converted = func(element) + + # Append to the list + __append_list(values, converted) + + +def __convert_enum(node): + """Converts an EnumProperty node to JSON format.""" + name = __get_attribute(node, 'Name') + logging.debug('Found EnumProperty named %s', name) + + converted_values = [] + + for value in node.getElementsByTagName('EnumValue'): + converted = __convert_node(value) + + converted['value'] = converted['name'] + converted['name'] = name + + # Modify flags when there is an argument child + __with_argument(value, converted) + + converted_values.append(converted) + + return converted_values + + +def __convert_bool(node): + """Converts an BoolProperty node to JSON format.""" + converted = __convert_node(node, default_value='true') + + # Check for a switch for reversing the value + reverse_switch = __get_attribute(node, 'ReverseSwitch') + + if reverse_switch: + converted_reverse = copy.deepcopy(converted) + + converted_reverse['switch'] = reverse_switch + converted_reverse['value'] = 'false' + + return [converted_reverse, converted] + + # Modify flags when there is an argument child + __with_argument(node, converted) + + return __check_for_flag(converted) + + +def __convert_string_list(node): + """Converts a StringListProperty node to JSON format.""" + converted = __convert_node(node) + + # Determine flags for the string list + flags = vsflags(VSFlags.UserValue) + + # Check for a separator to determine if it is semicolon appendable + # If not present assume the value should be ; + separator = __get_attribute(node, 'Separator', default_value=';') + + if separator == ';': + flags = vsflags(flags, VSFlags.SemicolonAppendable) + + converted['flags'] = flags + + return __check_for_flag(converted) + + +def __convert_string(node): + """Converts a StringProperty node to JSON format.""" + converted = __convert_node(node, default_flags=vsflags(VSFlags.UserValue)) + + return __check_for_flag(converted) + + +def __convert_node(node, default_value='', default_flags=vsflags()): + """Converts a XML node to a JSON equivalent.""" + name = __get_attribute(node, 'Name') + logging.debug('Found %s named %s', node.tagName, name) + + converted = {} + converted['name'] = name + converted['switch'] = __get_attribute(node, 'Switch') + converted['comment'] = __get_attribute(node, 'DisplayName') + converted['value'] = default_value + + # Check for the Flags attribute in case it was created during preprocessing + flags = __get_attribute(node, 'Flags') + + if flags: + flags = flags.split(',') + else: + flags = default_flags + + converted['flags'] = flags + + return converted + + +def __check_for_flag(value): + """Checks whether the value has a switch value. + + If not then returns None as it should not be added. + """ + if value['switch']: + return value + else: + logging.warning('Skipping %s which has no command line switch', + value['name']) + return None + + +def __with_argument(node, value): + """Modifies the flags in value if the node contains an Argument.""" + arguments = node.getElementsByTagName('Argument') + + if arguments: + logging.debug('Found argument within %s', value['name']) + value['flags'] = vsflags(VSFlags.UserValueIgnored, VSFlags.Continue) + + +def __preprocess_arguments(root): + """Preprocesses occurrances of Argument within the root. + + Argument XML values reference other values within the document by name. The + referenced value does not contain a switch. This function will add the + switch associated with the argument. + """ + # Set the flags to require a value + flags = ','.join(vsflags(VSFlags.UserValueRequired)) + + # Search through the arguments + arguments = root.getElementsByTagName('Argument') + + for argument in arguments: + reference = __get_attribute(argument, 'Property') + found = None + + # Look for the argument within the root's children + for child in root.childNodes: + # Ignore Text nodes + if isinstance(child, Element): + name = __get_attribute(child, 'Name') + + if name == reference: + found = child + break + + if found is not None: + logging.info('Found property named %s', reference) + # Get the associated switch + switch = __get_attribute(argument.parentNode, 'Switch') + + # See if there is already a switch associated with the element. + if __get_attribute(found, 'Switch'): + logging.debug('Copying node %s', reference) + clone = found.cloneNode(True) + root.insertBefore(clone, found) + found = clone + + found.setAttribute('Switch', switch) + found.setAttribute('Flags', flags) + else: + logging.warning('Could not find property named %s', reference) + + +def __get_attribute(node, name, default_value=''): + """Retrieves the attribute of the given name from the node. + + If not present then the default_value is used. + """ + if node.hasAttribute(name): + return node.attributes[name].value.strip() + else: + return default_value + + +########################################################################################### +# private path functions +def __get_path(path): + """Gets the path to the file.""" + if not os.path.isabs(path): + path = os.path.join(os.getcwd(), path) + + return os.path.normpath(path) + + +def __output_path(toolchain, rule, output_dir): + """Gets the output path for a file given the toolchain, rule and output_dir""" + filename = '%s_%s.json' % (toolchain, rule) + return os.path.join(output_dir, filename) + + +########################################################################################### +# private JSON file functions +def __read_json_file(path): + """Reads a JSON file at the path.""" + with open(path, 'r') as f: + return json.load(f) + + +def __write_json_file(path, values): + """Writes a JSON file at the path with the values provided.""" + # Sort the keys to ensure ordering + sort_order = ['name', 'switch', 'comment', 'value', 'flags'] + sorted_values = [ + OrderedDict( + sorted( + value.items(), key=lambda value: sort_order.index(value[0]))) + for value in values + ] + + with open(path, 'w') as f: + json.dump(sorted_values, f, indent=2, separators=(',', ': ')) + + +########################################################################################### +# private list helpers +def __append_list(append_to, value): + """Appends the value to the list.""" + if value is not None: + if isinstance(value, list): + append_to.extend(value) + else: + append_to.append(value) + +########################################################################################### +# main entry point +if __name__ == "__main__": + main() diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index bfc4857..ed34ce6 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -198,7 +198,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->GetLinkLibsCMP0065( linkLanguage, *this->GeneratorTarget)); - if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) { + if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed"); } @@ -375,7 +375,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.LinkFlags = linkFlags.c_str(); vars.Manifests = manifests.c_str(); - if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) { + if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); cmakeCommand += " -E __run_iwyu --lwyu="; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index 4488f06..a19d70e 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -168,7 +168,7 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags); - if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE")) { + if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); } this->WriteLibraryRules(linkRuleVar, extraFlags, relink); @@ -365,18 +365,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress); } - const char* forbiddenFlagVar = CM_NULLPTR; - switch (this->GeneratorTarget->GetType()) { - case cmState::SHARED_LIBRARY: - forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS"; - break; - case cmState::MODULE_LIBRARY: - forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS"; - break; - default: - break; - } - // Clean files associated with this library. std::vector<std::string> libCleanFiles; libCleanFiles.push_back(this->LocalGenerator->MaybeConvertToRelativePath( @@ -607,11 +595,6 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( this->LocalGenerator->AddArchitectureFlags( langFlags, this->GeneratorTarget, linkLanguage, this->ConfigName); - // remove any language flags that might not work with the - // particular os - if (forbiddenFlagVar) { - this->RemoveForbiddenFlags(forbiddenFlagVar, linkLanguage, langFlags); - } vars.LanguageCompileFlags = langFlags.c_str(); // Construct the main link rule and expand placeholders. @@ -660,7 +643,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the set of commands. std::string linkRule = this->GetLinkRule(linkRuleVar); cmSystemTools::ExpandListArgument(linkRule, real_link_commands); - if (this->GeneratorTarget->GetProperty("LINK_WHAT_YOU_USE") && + if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") && (this->GeneratorTarget->GetType() == cmState::SHARED_LIBRARY)) { std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 1483fbb..84ae726 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1208,9 +1208,7 @@ void cmMakefileTargetGenerator::WriteObjectsVariable( i != this->ExternalObjects.end(); ++i) { object = this->LocalGenerator->MaybeConvertToRelativePath(currentBinDir, *i); - *this->BuildFileStream << " " << lineContinue << "\n" - << this->Makefile->GetSafeDefinition( - "CMAKE_OBJECT_NAME"); + *this->BuildFileStream << " " << lineContinue << "\n"; *this->BuildFileStream << this->LocalGenerator->ConvertToQuotedOutputPath( i->c_str(), useWatcomQuote); } @@ -1422,52 +1420,6 @@ void cmMakefileTargetGenerator::CloseFileStreams() delete this->FlagFileStream; } -void cmMakefileTargetGenerator::RemoveForbiddenFlags( - const char* flagVar, const std::string& linkLang, std::string& linkFlags) -{ - // check for language flags that are not allowed at link time, and - // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool - // which fails, there may be more] - - std::string removeFlags = "CMAKE_"; - removeFlags += linkLang; - removeFlags += flagVar; - std::string removeflags = this->Makefile->GetSafeDefinition(removeFlags); - std::vector<std::string> removeList; - cmSystemTools::ExpandListArgument(removeflags, removeList); - - for (std::vector<std::string>::iterator i = removeList.begin(); - i != removeList.end(); ++i) { - std::string tmp; - std::string::size_type lastPosition = 0; - - for (;;) { - std::string::size_type position = linkFlags.find(*i, lastPosition); - - if (position == std::string::npos) { - tmp += linkFlags.substr(lastPosition); - break; - } else { - std::string::size_type prefixLength = position - lastPosition; - tmp += linkFlags.substr(lastPosition, prefixLength); - lastPosition = position + i->length(); - - bool validFlagStart = - position == 0 || isspace(linkFlags[position - 1]); - - bool validFlagEnd = - lastPosition == linkFlags.size() || isspace(linkFlags[lastPosition]); - - if (!validFlagStart || !validFlagEnd) { - tmp += *i; - } - } - } - - linkFlags = tmp; - } -} - void cmMakefileTargetGenerator::CreateLinkScript( const char* name, std::vector<std::string> const& link_commands, std::vector<std::string>& makefile_commands, diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h index 526cbcd..4c61011 100644 --- a/Source/cmMakefileTargetGenerator.h +++ b/Source/cmMakefileTargetGenerator.h @@ -171,8 +171,6 @@ protected: const std::string& lang) CM_OVERRIDE; virtual void CloseFileStreams(); - void RemoveForbiddenFlags(const char* flagVar, const std::string& linkLang, - std::string& linkFlags); cmLocalUnixMakefileGenerator3* LocalGenerator; cmGlobalUnixMakefileGenerator3* GlobalGenerator; diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index ab086eb..d729114 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -316,7 +316,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd() const char* linkCmd = mf->GetDefinition(linkCmdVar); if (linkCmd) { cmSystemTools::ExpandListArgument(linkCmd, linkCmds); - if (this->GetGeneratorTarget()->GetProperty("LINK_WHAT_YOU_USE")) { + if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); @@ -512,7 +512,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["LINK_PATH"] = frameworkPath + linkPath; std::string lwyuFlags; - if (genTarget.GetProperty("LINK_WHAT_YOU_USE")) { + if (genTarget.GetPropertyAsBool("LINK_WHAT_YOU_USE")) { lwyuFlags = " -Wl,--no-as-needed"; } @@ -652,7 +652,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() std::string postBuildCmdLine = localGen.BuildCommandLine(postBuildCmdLines); cmNinjaVars symlinkVars; - if (targetOutput == targetOutputReal) { + bool const symlinkNeeded = + (targetOutput != targetOutputReal && !gt.IsFrameworkOnApple()); + if (!symlinkNeeded) { vars["POST_BUILD"] = postBuildCmdLine; } else { vars["POST_BUILD"] = ":"; @@ -694,7 +696,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() commandLineLengthLimit, &usedResponseFile); this->WriteLinkRule(usedResponseFile); - if (targetOutput != targetOutputReal && !gt.IsFrameworkOnApple()) { + if (symlinkNeeded) { if (targetType == cmState::EXECUTABLE) { globalGen.WriteBuild( this->GetBuildFileStream(), diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index fb2581d..46a6161 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -427,7 +427,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) : mf->GetSafeDefinition("CMAKE_CXX_COMPILER"); cldeps = "\""; cldeps += cmSystemTools::GetCMClDepsCommand(); - cldeps += "\" " + lang + " $in \"$DEP_FILE\" $out \""; + cldeps += "\" " + lang + " " + vars.Source + " \"$DEP_FILE\" $out \""; cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"); cldeps += "\" \"" + cl + "\" "; } diff --git a/Source/cmVS140CLFlagTable.h b/Source/cmVS140CLFlagTable.h new file mode 100644 index 0000000..317cc18 --- /dev/null +++ b/Source/cmVS140CLFlagTable.h @@ -0,0 +1,237 @@ +static cmVS7FlagTable cmVS140CLFlagTable[] = { + + // Enum Properties + { "DebugInformationFormat", "", "None", "None", 0 }, + { "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 }, + { "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 }, + { "DebugInformationFormat", "ZI", "Program Database for Edit And Continue", + "EditAndContinue", 0 }, + + { "WarningLevel", "W0", "Turn Off All Warnings", "TurnOffAllWarnings", 0 }, + { "WarningLevel", "W1", "Level1", "Level1", 0 }, + { "WarningLevel", "W2", "Level2", "Level2", 0 }, + { "WarningLevel", "W3", "Level3", "Level3", 0 }, + { "WarningLevel", "W4", "Level4", "Level4", 0 }, + { "WarningLevel", "Wall", "EnableAllWarnings", "EnableAllWarnings", 0 }, + + { "Optimization", "", "Custom", "Custom", 0 }, + { "Optimization", "Od", "Disabled", "Disabled", 0 }, + { "Optimization", "O1", "Minimize Size", "MinSpace", 0 }, + { "Optimization", "O2", "Maximize Speed", "MaxSpeed", 0 }, + { "Optimization", "Ox", "Full Optimization", "Full", 0 }, + + { "InlineFunctionExpansion", "", "Default", "Default", 0 }, + { "InlineFunctionExpansion", "Ob0", "Disabled", "Disabled", 0 }, + { "InlineFunctionExpansion", "Ob1", "Only __inline", "OnlyExplicitInline", + 0 }, + { "InlineFunctionExpansion", "Ob2", "Any Suitable", "AnySuitable", 0 }, + + { "FavorSizeOrSpeed", "Os", "Favor small code", "Size", 0 }, + { "FavorSizeOrSpeed", "Ot", "Favor fast code", "Speed", 0 }, + { "FavorSizeOrSpeed", "", "Neither", "Neither", 0 }, + + { "ExceptionHandling", "EHa", "Yes with SEH Exceptions", "Async", 0 }, + { "ExceptionHandling", "EHsc", "Yes", "Sync", 0 }, + { "ExceptionHandling", "EHs", "Yes with Extern C functions", "SyncCThrow", + 0 }, + { "ExceptionHandling", "", "No", "false", 0 }, + + { "BasicRuntimeChecks", "RTCs", "Stack Frames", "StackFrameRuntimeCheck", + 0 }, + { "BasicRuntimeChecks", "RTCu", "Uninitialized variables", + "UninitializedLocalUsageCheck", 0 }, + { "BasicRuntimeChecks", "RTC1", "Both (/RTC1, equiv. to /RTCsu)", + "EnableFastChecks", 0 }, + { "BasicRuntimeChecks", "", "Default", "Default", 0 }, + + { "RuntimeLibrary", "MT", "Multi-threaded", "MultiThreaded", 0 }, + { "RuntimeLibrary", "MTd", "Multi-threaded Debug", "MultiThreadedDebug", 0 }, + { "RuntimeLibrary", "MD", "Multi-threaded DLL", "MultiThreadedDLL", 0 }, + { "RuntimeLibrary", "MDd", "Multi-threaded Debug DLL", + "MultiThreadedDebugDLL", 0 }, + + { "StructMemberAlignment", "Zp1", "1 Byte", "1Byte", 0 }, + { "StructMemberAlignment", "Zp2", "2 Bytes", "2Bytes", 0 }, + { "StructMemberAlignment", "Zp4", "4 Byte", "4Bytes", 0 }, + { "StructMemberAlignment", "Zp8", "8 Bytes", "8Bytes", 0 }, + { "StructMemberAlignment", "Zp16", "16 Bytes", "16Bytes", 0 }, + { "StructMemberAlignment", "", "Default", "Default", 0 }, + + { "BufferSecurityCheck", "GS-", "Disable Security Check", "false", 0 }, + { "BufferSecurityCheck", "GS", "Enable Security Check", "true", 0 }, + + { "EnableEnhancedInstructionSet", "arch:SSE", "Streaming SIMD Extensions", + "StreamingSIMDExtensions", 0 }, + { "EnableEnhancedInstructionSet", "arch:SSE2", "Streaming SIMD Extensions 2", + "StreamingSIMDExtensions2", 0 }, + { "EnableEnhancedInstructionSet", "arch:AVX", "Advanced Vector Extensions", + "AdvancedVectorExtensions", 0 }, + { "EnableEnhancedInstructionSet", "arch:AVX2", + "Advanced Vector Extensions 2", "AdvancedVectorExtensions2", 0 }, + { "EnableEnhancedInstructionSet", "arch:IA32", "No Enhanced Instructions", + "NoExtensions", 0 }, + { "EnableEnhancedInstructionSet", "", "Not Set", "NotSet", 0 }, + + { "FloatingPointModel", "fp:precise", "Precise", "Precise", 0 }, + { "FloatingPointModel", "fp:strict", "Strict", "Strict", 0 }, + { "FloatingPointModel", "fp:fast", "Fast", "Fast", 0 }, + + { "PrecompiledHeader", "Yc", "Create", "Create", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "PrecompiledHeader", "Yu", "Use", "Use", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "PrecompiledHeader", "", "Not Using Precompiled Headers", "NotUsing", 0 }, + + { "AssemblerOutput", "", "No Listing", "NoListing", 0 }, + { "AssemblerOutput", "FA", "Assembly-Only Listing", "AssemblyCode", 0 }, + { "AssemblerOutput", "FAc", "Assembly With Machine Code", + "AssemblyAndMachineCode", 0 }, + { "AssemblerOutput", "FAs", "Assembly With Source Code", + "AssemblyAndSourceCode", 0 }, + { "AssemblerOutput", "FAcs", "Assembly, Machine Code and Source", "All", 0 }, + + { "CallingConvention", "Gd", "__cdecl", "Cdecl", 0 }, + { "CallingConvention", "Gr", "__fastcall", "FastCall", 0 }, + { "CallingConvention", "Gz", "__stdcall", "StdCall", 0 }, + { "CallingConvention", "Gv", "__vectorcall", "VectorCall", 0 }, + + { "CompileAs", "", "Default", "Default", 0 }, + { "CompileAs", "TC", "Compile as C Code", "CompileAsC", 0 }, + { "CompileAs", "TP", "Compile as C++ Code", "CompileAsCpp", 0 }, + + { "ErrorReporting", "errorReport:none", "Do Not Send Report", "None", 0 }, + { "ErrorReporting", "errorReport:prompt", "Prompt Immediately", "Prompt", + 0 }, + { "ErrorReporting", "errorReport:queue", "Queue For Next Login", "Queue", + 0 }, + { "ErrorReporting", "errorReport:send", "Send Automatically", "Send", 0 }, + + { "CompileAsManaged", "", "No Common Language RunTime Support", "false", 0 }, + { "CompileAsManaged", "clr", "Common Language RunTime Support", "true", 0 }, + { "CompileAsManaged", "clr:pure", + "Pure MSIL Common Language RunTime Support", "Pure", 0 }, + { "CompileAsManaged", "clr:safe", + "Safe MSIL Common Language RunTime Support", "Safe", 0 }, + { "CompileAsManaged", "clr:oldSyntax", + "Common Language RunTime Support, Old Syntax", "OldSyntax", 0 }, + + { "CppLanguageStandard", "", "Default", "Default", 0 }, + { "CppLanguageStandard", "std=c++98", "C++03", "c++98", 0 }, + { "CppLanguageStandard", "std=c++11", "C++11", "c++11", 0 }, + { "CppLanguageStandard", "std=c++1y", "C++14", "c++1y", 0 }, + { "CppLanguageStandard", "std=c++14", "C++14", "c++1y", 0 }, + { "CppLanguageStandard", "std=gnu++98", "C++03 (GNU Dialect)", "gnu++98", + 0 }, + { "CppLanguageStandard", "std=gnu++11", "C++11 (GNU Dialect)", "gnu++11", + 0 }, + { "CppLanguageStandard", "std=gnu++1y", "C++14 (GNU Dialect)", "gnu++1y", + 0 }, + { "CppLanguageStandard", "std=gnu++14", "C++14 (GNU Dialect)", "gnu++1y", + 0 }, + + // Bool Properties + { "CompileAsWinRT", "ZW", "", "true", 0 }, + { "WinRTNoStdLib", "ZW:nostdlib", "", "true", 0 }, + { "SuppressStartupBanner", "nologo", "", "true", 0 }, + { "TreatWarningAsError", "WX-", "", "false", 0 }, + { "TreatWarningAsError", "WX", "", "true", 0 }, + { "SDLCheck", "sdl-", "", "false", 0 }, + { "SDLCheck", "sdl", "", "true", 0 }, + { "IntrinsicFunctions", "Oi", "", "true", 0 }, + { "OmitFramePointers", "Oy-", "", "false", 0 }, + { "OmitFramePointers", "Oy", "", "true", 0 }, + { "EnableFiberSafeOptimizations", "GT", "", "true", 0 }, + { "WholeProgramOptimization", "GL", "", "true", 0 }, + { "UndefineAllPreprocessorDefinitions", "u", "", "true", 0 }, + { "IgnoreStandardIncludePath", "X", "", "true", 0 }, + { "PreprocessToFile", "P", "", "true", 0 }, + { "PreprocessSuppressLineNumbers", "EP", "", "true", 0 }, + { "PreprocessKeepComments", "C", "", "true", 0 }, + { "StringPooling", "GF-", "", "false", 0 }, + { "StringPooling", "GF", "", "true", 0 }, + { "MinimalRebuild", "Gm-", "", "false", 0 }, + { "MinimalRebuild", "Gm", "", "true", 0 }, + { "SmallerTypeCheck", "RTCc", "", "true", 0 }, + { "FunctionLevelLinking", "Gy-", "", "false", 0 }, + { "FunctionLevelLinking", "Gy", "", "true", 0 }, + { "EnableParallelCodeGeneration", "Qpar-", "", "false", 0 }, + { "EnableParallelCodeGeneration", "Qpar", "", "true", 0 }, + { "FloatingPointExceptions", "fp:except-", "", "false", 0 }, + { "FloatingPointExceptions", "fp:except", "", "true", 0 }, + { "CreateHotpatchableImage", "hotpatch", "", "true", 0 }, + { "DisableLanguageExtensions", "Za", "", "true", 0 }, + { "TreatWChar_tAsBuiltInType", "Zc:wchar_t-", "", "false", 0 }, + { "TreatWChar_tAsBuiltInType", "Zc:wchar_t", "", "true", 0 }, + { "ForceConformanceInForLoopScope", "Zc:forScope-", "", "false", 0 }, + { "ForceConformanceInForLoopScope", "Zc:forScope", "", "true", 0 }, + { "RuntimeTypeInfo", "GR-", "", "false", 0 }, + { "RuntimeTypeInfo", "GR", "", "true", 0 }, + { "OpenMPSupport", "openmp-", "", "false", 0 }, + { "OpenMPSupport", "openmp", "", "true", 0 }, + { "ExpandAttributedSource", "Fx", "", "true", 0 }, + { "UseUnicodeForAssemblerListing", "FAu", "", "true", 0 }, + { "ShowIncludes", "showIncludes", "", "true", 0 }, + { "EnablePREfast", "analyze-", "", "false", 0 }, + { "EnablePREfast", "analyze", "", "true", 0 }, + { "UseFullPaths", "FC", "", "true", 0 }, + { "OmitDefaultLibName", "Zl", "", "true", 0 }, + + // Bool Properties With Argument + { "MultiProcessorCompilation", "MP", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "ProcessorNumber", "MP", "Multi-processor Compilation", "", + cmVS7FlagTable::UserValueRequired }, + { "GenerateXMLDocumentationFiles", "doc", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "XMLDocumentationFileName", "doc", "Generate XML Documentation Files", "", + cmVS7FlagTable::UserValueRequired }, + { "BrowseInformation", "FR", "", "true", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue }, + { "BrowseInformationFile", "FR", "Enable Browse Information", "", + cmVS7FlagTable::UserValueRequired }, + + // String List Properties + { "AdditionalIncludeDirectories", "I", "Additional Include Directories", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "AdditionalUsingDirectories", "AI", "Additional #using Directories", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "PreprocessorDefinitions", "D ", "Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "UndefinePreprocessorDefinitions", "U", + "Undefine Preprocessor Definitions", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "DisableSpecificWarnings", "wd", "Disable Specific Warnings", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "ForcedIncludeFiles", "FI", "Forced Include File", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "ForcedUsingFiles", "FU", "Forced #using File", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "PREfastLog", "analyze:log", "Code Analysis Log", "", + cmVS7FlagTable::UserFollowing }, + { "PREfastAdditionalPlugins", "analyze:plugin", + "Additional Code Analysis Native plugins", "", + cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + { "TreatSpecificWarningsAsErrors", "we", "Treat Specific Warnings As Errors", + "", cmVS7FlagTable::UserValue | cmVS7FlagTable::SemicolonAppendable }, + + // String Properties + // Skip [TrackerLogDirectory] - no command line Switch. + { "PreprocessOutputPath", "Fi", "Preprocess Output Path", "", + cmVS7FlagTable::UserValue }, + { "PrecompiledHeaderFile", "Yc", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired }, + { "PrecompiledHeaderFile", "Yu", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired }, + { "PrecompiledHeaderOutputFile", "Fp", "Precompiled Header Output File", "", + cmVS7FlagTable::UserValue }, + { "AssemblerListingLocation", "Fa", "ASM List Location", "", + cmVS7FlagTable::UserValue }, + { "ObjectFileName", "Fo", "Object File Name", "", + cmVS7FlagTable::UserValue }, + { "ProgramDataBaseFileName", "Fd", "Program Database File Name", "", + cmVS7FlagTable::UserValue }, + // Skip [XMLDocumentationFileName] - no command line Switch. + // Skip [BrowseInformationFile] - no command line Switch. + // Skip [AdditionalOptions] - no command line Switch. + { 0, 0, 0, 0, 0 } +}; diff --git a/Source/cmVS14CLFlagTable.h b/Source/cmVS141CLFlagTable.h index c48db68..895b3e8 100644 --- a/Source/cmVS14CLFlagTable.h +++ b/Source/cmVS141CLFlagTable.h @@ -1,4 +1,4 @@ -static cmVS7FlagTable cmVS14CLFlagTable[] = { +static cmVS7FlagTable cmVS141CLFlagTable[] = { // Enum Properties { "DebugInformationFormat", "", "None", "None", 0 }, diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 6690bfa..82f4b99 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -25,7 +25,8 @@ #include "cmVS12LinkFlagTable.h" #include "cmVS12MASMFlagTable.h" #include "cmVS12RCFlagTable.h" -#include "cmVS14CLFlagTable.h" +#include "cmVS140CLFlagTable.h" +#include "cmVS141CLFlagTable.h" #include "cmVS14LibFlagTable.h" #include "cmVS14LinkFlagTable.h" #include "cmVS14MASMFlagTable.h" @@ -43,7 +44,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetClFlagTable() const cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); if (v >= cmGlobalVisualStudioGenerator::VS14) { - return cmVS14CLFlagTable; + // FIXME: All flag table selection should be based on the toolset name. + // See issue #16153. For now, treat VS 15's toolset as a special case. + const char* toolset = this->GlobalGenerator->GetPlatformToolset(); + if (toolset && cmHasLiteralPrefix(toolset, "v141")) { + return cmVS141CLFlagTable; + } + return cmVS140CLFlagTable; } else if (v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12CLFlagTable; } else if (v == cmGlobalVisualStudioGenerator::VS11) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index e0f4000..5936d77 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -932,7 +932,7 @@ void cmake::GetRegisteredGenerators( gen != genList.end(); ++gen) { GeneratorInfo info; info.name = cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - (*i)->GetName(), *gen); + *gen, (*i)->GetName()); info.baseName = *gen; info.extraName = (*i)->GetName(); info.supportsPlatform = false; @@ -1313,54 +1313,7 @@ int cmake::ActualConfigure() cmSystemTools::SetForceUnixPaths( this->GlobalGenerator->GetForceUnixPaths()); } else { -#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) - std::string installedCompiler; - // Try to find the newest VS installed on the computer and - // use that as a default if -G is not specified - const std::string vsregBase = - "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"; - std::vector<std::string> vsVerions; - vsVerions.push_back("VisualStudio\\"); - vsVerions.push_back("VCExpress\\"); - vsVerions.push_back("WDExpress\\"); - struct VSRegistryEntryName - { - const char* MSVersion; - const char* GeneratorName; - }; - VSRegistryEntryName version[] = { - /* clang-format needs this comment to break after the opening brace */ - { "7.1", "Visual Studio 7 .NET 2003" }, - { "8.0", "Visual Studio 8 2005" }, - { "9.0", "Visual Studio 9 2008" }, - { "10.0", "Visual Studio 10 2010" }, - { "11.0", "Visual Studio 11 2012" }, - { "12.0", "Visual Studio 12 2013" }, - { "14.0", "Visual Studio 14 2015" }, - { "15.0", "Visual Studio 15" }, - { 0, 0 } - }; - 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]"; - cmSystemTools::ExpandRegistryValues(reg, cmSystemTools::KeyWOW64_32); - if (!(reg == "/registry")) { - installedCompiler = version[i].GeneratorName; - break; - } - } - } - cmGlobalGenerator* gen = - this->CreateGlobalGenerator(installedCompiler.c_str()); - if (!gen) { - gen = new cmGlobalNMakeMakefileGenerator(this); - } - this->SetGlobalGenerator(gen); - std::cout << "-- Building for: " << gen->GetName() << "\n"; -#else - this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this)); -#endif + this->CreateDefaultGlobalGenerator(); } if (!this->GlobalGenerator) { cmSystemTools::Error("Could not create generator"); @@ -1488,6 +1441,63 @@ int cmake::ActualConfigure() return 0; } +void cmake::CreateDefaultGlobalGenerator() +{ +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(CMAKE_BOOT_MINGW) + std::string found; + // Try to find the newest VS installed on the computer and + // use that as a default if -G is not specified + const std::string vsregBase = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\"; + static const char* const vsVariants[] = { + /* clang-format needs this comment to break after the opening brace */ + "VisualStudio\\", "VCExpress\\", "WDExpress\\" + }; + struct VSVersionedGenerator + { + const char* MSVersion; + const char* GeneratorName; + }; + static VSVersionedGenerator const vsGenerators[] = { + { "15.0", "Visual Studio 15" }, // + { "14.0", "Visual Studio 14 2015" }, // + { "12.0", "Visual Studio 12 2013" }, // + { "11.0", "Visual Studio 11 2012" }, // + { "10.0", "Visual Studio 10 2010" }, // + { "9.0", "Visual Studio 9 2008" }, // + { "8.0", "Visual Studio 8 2005" }, // + { "7.1", "Visual Studio 7 .NET 2003" } + }; + static const char* const vsEntries[] = { + "\\Setup\\VC;ProductDir", // + ";InstallDir" // + }; + for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators); + found.empty() && g != cmArrayEnd(vsGenerators); ++g) { + for (const char* const* v = cmArrayBegin(vsVariants); + found.empty() && v != cmArrayEnd(vsVariants); ++v) { + for (const char* const* e = cmArrayBegin(vsEntries); + found.empty() && e != cmArrayEnd(vsEntries); ++e) { + std::string const reg = vsregBase + *v + g->MSVersion + *e; + std::string dir; + if (cmSystemTools::ReadRegistryValue(reg, dir, + cmSystemTools::KeyWOW64_32) && + cmSystemTools::PathExists(dir)) { + found = g->GeneratorName; + } + } + } + } + cmGlobalGenerator* gen = this->CreateGlobalGenerator(found); + if (!gen) { + gen = new cmGlobalNMakeMakefileGenerator(this); + } + this->SetGlobalGenerator(gen); + std::cout << "-- Building for: " << gen->GetName() << "\n"; +#else + this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this)); +#endif +} + void cmake::PreLoadCMakeFiles() { std::vector<std::string> args; diff --git a/Source/cmake.h b/Source/cmake.h index ae1a502..865748b 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -500,6 +500,8 @@ private: // Print a list of valid generators to stderr. void PrintGeneratorList(); + void CreateDefaultGlobalGenerator(); + /** * Convert a message type between a warning and an error, based on the state * of the error output CMake variables, in the cache. |