#pragma mark - Private rule PackageFamily packageBaseName { return $(packageBaseName:G=package-family) ; } rule SetRepositoryMethod repository : methodName : method { HAIKU_REPOSITORY_METHOD_$(methodName) on $(repository) = $(method) ; } rule InvokeRepositoryMethod repository : methodName : arg1 : arg2 : arg3 : arg4 : arg5 : arg6 : arg7 { local method = [ on $(repository) return $(HAIKU_REPOSITORY_METHOD_$(methodName)) ] ; if ! $(method) { Exit "Method" $(methodName) " not defined for repository" $(repository) ; } return [ $(method) $(repository) : $(arg1) : $(arg2) : $(arg3) : $(arg4) : $(arg5) : $(arg6) : $(arg7) ] ; } rule AddRepositoryPackage repository : architecture : baseName : version { local package = $(baseName)-$(version) ; package = $(package:E=$(baseName):G=package-in-$(repository:G=)) ; HAIKU_PACKAGE_REPOSITORY on $(package) = $(repository) ; HAIKU_PACKAGE_ARCHITECTURE on $(package) = $(architecture) ; HAIKU_PACKAGE_FILE_NAME on $(package) = $(package:G=)-$(architecture).hpkg ; local packageFamily = [ InvokeRepositoryMethod $(repository) : PackageFamily : $(baseName) ] ; baseName = $(packageFamily:G=) ; if ! $(baseName) in $(HAIKU_AVAILABLE_PACKAGES) { HAIKU_AVAILABLE_PACKAGES += $(baseName) ; } HAIKU_PACKAGE_VERSIONS on $(packageFamily) += $(package) ; HAIKU_REPOSITORY_PACKAGES on $(repository) += $(package) ; return $(package) ; } rule AddRepositoryPackages repository : architecture : packages : sourcePackages : debugInfoPackages { local packageTargets ; local package ; for package in $(packages) { local splitName = [ Match "([^-]*)-(.*)" : $(package) ] ; local baseName = $(splitName[1]:E=$(package)) ; local version = $(splitName[2]) ; packageTargets += [ AddRepositoryPackage $(repository) : $(architecture) : $(baseName) : $(version) ] ; if $(baseName) in $(sourcePackages) { AddRepositoryPackage $(repository) : source : $(baseName)_source : $(version) ; } if $(baseName) in $(debugInfoPackages) { packageTargets += [ AddRepositoryPackage $(repository) : $(architecture) : $(baseName)_debuginfo : $(version) ] ; } } return $(packageTargets) ; } rule PackageRepository repository : architecture : anyPackages : packages : sourcePackages : debugInfoPackages { if $(architecture) != $(HAIKU_PACKAGING_ARCHS[1]) { return ; } HAIKU_REPOSITORIES += $(repository) ; HAIKU_REPOSITORY_DEFINITION_FILE on $(repository) = $(HAIKU_REPOSITORY_JAMFILE) ; return [ AddRepositoryPackages $(repository) : any : $(anyPackages) : $(sourcePackages) : $(debugInfoPackages) ] [ AddRepositoryPackages $(repository) : $(architecture) : $(packages) : $(sourcePackages) : $(debugInfoPackages) ] ; } #pragma mark - Remote Repository rule RemoteRepositoryPackageFamily repository : packageBaseName { return [ PackageFamily $(packageBaseName) ] ; } rule RemoteRepositoryFetchPackage repository : package : fileName { local baseUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ; local packagesChecksumFile = [ on $(repository) return $(HAIKU_REPOSITORY_PACKAGES_CHECKSUM_FILE) ] ; local downloadedFile = [ DownloadFile $(fileName) : "$(baseUrl)/`cat $source`/packages/$(fileName)" : $(packagesChecksumFile) ] ; NoUpdate $(downloadedFile) ; # Don't download the file again when something in the repository # changes. It is (supposed to be) still the same file. return $(downloadedFile) ; } rule RemotePackageRepository repository : architecture : repositoryUrl : anyPackages : packages : sourcePackages : debugInfoPackages { repository = $(repository:G=repository) ; SetRepositoryMethod $(repository) : PackageFamily : RemoteRepositoryPackageFamily ; SetRepositoryMethod $(repository) : FetchPackage : RemoteRepositoryFetchPackage ; HAIKU_REPOSITORY_URL on $(repository) = $(repositoryUrl) ; PackageRepository $(repository) : $(architecture) : $(anyPackages) : $(packages) : $(sourcePackages) : $(debugInfoPackages) ; # build package list file local packageListFile = $(repository:G=repository-package-list)-packages ; local repositoriesDir = $(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture)) ; MakeLocate $(packageListFile) : $(repositoriesDir) ; GeneratedRepositoryPackageList $(packageListFile) : $(repository) ; # build package list checksum file local packagesChecksumFile = $(repository:G=repository-package-checksum)-checksum ; MakeLocate $(packagesChecksumFile) : $(repositoriesDir) ; Depends $(packagesChecksumFile) : $(packageListFile) ; ChecksumFileSHA256 $(packagesChecksumFile) : $(packageListFile) ; # download repository info file local repositoryInfo = $(repository:G=repository-info)-info ; MakeLocate $(repositoryInfo) : $(repositoriesDir) ; local repoUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ; DownloadLocatedFile $(repositoryInfo) : "$(repoUrl)/`cat $source`/repo.info" : $(packagesChecksumFile) ; # download repository file local repositoryFile = $(repository:G=repository-cache) ; MakeLocate $(repositoryFile) : $(repositoriesDir) ; local repoUrl = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ; DownloadLocatedFile $(repositoryFile) : "$(repoUrl)/`cat $source`/repo" : $(packagesChecksumFile) ; # build repository config file local repositoryConfig = $(repository:G=repository-config)-config ; MakeLocate $(repositoryConfig) : $(repositoriesDir) ; RepositoryConfig $(repositoryConfig) : $(repositoryInfo) : $(packagesChecksumFile) : $(repository) ; HAIKU_REPOSITORY_CACHE_FILE on $(repository) = $(repositoryFile) ; HAIKU_REPOSITORY_CONFIG_FILE on $(repository) = $(repositoryConfig) ; HAIKU_REPOSITORY_PACKAGES_CHECKSUM_FILE on $(repository) = $(packagesChecksumFile) ; } rule GeneratedRepositoryPackageList target : repository { repository = $(repository:G=repository) ; # construct a list of file names local fileNames ; local package ; for package in [ on $(repository) return $(HAIKU_REPOSITORY_PACKAGES) ] { fileNames += [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ; } local definitionFile = [ on $(repository) return $(HAIKU_REPOSITORY_DEFINITION_FILE) ] ; Depends $(target) : $(definitionFile) ; HAIKU_REPOSITORY_PACKAGE_FILE_NAMES on $(target) = $(fileNames) ; GeneratedRepositoryPackageList1 $(target) ; } actions GeneratedRepositoryPackageList1 { (for file in $(HAIKU_REPOSITORY_PACKAGE_FILE_NAMES) ; do echo $file done) | LC_ALL=C sort -u > $(1) } rule RepositoryConfig repoConfig : repoInfo : packagesChecksumFile : repository { repository = $(repository:G=repository) ; HAIKU_REPOSITORY_URL on $(repoConfig) = [ on $(repository) return $(HAIKU_REPOSITORY_URL) ] ; Depends $(repoConfig) : create_repository_config $(repoInfo) $(packagesChecksumFile) ; RepositoryConfig1 $(repoConfig) : create_repository_config $(repoInfo) $(packagesChecksumFile) ; } actions RepositoryConfig1 { $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) $(2[1]) $(HAIKU_REPOSITORY_URL)/`cat $(2[3])` $(2[2]) $(1) } #pragma mark - Bootstrap Repository rule BootstrapRepositoryPackageFamily repository : packageBaseName { local splitBaseName = [ Match "(.*)_bootstrap(.*)" : $(packageBaseName) ] ; if $(splitBaseName) { packageBaseName = $(splitBaseName[1])$(splitBaseName[2]) ; } return [ PackageFamily $(packageBaseName) ] ; } rule BootstrapRepositoryFetchPackage repository : package : fileName { local outputDir = [ on $(repository) return $(HAIKU_REPOSITORY_BUILD_DIRECTORY) ] ; local configFile = [ on $(repository) return $(HAIKU_REPOSITORY_BUILD_CONFIG_FILE) ] ; local haikuCrossDevelPackages = [ on $(package) return $(HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES) ] ; local packageFile = $(fileName) ; if [ on $(packageFile) return $(HAIKU_REPOSITORY_BUILD_DIRECTORY) ] { # rule already called for this package return $(packageFile) ; } HAIKU_REPOSITORY_BUILD_DIRECTORY on $(packageFile) = $(outputDir) ; MakeLocate $(packageFile) : [ FDirName $(outputDir) packages ] ; NoUpdate $(packageFile) ; # Don't rebuild the file. Since the haiku cross devel package is # a dependency and is updated always, this package would otherwise be # rebuilt always as well. Depends $(packageFile) : $(haikuCrossDevelPackages) $(configFile) ; BootstrapRepositoryFetchPackage1 $(packageFile) : $(haikuCrossDevelPackages) ; return $(packageFile) ; } actions BootstrapRepositoryFetchPackage1 { # don't rebuild existing package package="$(1)" if [ -e "$package" ]; then exit 0 fi # make Haiku cross devel package path absolute haikuCrossDevelPackage="$(2[1])" if [ "x$haikuCrossDevelPackage" = "x${haikuCrossDevelPackage#/}" ]; then haikuCrossDevelPackage="`pwd`/$haikuCrossDevelPackage" fi # make secondary Haiku cross devel packages path absolute secondaryCrossDevelPackages= if [ -n "$(2[2-]:J)" ]; then for secondaryCrossDevelPackage in "$(2[2-])" ; do if [ "x$secondaryCrossDevelPackage" = "x${secondaryCrossDevelPackage#/}" ]; then secondaryCrossDevelPackage="`pwd`/$secondaryCrossDevelPackage" fi if [ -n "$secondaryCrossDevelPackages" ]; then secondaryCrossDevelPackages="secondaryCrossDevelPackages,$secondaryCrossDevelPackage" else secondaryCrossDevelPackages="--secondary-cross-devel-package=$secondaryCrossDevelPackage" fi done fi # determine the portName portName=`basename "$package" | sed 's@-.*@@'` case $portName in *_devel|*_doc|*_source|*_debuginfo) portName=`echo $portName | sed 's@_[^_]*$@@'` ;; *_source_rigged) portName=`echo $portName | sed 's@_source_rigged$@@'` ;; esac cd $(HAIKU_REPOSITORY_BUILD_DIRECTORY) $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) if [ -n "$secondaryCrossDevelPackages" ]; then $(HOST_HAIKU_PORTER) -j$(HAIKU_PORTER_CONCURRENT_JOBS) \ --cross-devel-package "$haikuCrossDevelPackage" \ "$secondaryCrossDevelPackages" $portName else $(HOST_HAIKU_PORTER) -j$(HAIKU_PORTER_CONCURRENT_JOBS) \ --cross-devel-package "$haikuCrossDevelPackage" $portName fi } actions BuildBootstrapRepositoryConfig { cat > $(1) << EOF PACKAGER="The Haiku build system " TREE_PATH="$(HAIKU_REPOSITORY_TREE_PATH)" TARGET_ARCHITECTURE="$(HAIKU_PACKAGING_ARCH)" DOWNLOAD_IN_PORT_DIRECTORY="yes" PACKAGE_COMMAND="$(2[1])" MIMESET_COMMAND="$(2[2])" SYSTEM_MIME_DB="$(2[3])" LICENSES_DIRECTORY="$(HAIKU_TOP)/data/system/data/licenses" OUTPUT_DIRECTORY="$(HAIKU_REPOSITORY_BUILD_DIRECTORY)" EOF # If we have cross tools, add the cross tools directory. gcc=$(HAIKU_CC_$(HAIKU_PACKAGING_ARCH)) if [ "x$gcc" != "x${gcc#/}" ]; then if [ `basename $gcc` = \ $(HAIKU_GCC_MACHINE_$(HAIKU_PACKAGING_ARCH))-gcc ]; then dir=`dirname $gcc` dir=`dirname $dir` echo CROSS_TOOLS=\"$dir\" >> $(1) fi fi # Add secondary architectures and cross tools. secondaryArchs="$(HAIKU_PACKAGING_ARCHS[2-]:E=)" if [ -n "$secondaryArchs" ]; then echo SECONDARY_TARGET_ARCHITECTURES=\" >> $(1) for arch in $secondaryArchs; do echo " $arch" >> $(1) done echo \" >> $(1) echo SECONDARY_CROSS_TOOLS=\" >> $(1) for gcc in $(HAIKU_CC_$(HAIKU_PACKAGING_ARCHS[2-])) ; do dir=`dirname $gcc` dir=`dirname $dir` echo " $dir" >> $(1) done echo \" >> $(1) fi } rule BootstrapPackageRepository repository : architecture : anyPackages : packagesStage1 : packagesStage2 : sourcePackages : debugInfoPackages { repository = $(repository:G=repository) ; packagesStage1 = [ FFilterByBuildFeatures $(packagesStage1) ] ; packagesStage2 = [ FFilterByBuildFeatures $(packagesStage2) ] ; sourcePackages = [ FFilterByBuildFeatures $(sourcePackages) ] ; debugInfoPackages = [ FFilterByBuildFeatures $(debugInfoPackages) ] ; SetRepositoryMethod $(repository) : PackageFamily : BootstrapRepositoryPackageFamily ; SetRepositoryMethod $(repository) : FetchPackage : BootstrapRepositoryFetchPackage ; # register repository with stage 1 packages local stage1PackageTargets = [ PackageRepository $(repository) : $(architecture) : $(anyPackages) : $(packagesStage1) : $(sourcePackages) : $(debugInfoPackages) ] ; if ! $(stage1PackageTargets) { return ; } local crossDevelPackageSuffixes = $(architecture) $(architecture)_$(HAIKU_PACKAGING_ARCHS[2-]) ; HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES on $(stage1PackageTargets) = haiku_cross_devel_sysroot_stage1_$(crossDevelPackageSuffixes).hpkg ; # add stage 2 packages local stage2PackageTargets = [ AddRepositoryPackages $(repository) : $(architecture) : $(packagesStage2) : $(sourcePackages) : $(debugInfoPackages) ] ; HAIKU_REPOSITORY_HAIKU_CROSS_DEVEL_PACKAGES on $(stage2PackageTargets) = haiku_cross_devel_sysroot_$(crossDevelPackageSuffixes).hpkg ; # prepare the config file for the HaikuPorts cross build local outputDir = [ FDirName $(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture)) $(repository:G=)-build ] ; local configFile = haikuports.conf ; configFile = $(configFile:G=repository-config-$(repository:G=)) ; MakeLocate $(configFile) : $(outputDir) ; NoUpdate $(configFile) ; Depends $(configFile) : package mimeset mime_db ; HAIKU_REPOSITORY_BUILD_DIRECTORY on $(configFile) = $(outputDir) ; HAIKU_PACKAGING_ARCH on $(configFile) = $(architecture) ; HAIKU_REPOSITORY_TREE_PATH on $(configFile) = $(HAIKU_PORTS_CROSS) ; BuildBootstrapRepositoryConfig $(configFile) : package mimeset mime_db ; HAIKU_REPOSITORY_BUILD_CONFIG_FILE on $(repository) = $(configFile) ; HAIKU_REPOSITORY_BUILD_DIRECTORY on $(repository) = $(outputDir) ; # Serialize all package file targets. We need to do this, since # haikuporter uses a common directory for building the ports, so building # two ports concurrently isn't possible. local previousPackageFile ; local package ; for package in $(stage1PackageTargets) $(stage2PackageTargets) { local fileName = [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ; local packageFile = [ BootstrapRepositoryFetchPackage $(repository) : $(package) : $(fileName) ] ; Depends $(packageFile) : $(previousPackageFile) ; previousPackageFile = $(packageFile) ; } } #pragma mark - Public rule FSplitPackageName packageName { local splitName = [ Match "(.*)_([^_]*)" : $(packageName) ] ; local knownPackageSuffixes = devel doc source debuginfo ; if $(splitName[2]) && $(splitName[2]) in $(knownPackageSuffixes) { return $(splitName) ; } return $(packageName) ; } rule IsPackageAvailable package : flags { # for a secondary architecture adjust the package name if $(TARGET_PACKAGING_ARCH) != $(TARGET_PACKAGING_ARCHS[1]) && ! nameResolved in $(flags) { local splitName = [ FSplitPackageName $(package) ] ; splitName = $(splitName[1]) $(TARGET_PACKAGING_ARCH) $(splitName[2-]) ; package = $(splitName:J=_) ; } if $(package) in $(HAIKU_AVAILABLE_PACKAGES) { return $(package) ; } return ; } rule FetchPackage packageName : flags { local foundPackageName = [ IsPackageAvailable $(packageName) : $(flags) ] ; if ! $(foundPackageName) { Exit "DownloadPackage: package" $(packageName) "not available!" ; return ; } packageName = $(foundPackageName) ; # TODO: We should support explicitly specified versions (or partial/minimum # versions like gcc-2 or gcc-4). local packageFamily = [ PackageFamily $(packageName) ] ; local package = [ on $(packageFamily) return $(HAIKU_PACKAGE_VERSIONS[1]) ] ; local fileName = [ on $(package) return $(HAIKU_PACKAGE_FILE_NAME) ] ; local repository = [ on $(package) return $(HAIKU_PACKAGE_REPOSITORY) ] ; return [ InvokeRepositoryMethod $(repository) : FetchPackage : $(package) : $(fileName) ] ; } rule BuildHaikuPortsSourcePackageDirectory { local architecture = $(TARGET_PACKAGING_ARCH) ; local outputDir = [ FDirName $(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture)) HaikuPorts-sources-build ] ; local sourcePackageDir = packages ; MakeLocate $(sourcePackageDir) : $(outputDir) ; # build the package list file local packageList = package_list ; MakeLocate $(packageList) : $(outputDir) ; Depends $(packageList) : [ FDirName $(HAIKU_BUILD_RULES_DIR) repositories HaikuPorts $(architecture) ] ; # Note: Those are packages we need for building on the bootstrap Haiku. They # are build-pre-requires and as such won't be detected by haikuporter as # required dependencies when building the source packages. HAIKU_REPOSITORY_BUILD_ADDITIONAL_PACKAGES on $(packageList) = htmldoc texi2html ; BuildHaikuPortsPackageList $(packageList) ; # prepare the config file for the HaikuPorts build local configFile = haikuports.conf ; MakeLocate $(configFile) : $(outputDir) ; NoUpdate $(configFile) ; Depends $(configFile) : package mimeset mime_db ; HAIKU_REPOSITORY_BUILD_DIRECTORY on $(configFile) = $(outputDir) ; HAIKU_PACKAGING_ARCH on $(configFile) = $(architecture) ; HAIKU_REPOSITORY_TREE_PATH on $(configFile) = $(HAIKU_PORTS) ; BuildBootstrapRepositoryConfig $(configFile) : package mimeset mime_db ; # get Haiku cross-devel packages and build the sources local crossDevelPackageSuffixes = $(architecture) $(architecture)_$(HAIKU_PACKAGING_ARCHS[2-]) ; local haikuCrossDevelPackages = haiku_cross_devel_sysroot_stage1_$(crossDevelPackageSuffixes).hpkg ; HAIKU_REPOSITORY_BUILD_DIRECTORY on $(sourcePackageDir) = $(outputDir) ; Depends $(sourcePackageDir) : $(packageList) $(haikuCrossDevelPackages) $(configFile) ; BuildHaikuPortsSourcePackageDirectory1 $(sourcePackageDir) : $(packageList) $(haikuCrossDevelPackages) ; return $(sourcePackageDir) ; } actions BuildHaikuPortsPackageList { HAIKU_BOOTSTRAP_BUILD= $(JAM:E=jam) @alpha-raw build-package-list $(1) \ $(HAIKU_REPOSITORY_BUILD_ADDITIONAL_PACKAGES) } actions BuildHaikuPortsSourcePackageDirectory1 { packageList="$(2[1])" # make Haiku cross devel package path absolute haikuCrossDevelPackage="$(2[2])" if [ "x$haikuCrossDevelPackage" = "x${haikuCrossDevelPackage#/}" ]; then haikuCrossDevelPackage="`pwd`/$haikuCrossDevelPackage" fi # make secondary Haiku cross devel packages path absolute secondaryCrossDevelPackages= if [ -n "$(2[3-]:J)" ]; then for secondaryCrossDevelPackage in "$(2[3-])" ; do if [ "x$secondaryCrossDevelPackage" = "x${secondaryCrossDevelPackage#/}" ]; then secondaryCrossDevelPackage="`pwd`/$secondaryCrossDevelPackage" fi if [ -n "$secondaryCrossDevelPackages" ]; then secondaryCrossDevelPackages="secondaryCrossDevelPackages,$secondaryCrossDevelPackage" else secondaryCrossDevelPackages="--secondary-cross-devel-package=$secondaryCrossDevelPackage" fi done fi cd $(HAIKU_REPOSITORY_BUILD_DIRECTORY) $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) if [ -n "$secondaryCrossDevelPackages" ]; then $(HOST_HAIKU_PORTER) --cross-devel-package "$haikuCrossDevelPackage" \ "$secondaryCrossDevelPackages" \ --create-source-packages-for-bootstrap --portsfile $packageList else $(HOST_HAIKU_PORTER) --cross-devel-package "$haikuCrossDevelPackage" \ --create-source-packages-for-bootstrap --portsfile $packageList fi } rule BuildHaikuPortsRepositoryConfig treePath { local architecture = $(TARGET_PACKAGING_ARCH) ; local outputDir = [ FDirName $(HAIKU_PACKAGE_REPOSITORIES_DIR_$(architecture)) HaikuPorts-bootstrap ] ; local configFile = haikuports.conf ; MakeLocate $(configFile) : $(outputDir) ; NoUpdate $(configFile) ; HAIKU_REPOSITORY_TREE_PATH on $(configFile) = $(treePath) ; BuildHaikuPortsRepositoryConfig1 $(configFile) ; return $(configFile) ; } actions BuildHaikuPortsRepositoryConfig1 { cat > $(1) << EOF PACKAGER="The Haiku build system " TREE_PATH="$(HAIKU_REPOSITORY_TREE_PATH)" TARGET_ARCHITECTURE="$(HAIKU_PACKAGING_ARCH)" EOF } rule BuildRemoteHaikuPortsRepository target : packages { local packageListFile = HaikuPorts-packages ; Depends $(target) : $(packageListFile) ; HAIKU_REMOTE_REPOSITORY_PACKAGES on $(target) = $(packages) ; BuildRemoteHaikuPortsRepository1 $(target) : $(packageListFile) ; } actions BuildRemoteHaikuPortsRepository1 { remote=haiku_files@haiku-files.org if [ -n "$(HAIKU_REMOTE_REPOSITORY_PACKAGES:E=:J)" ]; then for package in $(HAIKU_REMOTE_REPOSITORY_PACKAGES) ; do file=`basename $package` if ! grep -q $file $(2); then echo "Error: $file is not being referenced in $(2)" exit 1 fi done scp $(HAIKU_REMOTE_REPOSITORY_PACKAGES) \ $remote:haiku-files.org/files/hpkg/ fi packageList=package-list.$(TARGET_PACKAGING_ARCH) scp $(2) $remote:build_repository/$packageList ssh $remote \ "cd build_repository \ && ./build_repo.sh $(TARGET_PACKAGING_ARCH) $packageList" }