Пример #1
0
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;
}
Пример #3
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;
}