[PATCH rdma-core 06/20] build: Support rst as a man page option

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Jason Gunthorpe <jgg@xxxxxxxxxxxx>

infiniband-diags uses rst as a man page preprocessor, so add it along side
pandoc in the build system.

Signed-off-by: Jason Gunthorpe <jgg@xxxxxxxxxxxx>
---
 .travis.yml                 |  1 +
 CMakeLists.txt              | 10 ++++++-
 buildlib/Findrst2man.cmake  | 21 +++++++++++++
 buildlib/cbuild             | 12 +++++++-
 buildlib/pandoc-prebuilt.py | 33 +++++++++++++++++---
 buildlib/rdma_man.cmake     | 60 ++++++++++++++++++++++++++++++-------
 debian/control              |  1 +
 redhat/rdma-core.spec       |  1 +
 suse/rdma-core.spec         |  1 +
 9 files changed, 123 insertions(+), 17 deletions(-)
 create mode 100644 buildlib/Findrst2man.cmake

diff --git a/.travis.yml b/.travis.yml
index 660b306797bf6b..1cc2c69ca8671d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,6 +19,7 @@ addons:
       - make
       - ninja-build
       - pandoc
+      - python-docutils
       - pkg-config
       - python
       - valgrind
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5cb3c32c318821..9428ce02191bc4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -406,8 +406,9 @@ if (CYTHON_EXECUTABLE)
   string(STRIP ${py_path} CMAKE_PYTHON_SO_SUFFIX)
 endif()
 
-# Look for pandoc
+# Look for pandoc and rst2man for making manual pages
 FIND_PACKAGE(pandoc)
+FIND_PACKAGE(rst2man)
 
 #-------------------------
 # Find libraries
@@ -668,6 +669,13 @@ if (NOT PANDOC_FOUND)
     message(STATUS " pandoc NOT found (using prebuilt man pages)")
   endif()
 endif()
+if (NOT RST2MAN_FOUND)
+  if (NOT EXISTS "${CMAKE_SOURCE_DIR}/buildlib/pandoc-prebuilt")
+    message(STATUS " rst2man NOT found and NO prebuilt man pages. 'install' disabled")
+  else()
+    message(STATUS " rst2man NOT found (using prebuilt man pages)")
+  endif()
+endif()
 if (NOT CYTHON_EXECUTABLE)
   message(STATUS " cython NOT found (disabling pyverbs)")
 endif()
diff --git a/buildlib/Findrst2man.cmake b/buildlib/Findrst2man.cmake
new file mode 100644
index 00000000000000..a7236604dfcc28
--- /dev/null
+++ b/buildlib/Findrst2man.cmake
@@ -0,0 +1,21 @@
+# COPYRIGHT (c) 2019 Mellanox Technologies Ltd
+# Licensed under BSD (MIT variant) or GPLv2. See COPYING.
+find_program(RST2MAN_EXECUTABLE NAMES rst2man)
+
+if(RST2MAN_EXECUTABLE)
+  execute_process(COMMAND "${RST2MAN_EXECUTABLE}" --version
+    OUTPUT_VARIABLE _VERSION
+    RESULT_VARIABLE _VERSION_RESULT
+    ERROR_QUIET)
+
+  if(NOT _VERSION_RESULT)
+    string(REGEX REPLACE "^rst2man \\(Docutils ([^,]+), .*" "\\1" RST2MAN_VERSION_STRING "${_VERSION}")
+  endif()
+  unset(_VERSION_RESULT)
+  unset(_VERSION)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(rst2man REQUIRED_VARS RST2MAN_EXECUTABLE RST2MAN_VERSION_STRING VERSION_VAR RST2MAN_VERSION_STRING)
+
+mark_as_advanced(RST2MAN_EXECUTABLE)
diff --git a/buildlib/cbuild b/buildlib/cbuild
index e012b08b5fbb76..2d0fc46a1ee913 100755
--- a/buildlib/cbuild
+++ b/buildlib/cbuild
@@ -104,6 +104,7 @@ class centos6(YumEnvironment):
         'pkgconfig',
         'python',
         'python-argparse',
+        'python-docutils',
         'rpm-build',
         'valgrind-devel',
     };
@@ -149,7 +150,14 @@ class centos7_epel(centos7):
 
 class fc30(Environment):
     docker_parent = "fedora:30";
-    pkgs = (centos7.pkgs - {"make", "python-argparse" }) | {"ninja-build","pandoc","perl-generators","python3-Cython","python3-devel"};
+    pkgs = (centos7.pkgs - {"make", "python-argparse" }) | {
+        "ninja-build",
+        "pandoc",
+        "perl-generators",
+        "python3-docutils",
+        "python3-Cython",
+        "python3-devel",
+    };
     name = "fc30";
     specfile = "redhat/rdma-core.spec";
     ninja_cmd = "ninja-build";
@@ -190,6 +198,7 @@ class xenial(APTEnvironment):
         'pandoc',
         'pkg-config',
         'python3',
+        "python3-docutils",
         'valgrind',
     };
     name = "ubuntu-16.04";
@@ -354,6 +363,7 @@ class leap(ZypperEnvironment):
         'valgrind-devel',
         'python3-Cython',
         'python3-devel',
+        'python3-docutils',
     };
     rpmbuild_options = [ "--without=curlmini" ];
     name = "opensuse-15.0";
diff --git a/buildlib/pandoc-prebuilt.py b/buildlib/pandoc-prebuilt.py
index c1db6a25a23bad..afba326324345b 100644
--- a/buildlib/pandoc-prebuilt.py
+++ b/buildlib/pandoc-prebuilt.py
@@ -4,19 +4,31 @@ import shutil
 import subprocess
 import sys
 import hashlib
+import re
+
+def hash_rst_includes(incdir,txt):
+    h = ""
+    for fn in re.findall(br"^..\s+include::\s+(.*)$", txt, flags=re.MULTILINE):
+        with open(os.path.join(incdir,fn.decode()),"rb") as F:
+            h = h +  hashlib.sha1(F.read()).hexdigest();
+    return h.encode();
 
 def get_id(SRC):
     """Return a unique ID for the SRC file. For simplicity and robustness we just
     content hash it"""
+    incdir = os.path.dirname(SRC)
     with open(SRC,"rb") as F:
-        return hashlib.sha1(F.read()).hexdigest();
+        txt = F.read();
+        if SRC.endswith(".rst"):
+            txt = txt + hash_rst_includes(incdir,txt);
+        return hashlib.sha1(txt).hexdigest();
 
 def do_retrieve(src_root,SRC):
     """Retrieve the file from the prebuild cache and write it to DEST"""
     prebuilt = os.path.join(src_root,"buildlib","pandoc-prebuilt",get_id(SRC))
     sys.stdout.write(prebuilt);
 
-def do_build(build_root,pandoc,SRC,DEST):
+def do_build_pandoc(build_root,pandoc,SRC,DEST):
     """Build the markdown into a man page with pandoc and then keep a copy of the
     output under build/pandoc-prebuilt"""
     try:
@@ -25,13 +37,26 @@ def do_build(build_root,pandoc,SRC,DEST):
         sys.exit(100);
     shutil.copy(DEST,os.path.join(build_root,"pandoc-prebuilt",get_id(SRC)));
 
+def do_build_rst2man(build_root,rst2man,SRC,DEST):
+    """Build the markdown into a man page with pandoc and then keep a copy of the
+    output under build/pandoc-prebuilt"""
+    try:
+        subprocess.check_call([rst2man,SRC,DEST]);
+    except subprocess.CalledProcessError:
+        sys.exit(100);
+    shutil.copy(DEST,os.path.join(build_root,"pandoc-prebuilt",get_id(SRC)));
+
 # We support python 2.6 so argparse is not available.
 if len(sys.argv) == 4:
     assert(sys.argv[1] == "--retrieve");
     do_retrieve(sys.argv[2],sys.argv[3]);
 elif len(sys.argv) == 7:
     assert(sys.argv[1] == "--build");
-    assert(sys.argv[3] == "--pandoc");
-    do_build(sys.argv[2],sys.argv[4],sys.argv[5],sys.argv[6]);
+    if sys.argv[3] == "--pandoc":
+        do_build_pandoc(sys.argv[2],sys.argv[4],sys.argv[5],sys.argv[6]);
+    elif sys.argv[3] == "--rst":
+        do_build_rst2man(sys.argv[2],sys.argv[4],sys.argv[5],sys.argv[6]);
+    else:
+        raise ValueError("Bad sys.argv[3]");
 else:
     raise ValueError("Must provide --build or --retrieve");
diff --git a/buildlib/rdma_man.cmake b/buildlib/rdma_man.cmake
index 0db455f0cc6029..f8f43c9fe55a6e 100644
--- a/buildlib/rdma_man.cmake
+++ b/buildlib/rdma_man.cmake
@@ -4,6 +4,22 @@
 rdma_make_dir("${CMAKE_BINARY_DIR}/pandoc-prebuilt")
 add_custom_target("docs" ALL DEPENDS "${OBJ}")
 
+function(rdma_man_get_prebuilt SRC OUT)
+  # If rst2man is not installed then we install the man page from the
+  # pre-built cache directory under buildlib. When the release tar file is
+  # made the man pages are pre-built and included. This is done via install
+  # so that ./build.sh never depends on pandoc, only 'ninja install'.
+  execute_process(
+    COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/buildlib/pandoc-prebuilt.py" --retrieve "${CMAKE_SOURCE_DIR}" "${SRC}"
+    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
+    OUTPUT_VARIABLE OBJ
+    RESULT_VARIABLE retcode)
+  if(NOT "${retcode}" STREQUAL "0")
+    message(FATAL_ERROR "Failed to load prebuilt pandoc output")
+  endif()
+  set(${OUT} "${OBJ}" PARENT_SCOPE)
+endfunction()
+
 function(rdma_md_man_page SRC MAN_SECT MANFN)
   set(OBJ "${CMAKE_CURRENT_BINARY_DIR}/${MANFN}")
 
@@ -18,18 +34,29 @@ function(rdma_md_man_page SRC MAN_SECT MANFN)
     add_custom_target("man-${MANFN}" ALL DEPENDS "${OBJ}")
     add_dependencies("docs" "man-${MANFN}")
   else()
-    # If pandoc is not installed then we install the man page from the
-    # pre-built cache directory under buildlib. When the release tar file is
-    # made the man pages are pre-built and included. This is done via install
-    # so that ./build.sh never depends on pandoc, only 'ninja install'.
-    execute_process(
-      COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/buildlib/pandoc-prebuilt.py" --retrieve "${CMAKE_SOURCE_DIR}" "${SRC}"
+    rdma_man_get_prebuilt(${SRC} OBJ)
+  endif()
+
+  install(FILES "${OBJ}"
+    RENAME "${MANFN}"
+    DESTINATION "${CMAKE_INSTALL_MANDIR}/man${MAN_SECT}/")
+endfunction()
+
+function(rdma_rst_man_page SRC MAN_SECT MANFN)
+  set(OBJ "${CMAKE_CURRENT_BINARY_DIR}/${MANFN}")
+
+  if (RST2MAN_EXECUTABLE)
+    add_custom_command(
+      OUTPUT "${OBJ}"
+      COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/buildlib/pandoc-prebuilt.py" --build "${CMAKE_BINARY_DIR}" --rst "${RST2MAN_EXECUTABLE}" "${SRC}" "${OBJ}"
+      MAIN_DEPENDENCY "${SRC}"
       WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
-      OUTPUT_VARIABLE OBJ
-      RESULT_VARIABLE retcode)
-    if(NOT "${retcode}" STREQUAL "0")
-      message(FATAL_ERROR "Failed to load prebuilt pandoc output")
-    endif()
+      COMMENT "Creating man page ${MANFN}"
+      VERBATIM)
+    add_custom_target("man-${MANFN}" ALL DEPENDS "${OBJ}")
+    add_dependencies("docs" "man-${MANFN}")
+  else()
+    rdma_man_get_prebuilt(${SRC} OBJ)
   endif()
 
   install(FILES "${OBJ}"
@@ -50,6 +77,17 @@ function(rdma_man_pages)
 	"${I}"
 	"${MAN_SECT}"
 	"${BASE_NAME}")
+    elseif ("${I}" MATCHES "\\.in\\.rst$")
+      string(REGEX REPLACE "^.+[.](.+)\\.in\\.rst$" "\\1" MAN_SECT "${I}")
+      string(REGEX REPLACE "^(.+)\\.in\\.rst$" "\\1" BASE_NAME "${I}")
+      get_filename_component(BASE_NAME "${BASE_NAME}" NAME)
+
+      configure_file("${I}" "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}.rst" @ONLY)
+
+      rdma_rst_man_page(
+	"${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}.rst"
+	"${MAN_SECT}"
+	"${BASE_NAME}")
     elseif ("${I}" MATCHES "\\.in$")
       string(REGEX REPLACE "^.+[.](.+)\\.in$" "\\1" MAN_SECT "${I}")
       string(REGEX REPLACE "^(.+)\\.in$" "\\1" BASE_NAME "${I}")
diff --git a/debian/control b/debian/control
index 9fb546ac8999cd..f4480827bf86af 100644
--- a/debian/control
+++ b/debian/control
@@ -16,6 +16,7 @@ Build-Depends: cmake (>= 2.8.11),
                ninja-build,
                pandoc,
                pkg-config,
+               python-docutils,
                python3-dev,
                valgrind [amd64 arm64 armhf i386 mips mips64el mipsel powerpc ppc64 ppc64el s390x]
 Standards-Version: 4.3.0
diff --git a/redhat/rdma-core.spec b/redhat/rdma-core.spec
index ba563a7b87fa4e..ea48fc4e29a36f 100644
--- a/redhat/rdma-core.spec
+++ b/redhat/rdma-core.spec
@@ -20,6 +20,7 @@ BuildRequires: libudev-devel
 BuildRequires: pkgconfig
 BuildRequires: pkgconfig(libnl-3.0)
 BuildRequires: pkgconfig(libnl-route-3.0)
+BuildRequires: python-docutils
 BuildRequires: valgrind-devel
 BuildRequires: systemd
 BuildRequires: systemd-devel
diff --git a/suse/rdma-core.spec b/suse/rdma-core.spec
index d533059603b918..5ddb46aaf8f9cc 100644
--- a/suse/rdma-core.spec
+++ b/suse/rdma-core.spec
@@ -62,6 +62,7 @@ BuildRequires:  pkgconfig(libsystemd)
 BuildRequires:  pkgconfig(libudev)
 BuildRequires:  pkgconfig(systemd)
 BuildRequires:  pkgconfig(udev)
+BuildRequires:  python-docutils
 %if %{with_pyverbs}
 BuildRequires:  python3-Cython
 BuildRequires:  python3-devel
-- 
2.21.0




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Photo]     [Yosemite News]     [Yosemite Photos]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux