Repository: llvm/llvm-project

Issue:
[Flang] man pages cannot be built
I'm trying to build man pages along with LLVM, clang and flang with CMake options as such:

```
    -DLLVM_BUILD_DOCS=ON \
    -DLLVM_ENABLE_SPHINX=ON \
    -DLLVM_ENABLE_PROJECTS="llvm;clang;flang;lld" \
    -DLLVM_ENABLE_RUNTIMES="compiler-rt;flang-rt;libunwind;openmp"
```

It fails like this:

```
FAILED: tools/flang/docs/CMakeFiles/docs-flang-man build/tools/flang/docs/CMakeFiles/docs-flang-man
cd build/tools/flang/docs && /usr/bin/cmake -E env ~/.local/bin/sphinx-build -b man -d build/tools/flang/docs/_doctrees-flang-man -q -t builder-man -D version=21 -D release=21 -W flang/docs build/tools/flang/docs/man
WARNING: no "man_pages" config value found; no manual pages will be written
flang/docs/index.md:40: WARNING: toctree contains reference to nonexisting document 'FIRLangRef' [toc.not_readable]
flang/docs/index.md:40: WARNING: toctree contains reference to nonexisting document 'FlangCommandLineReference' [toc.not_readable]
```

The build does not fail when I add the following line, thought it won't build flang manpages:

```
  -DFLANG_INCLUDE_DOCS=OFF
```



Discussion:

Patch:
diff --git a/flang/docs/CMakeLists.txt b/flang/docs/CMakeLists.txt
index 92feb059d4caa..a9f5811fcd064 100644
--- a/flang/docs/CMakeLists.txt
+++ b/flang/docs/CMakeLists.txt
@@ -82,7 +82,7 @@ if (LLVM_ENABLE_DOXYGEN)
 endif()
 endif()
 
-function (gen_rst_file_from_td output_file td_option source docs_target)
+function (gen_rst_file_from_td output_file td_option source)
   if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${source}")
     message(FATAL_ERROR "Cannot find source file: ${source} in ${CMAKE_CURRENT_SOURCE_DIR}")
   endif()
@@ -90,12 +90,8 @@ function (gen_rst_file_from_td output_file td_option source docs_target)
   list(APPEND LLVM_TABLEGEN_FLAGS "-I${TABLEGEN_INCLUDE_DIR}")
   list(APPEND LLVM_TABLEGEN_FLAGS "-I${CMAKE_CURRENT_SOURCE_DIR}/../../clang/include/clang/Driver/")
   clang_tablegen(Source/${output_file} ${td_option} SOURCE ${source} TARGET "gen-${output_file}")
-  add_dependencies(${docs_target} "gen-${output_file}")
-
   # clang_tablegen() does not create the output directory automatically,
-  # so we have to create it explicitly. Note that copy-flang-src-docs below
-  # does create the output directory, but it is not necessarily run
-  # before RST generation.
+  # so we have to create it explicitly. 
   add_custom_target(create-flang-rst-output-dir
     COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/Source
   )
@@ -103,34 +99,70 @@ function (gen_rst_file_from_td output_file td_option source docs_target)
 endfunction()
 
 if (LLVM_ENABLE_SPHINX)
+  set (FLANG_DOCS_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/SourceHtml")
+  set (FLANG_DOCS_MAN_DIR "${CMAKE_CURRENT_BINARY_DIR}/SourceMan")
   include(AddSphinxTarget)
   if (SPHINX_FOUND)
-    if (${SPHINX_OUTPUT_HTML})
-      add_sphinx_target(html flang SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/Source")
 
-      add_dependencies(docs-flang-html copy-flang-src-docs)
+    # CLANG_TABLEGEN_EXE variable needs to be set for clang_tablegen to run without error
+    find_program(CLANG_TABLEGEN_EXE "clang-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH)
 
-      # Copy the flang/docs directory and the generated FIRLangRef.md file to a place in the binary directory.
-      # Having all the files in a single directory makes it possible for Sphinx to process them together.
-      # Add a dependency to the flang-doc target to ensure that the FIRLangRef.md file is generated before the copying happens.
-      add_custom_target(copy-flang-src-docs
-        COMMAND "${CMAKE_COMMAND}" -E copy_directory
-        "${CMAKE_CURRENT_SOURCE_DIR}"
-        "${CMAKE_CURRENT_BINARY_DIR}/Source"
-        DEPENDS flang-doc)
+    # Generate the RST file from TableGen (shared by both HTML and MAN builds)
+    gen_rst_file_from_td(FlangCommandLineReference.rst -gen-opt-docs FlangOptionsDocs.td)
 
-      # Runs a python script prior to HTML generation to prepend a header to FIRLangRef,
-      # Without the header, the page is incorrectly formatted, as it assumes the first entry is the page title.
-      add_custom_command(TARGET copy-flang-src-docs
+    if (${SPHINX_OUTPUT_HTML})
+      message(STATUS "Using index.md for html build")
+
+      # Copy the entire flang/docs directory to the build Source dir,
+      # then remove the index.rst file, to avoid clash with index.md 
+      # which is used for the HTML build.
+      add_custom_target(copy-flang-src-docs-html
+        COMMAND "${CMAKE_COMMAND}" -E copy_directory
+              "${CMAKE_CURRENT_SOURCE_DIR}"
+              "${FLANG_DOCS_HTML_DIR}"
+        COMMAND "${CMAKE_COMMAND}" -E remove
+          "${FLANG_DOCS_HTML_DIR}/CommandGuide/index.rst"
+        COMMAND "${CMAKE_COMMAND}" -E copy
+          "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineReference.rst"
+          "${FLANG_DOCS_HTML_DIR}/FlangCommandLineReference.rst"
+        DEPENDS flang-doc gen-FlangCommandLineReference.rst)
+
+      # Run Python preprocessing ONLY for HTML build
+      # This script prepends headers to FIRLangRef.md for proper formatting
+      add_custom_command(TARGET copy-flang-src-docs-html
         COMMAND "${Python3_EXECUTABLE}"
-        ARGS ${CMAKE_CURRENT_BINARY_DIR}/Source/FIR/CreateFIRLangRef.py)
+        ARGS "${FLANG_DOCS_HTML_DIR}/FIR/CreateFIRLangRef.py")
 
-      # CLANG_TABLEGEN_EXE variable needs to be set for clang_tablegen to run without error
-      find_program(CLANG_TABLEGEN_EXE "clang-tblgen" ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH)
-      gen_rst_file_from_td(FlangCommandLineReference.rst -gen-opt-docs FlangOptionsDocs.td docs-flang-html)
+      add_sphinx_target(html flang SOURCE_DIR "${FLANG_DOCS_HTML_DIR}")
+      add_dependencies(docs-flang-html copy-flang-src-docs-html)
     endif()
+
+    # ----------------------------
+    # MAN BUILD SETUP
+    # ----------------------------
     if (${SPHINX_OUTPUT_MAN})
-      add_sphinx_target(man flang)
+      message(STATUS "NOTE: The Flang man page is currently a placeholder with a TODO. See docs/CommandGuide/index.rst for details")
+
+      # Create minimal Source dir with ONLY the files needed for man build:
+      # - conf.py (Sphinx config)
+      # - index.rst (top-level man page)
+      # - FlangCommandLineReference.rst (generated reference)
+      add_custom_target(copy-flang-src-docs-man
+        COMMAND "${CMAKE_COMMAND}" -E make_directory
+                "${FLANG_DOCS_MAN_DIR}"
+        COMMAND "${CMAKE_COMMAND}" -E copy
+          "${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
+          "${FLANG_DOCS_MAN_DIR}/conf.py"
+        COMMAND "${CMAKE_COMMAND}" -E copy
+          "${CMAKE_CURRENT_BINARY_DIR}/Source/FlangCommandLineReference.rst"
+          "${FLANG_DOCS_MAN_DIR}/FlangCommandLineReference.rst"
+        COMMAND "${CMAKE_COMMAND}" -E copy
+                "${CMAKE_CURRENT_SOURCE_DIR}/CommandGuide/index.rst"
+                "${FLANG_DOCS_MAN_DIR}/index.rst"
+        DEPENDS flang-doc gen-FlangCommandLineReference.rst)
+        
+      add_sphinx_target(man flang SOURCE_DIR "${FLANG_DOCS_MAN_DIR}")
+      add_dependencies(docs-flang-man copy-flang-src-docs-man)
     endif()
   endif()
 endif()
diff --git a/flang/docs/CommandGuide/index.rst b/flang/docs/CommandGuide/index.rst
new file mode 100644
index 0000000000000..093c79fa185be
--- /dev/null
+++ b/flang/docs/CommandGuide/index.rst
@@ -0,0 +1,22 @@
+Flang Manual Page (In Progress)
+==================================================
+
+.. note::
+    This man page is under development.
+
+For full documentation, please see the online HTML docs:
+
+https://flang.llvm.org/docs/
+
+..  
+  The placeholder text "FlangCommandLineReference" below should eventually be replaced with the actual man page contents.  
+
+----
+
+Flang Command Line Reference
+----------------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   FlangCommandLineReference
diff --git a/flang/docs/FIR/CreateFIRLangRef.py b/flang/docs/FIR/CreateFIRLangRef.py
index b6077364cdee6..803cd9da3f127 100644
--- a/flang/docs/FIR/CreateFIRLangRef.py
+++ b/flang/docs/FIR/CreateFIRLangRef.py
@@ -4,9 +4,9 @@
 import os
 
 # These paths are relative to flang/docs in the build directory, not source, as that's where this tool is executed.
-HEADER_PATH = os.path.join("Source", "FIR", "FIRLangRef_Header.md")
+HEADER_PATH = os.path.join("SourceHtml", "FIR", "FIRLangRef_Header.md")
 DOCS_PATH = os.path.join("Dialect", "FIRLangRef.md")
-OUTPUT_PATH = os.path.join("Source", "FIRLangRef.md")
+OUTPUT_PATH = os.path.join("SourceHtml", "FIRLangRef.md")
 
 # 1. Writes line 1 from docs to output, (comment line that the file is autogenerated)
 # 2. Adds a new line
diff --git a/flang/docs/conf.py b/flang/docs/conf.py
index 48f7b69f5d750..a470d8afd7186 100644
--- a/flang/docs/conf.py
+++ b/flang/docs/conf.py
@@ -28,20 +28,22 @@
     "sphinx.ext.autodoc",
 ]
 
-# When building man pages, we do not use the markdown pages,
-# So, we can continue without the myst_parser dependencies.
-# Doing so reduces dependencies of some packaged llvm distributions.
 try:
     import myst_parser
 
     extensions.append("myst_parser")
 except ImportError:
-    if not tags.has("builder-man"):
-        raise
+    raise ImportError(
+        "myst_parser is required to build documentation, including man pages."
+    )
 
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ["_templates"]
+source_suffix = {
+    ".rst": "restructuredtext",
+    ".md": "markdown",
+}
 myst_heading_anchors = 6
 
 import sphinx
@@ -227,7 +229,15 @@
 
 # One entry per manual page. List of tuples
 # (source start file, name, description, authors, manual section).
-man_pages = []
+man_pages = [
+    (
+        "index",
+        "flang",
+        "Flang Documentation (In Progress)",
+        ["Flang Contributors"],
+        1,
+    )
+]
 
 # If true, show URL addresses after external links.
 # man_show_urls = False