Exemplo n.º 1
0
    def __init__(self, name, text=None, **kwargs):
        """
        Creates an XML node with given element name. If provided, the text is
        used for its textual content. Any provided keyword arguments are used
        to add attributes to the node.

        Examples:

        >>> Node("ImportGroup", Label="PropertySheets", Foo="A")
            # creates <ImportGroup Label="PropertySheets" Foo="a"/>
        >>> Node("LinkIncremental", True)
            # creates <LinkIncremental>true</LinkIncremental>
        """
        self.name = name
        self.text = text
        self.attrs = OrderedDict()
        self.children = []
        for key in sorted(kwargs.keys()):
            self.attrs[key] = kwargs[key]
Exemplo n.º 2
0
 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
Exemplo n.º 3
0
    def write(self):
        """Writes the solution to the file."""
        if not self.generate_outf:
            return # silently do nothing
        outf = self.outf
        self.write_header(outf)

        # Projects:
        all_own_projects = list(self.all_projects())
        additional_deps = self.additional_deps()
        included_projects = all_own_projects + additional_deps

        if not included_projects:
            return # don't write empty solution files

        configurations = OrderedSet()
        for prj in all_own_projects:
            configurations.update(prj.configurations)

        platforms = OrderedSet()
        for prj in all_own_projects:
            platforms.update(prj.platforms)
        # HACK: Don't use Any CPU for solution config if there are native ones:
        if "Any CPU" in platforms and len(platforms) > 1:
            platforms.remove("Any CPU")

        for prj in included_projects:
            outf.write('Project("%s") = "%s", "%s", "{%s}"\n' %
                       (prj.kind, prj.name, self.formatter.format(prj.projectfile), str(prj.guid)))
            if prj.dependencies:
                outf.write("\tProjectSection(ProjectDependencies) = postProject\n")
                for d in prj.dependencies:
                    outf.write("\t\t{%(g)s} = {%(g)s}\n" % {'g':self._get_target_guid(d)})
                outf.write("\tEndProjectSection\n")
            outf.write("EndProject\n")

        # Folders in the solution:
        all_folders = list(self.all_subsolutions())
        if additional_deps:
            class AdditionalDepsFolder: pass
            extras = AdditionalDepsFolder()
            extras.name = "Additional Dependencies"
            extras.guid = GUID(NAMESPACE_INTERNAL, self.name, extras.name)
            extras.projects = OrderedDict()
            for prj in additional_deps:
                extras.projects[prj.name] = prj
            extras.subsolutions = []
            extras.parent_solution = None
            all_folders.append(extras)
        for sln in all_folders:
            # don't have folders with just one item in them:
            sln.omit_from_tree = (sln.parent_solution and
                                  (len(sln.projects) + len(sln.subsolutions)) <= 1)
            if sln.omit_from_tree:
                continue
            outf.write('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "%s", "%s", "{%s}"\n' %
                       (sln.name, sln.name, sln.guid))
            outf.write("EndProject\n")
        all_folders = list(x for x in all_folders if not x.omit_from_tree)

        # Global settings:
        outf.write("Global\n")
        outf.write("\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n")
        for cfg in configurations:
            for plat in platforms:
                outf.write("\t\t%s|%s = %s|%s\n" % (cfg.name, plat, cfg.name, plat))
        outf.write("\tEndGlobalSection\n")
        outf.write("\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n")
        for prj in included_projects:
            guid = prj.guid
            for cfg in configurations:
                cfgp = _get_matching_project_config(cfg, prj)
                for plat in platforms:
                    platp = _get_matching_project_platform(plat, prj)
                    if platp is None:
                        # Can't build in this solution config. Just use any project platform
                        # and omit the Build.0 node -- VS does the same in this case.
                        platp = prj.platforms[0]
                        outf.write("\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n" % (guid, cfg.name, plat, cfgp.name, platp))
                    else:
                        outf.write("\t\t{%s}.%s|%s.ActiveCfg = %s|%s\n" % (guid, cfg.name, plat, cfgp.name, platp))
                        if cfg not in prj.disabled_configurations:
                            outf.write("\t\t{%s}.%s|%s.Build.0 = %s|%s\n" % (guid, cfg.name, plat, cfgp.name, platp))
        outf.write("\tEndGlobalSection\n")
        outf.write("\tGlobalSection(SolutionProperties) = preSolution\n")
        outf.write("\t\tHideSolutionNode = FALSE\n")
        outf.write("\tEndGlobalSection\n")

        # Nesting of projects and folders in the tree:
        if all_folders:
            outf.write("\tGlobalSection(NestedProjects) = preSolution\n")

            def _gather_folder_children(sln):
                prjs = [p for p in sln.projects.itervalues()]
                slns = []
                for s in sln.subsolutions:
                    if s.omit_from_tree:
                        p2, s2 = _gather_folder_children(s)
                        prjs += p2
                        slns += s2
                    else:
                        slns.append(s)
                return (prjs, slns)

            for sln in all_folders:
                prjs, subslns = _gather_folder_children(sln)
                for prj in prjs:
                    outf.write("\t\t{%s} = {%s}\n" % (prj.guid, sln.guid))
                for subsln in subslns:
                    outf.write("\t\t{%s} = {%s}\n" % (subsln.guid, sln.guid))
            outf.write("\tEndGlobalSection\n")

        outf.write("EndGlobal\n")
        outf.commit()
Exemplo n.º 4
0
    def _gen_makefile(self, build_graphs, module):
        # Flag indicating whether this makefile actually builds anything.
        self.uses_builddir = False

        output_value = module.get_variable_value("%s.makefile" % self.name)
        output = output_value.as_native_path_for_output(module)

        paths_info = expr.PathAnchorsInfo(
                dirsep="/", # FIXME - format-configurable
                outfile=output,
                builddir=None,
                model=module)

        mk_fmt = self.Formatter()
        expr_fmt = self.ExprFormatter(self, paths_info)

        f = io.OutputFile(output, io.EOL_UNIX, creator=self, create_for=module)
        self.on_header(f, module)

        self._gen_settings(module, mk_fmt, expr_fmt, f)

        #FIXME: make this part of the formatter for (future) IdRefExpr
        def _format_dep(t):
            g = build_graphs[t].main
            if len(g.outputs) == 0:
                assert g.name
                if t.parent is not module:
                    raise Error("cross-module dependencies on phony targets (\"%s\") not supported yet" % t.name) # TODO
                out = g.name
            else:
                # FIXME: handle multi-output nodes too
                assert len(g.outputs) == 1
                out = g.outputs[0]
            return expr_fmt.format(out)

        def _get_submodule_deps(main, submodule):
            """
            Return list of dependencies that 'submodule' has on other submodules of
            'main'.  Submodules have dependency if a target from one depends on a
            target from another.
            """
            mod_deps = set()
            project = main.project
            inspect = [submodule] + [p for p in project.modules if p.is_submodule_of(submodule)]
            for mod in inspect:
                for target in mod.targets.itervalues():
                    for dep in target["deps"]:
                        tdep = project.get_target(dep.as_py())
                        tmod = tdep.parent
                        if tmod is main:
                            mod_deps.add(_format_dep(tdep))
                        elif tmod.is_submodule_of(main):
                            while tmod.parent is not main:
                                tmod = tmod.parent
                            if tmod is not submodule:
                                mod_deps.add(tmod.name)
            return sorted(mod_deps)

        # Write the "all" target:
        all_targets = (
                      [_format_dep(t) for t in module.targets.itervalues()] +
                      [sub.name for sub in module.submodules]
                      )
        f.write(mk_fmt.target(name="all", deps=all_targets, commands=None))

        phony_targets = ["all", "clean"]

        targets_from_submodules = OrderedDict()
        submakefiles = OrderedDict()
        for sub in module.submodules:
            subpath = sub.get_variable_value("%s.makefile" % self.name)
            # FIXME: use $dirname(), $basename() functions, this is hacky
            subdir = subpath.get_directory_path()
            subfile = subpath.components[-1]
            submakefiles[sub] = (sub.name,
                                 expr_fmt.format(subdir),
                                 expr_fmt.format(subfile),
                                 _get_submodule_deps(module, sub))
        for subname, subdir, subfile, subdeps in submakefiles.itervalues():
            subcmd = mk_fmt.submake_command(subdir, subfile, "all")
            f.write(mk_fmt.target(name=subname, deps=subdeps, commands=[subcmd]))
            phony_targets.append(subname)

        for t in module.targets.itervalues():
            with error_context(t):
                # collect target's dependencies
                target_deps = []
                for dep in t["deps"]:
                    tdep = module.project.get_target(dep.as_py())
                    tdepstr = _format_dep(tdep)
                    target_deps.append(tdepstr)
                    if tdep.parent is not module:
                        # link external dependencies with submodules to build them
                        tmod = tdep.parent
                        while tmod.parent is not None and tmod.parent is not module:
                            tmod = tmod.parent
                        if tmod in module.submodules:
                            targets_from_submodules[tdepstr] = tmod

                # generate code for the target's build graph:
                graph = build_graphs[t]
                for node in graph.all_nodes():
                    with error_context(node):
                        if node.outputs:
                            out = node.outputs
                        else:
                            out = [node.name]
                            phony_targets.append(expr_fmt.format(out[0]))

                        deps = [expr_fmt.format(i) for i in node.inputs]
                        if node is graph.main:
                            deps += target_deps

                        out_fmt = [expr_fmt.format(x) for x in out]
                        commands_fmt = [expr_fmt.format(c) for c in node.commands]
                        if len(out_fmt) == 1:
                            text = mk_fmt.target(name=out_fmt[0],
                                                 deps=deps,
                                                 commands=commands_fmt)
                        else:
                            text = mk_fmt.multifile_target(
                                                 outputs=out,
                                                 outfiles=out_fmt,
                                                 deps=deps,
                                                 commands=commands_fmt)
                        f.write(text)
                        all_targets += out_fmt

        # dependencies on submodules to build targets from them:
        if targets_from_submodules:
            f.write("# Targets from sub-makefiles:\n")
            for t, tsub in targets_from_submodules.iteritems():
                f.write(mk_fmt.target(name=t, deps=[submakefiles[tsub][0]], commands=None))

        # Write the "clean" target:
        clean_cmds = self._get_clean_commands(
                        mk_fmt, expr_fmt,
                        (build_graphs[t] for t in module.targets.itervalues()),
                        submakefiles.itervalues())
        f.write(mk_fmt.target(name="clean", deps=[], commands=clean_cmds))

        self.on_phony_targets(f, phony_targets)
        self.on_footer(f, module)

        f.commit()