1 # -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
3 # This file is part of the LibreOffice project.
5 # This Source Code Form is subject to the terms of the Mozilla Public
6 # License, v. 2.0. If a copy of the MPL was not distributed with this
7 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 # class ExternalProject
12 # Handles build of an external project
14 # Build of an external typically uses three gbuild classes:
15 # ExternalProject, ExternalPackage or Package, and UnpackedTarball. The
16 # first step is to prepare sources using UnpackedTarball. The tarball is
17 # passed to an ExternalProject, which handles the build proper and the
18 # results are delivered by an ExternalPackage (or Package, again;
19 # Package is sufficient if no files--e.g., headers--from the unpacked
20 # tarball need to be delivered.)
22 # An ExternalProject always uses one UnpackedTarball with the same name.
23 # The dependency strucure ensures that any change on a dependency
24 # of the ExternalProject will cause the UnpackedTarball to be unpacked
25 # again, so the ExternalProject always does a clean build and is not at
26 # the mercy of the external's build system's dubious incremental builds.
28 # ExternalProject target
29 # => ExternalProject state target(s) (these actually build stuff)
30 # => UnpackedTarball target (unpack the tarball)
31 # => UnpackedTarball prepare target
32 # => ExternalProject prepare target
33 # => stuff the external depends upon
35 # ExternalProject has no gbuild abstraction for actually building the
36 # external code, so it is necessary to define rule(s) and recipe(s) to
37 # handle it. It does not matter if there are several rules handling
38 # separate phases of the build (e.g., configure, build, install) or if
39 # the whole build is handled by one rule.
41 # ExternalProject uses two directories during the build: state dir
42 # serves to keep file targets that mark state of the build progress
43 # (e.g., "configure done", "build done") and the targets are accessible
44 # via gb_ExternalProject_get_state_target. It is highly advised to
45 # register them using gb_ExternalProject_register_targets. The second
46 # directory is work dir, accessible only from recipes via variable
47 # $(EXTERNAL_WORKDIR).
49 $(dir $(call gb_ExternalProject_get_statedir
,%))%/.
dir :
50 $(if
$(wildcard $(dir $@
)),,mkdir
-p
$(dir $@
))
52 $(dir $(call gb_ExternalProject_get_target
,%)).
dir :
53 $(if
$(wildcard $(dir $@
)),,mkdir
-p
$(dir $@
))
55 $(call gb_ExternalProject_get_preparation_target
,%) :
58 $(call gb_ExternalProject_get_target
,%) :
59 $(call gb_Output_announce
,$*,$(true
),PRJ
,3)
62 .PHONY
: $(call gb_ExternalProject_get_clean_target
,%)
63 $(call gb_ExternalProject_get_clean_target
,%) :
64 $(call gb_Output_announce
,$*,$(false
),PRJ
,3)
65 $(call gb_Helper_abbreviate_dirs
,\
67 $(call gb_ExternalProject_get_target
,$*) \
68 $(call gb_ExternalProject_get_statedir
,$*) \
71 # Define a new external project, using an unpacked tarball of the same name
73 # gb_ExternalProject_ExternalProject project
74 define gb_ExternalProject_ExternalProject
75 $(call gb_ExternalProject_get_target
,$(1)) : EXTERNAL_WORKDIR
:= $(call gb_UnpackedTarball_get_dir
,$(1))
77 $(call gb_ExternalProject_get_preparation_target
,$(1)) : $(gb_Module_CURRENTMAKEFILE
)
78 $(call gb_ExternalProject_get_preparation_target
,$(1)) :|
$(dir $(call gb_ExternalProject_get_target
,$(1))).
dir
79 $(call gb_UnpackedTarball_get_preparation_target
,$(1)) : $(call gb_ExternalProject_get_preparation_target
,$(1))
80 $(call gb_ExternalProject_get_clean_target
,$(1)) : $(call gb_UnpackedTarball_get_clean_target
,$(1))
81 $(call gb_ExternalProject_get_target
,$(1)) : $(call gb_UnpackedTarball_get_target
,$(1))
82 $(call gb_ExternalProject_get_target
,$(1)) :|
$(dir $(call gb_ExternalProject_get_target
,$(1))).
dir
84 $$(eval
$$(call gb_Module_register_target
,$(call gb_ExternalProject_get_target
,$(1)),$(call gb_ExternalProject_get_clean_target
,$(1))))
85 $(call gb_Helper_make_userfriendly_targets
,$(1),ExternalProject
)
89 # Depend on an unpacked tarball
91 # This is needed to express dependencies on header-only projects, which
92 # do not have any ExternalProject.
94 # gb_ExternalProject_use_unpacked project unpacked
95 define gb_ExternalProject_use_unpacked
96 $(call gb_ExternalProject_get_preparation_target
,$(1)) : $(call gb_UnpackedTarball_get_target
,$(2))
100 # Register a target in state directory
102 # This function defines proper dependencies for the target to ensure
104 # * the main target is updated if this target is updated
105 # * this target is updated if the unpacked tarball has changed.
107 # gb_ExternalProject_register_target project target
108 define gb_ExternalProject_register_target
109 $(call gb_ExternalProject_get_target
,$(1)) : $(call gb_ExternalProject_get_state_target
,$(1),$(2))
110 $(call gb_ExternalProject_get_state_target
,$(1),$(2)) : $(call gb_UnpackedTarball_get_target
,$(1))
111 $(call gb_ExternalProject_get_state_target
,$(1),$(2)) :|
$(dir $(call gb_ExternalProject_get_state_target
,$(1),$(2))).
dir
115 # Register several targets at once
117 # gb_ExternalProject_register_targets project target(s)
118 define gb_ExternalProject_register_targets
119 $(foreach target
,$(2),$(call gb_ExternalProject_register_target
,$(1),$(target
)))
123 # Make an external Project depend on another ExternalProject
124 define gb_ExternalProject_use_external_project
125 $(call gb_ExternalProject_get_preparation_target
,$(1)) : $(call gb_ExternalProject_get_target
,$(2))
129 # call gb_ExternalProject_use_external_projects,project,projects
130 define gb_ExternalProject_use_external_projects
131 $(foreach ext
,$(2),$(call gb_ExternalProject_use_external_project
,$(1),$(ext
)))
134 # Make an ExternalProject depend on an external
136 # this forwards to functions that must be defined in RepositoryExternal.mk.
137 # $(eval $(call gb_ExternalProject_use_external,library,external))
138 define gb_ExternalProject_use_external
139 $(if
$(filter undefined
,$(origin gb_ExternalProject__use_
$(2))),\
140 $(error gb_ExternalProject_use_external
: unknown external
: $(2)),\
141 $(call gb_ExternalProject__use_
$(2),$(1)))
144 define gb_ExternalProject_use_externals
145 $(foreach external
,$(2),$(call gb_ExternalProject_use_external
,$(1),$(external
)))
148 # Make an external project depend on a package
150 # This is most useful for depending on output files created by another
153 # gb_ExternalProject_use_package external package
154 define gb_ExternalProject_use_package
155 $(call gb_ExternalProject_get_preparation_target
,$(1)) : $(call gb_Package_get_target
,$(2))
159 # Make an external project depend on several packages at once
161 # gb_ExternalProject_use_packages external package(s)
162 define gb_ExternalProject_use_packages
163 $(foreach package
,$(2),$(call gb_ExternalProject_use_package
,$(1),$(package
)))
167 # Make an external project depend on a StaticLibrary
169 # Realistically there are some externals that do not have a usable build
170 # system, and other externals that do may depend on those.
172 # gb_ExternalProject_use_static_libraries external staticlibraries
173 define gb_ExternalProject_use_static_libraries
174 $(call gb_ExternalProject_get_preparation_target
,$(1)) : \
175 $(foreach lib
,$(2),$(call gb_StaticLibrary_get_target
,$(lib
)))
179 # Make an external project depend on a Library
181 # Realistically there are some externals that do not have a usable build
182 # system, and other externals that do may depend on those.
184 # gb_ExternalProject_use_libraries external libraries
185 define gb_ExternalProject_use_libraries
186 ifneq (,$$(filter-out $(gb_Library_KNOWNLIBS
),$(2)))
187 $$(eval
$$(call gb_Output_info
,currently known libraries are
: $(sort $(gb_Library_KNOWNLIBS
)),ALL
))
188 $$(eval
$$(call gb_Output_error
,Cannot link against library
/libraries
$$(filter-out $(gb_Library_KNOWNLIBS
),$(2)). Libraries must be registered in Repository.mk or RepositoryExternal.mk
))
190 ifneq (,$$(filter $$(gb_MERGEDLIBS
),$(2)))
191 $$(eval
$$(call gb_Output_error
,Cannot link against library
/libraries
$$(filter $$(gb_MERGEDLIBS
),$(2)) because they are merged.
))
194 $(call gb_ExternalProject_get_preparation_target
,$(1)) : \
195 $(foreach lib
,$(2),$(call gb_Library_get_target
,$(lib
)))
199 # Make an external project depend on a Jar file
201 # gb_ExternalProject_use_jars external jars
202 define gb_ExternalProject_use_jars
203 $(call gb_ExternalProject_get_preparation_target
,$(1)) : \
204 $(foreach jar
,$(2),$(call gb_Jar_get_target
,$(jar
)))
208 # Run a target command
210 # This provides a wrapper that changes to the right directory,
211 # touches the 'target' if successful and also provides
212 # the ability to hide the output if there is no failure
213 # gb_ExternalProject_run,run_target,command,optional_extra_sub_directory,optional_log_filename)
214 # default log_filename is <run_target>.log
217 define gb_ExternalProject_run
218 $(if
$(findstring YES
,$(UNPACKED_IS_BIN_TARBALL
)),\
220 $(call gb_Helper_print_on_error
,cd
$(EXTERNAL_WORKDIR
)/$(3) && \
222 $(if
$(WRAPPERS
),export $(WRAPPERS
) &&) \
223 $(if
$(NMAKE
),INCLUDE
="$(gb_ExternalProject_INCLUDE)" LIB
="$(ILIB)" MAKEFLAGS
=) \
224 $(2) && touch
$@
,$(EXTERNAL_WORKDIR
)/$(if
$(3),$(3)/,)$(if
$(4),$(4),$(1).log
))
228 # vim: set noet sw=4 ts=4: