diff options
Diffstat (limited to 'solenv/gbuild/ExternalProject.mk')
-rw-r--r-- | solenv/gbuild/ExternalProject.mk | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/solenv/gbuild/ExternalProject.mk b/solenv/gbuild/ExternalProject.mk new file mode 100644 index 000000000..5227e6c13 --- /dev/null +++ b/solenv/gbuild/ExternalProject.mk @@ -0,0 +1,238 @@ +# -*- 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 := $(call gb_UnpackedTarball_get_dir,$(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: |