Added getLLVMDocsBuildFactory to build and publish LLVM documentation.
This is to build and publish LLVM Sphinx documentation.

Differential Revision: https://reviews.llvm.org/D75593
diff --git a/zorg/buildbot/builders/SphinxDocsBuilder.py b/zorg/buildbot/builders/SphinxDocsBuilder.py
index 9a2cc2b..5e2bb83 100644
--- a/zorg/buildbot/builders/SphinxDocsBuilder.py
+++ b/zorg/buildbot/builders/SphinxDocsBuilder.py
@@ -1,7 +1,24 @@
+from collections import OrderedDict
+
+from buildbot.steps.shell import ShellCommand
+
 from zorg.buildbot.builders import UnifiedTreeBuilder
 from zorg.buildbot.commands.CmakeCommand import CmakeCommand
 from zorg.buildbot.commands.NinjaCommand import NinjaCommand
 
+llvm_docs = OrderedDict([
+  # Project              Build target             Local path                            Remote path
+  ("llvm",              ("docs-llvm-html",        "docs/html/",                         "llvm")),
+  ("clang",             ("docs-clang-html",       "tools/clang/docs/html/",             "cfe")),
+  ("clang-tools-extra", ("docs-clang-tools-html", "tools/clang/tools/extra/docs/html/", "clang-tools-extra")),
+  ("libcxx",            ("docs-libcxx-html",      "projects/libcxx/docs/html/",         "libcxx")),
+  ("libunwind",         ("docs-libunwind-html",   "projects/libunwind/docs/html/",      "libunwind")),
+  ("lld",               ("docs-lld-html",         "tools/lld/docs/html/",               "lld")),
+  ("lldb",              ("docs-lldb-html",        "tools/lldb/docs/html/",              "lldb")),
+  ("polly",             ("docs-polly-html",       "tools/polly/docs/html/",             "polly")),
+])
+
+
 def getSphinxDocsBuildFactory(
         llvm_html         = False, # Build LLVM HTML documentation
         llvm_man          = False, # Build LLVM man pages
@@ -120,3 +137,109 @@
                               ))
 
     return f
+
+
+def getLLVMDocsBuildFactory(
+        clean = False,
+        depends_on_projects = None,
+        extra_configure_args = None,
+        env = None,
+        **kwargs):
+
+    if depends_on_projects is None:
+        # All the projects by default.
+        _depends_on_projects=[
+            "llvm",
+            "clang",
+            "clang-tools-extra",
+            "libcxx",
+            "libcxxabi",
+            "libunwind",
+            "lld",
+            "lldb",
+            "polly",
+        ]
+    else:
+        # Make a local copy of depends_on_projects, as we are going to modify
+        # that.
+        _depends_on_projects=depends_on_projects[:]
+        # Some projects are interdependent for the purpose of documentation.
+        # Enforce the dependencies.
+        if ("clang-tools-extra" in _depends_on_projects or \
+            "lldb" in _depends_on_projects
+           ) and "clang" not in _depends_on_projects:
+            _depends_on_projects.append("clang")
+        if "libcxx" in _depends_on_projects and \
+           "libcxxabi" not in _depends_on_projects:
+            _depends_on_projects.append("libcxxabi")
+        if "libcxxabi" in _depends_on_projects and \
+           "libcxx" not in _depends_on_projects:
+            _depends_on_projects.append("libcxx")
+
+    # Make a local copy of the configure args, as we are going to modify that.
+    if extra_configure_args:
+        cmake_args = extra_configure_args[:]
+    else:
+        cmake_args = list()
+
+    # Prepare environmental variables. Set here all env we want everywhere.
+    merged_env = {
+        'TERM' : 'dumb' # Be cautious and disable color output from all tools.
+    }
+    if env is not None:
+        # Overwrite pre-set items with the given ones, so user can set anything.
+        merged_env.update(env)
+
+    CmakeCommand.applyDefaultOptions(cmake_args, [
+        ("-G",                           "Ninja"),
+        ("-DLLVM_ENABLE_SPHINX=",        "ON"),
+        ("-DSPHINX_OUTPUT_HTML=",        "ON"),
+        ("-DSPHINX_OUTPUT_MAN=",         "OFF"),
+        ("-DSPHINX_WARNINGS_AS_ERRORS=", "OFF"),
+        ("-DLLVM_ENABLE_ASSERTIONS=",    "OFF"),
+        ("-DCMAKE_BUILD_TYPE=",          "Release"),
+        ])
+
+    # Build docs for each of the projects this builder depends on
+    docs = [
+        llvm_docs[project] for project in llvm_docs.keys()
+        if project in _depends_on_projects
+    ]
+
+    f = UnifiedTreeBuilder.getCmakeBuildFactory(
+            clean=clean,
+            depends_on_projects=_depends_on_projects,
+            extra_configure_args=cmake_args,
+            env=merged_env,
+            **kwargs) # Pass through all the extra arguments.
+
+    UnifiedTreeBuilder.addNinjaSteps(
+        f,
+        targets=[d[0] for d in docs],
+        checks=[],
+        env=merged_env,
+        **kwargs)
+
+    # Publish just built documentation
+    for target, local_path, remote_path in docs:
+        f.addStep(
+            ShellCommand(
+                name="Publish %s" % target,
+                description=[
+                    "Publish", "just", "built", "documentation", "fior",
+                    "%s" % target,
+                    ],
+                command=[
+                    'rsync',
+                    '-vrl',
+                    '--delete', '--force', '--delay-updates', '--delete-delay',
+                    '--ignore-times',
+                    '--checksum',
+                    "%s" % local_path,
+                    "lists.llvm.org:web/%s" % remote_path,
+                    ],
+                env=merged_env,
+            )
+        )
+
+    return f