Switch build system from optional package to repositories

* Build libsolv and the dependency solver part of the package kit for
  the build platform.
* Add build tool get_package_dependencies. Given a list of package files
  and a list of repository files it determines the additional packages
  that need to be retrieved from the repositories and prints their URLs.
* Add rules to work with external repositories in the build system
  (build/jam/RepositoryRules):
  - PackageRepository declares an external repository with all its
    packages. The URL of the repository file isn't specified. It is
    computed from a given base URL and the SHA256 hash of the list of
    package files.
  - GeneratedRepositoryPackageList generates a file containing the file
    names of all packages in a repository.
  - IsPackageAvailable returns whether a package is available in any
    repository.
  - PackageURL returns the URL for a package.
* Declare the HaikuPorts repository for x86_gcc2
  (build/jam/repositories/HaikuPorts/x86_gcc2).
* Add rule AddHaikuImagePackages to add a package to the image and rule
  IsHaikuImagePackageAdded to determine whether a package has been
  added.
* OptionalPackages: Remove all entries that just downloaded and
  installed an external package. AddHaikuImagePackages can be used
  instead and is used in the remaining entries. Also move the remaining
  optional package dependency declarations from
  OptionalPackageDependencies here.
* ExtractBuildFeatureArchives: Instead of the URL parameter a package
  name must be specified now. This allows to simplify BuildFeatures
  significantly, since there's no dealing with URLs anymore. "if" out
  the entries that aren't supported yet.
* build_haiku_image: For the packages installed in system and common
  resolve their dependencies and download and install them as well.
This commit is contained in:
Ingo Weinhold
2013-07-05 10:51:42 +02:00
parent 43d96d8f7a
commit 98c6dfa41e
30 changed files with 1146 additions and 2352 deletions
+1
View File
@@ -94,6 +94,7 @@ SubInclude HAIKU_TOP src tools fixup_amiga_boot_checksum ;
SubInclude HAIKU_TOP src tools fixup_tos_boot_checksum ;
SubInclude HAIKU_TOP src tools fs_shell ;
SubInclude HAIKU_TOP src tools gensyscalls ;
SubInclude HAIKU_TOP src tools get_package_dependencies ;
SubInclude HAIKU_TOP src tools hack_coff ;
SubInclude HAIKU_TOP src tools keymap ;
SubInclude HAIKU_TOP src tools locale ;
@@ -0,0 +1,19 @@
SubDir HAIKU_TOP src tools get_package_dependencies ;
UsePrivateBuildHeaders shared ;
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src bin pkgman ] ;
USES_BE_API on <build>get_package_dependencies = true ;
BuildPlatformMain <build>get_package_dependencies :
get_package_dependencies.cpp
# pkgman sources
PackageInfoErrorListener.cpp
RepositoryBuilder.cpp
:
libpackage-add-on-libsolv_build.so
libsolvext_build.so libsolv_build.so
libpackage_build.so $(HOST_LIBBE) $(HOST_LIBSTDC++)
;
@@ -0,0 +1,160 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <map>
#include <package/RepositoryCache.h>
#include <package/solver/Solver.h>
#include <package/solver/SolverPackageSpecifier.h>
#include <package/solver/SolverPackageSpecifierList.h>
#include <package/solver/SolverProblem.h>
#include <package/solver/SolverProblemSolution.h>
#include <package/solver/SolverRepository.h>
#include <package/solver/SolverResult.h>
#include "pkgman.h"
#include "RepositoryBuilder.h"
static const char* sProgramName = "get_package_dependencies";
void
print_usage_and_exit(bool error)
{
fprintf(error ? stderr : stdout,
"Usage: %s <repository> ... -- <package> ...\n"
"Resolves the dependencies of the given packages using the given\n"
"repositories and prints the URLs of the packages that are also\n"
"needed to satisfy all requirements. Fails, if there are conflicts\n"
"or some requirements cannot be satisfied.\n",
sProgramName);
exit(error ? 1 : 0);
}
int
main(int argc, const char* const* argv)
{
if (argc < 2)
print_usage_and_exit(true);
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
print_usage_and_exit(false);
// get lists of repositories and packages
int argIndex = 1;
const char* const* repositories = argv + argIndex;
while (argIndex < argc && strcmp(argv[argIndex], "--") != 0)
argIndex++;
int repositoryCount = argv + argIndex - repositories;
if (repositoryCount == 0 || argIndex == argc)
print_usage_and_exit(true);
const char* const* packages = argv + argIndex + 1;
int packageCount = argv + argc - packages;
// create the solver
BSolver* solver;
status_t error = BSolver::Create(solver);
if (error != B_OK)
DIE(error, "failed to create solver");
// add the "installed" repository with the given packages
BSolverRepository installedRepository;
{
RepositoryBuilder installedRepositoryBuilder(installedRepository,
"installed");
for (int i = 0; i < packageCount; i++)
installedRepositoryBuilder.AddPackage(packages[i]);
installedRepositoryBuilder.AddToSolver(solver, true);
}
// add external repositories
std::map<BSolverRepository*, BRepositoryInfo> repositoryInfos;
for (int i = 0; i < repositoryCount; i++) {
BSolverRepository* repository = new BSolverRepository;
BRepositoryCache cache;
error = cache.SetTo(repositories[i]);
if (error != B_OK)
DIE(error, "failed to read repository file '%s'", repositories[i]);
RepositoryBuilder(*repository, cache)
.AddToSolver(solver, false);
repositoryInfos[repository] = cache.Info();
}
// solve
error = solver->VerifyInstallation();
if (error != B_OK)
DIE(error, "failed to compute packages to install");
// print problems (and fail), if any
if (solver->HasProblems()) {
fprintf(stderr, "Encountered problems:\n");
int32 problemCount = solver->CountProblems();
for (int32 i = 0; i < problemCount; i++) {
// print problem and possible solutions
BSolverProblem* problem = solver->ProblemAt(i);
fprintf(stderr, "problem %" B_PRId32 ": %s\n", i + 1,
problem->ToString().String());
int32 solutionCount = problem->CountSolutions();
for (int32 k = 0; k < solutionCount; k++) {
const BSolverProblemSolution* solution = problem->SolutionAt(k);
fprintf(stderr, " solution %" B_PRId32 ":\n", k + 1);
int32 elementCount = solution->CountElements();
for (int32 l = 0; l < elementCount; l++) {
const BSolverProblemSolutionElement* element
= solution->ElementAt(l);
fprintf(stderr, " - %s\n", element->ToString().String());
}
}
}
exit(1);
}
// print URL of packages that additionally need to be installed
BSolverResult result;
error = solver->GetResult(result);
if (error != B_OK)
DIE(error, "failed to compute packages to install");
bool duplicatePackage = false;
for (int32 i = 0; const BSolverResultElement* element = result.ElementAt(i);
i++) {
BSolverPackage* package = element->Package();
switch (element->Type()) {
case BSolverResultElement::B_TYPE_INSTALL:
if (package->Repository() != &installedRepository) {
const BRepositoryInfo& info
= repositoryInfos[package->Repository()];
BString url = info.OriginalBaseURL();
url << '/' << package->Info().CanonicalFileName();
printf("%s\n", url.String());
}
break;
case BSolverResultElement::B_TYPE_UNINSTALL:
fprintf(stderr, "Error: would need to uninstall package %s\n",
package->VersionedName().String());
duplicatePackage = true;
break;
}
}
return duplicatePackage ? 1 : 0;
}