install-step fails for pandoc-prebuilt man-pages in infiniband-diags/man

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

 



I tested the following on release 0.26.0 and 0.26.1, with the *.tar.gz
provided on github. It is probably relevant for a lot more released
archives and future releases. My build environment is restricted and
does not have access to pandoc or rst2man.

The command 'ninja install' fails in environments without pandoc and/or
rst2man. There is an automatic fallback to use man-pages in
buildlib/pandoc-prebuilt that are added for every release-archive.
However, the install step fails with error such as:

CMake Error at infiniband-diags/man/cmake_install.cmake:40 (file):
file INSTALL cannot find
"rdma-core-26.0/buildlib/pandoc-prebuilt/64a3de4dd91635b29f4f8d11a987670751827c60".
Call Stack (most recent call first):
cmake_install.cmake:166 (include)

To reproduce the issue, you can try building (and installing) one of the
*.tar.gz releases from github, while preventing the checks in
buildlib/Findpandoc.cmake and /Findrst2man.cmake from finding anything
(e.g. by appending random letters to the searched binary name).

While investigating, I came up with the following explanation: The
hashes (generated by buildlib/pandoc-prebuilt.py) differ from machine to
machine, as the contents of the *.rst-files are hashed. Most of these
files are processed via cmake's configure_file from *.in.rst-files and
contain custom-per-build-data such as absolute paths. This means that
hashing *.rst-files will produce differing hashes based on the
build-directory-path (among other data points, possibly). I tested this
by looking at the hashes produced by two of my machines, they were
different for all but 3 files (ibcacheedit.8.rst, ibstatus.8.rst and
check_lft_balance.8.rst). These files (and their includes, as their
content is also hashed!) are the only files that to not contain any
differing data when being transformed from *.in.rst to *.rst via
configure_file, which supports my hypothesis.

>From my viewpoint, this tells me that

a) many/all released archives do not contain the correct pandoc-prebuilt
files for infiniband-diags/man
b) there is no automated test that builds and installs releases without
pandoc/rst2man present

With my limited time and expertise in the rdma-core project, I was only
able to come up with a solution that I don't find very practical. I will
append a diff of pandoc-prebuilt.py nonetheless, which replaces
hashing-calls for *.rst to *.in.rst if applicable. With these changes,
the hashes for all files are stable between my two machines. I tested
this by building rdma-core with my pandoc-prebuilt.py on a machine with
pandoc+rst2man, which produces the pandoc-prebuilt files. I can copy
those files to buildlib/pandoc-prebuilt on my other machine in the
restricted build environment (that also has my pandoc-prebuilt.py) and
the 'ninja install' step succeeds.

This is probably not the most suitable solution for this problem and I
do NOT consider it fit for production. But maybe it helps someone
understand and/or fix the root issue. Another fix could be to just hash
the filenames instead of their contents.

Thorben

--- rdma-core-26.0/buildlib/pandoc-prebuilt.py  2019-10-02
12:57:38.000000000 +0200
+++ pandoc-prebuilt.py  2019-12-04 15:21:14.755359320 +0100
@@ -6,10 +6,35 @@
 import hashlib
 import re

+# we shouldn't hash *.rst-files, as they can contain absolute paths
after being
+# transformed from an *.in.rst-file via cmake's configure_file. this
leads to
+# differing pandoc-prebuilt-ids from the build process and other build
+# environments that use pandoc-prebuilt (no rst2man and pandoc).
+# this functions instead corrects the filename from *.rst to *.in.rst
+# if applicable (file exists, correct file ext, ...)
+def infile_if_possible(SRC):
+    # only check *.rst files
+    if not SRC.endswith(".rst"):
+        return SRC;
+
+    # already the desired file
+    if SRC.endswith(".in.rst"):
+        return SRC;
+
+    infile = SRC.rsplit(".", 1)[0] + ".in.rst";
+
+    # use *.in.rst file if possible
+    if os.path.exists(infile):
+        return infile;
+
+    # *fallback*, this still leads to the same error
+    # maybe throw / fail here?
+    return SRC;
+
 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:
+        with
open(infile_if_possible(os.path.join(incdir,fn.decode())),"rb") as F:
             h = h +  hashlib.sha1(F.read()).hexdigest();
     return h.encode();

@@ -17,7 +42,7 @@
     """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:
+    with open(infile_if_possible(SRC),"rb") as F:
         txt = F.read();
         if SRC.endswith(".rst"):
             txt = txt + hash_rst_includes(incdir,txt);



[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