FreeIPA and the 'subdir-objects' option


The subject of this blog post will be FreeIPA Ticket #5873, a request to fix the warning messages produced when compiling FreeIPA:

automake: warning: possible forward-incompatibility.
automake: At least a source file is in a subdirectory, but the 'subdir-objects'
automake: automake option hasn't been enabled.  For now, the corresponding output
automake: object file(s) will be placed in the top-level directory.  However,
automake: this behaviour will change in future Automake versions: they will
automake: unconditionally cause object files to be placed in the same subdirectory
automake: of the corresponding sources.
automake: You are advised to start using 'subdir-objects' option throughout your
automake: project, to avoid future incompatibilities.

Step 1: Add 'subdir-objects'

It says we should enable the subdir-objects option, so let's try it:

diff --git a/client/configure.ac b/client/configure.ac
index 58f23af..a97edd1 100644
--- a/client/configure.ac
+++ b/client/configure.ac
@@ -8,7 +8,7 @@ LT_INIT
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])

 AM_MAINTAINER_MODE

diff --git a/daemons/configure.ac b/daemons/configure.ac
index 2906def..8dce469 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -7,7 +7,7 @@ AC_INIT([ipa-server],
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])

 AM_MAINTAINER_MODE

And the result:

make[1]: Entering directory '/home/blipton/src/freeipa/dist/freeipa-4.3.90.201606021746GIT63b597d/client'
Makefile:704: ../util/.deps/ipa_krb5.Po: No such file or directory

So what's happening here? If we search for the missing file:

$ find -name ipa_krb5.Po
./client/$(KRB5_UTIL_DIR)/.deps/ipa_krb5.Po

we see that it's in a very odd place, a directory literally named $(KRB5_UTIL_DIR). It turns out this is a known issue with automatic dependency tracking in automake, discussed extensively in this bug report. Basically, the config.status script (which generates Makefile from Makefile.in) is directly parsing the makefile, looking for lines that include makefiles under $(DEPDIR). It uses sed to replace $(DEPDIR) with .deps, but any other variables in the line are taken verbatim. Therefore, if the SOURCES line from which this is derived includes, say, $(KRB5_UTIL_DIR)/ipa_krb5.c, config.status ends up making the oddly-named directory mentioned above.

Step 2: No variables in paths

Ok, so we can't use variable references in our SOURCES. What if we expand all the variables, like this?

diff --git a/client/Makefile.am b/client/Makefile.am
index 3d135a3..3c9f4bb 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -13,7 +13,7 @@ endif
 export AM_CFLAGS

 KRB5_UTIL_DIR=../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
+KRB5_UTIL_SRCS=../util/ipa_krb5.c
 ASN1_UTIL_DIR=../asn1
 IPA_CONF_FILE=$(sysconfdir)/ipa/default.conf

diff --git a/client/configure.ac b/client/configure.ac
index 58f23af..a97edd1 100644
--- a/client/configure.ac
+++ b/client/configure.ac
@@ -8,7 +8,7 @@ LT_INIT
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])

 AM_MAINTAINER_MODE

diff --git a/daemons/configure.ac b/daemons/configure.ac
index 2906def..8dce469 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -7,7 +7,7 @@ AC_INIT([ipa-server],
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])

 AM_MAINTAINER_MODE
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index a4ea366..a4a970a 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -2,8 +2,8 @@ NULL =

 KRB5_UTIL_DIR = ../../util
 IPA_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c
+KRB5_UTIL_SRCS = ../../util/ipa_krb5.c \
+        ../../util/ipa_pwd.c

 AM_CPPFLAGS =                      \
    -I.                     \
diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
index ea14661..66ffdff 100644
--- a/daemons/ipa-sam/Makefile.am
+++ b/daemons/ipa-sam/Makefile.am
@@ -7,7 +7,7 @@ SAMBA40EXTRA_LIBS = $(SAMBA40EXTRA_LIBPATH) \
            $(NULL)

 KRB5_UTIL_DIR=../../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_SRCS=../../util/ipa_krb5.c ../../util/ipa_pwd_ntlm.c
 ASN1_UTIL_DIR=../../asn1

 AM_CPPFLAGS =                      \
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
index 46a6491..cf0ffbd 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
@@ -3,9 +3,9 @@ NULL =
 MAINTAINERCLEANFILES = *~ Makefile.in
 PLUGIN_COMMON_DIR = ../common
 KRB5_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_SRCS = ../../../util/ipa_krb5.c \
+        ../../../util/ipa_pwd.c \
+        ../../../util/ipa_pwd_ntlm.c
 ASN1_UTIL_DIR=../../../asn1

 AM_CPPFLAGS =                          \

Now we have a different problem:

Making distclean in ipa-pwd-extop
make[3]: Entering directory '/home/blipton/src/freeipa/dist/freeipa-4.3.90.201606021827GIT4becc18/daemons/ipa-slapi-plugins/ipa-pwd-extop'
Makefile:535: ../../../util/.deps/ipa_krb5.Plo: No such file or directory
Makefile:536: ../../../util/.deps/ipa_pwd.Plo: No such file or directory
Makefile:537: ../../../util/.deps/ipa_pwd_ntlm.Plo: No such file or directory
make[3]: *** No rule to make target '../../../util/.deps/ipa_pwd_ntlm.Plo'.  Stop.

Here it turns out that because util/.deps is used by more than one Makefile in the subdirectories of daemons, it is being removed by make distclean running in the daemons/ipa-kdb directory, and then once make reaches the daemons/ipa-slapi-plugins/ipa-pwd-extop directory the needed Plo files aren't there anymore. There is a commit that claims to fix this issue, but I'm not certain it will be ok with the same file being referenced by multiple SOURCES directives, it's not included in any released version of automake anyway. So, we're going to need to try something else.

Step 3: Utils gets its own configure file

It seems we're having issues because multiple projects want to build and clean up the same files. So maybe it would be better to make utils its own project, repsonsible for building the files within that directory, and simply have the other projects depend on it. This is the same as what happens in the asn1 directory of the source tree. The following patch implements this approach:

diff --git a/Makefile b/Makefile
index 210b7ac..6e00220 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@

 include VERSION

-SUBDIRS=asn1 daemons install ipapython ipalib
+SUBDIRS=util asn1 daemons install ipapython ipalib
 CLIENTDIRS=ipapython ipalib client asn1
 CLIENTPYDIRS=ipaclient ipaplatform

diff --git a/client/Makefile.am b/client/Makefile.am
index 3d135a3..afc2977 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -13,7 +13,7 @@ endif
 export AM_CFLAGS

 KRB5_UTIL_DIR=../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
+KRB5_UTIL_LIBS=../util/ipa_krb5.la
 ASN1_UTIL_DIR=../asn1
 IPA_CONF_FILE=$(sysconfdir)/ipa/default.conf

@@ -52,7 +52,6 @@ sbin_SCRIPTS =            \
 ipa_getkeytab_SOURCES =        \
    ipa-getkeytab.c     \
    ipa-client-common.c \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipa_getkeytab_LDADD =      \
@@ -63,6 +62,7 @@ ipa_getkeytab_LDADD =         \
    $(POPT_LIBS)        \
    $(LIBINTL_LIBS)         \
    $(INI_LIBS)     \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 ipa_rmkeytab_SOURCES =     \
diff --git a/client/configure.ac b/client/configure.ac
index 58f23af..836cac4 100644
--- a/client/configure.ac
+++ b/client/configure.ac
@@ -6,9 +6,9 @@ AC_INIT([ipa-client],
 LT_INIT

 AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_SUBDIRS([../asn1])
+AC_CONFIG_SUBDIRS([../util ../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])

 AM_MAINTAINER_MODE

diff --git a/daemons/configure.ac b/daemons/configure.ac
index 2906def..f27312f 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -5,9 +5,9 @@ AC_INIT([ipa-server],
         [https://hosted.fedoraproject.org/projects/freeipa/newticket])

 AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_SUBDIRS([../asn1])
+AC_CONFIG_SUBDIRS([../util ../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])

 AM_MAINTAINER_MODE
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index a4ea366..2f8bcfb 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -2,8 +2,8 @@ NULL =

 KRB5_UTIL_DIR = ../../util
 IPA_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c
+KRB5_UTIL_LIBS = ../../util/ipa_krb5.la \
+        ../../util/ipa_pwd.la

 AM_CPPFLAGS =                      \
    -I.                     \
@@ -39,7 +39,6 @@ ipadb_la_SOURCES =        \
    ipa_kdb_mspac.c     \
    ipa_kdb_delegation.c    \
    ipa_kdb_audit_as.c  \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipadb_la_LDFLAGS =         \
@@ -53,6 +52,7 @@ ipadb_la_LIBADD =         \
    $(NDRPAC_LIBS)      \
    $(UNISTRING_LIBS)   \
    $(NSS_LIBS)             \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 if HAVE_CMOCKA
@@ -71,7 +71,6 @@ ipa_kdb_tests_SOURCES =        \
        ipa_kdb_mspac.c         \
        ipa_kdb_delegation.c    \
        ipa_kdb_audit_as.c      \
-       $(KRB5_UTIL_SRCS)       \
        $(NULL)
 ipa_kdb_tests_CFLAGS = $(CMOCKA_CFLAGS)
 ipa_kdb_tests_LDADD =          \
@@ -81,6 +80,7 @@ ipa_kdb_tests_LDADD =          \
        $(NDRPAC_LIBS)          \
        $(UNISTRING_LIBS)       \
        $(NSS_LIBS)             \
+       $(KRB5_UTIL_LIBS)       \
        -lkdb5                  \
        -lsss_idmap             \
        $(NULL)
diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
index ea14661..17d77aa 100644
--- a/daemons/ipa-sam/Makefile.am
+++ b/daemons/ipa-sam/Makefile.am
@@ -7,7 +7,7 @@ SAMBA40EXTRA_LIBS = $(SAMBA40EXTRA_LIBPATH) \
            $(NULL)

 KRB5_UTIL_DIR=../../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_LIBS=../../util/ipa_krb5.la ../../util/ipa_pwd_ntlm.la
 ASN1_UTIL_DIR=../../asn1

 AM_CPPFLAGS =                      \
@@ -39,7 +39,6 @@ plugin_LTLIBRARIES =      \

 ipasam_la_SOURCES =        \
    ipa_sam.c       \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipasam_la_LDFLAGS =        \
@@ -57,6 +56,7 @@ ipasam_la_LIBADD =        \
    $(SAMBA40EXTRA_LIBS)    \
    $(SSSIDMAP_LIBS)    \
    $(ASN1_UTIL_DIR)/libipaasn1.la  \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 EXTRA_DIST =           \
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
index 46a6491..50c9c66 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
@@ -3,9 +3,9 @@ NULL =
 MAINTAINERCLEANFILES = *~ Makefile.in
 PLUGIN_COMMON_DIR = ../common
 KRB5_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_LIBS = ../../../util/ipa_krb5.la \
+        ../../../util/ipa_pwd.la \
+        ../../../util/ipa_pwd_ntlm.la
 ASN1_UTIL_DIR=../../../asn1

 AM_CPPFLAGS =                          \
@@ -41,6 +41,7 @@ plugin_LTLIBRARIES = libipa_pwd_extop.la
 libipa_pwd_extop_la_LIBADD  = \
    $(builddir)/../libotp/libotp.la \
    $(ASN1_UTIL_DIR)/libipaasn1.la  \
+   $(KRB5_UTIL_LIBS)       \
    $(NULL)
 libipa_pwd_extop_la_SOURCES =      \
    common.c            \
@@ -48,7 +49,6 @@ libipa_pwd_extop_la_SOURCES =         \
    prepost.c           \
    ipa_pwd_extop.c         \
    otpctrl.c           \
-   $(KRB5_UTIL_SRCS)       \
    $(NULL)

 appdir = $(IPA_DATA_DIR)
diff --git a/util/Makefile.am b/util/Makefile.am
new file mode 100644
index 0000000..a848a7c
--- /dev/null
+++ b/util/Makefile.am
@@ -0,0 +1,8 @@
+#AM_CPPFLAGS = -I../util -Iasn1c
+
+noinst_LTLIBRARIES=libipa_krb5.la libipa_pwd.la libipa_pwd_ntlm.la
+noinst_HEADERS=ipa_krb5.h ipa_mspac.h ipa_pwd.h
+
+libipa_krb5_la_SOURCES=ipa_krb5.c
+libipa_pwd_la_SOURCES=ipa_pwd.c
+libipa_pwd_ntlm_la_SOURCES=ipa_pwd_ntlm.c
diff --git a/util/configure.ac b/util/configure.ac
new file mode 100644
index 0000000..2b323c1
--- /dev/null
+++ b/util/configure.ac
@@ -0,0 +1,23 @@
+AC_PREREQ(2.59)
+m4_include(../version.m4)
+AC_INIT([ipa-server],
+        IPA_VERSION,
+        [https://hosted.fedoraproject.org/projects/freeipa/newticket])
+
+AC_CONFIG_HEADERS([config.h])
+AC_PROG_CC_C99
+LT_INIT
+
+AM_INIT_AUTOMAKE([foreign])
+
+AM_MAINTAINER_MODE
+
+AC_SUBST(VERSION)
+
+# Files
+
+AC_CONFIG_FILES([
+    Makefile
+])
+
+AC_OUTPUT

But being its own project means that the utils directory is now responsible for handling its own dependencies, which was previously done by the configure.ac files in the client and daemons directories. So with the simple utils/configure.ac file introduced by this patch, the build fails due to missing dependencies:

In file included from ipa_pwd_ntlm.c:30:0:
/usr/include/dirsrv/slapi-plugin.h:30:21: fatal error: prtypes.h: No such file or directory
compilation terminated.
Makefile:427: recipe for target 'ipa_pwd_ntlm.lo' failed

We might be able to make this work by copying the necessary dependencies into the new configure.ac file. However, adding the maintenance burden of another configure script seems undesirable, so let's see if we can take advantage of the work that's already being done by the existing configure scripts.

Step 4: Old configure, new makefile

Configure scripts can generate more than one Makefile by adjusting the AC_CONFIG_FILES definition within configure.ac. So instead of giving utils its own configure script, what if we just make the packages that need it responsible for generating its Makefile themselves? The following patch does this:

diff --git a/Makefile b/Makefile
index 210b7ac..6e00220 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@

 include VERSION

-SUBDIRS=asn1 daemons install ipapython ipalib
+SUBDIRS=util asn1 daemons install ipapython ipalib
 CLIENTDIRS=ipapython ipalib client asn1
 CLIENTPYDIRS=ipaclient ipaplatform

diff --git a/client/Makefile.am b/client/Makefile.am
index 3d135a3..afc2977 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -13,7 +13,7 @@ endif
 export AM_CFLAGS

 KRB5_UTIL_DIR=../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c
+KRB5_UTIL_LIBS=../util/ipa_krb5.la
 ASN1_UTIL_DIR=../asn1
 IPA_CONF_FILE=$(sysconfdir)/ipa/default.conf

@@ -52,7 +52,6 @@ sbin_SCRIPTS =            \
 ipa_getkeytab_SOURCES =        \
    ipa-getkeytab.c     \
    ipa-client-common.c \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipa_getkeytab_LDADD =      \
@@ -63,6 +62,7 @@ ipa_getkeytab_LDADD =         \
    $(POPT_LIBS)        \
    $(LIBINTL_LIBS)         \
    $(INI_LIBS)     \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 ipa_rmkeytab_SOURCES =     \
diff --git a/client/configure.ac b/client/configure.ac
index 58f23af..4ca9caf 100644
--- a/client/configure.ac
+++ b/client/configure.ac
@@ -8,7 +8,7 @@ LT_INIT
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])

 AM_MAINTAINER_MODE

@@ -220,6 +220,7 @@ dnl ---------------------------------------------------------------------------

 AC_CONFIG_FILES([
     Makefile
+    ../util/Makefile
     ../asn1/Makefile
     man/Makefile
 ])
diff --git a/daemons/configure.ac b/daemons/configure.ac
index 2906def..761c15c 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -7,7 +7,7 @@ AC_INIT([ipa-server],
 AC_CONFIG_HEADERS([config.h])
 AC_CONFIG_SUBDIRS([../asn1])

-AM_INIT_AUTOMAKE([foreign])
+AM_INIT_AUTOMAKE([foreign subdir-objects])
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])

 AM_MAINTAINER_MODE
@@ -332,6 +332,7 @@ AC_SUBST(LDFLAGS)
 AC_CONFIG_FILES([
     Makefile
     ../asn1/Makefile
+    ../util/Makefile
     ipa-kdb/Makefile
     ipa-sam/Makefile
     ipa-otpd/Makefile
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index a4ea366..2f8bcfb 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -2,8 +2,8 @@ NULL =

 KRB5_UTIL_DIR = ../../util
 IPA_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c
+KRB5_UTIL_LIBS = ../../util/ipa_krb5.la \
+        ../../util/ipa_pwd.la

 AM_CPPFLAGS =                      \
    -I.                     \
@@ -39,7 +39,6 @@ ipadb_la_SOURCES =        \
    ipa_kdb_mspac.c     \
    ipa_kdb_delegation.c    \
    ipa_kdb_audit_as.c  \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipadb_la_LDFLAGS =         \
@@ -53,6 +52,7 @@ ipadb_la_LIBADD =         \
    $(NDRPAC_LIBS)      \
    $(UNISTRING_LIBS)   \
    $(NSS_LIBS)             \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 if HAVE_CMOCKA
@@ -71,7 +71,6 @@ ipa_kdb_tests_SOURCES =        \
        ipa_kdb_mspac.c         \
        ipa_kdb_delegation.c    \
        ipa_kdb_audit_as.c      \
-       $(KRB5_UTIL_SRCS)       \
        $(NULL)
 ipa_kdb_tests_CFLAGS = $(CMOCKA_CFLAGS)
 ipa_kdb_tests_LDADD =          \
@@ -81,6 +80,7 @@ ipa_kdb_tests_LDADD =          \
        $(NDRPAC_LIBS)          \
        $(UNISTRING_LIBS)       \
        $(NSS_LIBS)             \
+       $(KRB5_UTIL_LIBS)       \
        -lkdb5                  \
        -lsss_idmap             \
        $(NULL)
diff --git a/daemons/ipa-sam/Makefile.am b/daemons/ipa-sam/Makefile.am
index ea14661..17d77aa 100644
--- a/daemons/ipa-sam/Makefile.am
+++ b/daemons/ipa-sam/Makefile.am
@@ -7,7 +7,7 @@ SAMBA40EXTRA_LIBS = $(SAMBA40EXTRA_LIBPATH) \
            $(NULL)

 KRB5_UTIL_DIR=../../util
-KRB5_UTIL_SRCS=$(KRB5_UTIL_DIR)/ipa_krb5.c $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_LIBS=../../util/ipa_krb5.la ../../util/ipa_pwd_ntlm.la
 ASN1_UTIL_DIR=../../asn1

 AM_CPPFLAGS =                      \
@@ -39,7 +39,6 @@ plugin_LTLIBRARIES =      \

 ipasam_la_SOURCES =        \
    ipa_sam.c       \
-   $(KRB5_UTIL_SRCS)   \
    $(NULL)

 ipasam_la_LDFLAGS =        \
@@ -57,6 +56,7 @@ ipasam_la_LIBADD =        \
    $(SAMBA40EXTRA_LIBS)    \
    $(SSSIDMAP_LIBS)    \
    $(ASN1_UTIL_DIR)/libipaasn1.la  \
+   $(KRB5_UTIL_LIBS)   \
    $(NULL)

 EXTRA_DIST =           \
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
index 46a6491..50c9c66 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile.am
@@ -3,9 +3,9 @@ NULL =
 MAINTAINERCLEANFILES = *~ Makefile.in
 PLUGIN_COMMON_DIR = ../common
 KRB5_UTIL_DIR = ../../../util
-KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd.c \
-        $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
+KRB5_UTIL_LIBS = ../../../util/ipa_krb5.la \
+        ../../../util/ipa_pwd.la \
+        ../../../util/ipa_pwd_ntlm.la
 ASN1_UTIL_DIR=../../../asn1

 AM_CPPFLAGS =                          \
@@ -41,6 +41,7 @@ plugin_LTLIBRARIES = libipa_pwd_extop.la
 libipa_pwd_extop_la_LIBADD  = \
    $(builddir)/../libotp/libotp.la \
    $(ASN1_UTIL_DIR)/libipaasn1.la  \
+   $(KRB5_UTIL_LIBS)       \
    $(NULL)
 libipa_pwd_extop_la_SOURCES =      \
    common.c            \
@@ -48,7 +49,6 @@ libipa_pwd_extop_la_SOURCES =         \
    prepost.c           \
    ipa_pwd_extop.c         \
    otpctrl.c           \
-   $(KRB5_UTIL_SRCS)       \
    $(NULL)

 appdir = $(IPA_DATA_DIR)
diff --git a/util/Makefile.am b/util/Makefile.am
new file mode 100644
index 0000000..a848a7c
--- /dev/null
+++ b/util/Makefile.am
@@ -0,0 +1,8 @@
+#AM_CPPFLAGS = -I../util -Iasn1c
+
+noinst_LTLIBRARIES=libipa_krb5.la libipa_pwd.la libipa_pwd_ntlm.la
+noinst_HEADERS=ipa_krb5.h ipa_mspac.h ipa_pwd.h
+
+libipa_krb5_la_SOURCES=ipa_krb5.c
+libipa_pwd_la_SOURCES=ipa_pwd.c
+libipa_pwd_ntlm_la_SOURCES=ipa_pwd_ntlm.c

But this ends badly too:

make[2]: Entering directory '/home/blipton/src/freeipa/rpmbuild/BUILD/freeipa-4.3.90.201606132126GIT475c6bc/util'
cd ../.. && make  am--refresh

Notice that make is trying to change to a directory outside of the build directory. No surprise that it doesn't find a Makefile there. What's going on?

The cd is triggered by one of several makefile lines that run

cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh

and in the same Makefile, top_builddir is defined to be ../... Since this build is actually taking place in the client subdirectory, the correct relative path would be ../client. But if we look at the code in config.status, we see:

ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
# A ".." for each directory in $ac_dir_suffix.
ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`

As the comment says, this looks at the relative path from the configure script to the Makefile (in this case ../util/Makefile), and replaces each directory component with ... This makes sense when the Makefile is within the same source tree (i.e. when the Makefile is "two levels deep", the path should be ../..) but with the Makefile external to the configure tree, it doesn't work at all. Since this code is directly generated by automake, there doesn't seem to be much we can do about this bad behavior.

Step N: do we really need to fix this now?

One interesting option to consider would be to replace these relative paths with absolute ones based on one of the variables defined in the Makefile automatically, such as $(top_srcdir). It is possible that the logic in config.status would handle these paths better as they wouldn't include any ... However, thanks to the bug discussed way back in Step 1, variable references in SOURCES don't work correctly! So that's probably no help either.

According to a message on the automake mailing list, this bug is being considered a blocker for the release of automake 2.0, so despite the scary compatibility warning in the output, we shouldn't be forced to use subdir-objects until the handling of it is fixed. In fact, there are patches in the automake repository that are supposed to fix the bug, but the last automake release was over a year ago, so no distros are using those patches and I haven't tested against them. Since there seems to be no good way to add this option until automake 1.16, and not having the option won't break anything until automake 2.0, it may be easiest to just leave it alone for now.