@@ -19,6 +19,7 @@ addons:
- make
- ninja-build
- pandoc
+ - python-docutils
- pkg-config
- python
- valgrind
@@ -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()
new file mode 100644
@@ -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)
@@ -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";
@@ -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");
@@ -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}")
@@ -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
@@ -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
@@ -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