Search code examples
autoconfautomake

custom object rules inside Makefile.am for automake


Typical makefile.am, which works, would look like this for my project:

noinst_LTLIBRARIES = libwinsane.la

CLEANFILES = init.cpp

libwinsane_la_CXXFLAGS = \
  -I$(top_srcdir)
libwinsane_la_SOURCES = \
  init.cpp
noinst_HEADERS = \
  init.h

the issue is that I need to also process resource files. I need to use something like this:

noinst_LTLIBRARIES = libwinsane.la

libwinsane.o: init.o manifest.o
    ld -relocatable -o $@ init.o manifest.o

manifest.o: manifest.rc utf8.xml
    windres -o $@ manifest.rc

clean:
    rm -f init.o manifest.o libwinsane.o

While this last example is valid makefile by itself (except noinst_LIBRARIES), its obviously wrong syntax for automake. But maybe there is a way for automake to just accept it and produce library in the end somehow?


Solution

  • Off the top of my head, and without 100% verifying its consistency with https://www.gnu.org/software/automake/manual/html_node/Program-and-Library-Variables.html or testing it, something like this should work more or less:

    CLEANFILES =
    
    noinst_LTLIBRARIES          = libwinsane.la
    libwinsane_la_SOURCES       =
    libwinsane_la_SOURCES      += init.cpp
    libwinsane_la_SOURCES      += init.h
    libwinsane_la_CXXFLAGS      = -I$(top_srcdir)
    
    libwinsane_la_DEPENDENCIES  = manifest.$(OBJEXT)
    libwinsane_la_LIBADD        = manifest.$(OBJEXT)
    CLEANFILES                 += manifest.$(OBJEXT)
    manifest.$(OBJEXT): manifest.rc utf8.xml
            windres -o $@ $(srcdir)/manifest.rc
    

    A few additional remarks:

    • The windres recipe probably does not work for out of source builds if utf8.xml has not just been buitl in $(builddir) and is therefore located in $(srcdir). Adding something like -I $(srcdir) to the windres command line will probably fix this, but cannot verify that without a MWE.
    • You will want to make windres configurable and replace the hard coded windres call by $(WINDRES), made user configurable by AC_ARG_VAR and (if $WINDRES has not been set) AC_CHECK_TOOL, and probably protected with a check in configure.ac that $WINDRES actually works. Depending on your project you can then either AC_MSG_ERROR(...) in case $WINDRES does not work, or AM_CONDITIONAL([HAVE_WINDRES], ...) and then put the Makefile.am parts related to manifest.$(OBJEXT) inside a if HAVE_WINDRES / endif conditional. The actual windres command might be called something like x86_64-w64-mingw32-windres when cross-compiling.
    • Why do you have CLEANFILES += init.cpp? I have left that out, as you do not want make clean to delete your source files. Or does init.cpp belong to BUILT_SOURCES?

    Update: Apparently, I have overlooked something for compiling and linking with libtool: cannot build libtool library from non-libtool objects - any workaround?