xref: /haiku/build/jam/FileRules (revision 16d5c24e533eb14b7b8a99ee9f3ec9ba66335b1e)
1rule SymLink
2{
3	# SymLink <target> : <source> : <makeDefaultDependencies> ;
4	# Links <target> to <source>.
5	# <source> is the exact link contents. No binding is done.
6	# <makeDefaultDependencies> If true, <target> will be made a dependency
7	# of the `all' pseudo target, i.e. it will be made by default, and removed
8	# on `jam clean'.
9
10	local target = $(1) ;
11	local source = $(2) ;
12	local makeDefaultDependencies = $(3) ;
13	if ! $(makeDefaultDependencies) {
14		makeDefaultDependencies = true ;
15	}
16	LINKCONTENTS on $(target) = $(source) ;
17	SymLink1 $(target) ;
18	if $(makeDefaultDependencies) = true {
19		LocalDepends files : $(target) ;
20		LocalClean clean : $(target) ;
21	}
22}
23
24actions SymLink1
25{
26	$(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)"
27}
28
29rule RelSymLink
30{
31	# RelSymLink <link> : <link target> : <makeDefaultDependencies> ;
32	# Creates a relative symbolic link from <link> to <link target>.
33	# <link> and <link target> can be usual targets. They may have a grist
34	# and don't need to have any dirname. Their LOCATE variables are used to
35	# find their locations.
36	# <makeDefaultDependencies> If true (which is the default), <link> will be
37	# made a dependency of the `files' pseudo target, i.e. it will be made by
38	# default, and removed on `jam clean'.
39
40	local target = $(1) ;
41	local source = $(2) ;
42	local makeDefaultDependencies = $(3) ;
43	local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ;
44	local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ;
45	local sourcePath = $(source:G=) ;
46	sourcePath = $(sourcePath:D=$(sourceDir)) ;
47	local targetDirComponents = [ FSplitPath $(targetDir) ] ;
48	local sourceComponents = [ FSplitPath $(sourcePath) ] ;
49
50	SymLink $(target)
51		: [ FRelPath $(targetDirComponents) : $(sourceComponents) ]
52		: $(makeDefaultDependencies) ;
53	NOUPDATE $(target) ;
54	Depends $(target) : $(source) ;
55}
56
57rule AbsSymLink
58{
59	# AbsSymLink <link> : <link target> : <link dir>
60	#			: <makeDefaultDependencies> ;
61	# Creates an absolute symbolic link from <link> to <link target>.
62	# <link> and <link target> must be usual targets. If <link dir> is
63	# given, then it is set as LOCATE directory on <link>.
64	# <makeDefaultDependencies> If true (which is the default), <link> will be
65	# made a dependency of the `files' pseudo target, i.e. it will be made by
66	# default, and removed on `jam clean'.
67
68	local makeDefaultDependencies = $(4) ;
69	if ! $(makeDefaultDependencies) {
70		makeDefaultDependencies = true ;
71	}
72
73	Depends $(1) : $(2) ;
74	if $(3) {
75		MakeLocate $(1) : $(3) ;
76	}
77	SEARCH on $(2) += $(SEARCH_SOURCE) ;
78	if $(makeDefaultDependencies) = true {
79		LocalDepends files : $(1) ;
80		LocalClean clean : $(1) ;
81	}
82}
83
84actions AbsSymLink
85{
86	target="$(2)"
87	case "$target" in
88		/*) ;;
89		*) target=`pwd`/"$target";;
90	esac
91	$(RM) "$(1)" && $(LN) -s "$target" "$(1)"
92}
93
94rule HaikuInstall
95{
96	# Usage: HaikuInstall <[ install [ and uninstall ] pseudotarget ]>
97	#					 : <directory> : <sources to install>
98	#					 : [ <installgrist> ] : [ <install rule> ] ;
99	local install = $(1[1]) ;
100	install ?= install ;
101	local uninstall = $(1[2]) ;
102	uninstall ?= un$(install) ;
103	local dir = $(2) ;
104	local sources = $(3) ;
105	local installgrist = $(4) ;
106	installgrist ?= $(INSTALLGRIST) ;
107	local installRule = $(5) ;
108	installRule ?= Install ;
109	local targets = $(sources:G=$(installgrist)) ;
110
111	NotFile $(install) ;
112	NotFile $(uninstall) ;
113	Depends $(install) : $(targets) ;
114	Clean $(uninstall) : $(targets) ;
115
116	SEARCH on $(sources) += $(SEARCH_SOURCE) ;
117	MakeLocate $(targets) : $(dir) ;
118
119	local source ;
120	for source in $(sources) {
121		local target = $(source:G=$(installgrist)) ;
122
123		Depends $(target) : $(source) ;
124		$(installRule) $(target) : $(source) ;
125
126		if [ on $(target) return $(MODE) ] {
127			Chmod $(target) ;
128		}
129
130		if $(OWNER) && $(CHOWN) {
131			Chown $(target) ;
132			OWNER on $(target) = $(OWNER) ;
133		}
134
135		if $(GROUP) && $(CHGRP) {
136			Chgrp $(target) ;
137			GROUP on $(target) = $(GROUP) ;
138		}
139	}
140}
141
142rule InstallAbsSymLinkAdapter
143{
144	# InstallAbsSymLinkAdapter <link> : <link target>
145	if ! [ on $(2) return $(TARGET) ] {
146		TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;
147	}
148	AbsSymLink $(1) : $(2) : : false ;
149}
150
151rule HaikuInstallAbsSymLink
152{
153	# Usage: HaikuInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]>
154	#							   : <directory> : <sources to install>
155	#							   : [ <installgrist> ] ;
156	HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ;
157}
158
159rule InstallRelSymLinkAdapter
160{
161	# InstallRelSymLinkAdapter <link> : <link target>
162	if ! [ on $(2) return $(TARGET) ] {
163		TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;
164	}
165	RelSymLink $(1) : $(2) : false ;
166}
167
168rule HaikuInstallRelSymLink
169{
170	# Usage: HaikuInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]>
171	#							   : <directory> : <sources to install>
172	#							   : [ <installgrist> ] ;
173	HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ;
174}
175
176
177rule UnarchiveObjects
178{
179	# UnarchiveObjects <target objects> : <static object>
180
181	MakeLocateArch $(1) ;
182	Depends $(1) : $(2) ;
183	SEARCH on $(2) = $(SEARCH_SOURCE) ;
184}
185
186actions UnarchiveObjects
187{
188	( cd $(1[1]:D) && $(TARGET_AR) $(TARGET_UNARFLAGS) "$(2)" $(1:BS) )
189}
190
191
192rule UnzipArchive directory : entries : zipFile : grist
193{
194	# UnzipArchive <directory> : <entries> : <zipFile> [ : <grist> ]
195	#
196	# Unzips the zip file target <zipFile> to directory <directory>. The rule
197	# can be called multiple times for different <entries> for the same
198	# <directory> and <zipFile> combo.
199	#
200	# <directory> - The directory into which to unzip the zip file. The
201	#               directory is created is by this rule and it is the target
202	#               that the unzip action is associated with.
203	# <entries>   - The entries of the zip file one is interested in. The rule
204	#               always unzips the complete zip file, from the given entries
205	#               the rule creates targets (using <grist>) representing the
206	#               unzipped entries. Those targets are returned by the rule.
207	# <zipFile>   - The zip file target to unzip.
208	# <grist>     - The grist used to create targets from <entries>. Defaults to
209	#               "unzipped".
210
211	grist ?= unzipped ;
212
213	# Turn the entries into targets to build.
214	local targets ;
215	local entry ;
216	for entry in $(entries) {
217		local target = $(entry:G=$(grist)) ;
218		targets += $(target) ;
219	}
220
221	LOCATE on $(targets) = $(directory) ;
222	Depends $(targets) : $(directory) ;
223	NoUpdate $(targets) ;
224
225	# one-time initialization for the main target (the directory)
226	if ! [ on $(directory) return $(INITIALIZED) ] {
227		# make sure the parent dir exists
228		local parentDir = $(directory:PG=dir) ;
229		Depends $(directory) : $(parentDir) ;
230		MkDir $(parentDir) ;
231
232		NoUpdate $(directory) ;
233		Depends $(directory) : $(zipFile) ;
234		UnzipArchive1 $(directory) : $(zipFile) ;
235		INITIALIZED on $(directory) = 1 ;
236	}
237
238	# Use a dummy rule so that it looks to jam like the targets are actually
239	# built from the directory target.
240	UnzipArchiveDummy $(targets) : $(directory) ;
241
242	return $(targets) ;
243}
244
245actions UnzipArchive1
246{
247	mkdir -p $(1[1])
248	unzip -q -u -o -d $(1[1]) $(2)
249}
250
251actions UnzipArchiveDummy
252{
253}
254
255
256rule ObjectReference
257{
258	# ObjectReference <reference object> : <source object>
259	# Makes <reference object> refer to the same file as <source object>.
260	# The filenames must of course be identical.
261	# <source object> must have already been LOCATEd.
262
263	local ref = $(1) ;
264	local source = $(2) ;
265	if $(ref) != $(source) {
266		Depends $(ref) : $(source) ;
267		LOCATE on $(ref) = [ on $(source) return $(LOCATE) ] ;
268	}
269}
270
271rule ObjectReferences
272{
273	# ObjectReferences <source objects>
274	# Creates local references to <source objects>, i.e. identifiers with the
275	# current grist referring to the same files. <source objects> must have
276	# already been LOCATEd.
277
278	local source ;
279	for source in $(1) {
280		ObjectReference [ FGristFiles $(source) ] : $(source) ;
281	}
282}
283
284rule CopySetHaikuRevision target : source
285{
286	# CopySetHaikuRevision <target> : <source>
287	#
288	# Copy <source> to <target>, writing the SVN revision of the working root
289	# directory into the haiku revision section of <target>.
290	#
291	# <target> - Output file target. Gristed and located target.
292	# <source> - ELF object to be copied. Gristed and located target.
293
294	# If existent, make the target depend on the .svn/entries file in the
295	# root directory, so it gets updated when the revision changes due to
296	# "svn up".
297	if [ Glob [ FDirName $(HAIKU_TOP) .svn ] : entries ] {
298		local svnEntries = <haiku-rootdir-svn>entries ;
299		SEARCH on $(svnEntries) = [ FDirName $(HAIKU_TOP) .svn ] ;
300		Depends $(target) : $(svnEntries) ;
301	} else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] {
302		local gitIndex = <haiku-rootdir-git>index ;
303		SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ;
304		Depends $(target) : $(gitIndex) ;
305	}
306
307	HAIKU_INCLUDE_IN_IMAGE on $(target)
308		= [ on $(source) return $(HAIKU_INCLUDE_IN_IMAGE) ] ;
309
310	Depends $(target) : <build>copyattr <build>set_haiku_revision $(source) ;
311	CopySetHaikuRevision1 $(target)
312		: <build>copyattr <build>set_haiku_revision $(source) ;
313}
314
315actions CopySetHaikuRevision1
316{
317	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
318	# Try svn or git-svn
319	# Extract from "Revision: 12345" line
320	revision=`(LC_ALL=C LANG=C svn info $(HAIKU_TOP) ||
321		(cd $(HAIKU_TOP) && LC_ALL=C LANG=C git svn info)) 2> /dev/null |
322			grep Revision | awk '{printf $2}'`
323	if [ "$revision" = 0 -o "$revision" = "" ]; then
324		# git-svn not present or not configured for this repository
325		# Try searching git logs for last git-svn commit
326		# Extract from " git-svn-id: .../haiku/trunk@12345 ..." line
327		revision=`cd $(HAIKU_TOP) &&
328			git log --max-count=1 --grep="git-svn-id:" 2> /dev/null |
329				grep "git-svn-id:" | cut -d '@' -f 2 |
330					awk '{printf $1}'`
331	fi
332	if [ "$revision" = "" ]; then
333		revision=0
334	fi
335	$(2[1]) --data $(2[3]) $(1) &&
336	$(2[2]) $(1) ${revision}
337}
338
339rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable
340{
341	sourceFile = [ FGristFiles $(sourceFile) ] ;
342	MakeLocateCommonPlatform $(sourceFile) ;
343
344	sizeVariable ?= $(dataVariable)Size ;
345
346	DATA_VARIABLE on $(sourceFile) = $(dataVariable) ;
347	SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ;
348
349	Depends $(sourceFile) : <build>data_to_source $(dataFile) ;
350	DataFileToSourceFile1 $(sourceFile) : <build>data_to_source $(dataFile) ;
351	LocalClean clean : $(sourceFile) ;
352}
353
354actions DataFileToSourceFile1
355{
356	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
357	$(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1)
358}
359
360rule DownloadFile target : url
361{
362	URL on $(target) = $(url) ;
363
364	DownloadFile1 $(target) ;
365}
366
367actions DownloadFile1
368{
369	wget -O $(1) $(URL)
370}
371
372rule DownloadOptionalPackage package : url
373{
374	# download zip file
375	local zipFile = $(package:G=download).zip ;
376
377	# Request the download only once.
378	if [ on $(zipFile) return $(HAIKU_OPTIONAL_PACKAGE_DOWNLOAD) ] {
379		return $(zipFile) ;
380	}
381
382	HAIKU_OPTIONAL_PACKAGE_DOWNLOAD on $(zipFile) = 1 ;
383
384	MakeLocate $(zipFile) : $(HAIKU_DOWNLOAD_DIR) ;
385	DownloadFile $(zipFile) : $(url) ;
386
387	return $(zipFile) ;
388}
389