doxygenautotoolsautomake

How to correctly use both Doxygen and GNU Autotools together


I wish to use the GNU build system to automatically compile C++ documentation with Doxygen and then install the resulting html and PDF. I found the following m4 script (ax_prog_doxygen) that is designed to help with using Doxygen inside of autotools: https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html

I am having two related issues:

(1) The Doxygen configuration file specifies source code path INPUT relative to where doxygen was run from. My concern is that I don't necessarily know where someone's relative build directory will reside, relative to the source code. (2) I'm unable to get the resulting documents (doxygen config "OUTPUT_DIRECTORY") paths to correctly install after they are built. My OUTPUT_DIRECTORY is within the build directory (presumably desirable) but autotools _DATA target seems to always prepend the relative path between my build directory and the top level source code.

First, to get the m4 doxygen script plugged in, I've setup my configure.ac file as below.

DX_HTML_FEATURE(ON)
DX_CHM_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
DX_MAN_FEATURE(OFF)
DX_RTF_FEATURE(OFF)
DX_XML_FEATURE(OFF)
DX_PDF_FEATURE(ON)
DX_PS_FEATURE(OFF)

DX_INIT_DOXYGEN([$PACKAGE_NAME], [$(top_srcdir)/Doxygen.config], [doc/doxygen])

I've kept a Doxygen.config file in the top-level directory. Additionally, I ask the macro to write to doc/doxygen, which I believe will reside in the build directory.

To be consistent with the build directory, inside Doxygen.config I've specified: OUTPUT_DIRECTORY = doc/doxygen

Finally, I've made minor modifications to Makefile.am, basically crudely clobbering things together from other stack overflow posts and a very minimal understanding of the autotools manuals.

EXTRA_DIST=Doxygen.config

# include Doxygen rules (requires autoconf-archive >2016-03-20)
@DX_RULES@

clean-local:
        -rm -rf doc/doxygen/*

doxygen-prepare:
        mkdir -p doc/doxygen

docs: doxygen-prepare doxygen-doc

# Try to tell autotools to install documentation
htmldir = $(docdir)/html
latexdir = $(docdir)/latex
html_DATA = $(abs_top_builddir)/doc/doxygen/html
latex_DATA = $(abs_top_builddir)/doc/doxygen/latex

Finally, my test case is this. I create a build directory within my package (arbitrarily), here: $(top_srcdir)/my_compile. To get past my first roadblock, I edited Doxygen.config to set INPUT = ../src (where all my source code is kept). edit: I use a plain vanilla configure command:

    ../configure --prefix=/u/software/project/

I can then successfully build documentation within $(top_srcdir)/my_compile directory using 'make docs' followed by 'make' to build the software.

edit: I've since noticed that if I instead first run 'make', I end up with the following interesting error that may or may not be related to this.

make[2]: *** No rule to make target `/u/project/mycompile/doc/doxygen/html', needed by `all-am'.  Stop.

If I instead run 'make docs', then 'make', this error does not appear but upon 'make install', the following happens.

make[2]: Entering directory `/u/project/mycompile'
make[2]: Nothing to be done for `install-exec-am'.
 /usr/bin/mkdir -p '/u/software/project/share/doc/project/html'
 /usr/bin/install -c -m 644 ../u/project/mycompile/doc/doxygen/html '/u/software/project/share/doc/project/html'
/usr/bin/install: cannot stat ‘../u/project/mycompile/doc/doxygen/html’: No such file or directory
make[2]: *** [install-htmlDATA] Error 1
make[2]: Leaving directory `/u/project/mycompile'

It fails because the absolute path to my build directory has be prepended with "../", presumably because this locally points from my build directory to $(top_srcdir).

I assume both these problems could be resolved within Makefile.am. My thoughts to resolve problems:

(1) Create a templated version of Doxygen.config and write a new version of the file within the build directory that corrects the INPUT directory (e.g., setting it to something like $(abs_top_srcdir)/src). I suspect I could probably figure this out but I'm not sure it's the philosophy "right" approach.

(2) I could set Doxygen's "OUTPUT_DIRECTORY" to a directory resides outside the build directory (e.g, $(top_srcdir)/my_docs). That would appear to create two follow-on problems: (a) once again, I don't know the relative path to $(top_srcdir) a priori (i.e., another version of problem (1)); and (b), it seems ugly to be essentially compiling documentation outside the build directory.

Any tips are most welcome.


Solution

  • I assume both these problems could be resolved within Makefile.am.

    Yes, but that's not necessarily the best alternative in all cases.

    My thoughts to resolve problems:

    (1) Create a templated version of Doxygen.config and write a new version of the file within the build directory that corrects the INPUT directory (e.g., setting it to something like $(abs_top_srcdir)/src). I suspect I could probably figure this out but I'm not sure it's the philosophy "right" approach.

    Generating a customized Doxyfile (by whatever name) from a template is exactly the kind of thing that Autoconf is built to do. That's how it creates your makefile(s), and it can as easily do the same for your Doxygen config or for other files. That or something analogous is what I would do, and have done in the past.

    To do that with Autoconf, add your doxyfile to the AC_CONFIG_FILES list in your configure.ac, and provide a template for it whose name is formed by appending .in. Inside, you can use symbols of the form @top_srcdir@ as placeholders for the values of Autoconf output variables.

    Also, files built by configure should be cleaned during distclean. To provide for that, add the built Doxyfile's name to the value of variable DISTCLEAN_FILES in your Makefile.am.

    (2) I could set Doxygen's "OUTPUT_DIRECTORY" to a directory resides outside the build directory (e.g, $(top_srcdir)/my_docs) [...]

    You should start by understanding the nature of the problem. The fundamental issue here is that Automake requires all items specified in installation variables to be regular files, but you are specifying a directory.

    That misuse runs afoul of an Automake convenience feature: Automake supports installing data files from the source directory even when you perform an out-of-source build. To achieve that, for each file on the install list, it first looks for a regular file of the designated name in the build directory. If it does not find such a (regular) file then it tries to install from the source directory instead, by prepending the source directory path captured when you ran configure. That appears to be what you are observing.

    I do not recommend building documentation to a location outside the build directory. That will cause more problems than it solves. You probably don't want to try name all the regular files in the generated HTML documentation, either. You need a different approach: instead of using html_DATA to specify what HTML documentation to install, write a local install rule in your Makefile.am. Perhaps something like this:

    # ...
    
    # This target name is an Automake extension point:
    install-data-local: install-html-docs
    
    install-html-docs:
            mkdir -p $(DESTDIR)$(htmldir)
            cp -r doc/doxygen/html/* $(DESTDIR)$(htmldir)
            chmod -R go+rX $(DESTDIR)$(htmldir)
    
    .PHONY: install-html-docs