编译内核时提示<openssl/bio.h>
缺失,原因是编译的机器上没有安装libssl库。
网上查了一下基本都需要用apt之类的安装libssl,但是我是在公用的机器上编译的,并不太方便直接安装。
于是下载编译了openssl源码,然后尝试在编译内核时把头文件和编译好的库添加进去,但是依然会报错。
实际上,用到openssl的是scripts下的extract-cert.c, 这个文件是用本地的GCC编译的,并不是内核的一部分, 所以make时直接传递的CFLAGS等参数是不会作用到这个文件的编译的。
研究了一下暂时没找到怎么在编译内核时给这个文件指定CFLAGS。 所以直接修改了scripts下的Makefile。
# SPDX-License-Identifier: GPL-2.0
###
# scripts contains sources for various helper programs used throughout
# the kernel for the build process.
# 修改的部分
OPENSSL_INSTALL=<.....>/openssl-build/ # 编译好的openssl
OPENSSL_LDFLAG=-L$(OPENSSL_INSTALL)lib # openssl的库文件
OPENSSL_CFLAG=-I$(OPENSSL_INSTALL)include # openssl的头文件
CRYPTO_LIBS = $(shell pkg-config --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto) # 把编译好的openssl库加进来
CRYPTO_CFLAGS = $(OPENSSL_CFLAG) $(shell pkg-config --cflags libcrypto 2> /dev/null) # 添加openssl的头文件
hostprogs-always-$(CONFIG_BUILD_BIN2C) += bin2c
hostprogs-always-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-always-$(BUILD_C_RECORDMCOUNT) += recordmcount
hostprogs-always-$(CONFIG_BUILDTIME_TABLE_SORT) += sorttable
hostprogs-always-$(CONFIG_ASN1) += asn1_compiler
hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
hostprogs-always-$(CONFIG_SYSTEM_REVOCATION_LIST) += extract-cert
HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS)
HOSTLDLIBS_sign-file = $(CRYPTO_LIBS)
HOSTCFLAGS_extract-cert.o = $(CRYPTO_CFLAGS)
HOSTLDLIBS_extract-cert = $(CRYPTO_LIBS)
ifdef CONFIG_UNWINDER_ORC
ifeq ($(ARCH),x86_64)
ARCH := x86
endif
HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include
HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED
HOSTLDLIBS_sorttable = -lpthread
endif
# The following programs are only built on demand
hostprogs += unifdef
# The module linker script is preprocessed on demand
targets += module.lds
subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins
subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
# Let clean descend into subdirs
subdir- += basic dtc gdb kconfig mod
之后正常执行内核编译步骤即可。
附openssl编译步骤:
# 下载openssl源码
./config --prefix=<.....>/openssl-build/ # 指定安装位置
make CC=x86_64-conda-linux-gnu-gcc -j # 编译,公用的机器gcc版本太低,所以使用的是conda安装的gcc
make install # 编译安装
以上编译的是5.9的内核。其他版本的Makefile会有区别,不过方法是一样的。
如果是新的内核,还需要涉及到其他地方。原来的scripts/Makefile里仍然需要修改,只是要编译的文件变成了sign-file
。
HOSTCFLAGS_sign-file.o = $(OPENSSL_CFLAG) # $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null)
HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto)
而extract-cert.c在/certs里,这个目录里的Makefile也需要修改。
HOSTCFLAGS_extract-cert.o := $(OPENSSL_CFLAG) # $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null)
HOSTLDLIBS_extract-cert := -L$(OPENSSL_INSTALL)lib -lcrypto # $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo $(OPENSSL_LDFLAG) -lcrypto)
但是make时还会报错,
certs/extract-cert: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
因为是用非系统库目录下的.so库文件编译的,所以编译好的extract-cert运行时还是会找不到动态链接库libcrypto.so。找到certs/Makefile
里的cmd_extract_certs
,
用环境变量LD_LIBRARY_PATH
来给它添加运行时的用到的动态链接库。
EXPORT_LD_LIBRARY_PATH=env "LD_LIBRARY_PATH=$(LD_LIBRARY_PATH):$(OPENSSL_INSTALL)lib"
quiet_cmd_extract_certs = CERT $@
cmd_extract_certs =$(EXPORT_LD_LIBRARY_PATH) $(obj)/extract-cert "$(extract-cert-in)" $@
extract-cert-in = $(filter-out $(obj)/extract-cert, $(real-prereqs))
这样应该能正常编译整个内核了。
主要是问题来自内核编译之前需要先编译scripts/
里的一些工具,它们和内核本身是没有关系的。本来编译它们时额外指定头文件和库很简单,只是在Linux本来就很复杂的Makefile工程里解决起来比较麻烦。