Files
s390-tools/common.mak
Steffen Eiden 03f7566436 New release s390-tools-2.44.0
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
2026-07-31 15:51:50 +02:00

536 lines
17 KiB
Makefile

COMMON_INCLUDED ?= false
V ?= 0
W ?= 0
G ?= 0
C ?= 0
D ?= 0
ASAN ?= 0
ENABLE_WERROR ?= 0
OPT_FLAGS ?=
MAKECMDGOALS ?=
CARGO ?= cargo
CARGOFLAGS ?=
ifeq ($(COMMON_INCLUDED),false)
COMMON_INCLUDED := true
override SHELL := /bin/bash
# 'BUILD_ARCH' is the architecture of the machine where the build takes place
BUILD_ARCH := $(shell uname -m | sed -e 's/i.86/i386/' -e 's/sun4u/sparc64/' -e 's/arm.*/arm/' -e 's/sa110/arm/')
# 'HOST_ARCH' is the architecture of the machine that will run the compiled output
HOST_ARCH ?= $(BUILD_ARCH)
# The `*clean` targets are mutually exclusive to all other targets
ifneq ($(filter %clean,$(MAKECMDGOALS)),)
ifneq ($(MAKECMDGOALS),$(filter %clean,$(MAKECMDGOALS)))
$(error The *clean targets are mutually exclusive to all other targets)
endif
endif
# Global definitions
# The variable "DISTRELEASE" should be overwritten in rpm spec files with:
# "make DISTRELEASE=%{release}" and "make install DISTRELEASE=%{release}"
VERSION := 2
RELEASE := 44
PATCHLEVEL := 0
DISTRELEASE := build-$(shell date +%Y%m%d)
S390_TOOLS_RELEASE := $(VERSION).$(RELEASE).$(PATCHLEVEL)-$(DISTRELEASE)
export S390_TOOLS_RELEASE
reldir = $(subst $(realpath $(dir $(filter %common.mak,$(MAKEFILE_LIST))))/,,$(CURDIR))
rootdir= $(dir $(filter %common.mak,$(MAKEFILE_LIST)))
export S390_TEST_LIB_PATH=$(rootdir)/s390-tools-testsuite/lib
#
# For cross compiles specify HOST_ARCH= and CROSS_COMPILE= on the commandline:
#
# $ make HOST_ARCH=s390x CROSS_COMPILE="s390x-linux-gnu-"
#
CROSS_COMPILE ?=
#
# Commands can be overwritten on the command line with "make <VAR>=<VALUE>":
#
# $ make CC=gcc-4.8
#
# The "cmd_define_and_export" macro wraps the command definition so that
# the commands can be user supplied and are still pretty-printed for the
# build process. In addition, the command variable gets exported so it
# can be used by sub-makes.
#
# The macro is called with the following parameters:
#
# $(1) - Used command variable in the Makefiles
# $(2) - Pretty Print output for the command
# $(3) - Default command if not user-specified
#
# The Example below...
#
# $(eval $(call cmd_define_and_export, CC," CC ",$(CROSS_COMPILE)gcc))
#
# ... produces the following code:
#
# CC = $(CROSS_COMPILE)gcc
# CC_SILENT := $(CC)
# override CC = $(call echocmd," CC ",/$@)$(CC_SILENT)
# export CC
#
# The "strip" make function is used for the first parameter to allow blanks,
# which improves readability.
#
define cmd_define
$(strip $(1)) = $(3)
$(strip $(1))_SILENT := $$($(strip $(1)))
override $(strip $(1)) = $$(call echocmd,$(2),/$$@)$$($(strip $(1))_SILENT)
endef
define cmd_define_and_export
$(call cmd_define,$(1),$(2),$(3))
export $(strip $(1))
endef
define define_toolchain_variables
$(call cmd_define_and_export, AS$(1)," AS$(1) ",$(2)as)
$(call cmd_define_and_export, CC$(1)," CC$(1) ",$(2)gcc)
$(call cmd_define_and_export, LINK$(1)," LINK$(1) ",$$(CC$(1)))
$(call cmd_define_and_export, CXX$(1)," CXX$(1) ",$(2)g++)
$(call cmd_define_and_export, LINKXX$(1)," LINKXX$(1) ",$$(CXX$(1)))
$(call cmd_define_and_export, CPP$(1)," CPP$(1) ",$(2)gcc -E)
$(call cmd_define_and_export, AR$(1)," AR$(1) ",$(2)ar)
$(call cmd_define_and_export, NM$(1)," NM$(1) ",$(2)nm)
$(call cmd_define_and_export, STRIP$(1)," STRIP$(1) ",$(2)strip)
$(call cmd_define_and_export,OBJCOPY$(1)," OBJCOPY$(1) ",$(2)objcopy)
$(call cmd_define_and_export,OBJDUMP$(1)," OBJDUMP$(1) ",$(2)objdump)
PKG_CONFIG$(1) = pkg-config
export PKG_CONFIG$(1)
endef
# If the host architecture is not the same as the build architecture
# 'CROSS_COMPILE=...' is always required (except for the '*clean' targets).
ifneq ($(HOST_ARCH),$(BUILD_ARCH))
ifeq ($(CROSS_COMPILE),)
# `make clean` and similar must always work!
ifeq ($(filter %clean,$(MAKECMDGOALS)),)
$(error Please specify CROSS_COMPILE=... and try it again!)
endif
endif
endif
# *_FOR_BUILD variables define compilation configurations for binaries used
# during the build process (e.g. autocompleteion script generators). This
# is especially important for cross-compilation where these binaries need to
# be executed on the build system.
$(eval $(call define_toolchain_variables,_FOR_BUILD,))
$(eval $(call define_toolchain_variables,,$(CROSS_COMPILE)))
$(eval $(call cmd_define, RUNTEST," RUNTEST ",$(S390_TEST_LIB_PATH)/s390_runtest))
$(eval $(call cmd_define, CAT," CAT ",cat))
$(eval $(call cmd_define, SED," SED ",sed))
$(eval $(call cmd_define, GZIP," GZIP ",gzip))
$(eval $(call cmd_define, MV," MV ",mv))
$(eval $(call cmd_define, PERLC," PERLC ",perl -c))
$(eval $(call cmd_define,CARGO_BUILD," CARGO BUILD ",$(CARGO) build))
$(eval $(call cmd_define,CARGO_TEST, " CARGO TEST ",$(CARGO) test))
$(eval $(call cmd_define,CARGO_CLEAN," CARGO CLEAN ",$(CARGO) clean))
CHECK = sparse
CHECK_SILENT := $(CHECK)
CHECKTOOL = $(call echocmd," CHECK ",/$@)$(CHECK_SILENT)
SKIP = echo " SKIP $(call reldir) due to"
INSTALL = install
CP = cp
ALL_CARGOFLAGS := $(CARGOFLAGS)
ifneq ("${V}","1")
MAKEFLAGS += --quiet
ALL_CARGOFLAGS += --quiet
echocmd=echo $1$(call reldir)$2;
RUNTEST += > /dev/null 2>&1
else
echocmd=
endif
DEFAULT_CFLAGS = -g -fstack-protector-all -W -Wall -Wformat-security
ifeq ("${W}","1")
DEFAULT_CFLAGS += -Wextra -Wshadow -Wundef -Wuninitialized -Wdouble-promotion -Wconversion
endif
ifeq ("${D}","1")
DEFAULT_CFLAGS += -Og -g3 -ggdb3
else
DEFAULT_CFLAGS += -O3
endif
ifeq ("${ENABLE_WERROR}", "1")
DEFAULT_CFLAGS += -Werror
endif
DEFAULT_CPPFLAGS = -D_GNU_SOURCE
DEFAULT_LDFLAGS = -rdynamic -Wl,--as-needed
ifeq ("${ASAN}","1")
DEFAULT_CFLAGS += -fsanitize=address -fno-omit-frame-pointer
DEFAULT_LDFLAGS += -fsanitize=address
endif
DEFAULT_PERLCFLAGS =
ifeq ("${W}","1")
DEFAULT_PERLCFLAGS += -w
endif
#
# Check for header prerequisite
#
# $1: Name of include file to check
# $2: Additional compiler & linker options (optional)
#
# Returns "yes" on success and nothing otherwise
#
define check_header_prereq
$(shell printf "#include <%s>\n int main(void) {return 0;}\n" $1 | \
( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) \
$2 -o /dev/null -x c - ) >/dev/null 2>&1 && echo -n yes)
endef
#
# Check for build dependency
#
# $1: Name of tool or feature that requires dependency
# $2: Name of include file to check
# $3: Name of required devel package
# $4: Option to skip build (e.g. HAVE_FUSE=0)
# $5: Additional compiler & linker options (optional)
#
check_dep=\
printf "\#include <%s>\n int main(void) {return 0;}\n" $2 | ( $(CC) $(filter-out --coverage, $(ALL_CFLAGS)) $(ALL_CPPFLAGS) -Wl,--no-as-needed $5 -o /dev/null -x c - ) > /dev/null 2>&1; \
if [ $$? != 0 ]; \
then \
printf " REQCHK %s (%s)\n" $1 $2; \
printf "********************************************************************************\n" >&2; \
printf "* Missing build requirement for: %-45s *\n" $1 >&2; \
printf "* Install package..............: %-45s *\n" $3 >&2; \
printf "* You can skip build with......: make %-40s *\n" $4 >&2; \
printf "********************************************************************************\n" >&2; \
exit 1; \
fi
#
# Test for linker option
#
# $1: Linker option
#
# Returns the linker option if available and nothing otherwise
#
define test_linker_flag
$(shell printf ".globl _start\n_start:\nnop\n" | \
( $(LINK) "-Wl,$1" -o /dev/null -nostdlib -x assembler -) >/dev/null 2>&1 && printf -- '-Wl,%s' "$1")
endef
NO_WARN_RWX_SEGMENTS_LDFLAGS := $(call test_linker_flag,"--no-warn-rwx-segments")
#
# Support alternate install root
#
# INSTALLDIR: Finally install s390-tools to INSTALLDIR. This can be used
# for testing locally installed tools.
# DESTDIR: Temporary install s390-tools to this directory. This can be
# used for building s390-tools e.g. with rpmbuild.
#
# The difference between INSTALLDIR and DESTDIR is that for INSTALLDIR
# internally used directories (e.g. for config files) are adjusted.
#
# Example:
#
# $ cd cpumf
# $ INSTALLDIR=/tmp make install
# $ cat /tmp/lib/s390-tools/cpumf_helper | grep DATA_DIR
# my $CPUMF_DATA_DIR = '/tmp/usr/share/s390-tools/cpumf';
#
# $ make clean
# $ DESTDIR=/tmp make install
# $ cat /tmp/lib/s390-tools/cpumf_helper | grep DATA_DIR
# my $CPUMF_DATA_DIR = '/usr/share/s390-tools/cpumf';
#
ifdef INSTROOT
$(error INSTROOT is no longer available, use DESTDIR instead)
endif
INSTALLDIR ?=
DESTDIR ?=
USRSBINDIR = $(INSTALLDIR)/usr/sbin
USRBINDIR = $(INSTALLDIR)/usr/bin
BINDIR = $(INSTALLDIR)/sbin
LIBDIR = $(INSTALLDIR)/lib
USRLIBDIR = $(INSTALLDIR)/usr/lib
USRLIB64DIR = $(INSTALLDIR)/usr/lib64
SYSCONFDIR = $(INSTALLDIR)/etc
DATADIR = $(INSTALLDIR)/usr/share
MANDIR = $(DATADIR)/man
BASHCOMPLETIONDIR = $(DATADIR)/bash-completion/completions
ZSHCOMPLETIONDIR = $(DATADIR)/zsh/site-functions
VARDIR = $(INSTALLDIR)/var
TOOLS_DATADIR = $(DATADIR)/s390-tools
TOOLS_LIBDIR = $(INSTALLDIR)/lib/s390-tools
ZFCPDUMP_DIR = $(TOOLS_LIBDIR)/zfcpdump
# Systemd support files are installed only if a directory is specified
# for SYSTEMDSYSTEMUNITDIR (e.g. /lib/systemd/system)
SYSTEMDSYSTEMUNITDIR =
USRINCLUDEDIR = $(INSTALLDIR)/usr/include
ZKEYKMSPLUGINDIR = $(USRLIB64DIR)/zkey
UDEVDIR = $(USRLIBDIR)/udev
UDEVRULESDIR = $(UDEVDIR)/rules.d
DRACUTDIR = $(USRLIBDIR)/dracut
DRACUTCONFDIR = $(DRACUTDIR)/dracut.conf.d
DRACUTMODDIR = $(DRACUTDIR)/modules.d
ifeq ($(LIBDIR),$(INSTALLDIR)/lib)
SOINSTALLDIR = $(USRLIB64DIR)
else
SOINSTALLDIR = $(LIBDIR)
endif
INSTDIRS = $(USRSBINDIR) $(USRBINDIR) $(BINDIR) $(LIBDIR) $(MANDIR) \
$(SYSCONFDIR) $(SYSCONFDIR)/sysconfig \
$(TOOLS_LIBDIR) $(TOOLS_DATADIR) \
$(ZFCPDUMP_DIR) $(SYSTEMDSYSTEMUNITDIR) \
$(USRLIB64DIR) $(USRINCLUDEDIR) $(ZKEYKMSPLUGINDIR) \
$(SOINSTALLDIR) $(USRLIBDIR)
OWNER := $(shell id -un)
GROUP := $(shell id -gn)
export INSTALLDIR BINDIR LIBDIR USRLIBDIR USRLIB64DIR MANDIR OWNER GROUP
# Special defines for zfcpdump
ZFCPDUMP_IMAGE = zfcpdump-image
ZFCPDUMP_INITRD = zfcpdump-initrd
ZFCPDUMP_FLAVOR = zfcpdump
export ZFCPDUMP_DIR ZFCPDUMP_IMAGE ZFCPDUMP_INITRD ZFCPDUMP_FLAVOR
CFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
CFLAGS_FOR_BUILD ?= -std=gnu11 $(DEFAULT_CFLAGS) $(OPT_FLAGS)
CPPFLAGS ?= $(DEFAULT_CPPFLAGS)
LDFLAGS ?= $(DEFAULT_LDFLAGS)
ALL_CFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-DS390_TOOLS_LIBDIR=$(TOOLS_LIBDIR) \
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
-DS390_TOOLS_BINDIR=$(BINDIR) \
-std=gnu11 $(CFLAGS)
CXXFLAGS ?= $(DEFAULT_CFLAGS) $(OPT_FLAGS)
ALL_CXXFLAGS = -DS390_TOOLS_RELEASE=$(S390_TOOLS_RELEASE) \
-DS390_TOOLS_LIBDIR=$(TOOLS_LIBDIR) \
-DS390_TOOLS_DATADIR=$(TOOLS_DATADIR) \
-DS390_TOOLS_SYSCONFDIR=$(SYSCONFDIR) \
-DS390_TOOLS_BINDIR=$(BINDIR) \
-std=gnu++11 $(CXXFLAGS)
ALL_CPPFLAGS = -I $(rootdir)include $(CPPFLAGS)
ALL_LDFLAGS = $(LDFLAGS)
ALL_PERLCFLAGS = $(DEFAULT_PERLCFLAGS)
# make G=1
# Compile tools so that gcov can be used to collect code coverage data.
# See the gcov man page for details.
ifeq ("${G}","1")
ALL_CFLAGS := $(filter-out -O%,$(ALL_CFLAGS)) --coverage
ALL_CXXFLAGS := $(filter-out -O%,$(ALL_CXXFLAGS)) --coverage
ALL_LDFLAGS += --coverage
endif
export INSTALL CFLAGS CXXFLAGS \
LDFLAGS CPPFLAGS ALL_CFLAGS ALL_CXXFLAGS ALL_LDFLAGS ALL_CPPFLAGS
# Overwrite implicit makefile rules for having nice compile output
%.o: %.c
ifeq ("${C}","1")
$(CHECKTOOL) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c $< -o $@
endif
$(CC) $(ALL_CPPFLAGS) $(ALL_CFLAGS) -c $< -o $@
%.o: %.cpp
$(CXX) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) -c $< -o $@
%: %.o
$(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@
%.a:
$(AR) rcs $@ $^
all:
help:
@echo 'Usage: make [TARGETS] [OPTIONS]'
@echo ''
@echo 'TARGETS'
@echo ' all Build all tools (default target)'
@echo ' install Install tools'
@echo ' clean Delete all generated files'
@echo ' compdb Generate compile_commands.json for clangd'
@echo ''
@echo 'OPTIONS'
@echo ' D=1 Build with debugging option "-Og"'
@echo ' C=1 Build with check tool defined with "CHECK=" (default=sparse)'
@echo ' G=1 Build with gcov to collect code coverage data'
@echo ' V=1 Generate verbose build output'
@echo ' W=1 Build with higher warning level'
@echo ' ASAN=1 Build with address sanitizer'
@echo ' ENABLE_WERROR=1 Build with -Werror'
@echo ''
@echo 'EXAMPLES'
@echo ' # make clean all D=1 W=1 -j'
@echo ' # make C=1 CHECK=smatch'
.PHONY: help
# 'compile_commands.json' generation
#
# Create the compilation database 'compile_commands.json'. See
# https://clang.llvm.org/docs/JSONCompilationDatabase.html for details.
#
.PHONY: compdb
compdb:
$(MAKE) clean
ifneq ($(shell command -v compiledb),)
compiledb $(MAKE)
else ifneq ($(shell command -v bear),)
ifeq ($(shell bear --help|grep -- '-- ...'),)
bear $(MAKE)
else
bear -- $(MAKE)
endif
else
$(error Please install either 'compiledb' or 'bear')
endif
# Prints the s390-tools release string
version:
$(info $(S390_TOOLS_RELEASE))
.PHONY: version
# Automatic dependency generation
#
# Create ".o.d" dependency files with the -MM compile option for all ".c" and
# ".cpp" files in the directory of the Makefile that includes common.mak:
#
# $ gcc -MM vmcp.c
# vmcp.o: vmcp.c vmcp.h ../include/zt_common.h
#
# Use -MM instead of -M to *not* mention system header files. We expect
# "make clean all" in case of system header updates.
# We consider header files in three possible directories
sources_h = \
$(wildcard *.h) \
$(wildcard ../include/*.h) \
$(wildcard $(rootdir)/include/lib/*.h)
# Rules to create ".o.d" files out of ".c" or ".cpp" files:
.%.o.d: %.c $(sources_h)
$(CC_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CFLAGS) $< > $@
.%.o.d: %.cpp $(sources_h)
$(CXX_SILENT) -MM $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< > $@
# The sources_c/cpp variable contains a list of all ".c" or ".cpp" files in
# in the current directory.
sources_c = $(wildcard *.c)
sources_cpp = $(wildcard *.cpp)
# The dependencies_c/cpp variable contains a list of all ".o.d" files,
# one for each ".c" or ".cpp" file.
dependencies_c = $(sources_c:%.c=.%.o.d)
dependencies_cpp = $(sources_cpp:%.cpp=.%.o.d)
# Include all ".o.d" dependency files for all make targets except for "clean"
ifneq ($(MAKECMDGOALS),clean)
-include $(dependencies_c)
-include $(dependencies_cpp)
endif
# Rules for internal libraries needed to ensure that these files are build
# with their own build flags even if they are build from external directories.
#
# Because of the PHONY directory dependency all tools that use libraries
# check the library directory via "make -C" when the tools Makefile is
# processed.
$(rootdir)/libutil/libutil.a: $(rootdir)/libutil
$(MAKE) -C $(rootdir)/libutil/ libutil.a
.PHONY: $(rootdir)/libutil
$(rootdir)/libccw/libccw.a: $(rootdir)/libccw
$(MAKE) -C $(rootdir)/libccw/ libccw.a
.PHONY: $(rootdir)/libccw
$(rootdir)/libvtoc/libvtoc.a: $(rootdir)/libvtoc
$(MAKE) -C $(rootdir)/libvtoc/ libvtoc.a
.PHONY: $(rootdir)/libvtoc
$(rootdir)/libdasd/libdasd.a: $(rootdir)/libdasd
$(MAKE) -C $(rootdir)/libdasd/ libdasd.a
.PHONY: $(rootdir)/libdasd
$(rootdir)/libzds/libzds.a: $(rootdir)/libzds
$(MAKE) -C $(rootdir)/libzds/ libzds.a
.PHONY: $(rootdir)/libzds
$(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
.PHONY: $(rootdir)/libvmcp
$(rootdir)/libcpumf/libcpumf.a: $(rootdir)/libcpumf
$(MAKE) -C $(rootdir)/libcpumf/ libcpumf.a
.PHONY: $(rootdir)/libcpumf
$(rootdir)/libekmfweb/libekmfweb.so: $(rootdir)/libekmfweb
$(MAKE) -C $(rootdir)/libekmfweb/ libekmfweb.so
.PHONY: $(rootdir)/libekmfweb
$(rootdir)/libseckey/libseckey.a: $(rootdir)/libseckey
$(MAKE) -C $(rootdir)/libseckey/ libseckey.a
.PHONY: $(rootdir)/libseckey
$(rootdir)/libkmipclient/libkmipclient.so: $(rootdir)/libkmipclient
$(MAKE) -C $(rootdir)/libkmipclient/ libkmipclient.so
.PHONY: $(rootdir)/libkmipclient
$(rootdir)/libap/libap.a: $(rootdir)/libap
$(MAKE) -C $(rootdir)/libap/ libap.a
.PHONY: $(rootdir)/libap
$(rootdir)/libpv/libpv.a: $(rootdir)/libpv
$(MAKE) -C $(rootdir)/libpv libpv.a
.PHONY: $(rootdir)/libpv
$(rootdir)/libzpci/libzpci.a: $(rootdir)/libzpci
$(MAKE) -C $(rootdir)/libzpci libzpci.a
.PHONY: $(rootdir)/libzpci
$(rootdir)/zipl/boot/.loaders:
$(MAKE) -C $(rootdir)/zipl/boot/ .loaders
install_dirs:
for dir in $(INSTDIRS); do \
test -d $(DESTDIR)$$dir || $(INSTALL) -g $(GROUP) -o $(OWNER) -d $(DESTDIR)$$dir; \
done
for i in 1 2 3 4 5 6 7 8; do \
test -d $(DESTDIR)$(MANDIR)/man$$i || $(INSTALL) -g $(GROUP) -o $(OWNER) \
-d $(DESTDIR)$(MANDIR)/man$$i; \
done
install_echo:
$(call echocmd," INSTALL ")
install: install_echo install_dirs
clean_echo:
$(call echocmd," CLEAN ")
clean_gcov:
rm -f -- *.gcda *.gcno *.gcov
clean_dep:
rm -f -- .*.o.d
clean: clean_echo clean_gcov clean_dep
endif