build: support selecting enabled utils in Meson

Add a new Meson array option, utils, to allow building only selected applets while keeping the default as all.

Gate source inclusion, dependencies, symlink/manpage/script install steps, and test registration by enabled util set, and make applet dispatch in src/main.c compile-time conditional via generated config defines.

Document selective build usage in README.
This commit is contained in:
2026-04-18 06:34:18 -05:00
parent e1b8aa1594
commit 26e2527492
4 changed files with 361 additions and 65 deletions
+9
View File
@@ -13,6 +13,7 @@ It bundles a growing set of FreeBSD-derived userland tools into a single `vx` bi
- `grep`, `egrep`, `fgrep`, `rgrep`
- `find`
- `xargs`
- `lspci`, `setpci`
## Build
@@ -24,6 +25,14 @@ meson compile -C builddir
meson test -C builddir
```
To build only selected utilities:
```text
meson setup builddir -Dutils=grep,find,xargs
```
The default is `-Dutils=all`.
## Run
You can invoke applets either through the multicall binary:
+282 -65
View File
@@ -6,6 +6,61 @@ project('vx', 'c',
],
)
all_utils = [
'patch',
'diff',
'cmp',
'diff3',
'sdiff',
'which',
'gzip',
'grep',
'find',
'xargs',
'lspci',
'setpci',
]
requested_utils = get_option('utils')
if requested_utils.length() == 0
error('utils option cannot be empty; specify one or more utilities or use "all"')
endif
enabled_utils = []
if requested_utils.contains('all')
enabled_utils = all_utils
else
enabled_utils = requested_utils
endif
enable_patch = enabled_utils.contains('patch')
enable_diff = enabled_utils.contains('diff')
enable_cmp = enabled_utils.contains('cmp')
enable_diff3 = enabled_utils.contains('diff3')
enable_sdiff = enabled_utils.contains('sdiff')
enable_which = enabled_utils.contains('which')
enable_gzip = enabled_utils.contains('gzip')
enable_grep = enabled_utils.contains('grep')
enable_find = enabled_utils.contains('find')
enable_xargs = enabled_utils.contains('xargs')
enable_lspci = enabled_utils.contains('lspci')
enable_setpci = enabled_utils.contains('setpci')
vx_cfg = configuration_data()
vx_cfg.set10('VX_ENABLE_PATCH', enable_patch)
vx_cfg.set10('VX_ENABLE_DIFF', enable_diff)
vx_cfg.set10('VX_ENABLE_CMP', enable_cmp)
vx_cfg.set10('VX_ENABLE_DIFF3', enable_diff3)
vx_cfg.set10('VX_ENABLE_SDIFF', enable_sdiff)
vx_cfg.set10('VX_ENABLE_WHICH', enable_which)
vx_cfg.set10('VX_ENABLE_GZIP', enable_gzip)
vx_cfg.set10('VX_ENABLE_GREP', enable_grep)
vx_cfg.set10('VX_ENABLE_FIND', enable_find)
vx_cfg.set10('VX_ENABLE_XARGS', enable_xargs)
vx_cfg.set10('VX_ENABLE_LSPCI', enable_lspci)
vx_cfg.set10('VX_ENABLE_SETPCI', enable_setpci)
configure_file(output : 'vx-config.h', configuration : vx_cfg)
# --- Portability shim for building BSD userland on Linux ---
compat_inc = include_directories('src/compat-headers')
@@ -77,14 +132,6 @@ grep_src = files(
grep_inc = include_directories('src/grep')
# --- yacc generator for find's getdate.y ---
yacc = find_program('yacc', 'bison')
getdate_gen = custom_target('getdate',
input : 'src/find/getdate.y',
output : 'getdate.c',
command : [yacc, '-o', '@OUTPUT@', '@INPUT@'],
)
find_src = files(
'src/find/find.c',
'src/find/function.c',
@@ -104,9 +151,15 @@ xargs_src = files(
xargs_inc = include_directories('src/xargs')
pci_src = files(
pci_common_src = files(
'src/pci/pci.c',
)
lspci_src = files(
'src/pci/lspci.c',
)
setpci_src = files(
'src/pci/setpci.c',
)
@@ -117,83 +170,247 @@ gzip_defines = [
'-DNO_ZSTD_SUPPORT',
]
vx_sources = files('src/main.c')
vx_sources += compat_src
vx_include_dirs = [compat_inc]
vx_c_args = compat_args
cc = meson.get_compiler('c')
libm = cc.find_library('m', required : false)
libz = dependency('zlib')
liblzma = dependency('liblzma')
libacl = cc.find_library('acl', required : true)
vx_dependencies = [libm]
if enable_patch
vx_sources += patch_src
endif
if enable_diff
vx_sources += diff_src
endif
if enable_cmp
vx_sources += cmp_src
endif
if enable_diff3
vx_sources += diff3_src
endif
if enable_sdiff
vx_sources += sdiff_src
endif
if enable_which
vx_sources += which_src
endif
if enable_gzip
vx_sources += gzip_src
vx_include_dirs += [gzip_inc]
vx_c_args += gzip_defines
vx_dependencies += [dependency('zlib'), dependency('liblzma')]
endif
if enable_grep
vx_sources += grep_src
vx_include_dirs += [grep_inc]
endif
if enable_find
# --- yacc generator for find's getdate.y ---
yacc = find_program('yacc', 'bison')
getdate_gen = custom_target('getdate',
input : 'src/find/getdate.y',
output : 'getdate.c',
command : [yacc, '-o', '@OUTPUT@', '@INPUT@'],
)
vx_sources += find_src
vx_sources += [getdate_gen]
vx_include_dirs += [find_inc]
vx_dependencies += [cc.find_library('acl', required : true)]
endif
if enable_xargs
vx_sources += xargs_src
vx_include_dirs += [xargs_inc]
endif
if enable_lspci or enable_setpci
vx_sources += pci_common_src
vx_include_dirs += [pci_inc]
endif
if enable_lspci
vx_sources += lspci_src
endif
if enable_setpci
vx_sources += setpci_src
endif
vx = executable('vx',
'src/main.c',
patch_src,
diff_src,
cmp_src,
diff3_src,
sdiff_src,
which_src,
gzip_src,
grep_src,
find_src,
getdate_gen,
xargs_src,
pci_src,
compat_src,
include_directories : [compat_inc, gzip_inc, grep_inc, find_inc, xargs_inc, pci_inc],
c_args : compat_args + gzip_defines,
dependencies : [libm, libz, liblzma, libacl],
vx_sources,
include_directories : vx_include_dirs,
c_args : vx_c_args,
dependencies : vx_dependencies,
install : true,
)
# Create symlinks for all applets pointing to the vx binary
# Create symlinks for selected applets pointing to the vx binary.
bindir = get_option('bindir')
foreach name : ['patch', 'diff', 'cmp', 'diff3', 'sdiff', 'which', 'gzip', 'gunzip', 'zcat', 'uncompress', 'grep', 'egrep', 'fgrep', 'rgrep', 'find', 'xargs', 'lspci', 'setpci']
install_applets = []
if enable_patch
install_applets += ['patch']
endif
if enable_diff
install_applets += ['diff']
endif
if enable_cmp
install_applets += ['cmp']
endif
if enable_diff3
install_applets += ['diff3']
endif
if enable_sdiff
install_applets += ['sdiff']
endif
if enable_which
install_applets += ['which']
endif
if enable_gzip
install_applets += ['gzip', 'gunzip', 'zcat', 'uncompress']
endif
if enable_grep
install_applets += ['grep', 'egrep', 'fgrep', 'rgrep']
endif
if enable_find
install_applets += ['find']
endif
if enable_xargs
install_applets += ['xargs']
endif
if enable_lspci
install_applets += ['lspci']
endif
if enable_setpci
install_applets += ['setpci']
endif
foreach name : install_applets
meson.add_install_script('sh', '-c',
'ln -sf vx "$MESON_INSTALL_DESTDIR_PREFIX/' + bindir + '/' + name + '"',
)
endforeach
# --- Manpages ---
install_man(
'src/patch/patch.1',
'src/diff/diff.1',
'src/cmp/cmp.1',
'src/diff3/diff3.1',
'src/sdiff/sdiff.1',
'src/which/which.1',
'src/gzip/gzip.1',
'src/gzip/gzexe.1',
'src/gzip/zdiff.1',
'src/gzip/zforce.1',
'src/gzip/zmore.1',
'src/gzip/znew.1',
'src/gzip/zgrep.1',
'src/grep/grep.1',
'src/find/find.1',
'src/xargs/xargs.1',
'src/pci/lspci.8',
'src/pci/setpci.8',
)
manpages = []
if enable_patch
manpages += ['src/patch/patch.1']
endif
if enable_diff
manpages += ['src/diff/diff.1']
endif
if enable_cmp
manpages += ['src/cmp/cmp.1']
endif
if enable_diff3
manpages += ['src/diff3/diff3.1']
endif
if enable_sdiff
manpages += ['src/sdiff/sdiff.1']
endif
if enable_which
manpages += ['src/which/which.1']
endif
if enable_gzip
manpages += [
'src/gzip/gzip.1',
'src/gzip/gzexe.1',
'src/gzip/zdiff.1',
'src/gzip/zforce.1',
'src/gzip/zmore.1',
'src/gzip/znew.1',
'src/gzip/zgrep.1',
]
endif
if enable_grep
manpages += ['src/grep/grep.1']
endif
if enable_find
manpages += ['src/find/find.1']
endif
if enable_xargs
manpages += ['src/xargs/xargs.1']
endif
if enable_lspci
manpages += ['src/pci/lspci.8']
endif
if enable_setpci
manpages += ['src/pci/setpci.8']
endif
# --- Gzip shell script utilities ---
foreach s : ['zdiff', 'zforce', 'zmore', 'znew', 'gzexe', 'zgrep', 'zless']
install_data('src/gzip/' + s,
install_dir : get_option('bindir'),
install_mode : 'rwxr-xr-x',
)
endforeach
install_man(manpages)
# Install symlinks for script aliases
foreach pair : [['zcmp', 'zdiff'], ['zegrep', 'zgrep'], ['zfgrep', 'zgrep']]
meson.add_install_script('sh', '-c',
'ln -sf ' + pair[1] + ' "$MESON_INSTALL_DESTDIR_PREFIX/' + bindir + '/' + pair[0] + '"',
)
endforeach
if enable_gzip
# --- Gzip shell script utilities ---
foreach s : ['zdiff', 'zforce', 'zmore', 'znew', 'gzexe', 'zgrep', 'zless']
install_data('src/gzip/' + s,
install_dir : get_option('bindir'),
install_mode : 'rwxr-xr-x',
)
endforeach
# Install symlinks for script aliases
foreach pair : [['zcmp', 'zdiff'], ['zegrep', 'zgrep'], ['zfgrep', 'zgrep']]
meson.add_install_script('sh', '-c',
'ln -sf ' + pair[1] + ' "$MESON_INSTALL_DESTDIR_PREFIX/' + bindir + '/' + pair[0] + '"',
)
endforeach
endif
# --- Tests ---
test_env = environment()
test_env.set('VX', vx.full_path())
foreach t : ['test_patch', 'test_diff', 'test_cmp', 'test_diff3', 'test_sdiff', 'test_which', 'test_gzip', 'test_grep', 'test_find', 'test_xargs', 'test_lspci', 'test_setpci']
test_targets = []
if enable_patch
test_targets += ['test_patch']
endif
if enable_diff
test_targets += ['test_diff']
endif
if enable_cmp
test_targets += ['test_cmp']
endif
if enable_diff3
test_targets += ['test_diff3']
endif
if enable_sdiff
test_targets += ['test_sdiff']
endif
if enable_which
test_targets += ['test_which']
endif
if enable_gzip
test_targets += ['test_gzip']
endif
if enable_grep
test_targets += ['test_grep']
endif
if enable_find
test_targets += ['test_find']
endif
if enable_xargs
test_targets += ['test_xargs']
endif
if enable_lspci
test_targets += ['test_lspci']
endif
if enable_setpci
test_targets += ['test_setpci']
endif
foreach t : test_targets
test(t, find_program('tests/' + t + '.sh'),
env : test_env,
depends : vx,
+20
View File
@@ -0,0 +1,20 @@
option('utils',
type : 'array',
value : ['all'],
choices : [
'all',
'patch',
'diff',
'cmp',
'diff3',
'sdiff',
'which',
'gzip',
'grep',
'find',
'xargs',
'lspci',
'setpci',
],
description : 'Utilities to include in vx (default: all)'
)
+50
View File
@@ -1,20 +1,46 @@
#include "vx-config.h"
#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if VX_ENABLE_PATCH
int patch_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_DIFF
int diff_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_CMP
int cmp_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_DIFF3
int diff3_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_SDIFF
int sdiff_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_WHICH
int which_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_GZIP
int gzip_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_GREP
int grep_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_FIND
int find_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_XARGS
int xargs_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_LSPCI
int lspci_main(int argc, char *argv[]);
#endif
#if VX_ENABLE_SETPCI
int setpci_main(int argc, char *argv[]);
#endif
struct applet {
const char *name;
@@ -22,25 +48,49 @@ struct applet {
};
static const struct applet applets[] = {
#if VX_ENABLE_PATCH
{ "patch", patch_main },
#endif
#if VX_ENABLE_DIFF
{ "diff", diff_main },
#endif
#if VX_ENABLE_CMP
{ "cmp", cmp_main },
#endif
#if VX_ENABLE_DIFF3
{ "diff3", diff3_main },
#endif
#if VX_ENABLE_SDIFF
{ "sdiff", sdiff_main },
#endif
#if VX_ENABLE_WHICH
{ "which", which_main },
#endif
#if VX_ENABLE_GZIP
{ "gzip", gzip_main },
{ "gunzip", gzip_main },
{ "zcat", gzip_main },
{ "gzcat", gzip_main },
{ "uncompress", gzip_main },
#endif
#if VX_ENABLE_GREP
{ "grep", grep_main },
{ "egrep", grep_main },
{ "fgrep", grep_main },
{ "rgrep", grep_main },
#endif
#if VX_ENABLE_FIND
{ "find", find_main },
#endif
#if VX_ENABLE_XARGS
{ "xargs", xargs_main },
#endif
#if VX_ENABLE_LSPCI
{ "lspci", lspci_main },
#endif
#if VX_ENABLE_SETPCI
{ "setpci", setpci_main },
#endif
};
static const size_t n_applets = sizeof(applets) / sizeof(applets[0]);