def build(self, recursive=True):
        """
        Building an assembly buffers the :meth:`components` and :meth:`constraints`.


        Running ``build()`` is optional, it's automatically run when requesting
        :meth:`components` or :meth:`constraints`.

        Mostly it's used to test that there aren't any critical runtime
        issues with its construction, but doing anything like *displaying* or
        *exporting* will ultimately run a build anyway.

        :param recursive: if set, iterates through child components and builds
                          those as well.
        :type recursive: :class:`bool`
        """

        # initialize values
        self._components = {}
        self._constraints = []

        def genwrap(obj, name, iter_type=None):
            # Force obj to act like a generator.
            # this wrapper will always yield at least once.
            if isinstance(obj, GeneratorType):
                for i in obj:
                    if (iter_type is not None) and (not isinstance(i, iter_type)):
                        raise TypeError("%s must yield a %r" % (name, iter_type))
                    yield i
            else:
                if (iter_type is not None) and (not isinstance(obj, iter_type)):
                    raise TypeError("%s must return a %r" % (name, iter_type))
                yield obj

        # Make Components
        components_iter = genwrap(self.make_components(), "make_components", dict)
        new_components = next(components_iter)
        self.verify_components(new_components)
        self._components.update(new_components)

        # Make Constraints
        constraints_iter = genwrap(self.make_constraints(), "make_components", list)
        new_constraints = next(constraints_iter)
        self.verify_constraints(new_constraints)
        self._constraints += new_constraints

        # Run solver : sets components' world coordinates
        self.solve()

        # Make Alterations
        alterations_iter = genwrap(self.make_alterations(), "make_alterations")
        next(alterations_iter)  # return value is ignored

        while True:
            (s1, s2, s3) = (True, True, True)  # stages
            # Make Components
            new_components = None
            try:
                new_components = next(components_iter)
                self.verify_components(new_components)
                self._components.update(new_components)
            except StopIteration:
                s1 = False

            # Make Constraints
            new_constraints = None
            try:
                new_constraints = next(constraints_iter)
                self.verify_constraints(new_constraints)
                self._constraints += new_constraints
            except StopIteration:
                s2 = False

            # Run solver : sets components' world coordinates
            if new_components or new_constraints:
                self.solve()

            # Make Alterations
            try:
                next(alterations_iter)  # return value is ignored
            except StopIteration:
                s3 = False

            # end loop when all iters are finished
            if not any((s1, s2, s3)):
                break

        if recursive:
            for (name, component) in self._components.items():
                component.build(recursive=recursive)