int BuildAction:: Run(Filesystem *filesystem, Options const &options) { // TODO(grp): Implement these options. if (!VerifySupportedOptions(options)) { return -1; } /* Verify the build options are not conflicting or invalid. */ if (!Action::VerifyBuildActions(options.actions())) { return -1; } /* * Create the formatter to format the build log. */ std::shared_ptr<xcformatter::Formatter> formatter = CreateFormatter(options.formatter()); if (formatter == nullptr) { fprintf(stderr, "error: unknown formatter '%s'\n", options.formatter()->c_str()); return -1; } /* * Create the executor used to perform the build. */ std::unique_ptr<xcexecution::Executor> executor = CreateExecutor(options.executor(), formatter, options.dryRun(), options.generate()); if (executor == nullptr) { fprintf(stderr, "error: unknown executor '%s'\n", options.executor()->c_str()); return -1; } /* * Use the default build environment. We don't need anything custom here. */ ext::optional<pbxbuild::Build::Environment> buildEnvironment = pbxbuild::Build::Environment::Default(filesystem); if (!buildEnvironment) { fprintf(stderr, "error: couldn't create build environment\n"); return -1; } /* The build settings passed in on the command line override all others. */ std::vector<pbxsetting::Level> overrideLevels = Action::CreateOverrideLevels(options, buildEnvironment->baseEnvironment()); /* * Create the build parameters. The executor uses this to load a workspace and create a * build context, but is not required to when the parameters haven't changed from a cache. */ xcexecution::Parameters parameters = Action::CreateParameters(options, overrideLevels); /* * Perform the build! */ bool success = executor->build(filesystem, *buildEnvironment, parameters); if (!success) { return 1; } return 0; }
int ShowBuildSettingsAction:: Run(Options const &options) { if (!Action::VerifyBuildActions(options.actions())) { return -1; } ext::optional<pbxbuild::Build::Environment> buildEnvironment = pbxbuild::Build::Environment::Default(); if (!buildEnvironment) { fprintf(stderr, "error: couldn't create build environment\n"); return -1; } std::vector<pbxsetting::Level> overrideLevels = Action::CreateOverrideLevels(options, buildEnvironment->baseEnvironment()); xcexecution::Parameters parameters = Action::CreateParameters(options, overrideLevels); ext::optional<pbxbuild::WorkspaceContext> workspaceContext = parameters.loadWorkspace(*buildEnvironment, FSUtil::GetCurrentDirectory()); if (!workspaceContext) { return -1; } ext::optional<pbxbuild::Build::Context> buildContext = parameters.createBuildContext(*workspaceContext); if (!buildContext) { return -1; } ext::optional<pbxbuild::DirectedGraph<pbxproj::PBX::Target::shared_ptr>> graph = parameters.resolveDependencies(*buildEnvironment, *buildContext); if (!graph) { return -1; } ext::optional<std::vector<pbxproj::PBX::Target::shared_ptr>> targets = graph->ordered(); if (!targets) { fprintf(stderr, "error: cycle detected in target dependencies\n"); return -1; } for (pbxproj::PBX::Target::shared_ptr const &target : *targets) { ext::optional<pbxbuild::Target::Environment> targetEnvironment = buildContext->targetEnvironment(*buildEnvironment, target); if (!targetEnvironment) { fprintf(stderr, "error: couldn't create target environment\n"); continue; } pbxsetting::Environment const &environment = targetEnvironment->environment(); std::unordered_map<std::string, std::string> values = environment.computeValues(pbxsetting::Condition::Empty()); std::map<std::string, std::string> orderedValues = std::map<std::string, std::string>(values.begin(), values.end()); printf("Build settings for action %s and target %s:\n", buildContext->action().c_str(), target->name().c_str()); for (auto const &value : orderedValues) { printf(" %s = %s\n", value.first.c_str(), value.second.c_str()); } printf("\n"); } return 0; }
int VersionAction:: Run(process::Context const *processContext, Filesystem const *filesystem, Options const &options) { if (!options.sdk()) { // TODO(grp): Real version numbers. printf("xcbuild version 0.1\n"); printf("Build version 1\n"); } else { ext::optional<std::string> developerRoot = xcsdk::Environment::DeveloperRoot(processContext, filesystem); if (!developerRoot) { fprintf(stderr, "error: unable to find developer dir\n"); return 1; } auto configuration = xcsdk::Configuration::Load(filesystem, xcsdk::Configuration::DefaultPaths(processContext)); auto manager = xcsdk::SDK::Manager::Open(filesystem, *developerRoot, configuration); if (manager == nullptr) { fprintf(stderr, "error: unable to open developer directory\n"); return 1; } xcsdk::SDK::Target::shared_ptr target = manager->findTarget(*options.sdk()); if (target == nullptr) { fprintf(stderr, "error: cannot find sdk '%s'\n", options.sdk()->c_str()); return 1; } /* Use over a standard map to preserve key order. */ auto values = plist::Dictionary::New(); if (target->version()) { values->set("SDKVersion", plist::String::New(*target->version())); } values->set("Path", plist::String::New(target->path())); if (target->platform()->version()) { values->set("PlatformVersion", plist::String::New(*target->platform()->version())); } values->set("PlatformPath", plist::String::New(target->platform()->path())); if (auto product = target->product()) { if (product->buildVersion()) { values->set("ProductBuildVersion", plist::String::New(*product->buildVersion())); } if (product->copyright()) { values->set("ProductCopyright", plist::String::New(*product->copyright())); } if (product->name()) { values->set("ProductName", plist::String::New(*product->name())); } if (product->userVisibleVersion()) { values->set("ProductUserVisibleVersion", plist::String::New(*product->userVisibleVersion())); } if (product->version()) { values->set("ProductVersion", plist::String::New(*product->version())); } } if (options.actions().empty()) { fprintf(stdout, "%s - %s (%s)\n", target->bundleName().c_str(), target->displayName().value_or(target->bundleName()).c_str(), target->canonicalName().value_or(target->bundleName()).c_str()); for (size_t n = 0; n < values->count(); n++) { if (plist::String const *value = values->value<plist::String>(n)) { fprintf(stdout, "%s: %s\n", values->key(n).c_str(), value->value().c_str()); } } fprintf(stdout, "\n"); } else { for (std::string const &action : options.actions()) { if (plist::String const *value = values->value<plist::String>(action)) { fprintf(stdout, "%s\n", value->value().c_str()); } } } } return 0; }