xref: /haiku/build/jam/RepositoryRules (revision 040a81419dda83d1014e9dc94936a4cb3f027303)
1#pragma mark - Private
2
3
4rule PackageFamily packageBaseName
5{
6	return $(packageBaseName:G=package-family) ;
7}
8
9
10rule SetRepositoryMethod repository : methodName : method
11{
12	HAIKU_REPOSITORY_METHOD_$(methodName) on $(repository) = $(method) ;
13}
14
15rule InvokeRepositoryMethod repository : methodName : arg1 : arg2 : arg3 : arg4
16	: arg5 : arg6 : arg7
17{
18	local method
19		= [ on $(repository) return $(HAIKU_REPOSITORY_METHOD_$(methodName)) ] ;
20	if ! $(method) {
21		Exit "Method" $(methodName) " not defined for repository"
22			$(repository) ;
23	}
24
25	return [ $(method) $(repository) : $(arg1) : $(arg2) : $(arg3) : $(arg4)
26		: $(arg5) : $(arg6) : $(arg7) ] ;
27}
28
29
30rule AddRepositoryPackage repository : architecture : baseName : version
31{
32	local package = $(baseName)-$(version) ;
33	package = $(package:E=$(baseName):G=package-in-$(repository:G=)) ;
34	HAIKU_PACKAGE_REPOSITORY on $(package) = $(repository) ;
35	HAIKU_PACKAGE_ARCHITECTURE on $(package) = $(architecture) ;
36	HAIKU_PACKAGE_FILE_NAME on $(package) = $(package:G=)-$(architecture).hpkg ;
37
38	local packageFamily = [ InvokeRepositoryMethod $(repository) : PackageFamily
39		: $(baseName) ] ;
40	baseName = $(packageFamily:G=) ;
41
42	if ! $(baseName) in $(HAIKU_AVAILABLE_PACKAGES) {
43		HAIKU_AVAILABLE_PACKAGES += $(baseName) ;
44	}
45
46	HAIKU_PACKAGE_VERSIONS on $(packageFamily) += $(package) ;
47	HAIKU_REPOSITORY_PACKAGES on $(repository) += $(package) ;
48
49	return $(package) ;
50}
51
52
53rule AddRepositoryPackages repository : architecture : packages : sourcePackages
54	: debugInfoPackages
55{
56	local packageTargets ;
57	local package ;
58	for package in $(packages) {
59		local splitName = [ Match "([^-]*)-(.*)" : $(package) ] ;
60		local baseName = $(splitName[1]:E=$(package)) ;
61		local version = $(splitName[2]) ;
62		packageTargets += [ AddRepositoryPackage $(repository) : $(architecture)
63			: $(baseName) : $(version) ] ;
64		if $(baseName) in $(sourcePackages) {
65			AddRepositoryPackage $(repository) : source : $(baseName)_source
66				: $(version) ;
67		}
68		if $(baseName) in $(debugInfoPackages) {
69			packageTargets += [ AddRepositoryPackage $(repository)
70				: $(architecture) : $(baseName)_debuginfo : $(version) ] ;
71		}
72	}
73
74	return $(packageTargets) ;
75}
76
77
78rule PackageRepository repository : architecture : anyPackages : packages
79	: sourcePackages : debugInfoPackages
80{
81	if $(architecture) != $(HAIKU_PACKAGING_ARCHS[1]) {
82		return ;
83	}
84
85	HAIKU_REPOSITORIES += $(repository) ;
86	HAIKU_REPOSITORY_DEFINITION_FILE on $(repository)
87		= $(HAIKU_REPOSITORY_JAMFILE) ;
88
89	return [ AddRepositoryPackages $(repository) : any : $(anyPackages)
90			: $(sourcePackages) : $(debugInfoPackages) ]
91		[ AddRepositoryPackages $(repository) : $(architecture) : $(packages)
92			: $(sourcePackages) : $(debugInfoPackages) ] ;
93}
94
95
96#pragma mark - Remote Repository
97
98
99rule RemoteRepositoryPackageFamily repository : packageBaseName
100{
101	return [ PackageFamily $(packageBaseName) ] ;
102}
103
104
105rule RemoteRepositoryFetchPackage repository : package : fileName
106{
107	local baseUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ;
108	local packagesChecksumFile
109		= [ on $(repository)
110			return $(HAIKU_REPOSITORY_PACKAGES_CHECKSUM_FILE) ] ;
111
112	local downloadedFile = [ DownloadFile $(fileName)
113		: "$(baseUrl)/`cat $source`/packages/$(fileName)"
114		: $(packagesChecksumFile) ] ;
115	NoUpdate $(downloadedFile) ;
116		# Don't download the file again when something in the repository
117		# changes. It is (supposed to be) still the same file.
118	return $(downloadedFile) ;
119}
120
121
122rule RemotePackageRepository repository : architecture : repositoryUrl
123	: anyPackages : packages : sourcePackages : debugInfoPackages
124{
125	repository = $(repository:G=repository) ;
126
127	SetRepositoryMethod $(repository) : PackageFamily
128		: RemoteRepositoryPackageFamily ;
129	SetRepositoryMethod $(repository) : FetchPackage
130		: RemoteRepositoryFetchPackage ;
131
132	HAIKU_REPOSITORY_URL on $(repository) = $(repositoryUrl) ;
133
134	PackageRepository $(repository) : $(architecture) : $(anyPackages)
135		: $(packages) : $(sourcePackages) : $(debugInfoPackages) ;
136
137	# build package list file
138	local packageListFile = $(repository:G=repository-package-list)-packages ;
139	local repositoriesDir = $(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture)) ;
140	MakeLocate $(packageListFile) : $(repositoriesDir) ;
141	GeneratedRepositoryPackageList $(packageListFile) : $(repository) ;
142
143	# build package list checksum file
144	local packagesChecksumFile
145		= $(repository:G=repository-package-checksum)-checksum ;
146	MakeLocate $(packagesChecksumFile) : $(repositoriesDir) ;
147	Depends $(packagesChecksumFile) : $(packageListFile) ;
148	ChecksumFileSHA256 $(packagesChecksumFile) : $(packageListFile) ;
149
150	# download repository info file
151	local repositoryInfo = $(repository:G=repository-info)-info ;
152	MakeLocate $(repositoryInfo) : $(repositoriesDir) ;
153	local repoUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ;
154	DownloadLocatedFile $(repositoryInfo)
155		: "$(repoUrl)/`cat $source`/repo.info"
156		: $(packagesChecksumFile) ;
157
158	# download repository file
159	local repositoryFile = $(repository:G=repository-cache) ;
160	MakeLocate $(repositoryFile) : $(repositoriesDir) ;
161	local repoUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ;
162	DownloadLocatedFile $(repositoryFile)
163		: "$(repoUrl)/`cat $source`/repo"
164		: $(packagesChecksumFile) ;
165
166	# build repository config file
167	local repositoryConfig = $(repository:G=repository-config)-config ;
168	MakeLocate $(repositoryConfig) : $(repositoriesDir) ;
169	RepositoryConfig $(repositoryConfig) : $(repositoryInfo)
170		: $(packagesChecksumFile) : $(repository) ;
171
172	HAIKU_REPOSITORY_CACHE_FILE on $(repository) = $(repositoryFile) ;
173	HAIKU_REPOSITORY_CONFIG_FILE on $(repository) = $(repositoryConfig) ;
174	HAIKU_REPOSITORY_PACKAGES_CHECKSUM_FILE on $(repository)
175		= $(packagesChecksumFile) ;
176}
177
178
179rule GeneratedRepositoryPackageList target : repository
180{
181	repository = $(repository:G=repository) ;
182
183	# construct a list of file names
184	local fileNames ;
185	local package ;
186	for package in [ on $(repository) return $(HAIKU_REPOSITORY_PACKAGES) ] {
187		fileNames += [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ;
188	}
189
190	local definitionFile
191		= [ on $(repository) return $(HAIKU_REPOSITORY_DEFINITION_FILE) ] ;
192	Depends $(target) : $(definitionFile) ;
193
194	HAIKU_REPOSITORY_PACKAGE_FILE_NAMES on $(target) = $(fileNames) ;
195	GeneratedRepositoryPackageList1 $(target) ;
196}
197
198
199actions GeneratedRepositoryPackageList1
200{
201	(for file in $(HAIKU_REPOSITORY_PACKAGE_FILE_NAMES) ; do
202		echo $file
203	done) | LC_ALL=C sort -u > $(1)
204}
205
206
207rule RepositoryConfig repoConfig : repoInfo : packagesChecksumFile : repository
208{
209	repository = $(repository:G=repository) ;
210
211	HAIKU_REPOSITORY_URL on $(repoConfig)
212		= [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ;
213	Depends $(repoConfig)
214		: <build>create_repository_config $(repoInfo) $(packagesChecksumFile) ;
215	RepositoryConfig1 $(repoConfig)
216		: <build>create_repository_config $(repoInfo) $(packagesChecksumFile) ;
217}
218
219
220actions RepositoryConfig1
221{
222	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
223	$(2[1]) $(HAIKU_REPOSITORY_URL)/`cat $(2[3])` $(2[2]) $(1)
224}
225
226
227#pragma mark - Bootstrap Repository
228
229
230rule BootstrapRepositoryPackageFamily repository : packageBaseName
231{
232	local splitBaseName = [ Match "(.*)_bootstrap(.*)" : $(packageBaseName) ] ;
233	if $(splitBaseName) {
234		packageBaseName = $(splitBaseName[1])$(splitBaseName[2]) ;
235	}
236
237	return [ PackageFamily $(packageBaseName) ] ;
238}
239
240
241rule BootstrapRepositoryFetchPackage repository : package : fileName
242{
243	local outputDir
244		= [ on $(repository) return $(HAIKU_REPOSITORY_BUILD_DIRECTORY) ] ;
245	local configFile
246		= [ on $(repository) return $(HAIKU_REPOSITORY_BUILD_CONFIG_FILE) ] ;
247	local haikuCrossDevelPackages = [ on $(package)
248		return $(HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES) ] ;
249
250	local packageFile = <cross-built>$(fileName) ;
251	if [ on $(packageFile) return $(HAIKU_REPOSITORY_BUILD_DIRECTORY) ] {
252		# rule already called for this package
253		return $(packageFile) ;
254	}
255
256	HAIKU_REPOSITORY_BUILD_DIRECTORY on $(packageFile) = $(outputDir) ;
257
258	MakeLocate $(packageFile) : [ FDirName $(outputDir) packages ] ;
259	NoUpdate $(packageFile) ;
260		# Don't rebuild the file. Since the haiku cross devel package is
261		# a dependency and is updated always, this package would otherwise be
262		# rebuilt always as well.
263
264	Depends $(packageFile) : $(haikuCrossDevelPackages) $(configFile) ;
265	BootstrapRepositoryFetchPackage1 $(packageFile)
266		: $(haikuCrossDevelPackages) ;
267
268	return $(packageFile) ;
269}
270
271
272actions BootstrapRepositoryFetchPackage1
273{
274	# don't rebuild existing package
275	package="$(1)"
276	if [ -e "$package" ]; then
277		exit 0
278	fi
279
280	# make Haiku cross devel package path absolute
281	haikuCrossDevelPackage="$(2[1])"
282	if [[ "$haikuCrossDevelPackage" != /* ]]; then
283		haikuCrossDevelPackage="`pwd`/$haikuCrossDevelPackage"
284	fi
285
286	# make secondary Haiku cross devel packages path absolute
287	secondaryCrossDevelPackages=
288	if [ -n "$(2[2-]:J)" ]; then
289		for secondaryCrossDevelPackage in "$(2[2-])" ; do
290			if [[ "$secondaryCrossDevelPackage" != /* ]]; then
291				secondaryCrossDevelPackage="`pwd`/$secondaryCrossDevelPackage"
292			fi
293			if [ -n "$secondaryCrossDevelPackages" ]; then
294				secondaryCrossDevelPackages="secondaryCrossDevelPackages,$secondaryCrossDevelPackage"
295			else
296				secondaryCrossDevelPackages="--secondary-cross-devel-package=$secondaryCrossDevelPackage"
297			fi
298		done
299	fi
300
301	# determine the portName
302	portName=`basename "$package" | sed 's@-.*@@'`
303	case $portName in
304		*_devel|*_doc|*_source|*_debuginfo)
305			portName=`echo $portName | sed 's@_[^_]*$@@'`
306			;;
307	esac
308
309	cd $(HAIKU_REPOSITORY_BUILD_DIRECTORY)
310
311	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
312	if [ -n "$secondaryCrossDevelPackages" ]; then
313		$(HOST_HAIKU_PORTER) --cross-devel-package "$haikuCrossDevelPackage" \
314			"$secondaryCrossDevelPackages" $portName
315	else
316		$(HOST_HAIKU_PORTER) --cross-devel-package "$haikuCrossDevelPackage" \
317			$portName
318	fi
319}
320
321
322actions BuildBootstrapRepositoryConfig
323{
324cat > $(1) << EOF
325PACKAGER="The Haiku build system <build-system@haiku-os.org>"
326TREE_PATH="$(HAIKU_PORTS_CROSS)"
327TARGET_ARCHITECTURE="$(HAIKU_PACKAGING_ARCH)"
328
329DOWNLOAD_IN_PORT_DIRECTORY="yes"
330PACKAGE_COMMAND="$(2[1])"
331MIMESET_COMMAND="$(2[2])"
332SYSTEM_MIME_DB="$(2[3])"
333LICENSES_DIRECTORY="$(HAIKU_TOP)/data/system/data/licenses"
334OUTPUT_DIRECTORY="$(HAIKU_REPOSITORY_BUILD_DIRECTORY)"
335EOF
336
337	# If we have cross tools, add the cross tools directory.
338	gcc=$(HAIKU_CC_$(HAIKU_PACKAGING_ARCH))
339	if [[ "$gcc" = /* ]]; then
340		if [ `basename $gcc` = \
341				$(HAIKU_GCC_MACHINE_$(HAIKU_PACKAGING_ARCH))-gcc ]; then
342			dir=`dirname $gcc`
343			dir=`dirname $dir`
344			echo CROSS_TOOLS=\"$dir\" >> $(1)
345		fi
346	fi
347
348	# Add secondary architectures and cross tools.
349	secondaryArchs="$(HAIKU_PACKAGING_ARCHS[2-]:E=)"
350	if [ -n "$secondaryArchs" ]; then
351		echo SECONDARY_TARGET_ARCHITECTURES=\" >> $(1)
352		for arch in $secondaryArchs; do
353			echo "  $arch" >> $(1)
354		done
355		echo \" >> $(1)
356
357		echo SECONDARY_CROSS_TOOLS=\" >> $(1)
358		for gcc in $(HAIKU_CC_$(HAIKU_PACKAGING_ARCHS[2-])) ; do
359			dir=`dirname $gcc`
360			dir=`dirname $dir`
361			echo "  $dir" >> $(1)
362		done
363		echo \" >> $(1)
364	fi
365}
366
367
368rule BootstrapPackageRepository repository : architecture
369	: anyPackages : packagesStage1 : packagesStage2 : sourcePackages
370	: debugInfoPackages
371{
372	repository = $(repository:G=repository) ;
373	packagesStage1 = [ FFilterByBuildFeatures $(packagesStage1) ] ;
374	packagesStage2 = [ FFilterByBuildFeatures $(packagesStage2) ] ;
375	sourcePackages = [ FFilterByBuildFeatures $(sourcePackages) ] ;
376	debugInfoPackages = [ FFilterByBuildFeatures $(debugInfoPackages) ] ;
377
378	SetRepositoryMethod $(repository) : PackageFamily
379		: BootstrapRepositoryPackageFamily ;
380	SetRepositoryMethod $(repository) : FetchPackage
381		: BootstrapRepositoryFetchPackage ;
382
383	# register repository with stage 1 packages
384	local stage1PackageTargets = [ PackageRepository $(repository)
385		: $(architecture) : $(anyPackages) : $(packagesStage1)
386		: $(sourcePackages) : $(debugInfoPackages) ] ;
387	if ! $(stage1PackageTargets) {
388		return ;
389	}
390	local crossDevelPackageSuffixes = $(architecture)
391		$(architecture)_$(HAIKU_PACKAGING_ARCHS[2-]) ;
392	HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES on $(stage1PackageTargets)
393		= haiku_cross_devel_sysroot_stage1_$(crossDevelPackageSuffixes).hpkg ;
394
395	# add stage 2 packages
396	local stage2PackageTargets = [ AddRepositoryPackages $(repository)
397		: $(architecture) : $(packagesStage2) : $(sourcePackages)
398		: $(debugInfoPackages) ] ;
399	HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES on $(stage2PackageTargets)
400		= haiku_cross_devel_sysroot_$(crossDevelPackageSuffixes).hpkg ;
401
402	# prepare the config file for the HaikuPorts cross build
403	local outputDir = [ FDirName
404		$(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture))
405		$(repository:G=)-build ] ;
406	local configFile = haikuports.conf ;
407	configFile = $(configFile:G=repository-config-$(repository:G=)) ;
408	MakeLocate $(configFile) : $(outputDir) ;
409	NoUpdate $(configFile) ;
410	Depends $(configFile) : <build>package <build>mimeset <mimedb>mime_db ;
411	HAIKU_REPOSITORY_BUILD_DIRECTORY on $(configFile) = $(outputDir) ;
412	HAIKU_PACKAGING_ARCH on $(configFile) = $(architecture) ;
413	BuildBootstrapRepositoryConfig $(configFile)
414		: <build>package <build>mimeset <mimedb>mime_db ;
415
416	HAIKU_REPOSITORY_BUILD_CONFIG_FILE on $(repository) = $(configFile) ;
417	HAIKU_REPOSITORY_BUILD_DIRECTORY on $(repository) = $(outputDir) ;
418
419	# Serialize all package file targets. We need to do this, since
420	# haikuporter uses a common directory for building the ports, so building
421	# two ports concurrently isn't possible.
422	local previousPackageFile ;
423	local package ;
424	for package in $(stage1PackageTargets) $(stage2PackageTargets) {
425		local fileName = [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ;
426		local packageFile = [ BootstrapRepositoryFetchPackage $(repository)
427			: $(package) : $(fileName) ] ;
428		Depends $(packageFile) : $(previousPackageFile) ;
429
430		previousPackageFile = $(packageFile) ;
431	}
432}
433
434
435#pragma mark - Public
436
437
438rule FSplitPackageName packageName
439{
440	local splitName = [ Match "(.*)_([^_]*)" : $(packageName) ] ;
441	local knownPackageSuffixes = devel doc source debuginfo ;
442	if $(splitName[2]) && $(splitName[2]) in $(knownPackageSuffixes) {
443		return $(splitName) ;
444	}
445
446	return $(packageName) ;
447}
448
449
450rule IsPackageAvailable package
451{
452	# for a secondary architecture adjust the package name
453	if $(TARGET_PACKAGING_ARCH) != $(TARGET_PACKAGING_ARCHS[1]) {
454		local splitName = [ FSplitPackageName $(package) ] ;
455		splitName = $(splitName[1]) $(TARGET_PACKAGING_ARCH) $(splitName[2-]) ;
456		package = $(splitName:J=_) ;
457	}
458
459	if $(package) in $(HAIKU_AVAILABLE_PACKAGES) {
460		return $(package) ;
461	}
462
463	return ;
464}
465
466
467rule FetchPackage packageName
468{
469	local foundPackageName = [ IsPackageAvailable $(packageName) ] ;
470	if ! $(foundPackageName) {
471		Exit "DownloadPackage: package" $(packageName) "not available!" ;
472		return ;
473	}
474	packageName = $(foundPackageName) ;
475
476	# TODO: We should support explicitly specified versions (or partial/minimum
477	# versions like gcc-2 or gcc-4).
478
479	local packageFamily = [ PackageFamily $(packageName) ] ;
480	local package
481		= [ on $(packageFamily) return $(HAIKU_PACKAGE_VERSIONS[1]) ] ;
482	local fileName = [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ;
483	local repository = [ on $(package) return $(HAIKU_PACKAGE_REPOSITORY) ] ;
484
485	return [ InvokeRepositoryMethod $(repository) : FetchPackage : $(package)
486		: $(fileName) ] ;
487}
488