build: support UsrMerge and Bin-Sbin merge with automatic detection

Introduce a new build-time option --enable-usrmerge to support modern
Linux distributions following the "UsrMerge" and "Bin-Sbin merge"
schemes.

Traditional systems install core binaries to /sbin, while UsrMerge
systems use /usr/sbin. The latest distributions (e.g., Fedora Rawhide)
are further unifying these into /usr/bin.

Key changes:
- Add --enable-usrmerge=TYPE option (no, sbin, bin, or auto).
- Implement robust automatic detection in configure.ac:
  - Detects 'bin' type (Bin-Sbin merge) if /usr/sbin and /usr/bin are
    the same physical directory (-ef check), if RPM macros define
    _sbindir as /usr/bin, or if key binaries are already linked.
  - Detects 'sbin' type (UsrMerge) if /sbin is a symlink to /usr/sbin.
- Introduce core_sbindir and badblocksdir to decouple installation
  paths from internal path references.
- Define CORE_SBINDIR and BADBLOCKSDIR macros via CPPFLAGS to replace
  hardcoded "/sbin/" paths in mkfs.c and cleaner_exec.c.
- Automate creation of compatibility symbolic links in /usr/sbin when
  installing to /usr/bin, provided that /usr/sbin exists.
- Update AC_PATH_PROG for ldconfig to search in /usr/sbin as well.

This ensures that NILFS utilities are installed to the correct
locations and maintain internal consistency across various Linux
distribution hierarchies.

[ adjusted for v2.2.y ]

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
This commit is contained in:
Ryusuke Konishi 2025-12-23 02:12:54 +09:00
parent 06ad4f4e50
commit 0a2bfde98e
11 changed files with 229 additions and 22 deletions

61
README
View File

@ -14,17 +14,6 @@
$ ./configure
$ make
If your system is a 64-bit architecture and libraries are installed
into /usr/lib64 instead of /usr/lib, change the library directory with
--libdir option:
$ ./configure --libdir=/usr/lib64
If you want to separate the library files into a subdirectory, specify
it as follows, for example:
$ ./configure --libdir=/usr/lib64/nilfs
If /etc/mtab is not a symlink to /proc/self/mounts but a regular file
in the target system, run the configure script with --without-libmount
option:
@ -40,6 +29,56 @@ the recommended configuration. This option is primarily intended for
legacy environments or specialized configurations that still rely on a
writable /etc/mtab file.
* Installation path configuration
If your system is a 64-bit architecture and libraries are installed
into /usr/lib64 instead of /usr/lib, change the library directory with
--libdir option:
$ ./configure --libdir=/usr/lib64
If you want to separate the library files into a subdirectory, specify
it as follows, for example:
$ ./configure --libdir=/usr/lib64/nilfs
Modern Linux distributions follow the "UsrMerge" or "Bin-Sbin merge"
schemes. The configure script automatically detects the system
hierarchy and adjusts the installation paths for core binaries
(mkfs.nilfs2, mount.nilfs2, nilfs_cleanerd, etc.):
- Legacy: Installs to /sbin
- UsrMerge: Installs to /usr/sbin
- Bin-Sbin merge (e.g., Fedora Rawhide): Installs to /usr/bin
When installing to /usr/bin, the build system also attempts to create
compatibility symbolic links in /usr/sbin if that directory exists on
the target system.
You can manually override this detection using the following options:
# Force installation into /usr/bin (Bin-Sbin merge style)
$ ./configure --enable-usrmerge=bin
# Force installation into /usr/sbin (UsrMerge style)
$ ./configure --enable-usrmerge=sbin
# Force installation into the traditional /sbin
$ ./configure --disable-usrmerge
By default, if the option is omitted, the script probes the system's
directory configuration to determine the appropriate hierarchy. If
the option is specified without a TYPE (i.e., --enable-usrmerge), it
defaults to "sbin" (/usr/sbin) to align with standard UsrMerge
practices.
Note: This option is significant even when /sbin is a symbolic link to
/usr/sbin (i.e., the physical installation destination is the same).
It ensures that the absolute paths used by the utilities to call other
binaries are consistent with the chosen hierarchy.
* Trouble shooting
If the blkid library in your environment is old and incompatible with

View File

@ -24,7 +24,7 @@ LT_PREREQ([2.4])
LT_INIT
AC_PATH_PROG([LDCONFIG], [ldconfig],
[AC_MSG_ERROR([ldconfig not found])],
[$PATH:/sbin])
[$PATH:/usr/sbin:/sbin])
dnl UTIL_CHECK_LIB(LIBRARY, FUNCTION, [VARSUFFIX = $1]))
dnl The VARSUFFIX is optional and overrides the default behaviour. For example:
@ -63,6 +63,25 @@ AC_ARG_ENABLE([uapi_header_install],
[enable_uapi_header_install="${enableval}"],
[enable_uapi_header_install=no])
AC_ARG_ENABLE([usrmerge],
[AS_HELP_STRING([--enable-usrmerge[[=TYPE]]],
[set UsrMerge hierarchy type (no, sbin, bin, or auto);
'sbin' (default TYPE) installs to /usr/sbin, 'bin' installs to
/usr/bin [default=auto, which probes the system configuration]])],
[enable_usrmerge="${enableval}"],
[enable_usrmerge=auto])
# Checks for UsrMerge hierarchy
AS_IF([test "x$enable_usrmerge" = "xauto"], [
AS_IF([test /usr/sbin -ef /usr/bin], [enable_usrmerge=bin],
[test -x /usr/bin/rpm && \
test "$(rpm --eval '%{_sbindir}')" = /usr/bin],
[enable_usrmerge=bin],
[test /usr/sbin/mkfs -ef /usr/bin/mkfs], [enable_usrmerge=bin],
[test /sbin -ef /usr/sbin], [enable_usrmerge=sbin],
[enable_usrmerge=no])
])
# Checks for libraries.
AC_CHECK_LIB([uuid], [uuid_generate],
[AC_DEFINE([HAVE_LIBUUID], 1,
@ -185,8 +204,37 @@ AC_SYS_LARGEFILE
AC_PREFIX_DEFAULT([/usr])
test "x$prefix" = "xNONE" && prefix="/usr"
test "x$exec_prefix" = "xNONE" && exec_prefix="${prefix}"
AC_SUBST([root_sbindir], [/sbin])
AC_SUBST([sbindir], [${exec_prefix}/sbin])
# Determine the location of /sbin binaries based on the --enable-usrmerge
# option
AS_CASE(["x$enable_usrmerge"],
[xbin], [
core_sbindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/bin'
badblocksdir='/usr/bin'
create_compat_sbin_link=yes
],
[xsbin|xyes], [
core_sbindir='${exec_prefix}/sbin'
sbindir='${exec_prefix}/sbin'
badblocksdir='/usr/sbin'
create_compat_sbin_link=no
],
[
core_sbindir='/sbin'
sbindir='${exec_prefix}/sbin'
badblocksdir='/sbin'
create_compat_sbin_link=no
]
)
AC_SUBST([core_sbindir])
AC_SUBST([sbindir])
AC_SUBST([badblocksdir])
AM_CONDITIONAL([CREATE_COMPAT_SBIN_LINK],
[test "x$create_compat_sbin_link" = "xyes"])
AC_SUBST([sysconfdir], [/etc])
AC_SUBST([localstatedir], [/var])

View File

@ -1,7 +1,7 @@
## Makefile.am
AM_CFLAGS = -Wall
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CPPFLAGS = -I$(top_srcdir)/include -DCORE_SBINDIR=\"$(core_sbindir)\"
lib_LTLIBRARIES = libnilfs.la libnilfsgc.la libnilfscleaner.la
noinst_LTLIBRARIES = librealpath.la libnilfsfeature.la libparser.la \

View File

@ -76,7 +76,7 @@
#define WAIT_CLEANERD_RETRY_INTERVAL 2 /* in seconds */
#define WAIT_CLEANERD_RETRY_TIMEOUT 8 /* in seconds */
static const char cleanerd[] = "/sbin/" NILFS_CLEANERD_NAME;
static const char cleanerd[] = CORE_SBINDIR "/" NILFS_CLEANERD_NAME;
static const char cleanerd_protperiod_opt[] = "-p";
static void default_logger(int priority, const char *fmt, ...)

View File

@ -1,6 +1,6 @@
## Makefile.am
root_sbin_PROGRAMS = nilfs_cleanerd
core_sbin_PROGRAMS = nilfs_cleanerd
LDADD = $(top_builddir)/lib/libnilfs.la $(top_builddir)/lib/libnilfsgc.la \
$(LIB_POSIX_MQ) -luuid
@ -14,4 +14,24 @@ nilfs_cleanerd_LDFLAGS = -static
dist_sysconf_DATA = nilfs_cleanerd.conf
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore

View File

@ -1,13 +1,33 @@
## Makefile.am
AM_CFLAGS = -Wall
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CPPFLAGS = -I$(top_srcdir)/include -DBADBLOCKSDIR=\"$(badblocksdir)\"
LDADD = $(LIB_BLKID) -luuid $(top_builddir)/lib/libnilfsfeature.la \
$(top_builddir)/lib/libmountchk.la \
$(top_builddir)/lib/libcrc32.la
root_sbin_PROGRAMS = mkfs.nilfs2
core_sbin_PROGRAMS = mkfs.nilfs2
mkfs_nilfs2_SOURCES = mkfs.c bitops.c mkfs.h
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore

View File

@ -93,7 +93,7 @@ extern __u32 crc32_le(__u32 seed, unsigned char const *data, size_t length);
#define BADBLOCKS_NAME "badblocks"
static const char badblocks[] = "/sbin/" BADBLOCKS_NAME;
static const char badblocks[] = BADBLOCKSDIR "/" BADBLOCKS_NAME;
/*
* Command interface primitives

View File

@ -7,12 +7,12 @@ LEGACYSOURCES = fstab.c mount_mntent.c mount_opts.c
LEGACYHEADERS = fstab.h mount_constants.h mount_mntent.h mount_opts.h
AM_CFLAGS = -Wall
AM_CPPFLAGS = -I$(top_srcdir)/include
AM_CPPFLAGS = -I$(top_srcdir)/include -DCORE_SBINDIR=\"$(core_sbindir)\"
LDADD = $(top_builddir)/lib/librealpath.la \
$(top_builddir)/lib/libcleanerexec.la $(LIB_MOUNT) $(LIB_SELINUX) \
$(LIB_POSIX_TIMER)
root_sbin_PROGRAMS = mount.nilfs2 umount.nilfs2
core_sbin_PROGRAMS = mount.nilfs2 umount.nilfs2
if CONFIG_LIBMOUNT
@ -32,4 +32,24 @@ umount_nilfs2_SOURCES = umount.nilfs2.c $(COMMONSOURCES) $(COMMONHEADERS)
endif # CONFIG_LIBMOUNT
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(core_sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore

View File

@ -10,4 +10,24 @@ sbin_PROGRAMS = nilfs-clean
nilfs_clean_SOURCES = nilfs-clean.c
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore

View File

@ -10,4 +10,24 @@ sbin_PROGRAMS = nilfs-resize
nilfs_resize_SOURCES = nilfs-resize.c
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore

View File

@ -10,4 +10,24 @@ sbin_PROGRAMS = nilfs-tune
nilfs_tune_SOURCES = nilfs-tune.c
if CREATE_COMPAT_SBIN_LINK
install-exec-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
echo " LN $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
ln -sf ../bin/$$p $(DESTDIR)$(exec_prefix)/sbin/$$p; \
done; \
fi
uninstall-hook:
@if [ -d "$(DESTDIR)$(exec_prefix)/sbin" ]; then \
for p in $(sbin_PROGRAMS); do \
if [ -L "$(DESTDIR)$(exec_prefix)/sbin/$$p" ]; then \
echo " RM $(DESTDIR)$(exec_prefix)/sbin/$$p"; \
rm -f "$(DESTDIR)$(exec_prefix)/sbin/$$p"; \
fi; \
done; \
fi
endif # CREATE_COMPAT_SBIN_LINK
EXTRA_DIST = .gitignore