Re: Using @bindir@ etc. in C headers

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

 



On Fri, 5 Jun 2020 21:07:32 +1000 Peter Johansson wrote:

> On 5/6/20 8:57 pm, Florian Weimer wrote:
> > I would like to define macros containing the standard paths, like
> > this:
> >
> > #define BINDIR "@bindir@"
> >
> > It does not work due to this code in lib/autoconf/general.m4 (which
> > appears to be predate DESTDIR support):
> >
> > # Installation directory options.
> > # These are left unexpanded so users can "make install exec_prefix=/foo"
> > # and all the variables that are supposed to be based on exec_prefix
> > # by default will actually change.
> > # Use braces instead of parens because sh, perl, etc. also accept them.
> > # (The list follows the same order as the GNU Coding Standards.) 
> > AC_SUBST([bindir],         ['${exec_prefix}/bin'])dnl
> > AC_SUBST([sbindir],        ['${exec_prefix}/sbin'])dnl
> >
> > Is there are generally approved way to work around this?  The manual
> > tells us to use -D preprocessor arguments, but I'd prefer the
> > explicitness of defining the macros via a header file.  
> 
> I have the following in my Makefile.am, which I believe I borrowed
> from the manual of autoconf or automake. BUILT_SOURCES makes the
> header file be created before any compilation and CLEANFILES makes
> the header file be removed by 'make clean'.
> 
> CLEANFILES += configmake.h
> 
> BUILT_SOURCES += configmake.h
> 
> configmake.h: Makefile
>      echo '#define BINDIR "$(bindir)"' >$@

The above is basically the example from Automake.info subsection "Built
Sources Example".

Note that the above will *NOT* rebuild if a different bindir value is
given on the make command line like "make bindir=/foo/bin".

Note also that the above *WILL* cause a rebuild of configmake.h and of
everything depending on configmake.h every time Makefile has changed
for any reason whatsoever, even if the content of configmake.h has not
changed at all.

AFAICT, those two issues discount it for Florian Weimer's use case.

I have solved similar problems in the past with a dummy stamp file
using Automake BUILD_SOURCES and cmp(1). I cannot remember where I
picked up that idea, though.

Sorry for bringing more Automake stuff to the autoconf list, but it
should be possible to adapt the following approach to
Autoconf-without-Automake buildsystems by basically adding
install-paths.stamp at the beginning of the dependency list of the
"all", "check", and "install" targets.

If you want to see the following approach in an example package, you can

    git clone https://github.com/ndim/automake-install-paths-test.git

and follow the example build commands in README.md.

dnl configure.ac snippet
AC_ARG_VAR([CMP], [cmp file compare program])
AC_PATH_PROG([CMP], [cmp], [false])
AS_IF([test "x$CMP" = "xfalse"],
      [AC_MSG_ERROR([CMP must be a cmp program])])

# Makefile.am snippet
CLEANFILES    += install-paths.h
CLEANFILES    += install-paths.stamp
BUILT_SOURCES += install-paths.stamp
install-paths.stamp:
	echo '/* Autogenerated file. Do not modify. */' > install-paths.h.tmp
	echo '#define BINDIR "$(bindir)"' >> install-paths.h.tmp
	@if test -f install-paths.h \
	    && $(CMP) install-paths.h.tmp install-paths.h; then \
	  echo "Not updating install-paths.h: it is up to date"; \
	  rm -f install-paths.h.tmp; \
	else \
	  echo "Updating install-paths.h"; \
	  mv -f install-paths.h.tmp install-paths.h; \
	fi

This uses the bindir value which make actually uses, whether that
value is defined in Makefile or given on the make command line.

This also only updates the install-paths.h file if it has actually
changed, whether that is because the value of bindir has changed or
whether we have just added another foobardir to install-paths.h with
another "echo" line. Unrelated changes to Makefile will not cause a
rebuild of install-paths.h and thus everything depending on
install-paths.h will not be rebuilt either.

Disadvantage: This requires a "cmp" program at build time. If we were to
ignore the absence of a "cmp" program, we would need to either never
update the install-paths.h file (even if it would have changed) or
always update the install-paths.h file (even if it has not changed).
The former would work for single one-off builds where bindir does not
change, the latter would always trigger a rebuild on "make install".

So the existence of a file comparison program is imperative for this,
and cmp(1) appears to be the tool for the job and can probably be
considered a standard tool. If there is no cmp(1) available, one could
try falling back onto diff(1) or system specific tools.

Please keep in mind the Automake section on Built Sources for when
install-paths.stamp target is built: "make all", "make check", and
"make install" will all update install-paths.h *if it has changed* and
thus trigger a rebuild for whatever depends on install-paths.h.

If you want to trigger the install-paths.stamp target for executable or
library targets, things will become more complicated very quickly. See
also the discussion in the Automake.info subsection "Built Sources
Example". Personally, I think the other methods generating a header
file cause more headaches than the restriction to "make all", "make
check", and "make install" causes.

Calling the rule "install-paths.stamp" with a trailing ".stamp" might
be considered a bit misleading as this stamp file target never
generates an actual stamp file.

This method of having a dummy BUILT_SOURCES stamp file updating an
actual source file based on content with a cmp(1) comparison has
served me very well during the last few years, but I am not certain how
"generally accepted" this method is.

Uli





[Index of Archives]     [GCC Help]     [Kernel Discussion]     [RPM Discussion]     [Red Hat Development]     [Yosemite News]     [Linux USB]     [Samba]

  Powered by Linux