office-gobmx/solenv/gbuild/ExternalProject.mk
Christian Lohmaier 875a1bf2e1 makefile simplification: replace $(call gb_UnpackedTarball_get_dir,foo)
…by a simple/static $(gb_UnpackedTarball_workdir)/foo
see also 0c4c84a14b

Change-Id: I8e6aa55c85534c4446556548910c950ddbe7c6fc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167163
Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice@googlemail.com>
Tested-by: Jenkins
2024-05-06 11:40:45 +02:00

238 lines
9.5 KiB
Makefile

# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#
# This file is part of the LibreOffice project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# class ExternalProject
# Handles build of an external project
# Build of an external typically uses three gbuild classes:
# ExternalProject, ExternalPackage or Package, and UnpackedTarball. The
# first step is to prepare sources using UnpackedTarball. The tarball is
# passed to an ExternalProject, which handles the build proper and the
# results are delivered by an ExternalPackage (or Package, again;
# Package is sufficient if no files--e.g., headers--from the unpacked
# tarball need to be delivered.)
#
# An ExternalProject always uses one UnpackedTarball with the same name.
# The dependency structure ensures that any change on a dependency
# of the ExternalProject will cause the UnpackedTarball to be unpacked
# again, so the ExternalProject always does a clean build and is not at
# the mercy of the external's build system's dubious incremental builds.
#
# ExternalProject target
# => ExternalProject state target(s) (these actually build stuff)
# => UnpackedTarball target (unpack the tarball)
# => UnpackedTarball prepare target
# => ExternalProject prepare target
# => stuff the external depends upon
#
# ExternalProject has no gbuild abstraction for actually building the
# external code, so it is necessary to define rule(s) and recipe(s) to
# handle it. It does not matter if there are several rules handling
# separate phases of the build (e.g., configure, build, install) or if
# the whole build is handled by one rule.
#
# ExternalProject uses two directories during the build: state dir
# serves to keep file targets that mark state of the build progress
# (e.g., "configure done", "build done") and the targets are accessible
# via gb_ExternalProject_get_state_target. It is highly advised to
# register them using gb_ExternalProject_register_targets. The second
# directory is work dir, accessible only from recipes via variable
# $(EXTERNAL_WORKDIR).
$(dir $(call gb_ExternalProject_get_statedir,%))%/.dir :
$(if $(wildcard $(dir $@)),,mkdir -p $(dir $@))
$(dir $(call gb_ExternalProject_get_target,%)).dir :
$(if $(wildcard $(dir $@)),,mkdir -p $(dir $@))
$(call gb_ExternalProject_get_preparation_target,%) :
touch $@
$(call gb_ExternalProject_get_target,%) :
$(call gb_Output_announce,$*,$(true),PRJ,3)
$(call gb_Trace_MakeMark,$*,PRJ)
touch $@
.PHONY : $(call gb_ExternalProject_get_clean_target,%)
$(call gb_ExternalProject_get_clean_target,%) :
$(call gb_Output_announce,$*,$(false),PRJ,3)
$(call gb_Helper_abbreviate_dirs,\
rm -rf \
$(call gb_ExternalProject_get_target,$*) \
$(call gb_ExternalProject_get_statedir,$*) \
)
# Define a new external project, using an unpacked tarball of the same name
#
# gb_ExternalProject_ExternalProject project
define gb_ExternalProject_ExternalProject
$(call gb_ExternalProject_get_target,$(1)) : EXTERNAL_WORKDIR := $(gb_UnpackedTarball_workdir)/$(1)
$(call gb_ExternalProject_get_preparation_target,$(1)) : $(gb_Module_CURRENTMAKEFILE)
$(call gb_ExternalProject_get_preparation_target,$(1)) :| $(dir $(call gb_ExternalProject_get_target,$(1))).dir
$(call gb_UnpackedTarball_get_preparation_target,$(1)) : $(call gb_ExternalProject_get_preparation_target,$(1))
$(call gb_ExternalProject_get_clean_target,$(1)) : $(call gb_UnpackedTarball_get_clean_target,$(1))
$(call gb_ExternalProject_get_target,$(1)) : $(call gb_UnpackedTarball_get_target,$(1))
$(call gb_ExternalProject_get_target,$(1)) :| $(dir $(call gb_ExternalProject_get_target,$(1))).dir
$$(eval $$(call gb_Module_register_target,$(call gb_ExternalProject_get_target,$(1)),$(call gb_ExternalProject_get_clean_target,$(1))))
$(call gb_Helper_make_userfriendly_targets,$(1),ExternalProject)
endef
# Depend on an unpacked tarball
#
# This is needed to express dependencies on header-only projects, which
# do not have any ExternalProject.
#
# gb_ExternalProject_use_unpacked project unpacked
define gb_ExternalProject_use_unpacked
$(call gb_ExternalProject_get_preparation_target,$(1)) : $(call gb_UnpackedTarball_get_target,$(2))
endef
# Register a target in state directory
#
# This function defines proper dependencies for the target to ensure
# that:
# * the main target is updated if this target is updated
# * this target is updated if the unpacked tarball has changed.
#
# gb_ExternalProject_register_target project target
define gb_ExternalProject_register_target
$(call gb_ExternalProject_get_target,$(1)) : $(call gb_ExternalProject_get_state_target,$(1),$(2))
$(call gb_ExternalProject_get_state_target,$(1),$(2)) : $(call gb_UnpackedTarball_get_target,$(1))
$(call gb_ExternalProject_get_state_target,$(1),$(2)) :| $(dir $(call gb_ExternalProject_get_state_target,$(1),$(2))).dir
endef
# Register several targets at once
#
# gb_ExternalProject_register_targets project target(s)
define gb_ExternalProject_register_targets
$(foreach target,$(2),$(call gb_ExternalProject_register_target,$(1),$(target)))
endef
# Make an external Project depend on another ExternalProject
define gb_ExternalProject_use_external_project
$(call gb_ExternalProject_get_preparation_target,$(1)) : $(call gb_ExternalProject_get_target,$(2))
endef
# call gb_ExternalProject_use_external_projects,project,projects
define gb_ExternalProject_use_external_projects
$(foreach ext,$(2),$(call gb_ExternalProject_use_external_project,$(1),$(ext)))
endef
# Make an ExternalProject depend on an external
#
# this forwards to functions that must be defined in RepositoryExternal.mk.
# $(eval $(call gb_ExternalProject_use_external,library,external))
define gb_ExternalProject_use_external
$(if $(filter undefined,$(origin gb_ExternalProject__use_$(2))),\
$(error gb_ExternalProject_use_external: unknown external: $(2)),\
$(call gb_ExternalProject__use_$(2),$(1)))
endef
define gb_ExternalProject_use_externals
$(foreach external,$(2),$(call gb_ExternalProject_use_external,$(1),$(external)))
endef
# Make an external project depend on a package
#
# This is most useful for depending on output files created by another
# ExternalProject.
#
# gb_ExternalProject_use_package external package
define gb_ExternalProject_use_package
$(call gb_ExternalProject_get_preparation_target,$(1)) : $(call gb_Package_get_target,$(2))
endef
# Make an external project depend on several packages at once
#
# gb_ExternalProject_use_packages external package(s)
define gb_ExternalProject_use_packages
$(foreach package,$(2),$(call gb_ExternalProject_use_package,$(1),$(package)))
endef
# Make an external project depend on a StaticLibrary
#
# Realistically there are some externals that do not have a usable build
# system, and other externals that do may depend on those.
#
# gb_ExternalProject_use_static_libraries external staticlibraries
define gb_ExternalProject_use_static_libraries
$(call gb_ExternalProject_get_preparation_target,$(1)) : \
$(foreach lib,$(2),$(call gb_StaticLibrary_get_target,$(lib)))
endef
# Make an external project depend on a Library
#
# Realistically there are some externals that do not have a usable build
# system, and other externals that do may depend on those.
#
# gb_ExternalProject_use_libraries external libraries
define gb_ExternalProject_use_libraries
ifneq (,$$(filter-out $(gb_Library_KNOWNLIBS) $(gb_LinkTarget__syslib),$(2)))
$$(eval $$(call gb_Output_info,currently known libraries are: $(sort $(gb_Library_KNOWNLIBS)),ALL))
$$(eval $$(call gb_Output_error,Cannot link against library/libraries $$(filter-out $(gb_Library_KNOWNLIBS) $(gb_LinkTarget__syslib),$(2)). Libraries must be registered in Repository.mk or RepositoryExternal.mk))
endif
ifneq (,$$(filter $$(gb_MERGEDLIBS),$(2)))
$$(eval $$(call gb_Output_error,Cannot link against library/libraries $$(filter $$(gb_MERGEDLIBS),$(2)) because they are merged.))
endif
$(call gb_ExternalProject_get_preparation_target,$(1)) : \
$(foreach lib,$(2),$(call gb_Library_get_target,$(lib)))
endef
# Make an external project depend on a Jar file
#
# gb_ExternalProject_use_jars external jars
define gb_ExternalProject_use_jars
$(call gb_ExternalProject_get_preparation_target,$(1)) : \
$(foreach jar,$(2),$(call gb_Jar_get_target,$(jar)))
endef
# Returns flags to include in CFLAGS/CXXFLAGS to enable optimizations and/or debugging.
# gb_ExternalProject_get_build_flags project
gb_ExternalProject_get_build_flags = $(call gb_LinkTarget__get_debugflags,ExternalProject_$(1))
# Returns flags to include in LDFLAGS to enable optimizations and/or debugging.
# gb_ExternalProject_get_link_flags project
gb_ExternalProject_get_link_flags = $(LDFLAGS) $(USE_LD) $(call gb_LinkTarget__get_debugldflags,ExternalProject_$(1))
# Run a target command
#
# This provides a wrapper that changes to the right directory,
# touches the 'target' if successful and also provides
# the ability to hide the output if there is no failure
# gb_ExternalProject_run,run_target,command,optional_extra_sub_directory,optional_log_filename)
# default log_filename is <run_target>.log
#
define gb_ExternalProject_run
$(if $(findstring YES,$(UNPACKED_IS_BIN_TARBALL)),\
touch $@,
$(call gb_Helper_print_on_error,cd $(EXTERNAL_WORKDIR)/$(3) && \
unset Platform && \
$(if $(WRAPPERS),export $(WRAPPERS) &&) \
$(if $(NMAKE),export $(NMAKE) &&) \
$(if $(gb_COMPILER_SETUP),export $(gb_COMPILER_SETUP) &&) \
$(2) && touch $@,$(EXTERNAL_WORKDIR)/$(if $(3),$(3)/,)$(if $(4),$(4),$(1).log))
)
endef
# vim: set noet sw=4 ts=4: