--- /dev/null
+From 9ba0b4add39e578ccdb91ca23b62a7de6ff45995 Mon Sep 17 00:00:00 2001
+From: Mykyta Yatsenko <yatsenko@meta.com>
+Date: Thu, 12 Mar 2026 17:03:27 -0700
+Subject: [PATCH] bpftool: Allow explicitly skip llvm, libbfd and libcrypto
+ dependencies
+
+Introduce SKIP_LLVM, SKIP_LIBBFD, and SKIP_CRYPTO build flags that let
+users build bpftool without these optional dependencies.
+
+SKIP_LLVM=1 skips LLVM even when detected. SKIP_LIBBFD=1 prevents the
+libbfd JIT disassembly fallback when LLVM is absent. Together, they
+produce a bpftool with no disassembly support.
+
+SKIP_CRYPTO=1 excludes sign.c and removes the -lcrypto link dependency.
+Inline stubs in main.h return errors with a clear message if signing
+functions are called at runtime.
+
+Use BPFTOOL_WITHOUT_CRYPTO (not HAVE_LIBCRYPTO_SUPPORT) as the C
+define, following the BPFTOOL_WITHOUT_SKELETONS naming convention for
+bpftool-internal build config, leaving HAVE_LIBCRYPTO_SUPPORT free for
+proper feature detection in the future.
+
+All three flags are propagated through the selftests Makefile to bpftool
+sub-builds.
+
+Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20260312-b4-bpftool_build-v2-1-4c9d57133644@meta.com
+---
+ src/Makefile | 30 ++++++++++++++++++++++++++----
+ src/main.c | 7 +++++++
+ src/main.h | 14 ++++++++++++++
+ 3 files changed, 47 insertions(+), 4 deletions(-)
+
+--- a/src/Makefile
++++ b/src/Makefile
+@@ -95,6 +95,15 @@ RM ?= rm -f
+
+ FEATURE_USER = .bpftool
+
++# Skip optional dependencies: LLVM (JIT disasm), libbfd (fallback
++# disasm), libcrypto (program signing).
++SKIP_LLVM ?=
++SKIP_LIBBFD ?=
++SKIP_CRYPTO ?=
++ifneq ($(SKIP_CRYPTO),1)
++ CRYPTO_LIBS := -lcrypto
++endif
++
+ FEATURE_TESTS := clang-bpf-co-re
+ FEATURE_TESTS += llvm
+ FEATURE_TESTS += libcap
+@@ -124,8 +133,8 @@ ifeq ($(check_feat),1)
+ include Makefile.feature
+ endif
+
+-LIBS = $(LIBBPF) -lelf -lcrypto -lz
+-LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf -lcrypto -lz
++LIBS = $(LIBBPF) -lelf $(CRYPTO_LIBS) -lz
++LIBS_BOOTSTRAP = $(LIBBPF_BOOTSTRAP) -lelf $(CRYPTO_LIBS) -lz
+
+ ifeq ($(feature-libelf-zstd),1)
+ LIBS += -lzstd
+@@ -144,7 +153,12 @@ all: $(OUTPUT)bpftool
+ SRCS := $(wildcard *.c)
+
+ ifeq ($(feature-llvm),1)
+- # If LLVM is available, use it for JIT disassembly
++ifneq ($(SKIP_LLVM),1)
++HAS_LLVM := 1
++endif
++endif
++
++ifeq ($(HAS_LLVM),1)
+ CFLAGS += -DHAVE_LLVM_SUPPORT
+ LLVM_CONFIG_LIB_COMPONENTS := mcdisassembler all-targets
+ # llvm-config always adds -D_GNU_SOURCE, however, it may already be in CFLAGS
+@@ -159,6 +173,7 @@ ifeq ($(feature-llvm),1)
+ endif
+ LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags)
+ else
++ ifneq ($(SKIP_LIBBFD),1)
+ # Fall back on libbfd
+ ifeq ($(feature-libbfd),1)
+ LIBS += -lbfd -ldl -lopcodes
+@@ -180,15 +195,22 @@ else
+ CFLAGS += -DDISASM_INIT_STYLED
+ endif
+ endif
++ endif # SKIP_LIBBFD
+ endif
+ ifeq ($(filter -DHAVE_LLVM_SUPPORT -DHAVE_LIBBFD_SUPPORT,$(CFLAGS)),)
+ # No support for JIT disassembly
+ SRCS := $(filter-out jit_disasm.c,$(SRCS))
+ endif
+
++ifeq ($(SKIP_CRYPTO),1)
++ CFLAGS += -DBPFTOOL_WITHOUT_CRYPTO
++ HOST_CFLAGS += -DBPFTOOL_WITHOUT_CRYPTO
++ SRCS := $(filter-out sign.c,$(SRCS))
++endif
++
+ BPFTOOL_BOOTSTRAP := $(BOOTSTRAP_OUTPUT)bpftool
+
+-BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o sign.o)
++BOOTSTRAP_OBJS = $(addprefix $(BOOTSTRAP_OUTPUT),main.o common.o json_writer.o gen.o btf.o $(if $(CRYPTO_LIBS),sign.o))
+ $(BOOTSTRAP_OBJS): $(LIBBPF_BOOTSTRAP)
+
+ OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
+--- a/src/main.c
++++ b/src/main.c
+@@ -132,6 +132,11 @@ static int do_version(int argc, char **a
+ #else
+ const bool has_skeletons = true;
+ #endif
++#ifdef BPFTOOL_WITHOUT_CRYPTO
++ const bool has_crypto = false;
++#else
++ const bool has_crypto = true;
++#endif
+ bool bootstrap = false;
+ int i;
+
+@@ -163,6 +168,7 @@ static int do_version(int argc, char **a
+ jsonw_start_object(json_wtr); /* features */
+ jsonw_bool_field(json_wtr, "libbfd", has_libbfd);
+ jsonw_bool_field(json_wtr, "llvm", has_llvm);
++ jsonw_bool_field(json_wtr, "crypto", has_crypto);
+ jsonw_bool_field(json_wtr, "skeletons", has_skeletons);
+ jsonw_bool_field(json_wtr, "bootstrap", bootstrap);
+ jsonw_end_object(json_wtr); /* features */
+@@ -181,6 +187,7 @@ static int do_version(int argc, char **a
+ printf("features:");
+ print_feature("libbfd", has_libbfd, &nb_features);
+ print_feature("llvm", has_llvm, &nb_features);
++ print_feature("crypto", has_crypto, &nb_features);
+ print_feature("skeletons", has_skeletons, &nb_features);
+ print_feature("bootstrap", bootstrap, &nb_features);
+ printf("\n");
+--- a/src/main.h
++++ b/src/main.h
+@@ -293,6 +293,20 @@ struct kernel_config_option {
+ int read_kernel_config(const struct kernel_config_option *requested_options,
+ size_t num_options, char **out_values,
+ const char *define_prefix);
++#ifndef BPFTOOL_WITHOUT_CRYPTO
+ int bpftool_prog_sign(struct bpf_load_and_run_opts *opts);
+ __u32 register_session_key(const char *key_der_path);
++#else
++static inline int bpftool_prog_sign(struct bpf_load_and_run_opts *opts)
++{
++ p_err("bpftool was built without signing support");
++ return -ENOTSUP;
++}
++
++static inline __u32 register_session_key(const char *key_der_path)
++{
++ p_err("bpftool was built without signing support");
++ return -1;
++}
++#endif
+ #endif