build: support library builds via lib/<libname>

This patch adds special handling for lib/<libname> arguments to the
build system, which supersedes the former LIB=<libname> mechanism.
Whereas the old mechanism was limited to a single library, the new
convention allows multiple library arguments, similar to regular
targets. The change brings the two immediate benefits.

First, the streamlining of library and target arguments allows for the
building of libraries via the 'build' command of the run tool.

Second, it alleviates the need for pseudo target.mk files for building
shared libraries that have no direct dependencies, in particular VFS
plugins.

Since this change eases the explicit creation of shared libraries
from run scripts, we may reconsider the automatic implicit building
of shared libraries driven by targets. E.g., while developing a Qt
application, a run script could import the Qt libraries from the
depot and combine those with the developed (fresh built) target without
triggering the build of the Qt libraries in the build directory.

When issueing 'make' without arguments, all targets are built. This
patch applies this behavior to libraries as well, thereby removing the
need for the base/src/lib/target.mk pseudo target as used by the CI
tools to build all libraries.

Note that target.mk files located under src/lib/ are no longer
reachable. Therefore, all run scripts that used to trigger the
build of a shared library via a pseudo target must be adapted.
E.g., 'build lib/vfs/tap' must be replaced by 'build lib/vfs_tap'.

With this patch, the LIB=<libname> option is no longer supported.

Fixes #4599
This commit is contained in:
Norman Feske 2022-08-31 16:50:07 +02:00
parent f50971b6a9
commit c560285d88
4 changed files with 38 additions and 60 deletions

View File

@ -119,8 +119,9 @@ warn_unsatisfied_requirements: generate_lib_rule_for_defect_library
@$(ECHO) "Skip library $(LIB) because it requires $(DARK_COL)$(UNSATISFIED_REQUIREMENTS)$(DEFAULT_COL)" @$(ECHO) "Skip library $(LIB) because it requires $(DARK_COL)$(UNSATISFIED_REQUIREMENTS)$(DEFAULT_COL)"
generate_lib_rule_for_defect_library: generate_lib_rule_for_defect_library:
@echo "INVALID_DEPS += $(LIB)" >> $(LIB_DEP_FILE) @(echo "INVALID_DEPS += $(LIB)"; \
@echo "" >> $(LIB_DEP_FILE) echo "$(LIB).lib:"; \
echo "") >> $(LIB_DEP_FILE)
LIBS_TO_VISIT = $(filter-out $(LIBS_READY),$(LIBS)) LIBS_TO_VISIT = $(filter-out $(LIBS_READY),$(LIBS))

View File

@ -1,33 +0,0 @@
#
# This is a dummy target description file with the sole purpose of building
# all libraries.
#
TARGET = libs
#
# Determine all 'lib/mk' sub directories residing within the repositories.
# Use 'wildcard' to handle the case when a repository does not host any
# 'lib/mk' sub directory.
#
LIB_MK_DIRS := $(wildcard $(addsuffix /lib/mk,$(REPOSITORIES)))
#
# Scan the 'lib/mk' directories of all repositories for library description
# files.
#
ALL_LIB_MK_FILES := $(notdir $(foreach DIR,$(LIB_MK_DIRS),$(shell find $(DIR) -name "*.mk")))
#
# Make the pseudo target depend on all libraries, for which an lib.mk file
# exists. Discard the '.mk' suffix and remove duplicates (via 'sort').
#
LIBS = $(sort $(ALL_LIB_MK_FILES:.mk=))
#
# Among all libraries found above, there may be several libraries with
# unsatisfied build requirements. Normally, the build system won't attempt to
# build the target (and its library dependencies) if one or more libraries
# cannot be built. By enabling 'FORCE_BUILD_LIBS', we let the build system
# visit all non-invalid libraries even in the presence of invalid libraries.
#
FORCE_BUILD_LIBS = yes

View File

@ -154,12 +154,35 @@ export LIBGCC_INC_DIR := $(shell dirname `$(CUSTOM_CXX_LIB) -print-libgcc-file-n
# #
# Find out about the target directories to build # Find out about the target directories to build
# #
DST_DIRS := $(filter-out clean cleanall again run/%,$(MAKECMDGOALS)) # Arguments starting with 'run/' and 'lib/' are special. The former triggers
# the execution of a run script. The latter issues the build of a library.
#
DST_DIRS := $(filter-out clean cleanall again run/% lib/%,$(MAKECMDGOALS))
ifeq ($(MAKECMDGOALS),) ifeq ($(MAKECMDGOALS),)
DST_DIRS := * DST_DIRS := *
endif endif
#
# Detect use of obsoleted LIB=<libname> option
#
ifneq ($(LIB),)
$(error the 'LIB=$(LIB)' option is no longer supported, use 'make lib/$(LIB)')
endif
#
# Determine library targets specified as lib/<libname> at the command line
#
LIBS := $(notdir $(filter lib/%,$(MAKECMDGOALS)))
ifeq ($(MAKECMDGOALS),)
ALL_LIB_MK_DIRS := $(wildcard \
$(foreach R,$(REPOSITORIES),\
$R/lib/mk $(foreach S,$(SPECS),$R/lib/mk/spec/$S)))
ALL_LIB_MK_FILES := $(wildcard $(addsuffix /*.mk,$(ALL_LIB_MK_DIRS)))
LIBS := $(sort $(notdir $(ALL_LIB_MK_FILES:.mk=)))
endif
# #
# Helper function to check if a needed tool is installed # Helper function to check if a needed tool is installed
# #
@ -187,7 +210,7 @@ endif
# #
# Default rule: build all directories specified as make arguments # Default rule: build all directories specified as make arguments
# #
_all $(DST_DIRS): gen_deps_and_build_targets _all $(DST_DIRS) $(addprefix lib/,$(LIBS)) : gen_deps_and_build_targets
@true @true
## ##
@ -275,8 +298,15 @@ endif
# we would need to spawn one additional shell per target, which would take # we would need to spawn one additional shell per target, which would take
# 10-20 percent more time. # 10-20 percent more time.
# #
traverse_target_dependencies: $(dir $(LIB_DEP_FILE)) init_libdep_file init_progress_log traverse_dependencies: $(dir $(LIB_DEP_FILE)) init_libdep_file init_progress_log
$(VERBOSE_MK) \ $(VERBOSE_MK) \
for lib in $(LIBS); do \
$(MAKE) $(VERBOSE_DIR) -f $(BASE_DIR)/mk/dep_lib.mk \
REP_DIR=$$rep LIB=$$lib \
BUILD_BASE_DIR=$(BUILD_BASE_DIR) \
DARK_COL="$(DARK_COL)" DEFAULT_COL="$(DEFAULT_COL)"; \
echo "all: $$lib.lib" >> $(LIB_DEP_FILE); \
done; \
for target in $(TARGETS_TO_VISIT); do \ for target in $(TARGETS_TO_VISIT); do \
for rep in $(REPOSITORIES); do \ for rep in $(REPOSITORIES); do \
test -f $$rep/src/$$target || continue; \ test -f $$rep/src/$$target || continue; \
@ -288,29 +318,9 @@ traverse_target_dependencies: $(dir $(LIB_DEP_FILE)) init_libdep_file init_progr
done; \ done; \
done; $$result; done; $$result;
#
# Generate content of libdep file if manually building a single library
# specified via the 'LIB' argument.
#
traverse_lib_dependencies: $(dir $(LIB_DEP_FILE)) init_libdep_file init_progress_log
$(VERBOSE_MK) \
$(MAKE) $(VERBOSE_DIR) -f $(BASE_DIR)/mk/dep_lib.mk \
REP_DIR=$$rep LIB=$(LIB) \
BUILD_BASE_DIR=$(BUILD_BASE_DIR) \
DARK_COL="$(DARK_COL)" DEFAULT_COL="$(DEFAULT_COL)"; \
echo "all: $(LIB).lib" >> $(LIB_DEP_FILE); \
.PHONY: $(LIB_DEP_FILE) .PHONY: $(LIB_DEP_FILE)
# $(LIB_DEP_FILE): traverse_dependencies
# Depending on whether the top-level target is a list of targets or a
# single library, we populate the LIB_DEP_FILE differently.
#
ifeq ($(LIB),)
$(LIB_DEP_FILE): traverse_target_dependencies
else
$(LIB_DEP_FILE): traverse_lib_dependencies
endif
## ##

View File

@ -99,7 +99,7 @@ proc core_link_address { } { return "0x03000000" }
proc elfweaver {} { proc elfweaver {} {
if { ![file exists tool/okl4/elfweaver] } { build LIB=tools } if { ![file exists tool/okl4/elfweaver] } { build lib/tools }
return tool/okl4/elfweaver return tool/okl4/elfweaver
} }