def _write_filters_file_for(self, filename, formatter, hdr_files, cl_files, idl_files, rc_files): root = Node("Project") root[ "ToolsVersion"] = "4.0" # even if tools_version is different (VS2013) root["xmlns"] = "http://schemas.microsoft.com/developer/msbuild/2003" filters = Node("ItemGroup") root.add(filters) f = Node("Filter", Include="Source Files") filters.add(f) f.add("UniqueIdentifier", "{4FC737F1-C7A5-4376-A066-2A32D752A2FF}") f.add("Extensions", "cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx") f = Node("Filter", Include="Header Files") filters.add(f) f.add("UniqueIdentifier", "{93995380-89BD-4b04-88EB-625FBE52EBFB}") f.add("Extensions", "h;hpp;hxx;hm;inl;inc;xsd") f = Node("Filter", Include="Resource Files") filters.add(f) f.add("UniqueIdentifier", "{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}") f.add( "Extensions", "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms" ) if hdr_files: group = Node("ItemGroup") root.add(group) for sfile in hdr_files: n = Node("ClInclude", Include=sfile.filename) group.add(n) n.add("Filter", "Header Files") if cl_files or idl_files: group = Node("ItemGroup") root.add(group) for sfile in cl_files: n = Node("ClCompile", Include=sfile.filename) group.add(n) n.add("Filter", "Source Files") for sfile in idl_files: n = Node("Midl", Include=sfile.filename) group.add(n) n.add("Filter", "Source Files") if rc_files: group = Node("ItemGroup") root.add(group) for sfile in rc_files: n = Node("ResourceCompile", Include=sfile.filename) group.add(n) n.add("Filter", "Resource Files") f = OutputFile(filename + ".filters", EOL_WINDOWS, creator=self, create_for=filename) f.write(codecs.BOM_UTF8) f.write(formatter.format(root)) f.commit()
def __init__(self, toolset, module): slnfile = module["%s.solutionfile" % toolset.name].as_native_path_for_output(module) self.name = module.name # unlike targets, modules' names aren't globally unique, so use the fully qualified name, which is self.guid = GUID(NAMESPACE_SLN_GROUP, module.project.top_module.name, module.fully_qualified_name) self.projects = OrderedDict() self.subsolutions = [] self.parent_solution = None paths_info = bkl.expr.PathAnchorsInfo( dirsep="\\", outfile=slnfile, builddir=None, model=module) self.formatter = VSExprFormatter(module.project.settings, paths_info) self.generate_outf = module["%s.generate-solution" % toolset.name] if self.generate_outf: self.outf = OutputFile(slnfile, EOL_WINDOWS, creator=toolset, create_for=module) else: self.outf = None
def gen_for_target(self, target, project): rc_files = [] cl_files = [] idl_files = [] for sfile in target.sources: ext = sfile.filename.get_extension() # TODO: share this code with VS200x # FIXME: make this more solid if ext == 'rc': rc_files.append(sfile) elif ext == 'idl': idl_files.append(sfile) else: cl_files.append(sfile) root = Node("Project") root["DefaultTargets"] = "Build" root["ToolsVersion"] = self.tools_version root["xmlns"] = "http://schemas.microsoft.com/developer/msbuild/2003" n_configs = Node("ItemGroup", Label="ProjectConfigurations") for cfg in self.configs_and_platforms(target): n = Node("ProjectConfiguration", Include="%s" % cfg.vs_name) n.add("Configuration", cfg.name) n.add("Platform", cfg.vs_platform) n_configs.add(n) root.add(n_configs) n_globals = Node("PropertyGroup", Label="Globals") n_globals.add("ProjectGuid", "{%s}" % project.guid) n_globals.add("Keyword", "Win32Proj") n_globals.add("RootNamespace", target.name) n_globals.add("ProjectName", target.name) self._add_extra_options_to_node(target, n_globals) root.add(n_globals) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props") for cfg in self.configs_and_platforms(target): n = Node("PropertyGroup", Label="Configuration") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name if is_program(target): n.add("ConfigurationType", "Application") elif is_library(target): n.add("ConfigurationType", "StaticLibrary") elif is_dll(target): n.add("ConfigurationType", "DynamicLibrary") else: assert False, "this code should only be called for supported target types" n.add("UseDebugLibraries", cfg.is_debug) if cfg["win32-unicode"]: n.add("CharacterSet", "Unicode") else: n.add("CharacterSet", "MultiByte") if self.platform_toolset: n.add("PlatformToolset", self.platform_toolset) self._add_extra_options_to_node(cfg, n) root.add(n) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.props") root.add("ImportGroup", Label="ExtensionSettings") for cfg in self.configs_and_platforms(target): n = Node("ImportGroup", Label="PropertySheets") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name n.add( "Import", Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props", Condition= "exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')", Label="LocalAppDataPlatform") root.add(n) root.add("PropertyGroup", Label="UserMacros") for cfg in self.configs_and_platforms(target): n = Node("PropertyGroup") if not is_library(target): n.add("LinkIncremental", cfg.is_debug) targetname = cfg["basename"] if targetname != target.name: n.add("TargetName", targetname) if not target.is_variable_null("extension"): n.add("TargetExt", target["extension"]) if is_module_dll(target): n.add("IgnoreImportLibrary", True) if target.is_variable_explicitly_set("outputdir"): n.add("OutDir", concat(cfg["outputdir"], "\\")) if self.needs_custom_intermediate_dir(target): if cfg.vs_platform != "Win32": intdir = "$(Platform)\\$(Configuration)\\$(ProjectName)\\" else: intdir = "$(Configuration)\\$(ProjectName)\\" n.add("IntDir", intdir) if n.has_children(): n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name self._add_extra_options_to_node(cfg, n) root.add(n) for cfg in self.configs_and_platforms(target): n = Node("ItemDefinitionGroup") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name n_cl = Node("ClCompile") n_cl.add("WarningLevel", self.get_vs_warning_level(cfg)) if cfg.is_debug: n_cl.add("Optimization", "Disabled") else: n_cl.add("Optimization", "MaxSpeed") n_cl.add("FunctionLevelLinking", True) n_cl.add("IntrinsicFunctions", True) std_defs = self.get_std_defines(target, cfg) std_defs.append("%(PreprocessorDefinitions)") n_cl.add("PreprocessorDefinitions", list(cfg["defines"]) + std_defs) n_cl.add("MultiProcessorCompilation", True) n_cl.add("MinimalRebuild", False) n_cl.add("AdditionalIncludeDirectories", cfg["includedirs"]) crt = "MultiThreaded" if cfg.is_debug: crt += "Debug" if cfg["win32-crt-linkage"] == "dll": crt += "DLL" n_cl.add("RuntimeLibrary", crt) # Currently we don't make any distinction between preprocessor, C # and C++ flags as they're basically all the same at MSVS level # too and all go into the same place in the IDE and same # AdditionalOptions node in the project file. all_cflags = VSList(" ", cfg["compiler-options"], cfg["c-compiler-options"], cfg["cxx-compiler-options"]) if all_cflags: all_cflags.append("%(AdditionalOptions)") n_cl.add("AdditionalOptions", all_cflags) self._add_extra_options_to_node(cfg, n_cl) n.add(n_cl) if rc_files: n_res = Node("ResourceCompile") n_res.add("AdditionalIncludeDirectories", cfg["includedirs"]) std_defs = [] if cfg["win32-unicode"]: std_defs.append("_UNICODE") std_defs.append("UNICODE") # See the comment in VCResourceCompilerTool in vs200x.py for # the explanation of why do we do this even though the native # projects don't define _DEBUG/NDEBUG for the RC files. std_defs.append("_DEBUG" if cfg.is_debug else "NDEBUG") std_defs.append("%(PreprocessorDefinitions)") n_res.add("PreprocessorDefinitions", list(cfg["defines"]) + std_defs) self._add_extra_options_to_node(cfg, n_res) n.add(n_res) if idl_files: n_idl = Node("Midl") n_idl.add("AdditionalIncludeDirectories", cfg["includedirs"]) self._add_extra_options_to_node(cfg, n_idl) n.add(n_idl) n_link = Node("Link") if is_program(target) and target["win32-subsystem"] == "console": n_link.add("SubSystem", "Console") else: n_link.add("SubSystem", "Windows") n_link.add("GenerateDebugInformation", True) if not cfg.is_debug: n_link.add("EnableCOMDATFolding", True) n_link.add("OptimizeReferences", True) if not is_library(target): libdirs = VSList(";", target.type.get_libdirs(cfg)) if libdirs: libdirs.append("%(AdditionalLibraryDirectories)") n_link.add("AdditionalLibraryDirectories", libdirs) ldflags = VSList(" ", target.type.get_link_options(cfg)) if ldflags: ldflags.append("%(AdditionalOptions)") n_link.add("AdditionalOptions", ldflags) libs = target.type.get_ldlibs(cfg) if libs: addlibs = VSList(";", ("%s.lib" % x.as_py() for x in libs if x)) addlibs.append("%(AdditionalDependencies)") if is_library(target): n_lib = Node("Lib") self._add_extra_options_to_node(cfg, n_lib) n.add(n_lib) n_lib.add("AdditionalDependencies", addlibs) else: n_link.add("AdditionalDependencies", addlibs) self._add_extra_options_to_node(cfg, n_link) n.add(n_link) pre_build = cfg["pre-build-commands"] if pre_build: n_script = Node("PreBuildEvent") n_script.add("Command", VSList("\n", pre_build)) n.add(n_script) post_build = cfg["post-build-commands"] if post_build: n_script = Node("PostBuildEvent") n_script.add("Command", VSList("\n", post_build)) n.add(n_script) root.add(n) # Source files: if cl_files: items = Node("ItemGroup") root.add(items) cl_files_map = bkl.compilers.disambiguate_intermediate_file_names( cl_files) for sfile in cl_files: if sfile["compile-commands"]: self._add_custom_build_file(items, sfile) else: ext = sfile.filename.get_extension() # TODO: share this code with VS200x # FIXME: make this more solid if ext in ['cpp', 'cxx', 'cc', 'c']: n_cl_compile = Node("ClCompile", Include=sfile.filename) else: # FIXME: handle both compilation into cpp and c files genfiletype = bkl.compilers.CxxFileType.get() genname = bkl.expr.PathExpr( [ bkl.expr.LiteralExpr( sfile.filename.get_basename()) ], bkl.expr.ANCHOR_BUILDDIR, pos=sfile.filename.pos).change_extension("cpp") ft_from = bkl.compilers.get_file_type(ext) compiler = bkl.compilers.get_compiler( self, ft_from, genfiletype) customBuild = Node("CustomBuild", Include=sfile.filename) customBuild.add( "Command", VSList( "\n", compiler.commands(self, target, sfile.filename, genname))) customBuild.add("Outputs", genname) items.add(customBuild) n_cl_compile = Node("ClCompile", Include=genname) # Handle files with custom object name: if sfile in cl_files_map: n_cl_compile.add( "ObjectFileName", concat("$(IntDir)\\", cl_files_map[sfile], ".obj")) self._add_per_file_options(sfile, n_cl_compile) items.add(n_cl_compile) # Headers files: if target.headers: items = Node("ItemGroup") root.add(items) for sfile in target.headers: if sfile["compile-commands"]: self._add_custom_build_file(items, sfile) else: items.add("ClInclude", Include=sfile.filename) # Resources: if rc_files: items = Node("ItemGroup") root.add(items) rc_files_map = bkl.compilers.disambiguate_intermediate_file_names( rc_files) for sfile in rc_files: n_rc_compile = Node("ResourceCompile", Include=sfile.filename) # Handle files with custom object name: if sfile in rc_files_map: n_rc_compile.add( "ResourceOutputFileName", concat("$(IntDir)\\", rc_files_map[sfile], ".res")) self._add_per_file_options(sfile, n_rc_compile) items.add(n_rc_compile) # IDL files: if idl_files: items = Node("ItemGroup") root.add(items) for sfile in idl_files: n_midl = Node("Midl", Include=sfile.filename) self._add_per_file_options(sfile, n_midl) items.add(n_midl) # Dependencies: target_deps = self._get_references(target) if target_deps: refs = Node("ItemGroup") root.add(refs) for dep in target_deps: dep_prj = self.get_project_object(dep) depnode = Node("ProjectReference", Include=dep_prj.projectfile) depnode.add("Project", "{%s}" % dep_prj.guid.lower()) refs.add(depnode) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.targets") root.add("ImportGroup", Label="ExtensionTargets") filename = project.projectfile.as_native_path_for_output(target) paths_info = self.get_project_paths_info(target, project) formatter = self.XmlFormatter(target.project.settings, paths_info) f = OutputFile(filename, EOL_WINDOWS, creator=self, create_for=target) f.write(codecs.BOM_UTF8) f.write(formatter.format(root)) f.commit() self._write_filters_file_for(filename, formatter, target.headers, cl_files, idl_files, rc_files)
def gen_for_target(self, target, project): rc_files = [] cl_files = [] idl_files = [] for sfile in target.sources: ext = sfile.filename.get_extension() # TODO: share this code with VS200x # FIXME: make this more solid if ext == 'rc': rc_files.append(sfile) elif ext == 'idl': idl_files.append(sfile) else: cl_files.append(sfile) root = Node("Project") root["DefaultTargets"] = "Build" root["ToolsVersion"] = self.tools_version root["xmlns"] = "http://schemas.microsoft.com/developer/msbuild/2003" n_configs = Node("ItemGroup", Label="ProjectConfigurations") for cfg in self.configs_and_platforms(target): n = Node("ProjectConfiguration", Include="%s" % cfg.vs_name) n.add("Configuration", cfg.name) n.add("Platform", cfg.vs_platform) n_configs.add(n) root.add(n_configs) n_globals = Node("PropertyGroup", Label="Globals") n_globals.add("ProjectGuid", "{%s}" % project.guid) n_globals.add("Keyword", "Win32Proj") n_globals.add("RootNamespace", target.name) n_globals.add("ProjectName", target.name) self._add_extra_options_to_node(target, n_globals) root.add(n_globals) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props") for cfg in self.configs_and_platforms(target): n = Node("PropertyGroup", Label="Configuration") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name if is_program(target): n.add("ConfigurationType", "Application") elif is_library(target): n.add("ConfigurationType", "StaticLibrary") elif is_dll(target): n.add("ConfigurationType", "DynamicLibrary") else: assert False, "this code should only be called for supported target types" n.add("UseDebugLibraries", cfg.is_debug) if cfg["win32-unicode"]: n.add("CharacterSet", "Unicode") else: n.add("CharacterSet", "MultiByte") if self.platform_toolset: n.add("PlatformToolset", self.platform_toolset) self._add_extra_options_to_node(cfg, n) root.add(n) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.props") root.add("ImportGroup", Label="ExtensionSettings") for cfg in self.configs_and_platforms(target): n = Node("ImportGroup", Label="PropertySheets") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name n.add("Import", Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props", Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')", Label="LocalAppDataPlatform") root.add(n) root.add("PropertyGroup", Label="UserMacros") for cfg in self.configs_and_platforms(target): n = Node("PropertyGroup") if not is_library(target): n.add("LinkIncremental", cfg.is_debug) targetname = cfg["basename"] if targetname != target.name: n.add("TargetName", targetname) if not target.is_variable_null("extension"): n.add("TargetExt", target["extension"]) if is_module_dll(target): n.add("IgnoreImportLibrary", True) if target.is_variable_explicitly_set("outputdir"): n.add("OutDir", concat(cfg["outputdir"], "\\")) if self.needs_custom_intermediate_dir(target): if cfg.vs_platform != "Win32": intdir = "$(Platform)\\$(Configuration)\\$(ProjectName)\\" else: intdir = "$(Configuration)\\$(ProjectName)\\" n.add("IntDir", intdir) if n.has_children(): n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name self._add_extra_options_to_node(cfg, n) root.add(n) for cfg in self.configs_and_platforms(target): n = Node("ItemDefinitionGroup") n["Condition"] = "'$(Configuration)|$(Platform)'=='%s'" % cfg.vs_name n_cl = Node("ClCompile") n_cl.add("WarningLevel", self.get_vs_warning_level(cfg)) if cfg.is_debug: n_cl.add("Optimization", "Disabled") else: n_cl.add("Optimization", "MaxSpeed") n_cl.add("FunctionLevelLinking", True) n_cl.add("IntrinsicFunctions", True) std_defs = self.get_std_defines(target, cfg) std_defs.append("%(PreprocessorDefinitions)") n_cl.add("PreprocessorDefinitions", list(cfg["defines"]) + std_defs) n_cl.add("MultiProcessorCompilation", True) n_cl.add("MinimalRebuild", False) n_cl.add("AdditionalIncludeDirectories", cfg["includedirs"]) crt = "MultiThreaded" if cfg.is_debug: crt += "Debug" if cfg["win32-crt-linkage"] == "dll": crt += "DLL" n_cl.add("RuntimeLibrary", crt) # Currently we don't make any distinction between preprocessor, C # and C++ flags as they're basically all the same at MSVS level # too and all go into the same place in the IDE and same # AdditionalOptions node in the project file. all_cflags = VSList(" ", cfg["compiler-options"], cfg["c-compiler-options"], cfg["cxx-compiler-options"]) if all_cflags: all_cflags.append("%(AdditionalOptions)") n_cl.add("AdditionalOptions", all_cflags) self._add_extra_options_to_node(cfg, n_cl) n.add(n_cl) if rc_files: n_res = Node("ResourceCompile") n_res.add("AdditionalIncludeDirectories", cfg["includedirs"]) std_defs = [] if cfg["win32-unicode"]: std_defs.append("_UNICODE") std_defs.append("UNICODE") # See the comment in VCResourceCompilerTool in vs200x.py for # the explanation of why do we do this even though the native # projects don't define _DEBUG/NDEBUG for the RC files. std_defs.append("_DEBUG" if cfg.is_debug else "NDEBUG") std_defs.append("%(PreprocessorDefinitions)") n_res.add("PreprocessorDefinitions", list(cfg["defines"]) + std_defs) self._add_extra_options_to_node(cfg, n_res) n.add(n_res) if idl_files: n_idl = Node("Midl") n_idl.add("AdditionalIncludeDirectories", cfg["includedirs"]) self._add_extra_options_to_node(cfg, n_idl) n.add(n_idl) n_link = Node("Link") if is_program(target) and target["win32-subsystem"] == "console": n_link.add("SubSystem", "Console") else: n_link.add("SubSystem", "Windows") n_link.add("GenerateDebugInformation", True) if not cfg.is_debug: n_link.add("EnableCOMDATFolding", True) n_link.add("OptimizeReferences", True) if not is_library(target): libdirs = VSList(";", target.type.get_libdirs(cfg)) if libdirs: libdirs.append("%(AdditionalLibraryDirectories)") n_link.add("AdditionalLibraryDirectories", libdirs) ldflags = VSList(" ", target.type.get_link_options(cfg)) if ldflags: ldflags.append("%(AdditionalOptions)") n_link.add("AdditionalOptions", ldflags) libs = target.type.get_ldlibs(cfg) if libs: addlibs = VSList(";", ("%s.lib" % x.as_py() for x in libs if x)) addlibs.append("%(AdditionalDependencies)") if is_library(target): n_lib = Node("Lib") self._add_extra_options_to_node(cfg, n_lib) n.add(n_lib) n_lib.add("AdditionalDependencies", addlibs) else: n_link.add("AdditionalDependencies", addlibs) self._add_extra_options_to_node(cfg, n_link) n.add(n_link) pre_build = cfg["pre-build-commands"] if pre_build: n_script = Node("PreBuildEvent") n_script.add("Command", VSList("\n", pre_build)) n.add(n_script) post_build = cfg["post-build-commands"] if post_build: n_script = Node("PostBuildEvent") n_script.add("Command", VSList("\n", post_build)) n.add(n_script) root.add(n) # Source files: if cl_files: items = Node("ItemGroup") root.add(items) cl_files_map = bkl.compilers.disambiguate_intermediate_file_names(cl_files) for sfile in cl_files: if sfile["compile-commands"]: self._add_custom_build_file(items, sfile) else: ext = sfile.filename.get_extension() # TODO: share this code with VS200x # FIXME: make this more solid if ext in ['cpp', 'cxx', 'cc', 'c']: n_cl_compile = Node("ClCompile", Include=sfile.filename) else: # FIXME: handle both compilation into cpp and c files genfiletype = bkl.compilers.CxxFileType.get() genname = bkl.expr.PathExpr([bkl.expr.LiteralExpr(sfile.filename.get_basename())], bkl.expr.ANCHOR_BUILDDIR, pos=sfile.filename.pos).change_extension("cpp") ft_from = bkl.compilers.get_file_type(ext) compiler = bkl.compilers.get_compiler(self, ft_from, genfiletype) customBuild = Node("CustomBuild", Include=sfile.filename) customBuild.add("Command", VSList("\n", compiler.commands(self, target, sfile.filename, genname))) customBuild.add("Outputs", genname) items.add(customBuild) n_cl_compile = Node("ClCompile", Include=genname) # Handle files with custom object name: if sfile in cl_files_map: n_cl_compile.add("ObjectFileName", concat("$(IntDir)\\", cl_files_map[sfile], ".obj")) self._add_per_file_options(sfile, n_cl_compile) items.add(n_cl_compile) # Headers files: if target.headers: items = Node("ItemGroup") root.add(items) for sfile in target.headers: if sfile["compile-commands"]: self._add_custom_build_file(items, sfile) else: items.add("ClInclude", Include=sfile.filename) # Resources: if rc_files: items = Node("ItemGroup") root.add(items) rc_files_map = bkl.compilers.disambiguate_intermediate_file_names(rc_files) for sfile in rc_files: n_rc_compile = Node("ResourceCompile", Include=sfile.filename) # Handle files with custom object name: if sfile in rc_files_map: n_rc_compile.add("ResourceOutputFileName", concat("$(IntDir)\\", rc_files_map[sfile], ".res")) self._add_per_file_options(sfile, n_rc_compile) items.add(n_rc_compile) # IDL files: if idl_files: items = Node("ItemGroup") root.add(items) for sfile in idl_files: n_midl = Node("Midl", Include=sfile.filename) self._add_per_file_options(sfile, n_midl) items.add(n_midl) # Dependencies: target_deps = self._get_references(target) if target_deps: refs = Node("ItemGroup") root.add(refs) for dep in target_deps: dep_prj = self.get_project_object(dep) depnode = Node("ProjectReference", Include=dep_prj.projectfile) depnode.add("Project", "{%s}" % dep_prj.guid.lower()) refs.add(depnode) root.add("Import", Project="$(VCTargetsPath)\\Microsoft.Cpp.targets") root.add("ImportGroup", Label="ExtensionTargets") filename = project.projectfile.as_native_path_for_output(target) paths_info = self.get_project_paths_info(target, project) formatter = self.XmlFormatter(target.project.settings, paths_info) f = OutputFile(filename, EOL_WINDOWS, creator=self, create_for=target) f.write(codecs.BOM_UTF8) f.write(formatter.format(root)) f.commit() self._write_filters_file_for(filename, formatter, target.headers, cl_files, idl_files, rc_files)