Esempio n. 1
0
std::pair<bool, std::vector<pbxbuild::Tool::Invocation>> SimpleExecutor::
performInvocations(
    Filesystem *filesystem,
    pbxproj::PBX::Target::shared_ptr const &target,
    pbxbuild::Target::Environment const &targetEnvironment,
    std::vector<pbxbuild::Tool::Invocation> const &orderedInvocations,
    bool createProductStructure)
{
    for (pbxbuild::Tool::Invocation const &invocation : orderedInvocations) {
        // TODO(grp): This should perhaps be a separate flag for a 'phony' invocation.
        if (invocation.executable().path().empty()) {
            continue;
        }

        if (invocation.createsProductStructure() != createProductStructure) {
            continue;
        }

        std::map<std::string, std::string> sortedEnvironment = std::map<std::string, std::string>(invocation.environment().begin(), invocation.environment().end());

        xcformatter::Formatter::Print(_formatter->beginInvocation(invocation, invocation.executable().displayName(), createProductStructure));

        if (!_dryRun) {
            for (std::string const &output : invocation.outputs()) {
                std::string directory = FSUtil::GetDirectoryName(output);

                if (!filesystem->createDirectory(directory)) {
                    return std::make_pair(false, std::vector<pbxbuild::Tool::Invocation>({ invocation }));
                }
            }

            if (!invocation.executable().builtin().empty()) {
                /* For built-in tools, run them in-process. */
                std::shared_ptr<builtin::Driver> driver = _builtins.driver(invocation.executable().builtin());
                if (driver == nullptr) {
                    xcformatter::Formatter::Print(_formatter->finishInvocation(invocation, invocation.executable().displayName(), createProductStructure));
                    return std::make_pair(false, std::vector<pbxbuild::Tool::Invocation>({ invocation }));
                }

                if (driver->run(invocation.arguments(), invocation.environment(), filesystem, invocation.workingDirectory()) != 0) {
                    xcformatter::Formatter::Print(_formatter->finishInvocation(invocation, invocation.executable().displayName(), createProductStructure));
                    return std::make_pair(false, std::vector<pbxbuild::Tool::Invocation>({ invocation }));
                }
            } else {
                /* External tool, run the tool externally. */
                Subprocess process;
                if (!process.execute(invocation.executable().path(), invocation.arguments(), invocation.environment(), invocation.workingDirectory()) || process.exitcode() != 0) {
                    xcformatter::Formatter::Print(_formatter->finishInvocation(invocation, invocation.executable().displayName(), createProductStructure));
                    return std::make_pair(false, std::vector<pbxbuild::Tool::Invocation>({ invocation }));
                }
            }
        }

        xcformatter::Formatter::Print(_formatter->finishInvocation(invocation, invocation.executable().displayName(), createProductStructure));
    }

    return std::make_pair(true, std::vector<pbxbuild::Tool::Invocation>());
}
Esempio n. 2
0
static bool
CopyPath(std::string const &inputPath, std::string const &outputPath)
{
    if (!FSUtil::CreateDirectory(FSUtil::GetDirectoryName(outputPath))) {
        return false;
    }

    Subprocess cp;
    if (!cp.execute("/bin/cp", { "-R", inputPath, outputPath }) || cp.exitcode() != 0) {
        return false;
    }

    /* Should preserve permissions but make writable. */
    Subprocess chmod;
    if (!chmod.execute("/bin/chmod", { "-R", "+w", outputPath }) || chmod.exitcode() != 0) {
        return false;
    }

    return true;
}
Esempio n. 3
0
int
main(int argc, char **argv)
{
    std::vector<std::string> args = std::vector<std::string>(argv + 1, argv + argc);

    /*
     * Parse out the options, or print help & exit.
     */
    Options options;
    std::pair<bool, std::string> result = libutil::Options::Parse<Options>(&options, args);
    if (!result.first) {
        return Help(result.second);
    }

    /*
     * Handle the basic options that don't need SDKs.
     */
    if (options.tool().empty()) {
        if (options.help()) {
            return Help();
        } else if (options.version()) {
            return Version();
        }
    }

    /*
     * Parse fallback options from the environment.
     */
    std::string toolchainsInput = options.toolchain();
    if (toolchainsInput.empty()) {
        if (char const *toolchains = getenv("TOOLCHAINS")) {
            toolchainsInput = std::string(toolchains);
        }
    }
    std::string SDK = options.SDK();
    if (SDK.empty()) {
        if (char const *sdkroot = getenv("SDKROOT")) {
            SDK = std::string(sdkroot);
        } else {
            /* Default SDK. */
            SDK = "macosx";
        }
    }
    bool verbose = options.verbose() || getenv("xcrun_verbose") != NULL;
    bool log = options.log() || getenv("xcrun_log") != NULL;
    bool nocache = options.noCache() || getenv("xcrun_nocache") != NULL;

    /*
     * Warn about unhandled arguments.
     */
    if (nocache || options.killCache()) {
        fprintf(stderr, "warning: cache options not implemented\n");
    }

    /*
     * Create filesystem.
     */
    auto filesystem = std::unique_ptr<Filesystem>(new DefaultFilesystem());

    /*
     * Load the SDK manager from the developer root.
     */
    ext::optional<std::string> developerRoot = xcsdk::Environment::DeveloperRoot(filesystem.get());
    if (!developerRoot) {
        fprintf(stderr, "error: unable to find developer root\n");
        return -1;
    }
    auto configuration = xcsdk::Configuration::Load(filesystem.get(), xcsdk::Configuration::DefaultPaths());
    auto manager = xcsdk::SDK::Manager::Open(filesystem.get(), *developerRoot, configuration);
    if (manager == nullptr) {
        fprintf(stderr, "error: unable to load manager from '%s'\n", developerRoot->c_str());
        return -1;
    }
    if (verbose) {
        fprintf(stderr, "verbose: using developer root '%s'\n", manager->path().c_str());
    }

    /*
     * Determine the SDK to use.
     */
    xcsdk::SDK::Target::shared_ptr target = manager->findTarget(SDK);
    if (target == nullptr) {
        fprintf(stderr, "error: unable to find sdk '%s'\n", SDK.c_str());
        return -1;
    }
    if (verbose) {
        fprintf(stderr, "verbose: using sdk '%s': %s\n", target->canonicalName().c_str(), target->path().c_str());
    }

    /*
     * Determine the toolchains to use. Default to the SDK's toolchains.
     */
    xcsdk::SDK::Toolchain::vector toolchains;
    if (!toolchainsInput.empty()) {
        /* If the custom toolchain exists, use it instead. */
        std::vector<std::string> toolchainTokens = pbxsetting::Type::ParseList(toolchainsInput);
        for (std::string const &toolchainToken : toolchainTokens) {
            if (auto TC = manager->findToolchain(toolchainToken)) {
                toolchains.push_back(TC);
            }
        }

        if (toolchains.empty()) {
            fprintf(stderr, "error: unable to find toolchains in '%s'\n", toolchainsInput.c_str());
            return -1;
        }
    } else {
        toolchains = target->toolchains();
    }
    if (toolchains.empty()) {
        fprintf(stderr, "error: unable to find any toolchains\n");
        return -1;
    }
    if (verbose) {
        fprintf(stderr, "verbose: using toolchain(s):");
        for (xcsdk::SDK::Toolchain::shared_ptr const &toolchain : toolchains) {
            fprintf(stderr, " '%s'", toolchain->identifier().c_str());
        }
        fprintf(stderr, "\n");
    }

    /*
     * Perform actions.
     */
    if (options.showSDKPath()) {
        printf("%s\n", target->path().c_str());
        return 0;
    } else if (options.showSDKVersion()) {
        printf("%s\n", target->path().c_str());
        return 0;
    } else if (options.showSDKBuildVersion()) {
        if (auto product = target->product()) {
            printf("%s\n", product->buildVersion().c_str());
            return 0;
        } else {
            fprintf(stderr, "error: sdk has no build version\n");
            return -1;
        }
    } else if (options.showSDKPlatformPath()) {
        if (auto platform = target->platform()) {
            printf("%s\n", platform->path().c_str());
        } else {
            fprintf(stderr, "error: sdk has no platform\n");
            return -1;
        }
    } else if (options.showSDKPlatformVersion()) {
        if (auto platform = target->platform()) {
            printf("%s\n", platform->version().c_str());
        } else {
            fprintf(stderr, "error: sdk has no platform\n");
            return -1;
        }
    } else {
        if (options.tool().empty()) {
            return Help("no tool provided");
        }

        /*
         * Collect search paths for the tool. Can be in toolchains, target, developer root, or default paths.
         */
        std::vector<std::string> executablePaths = target->executablePaths(toolchains);
        std::vector<std::string> defaultExecutablePaths = FSUtil::GetExecutablePaths();
        executablePaths.insert(executablePaths.end(), defaultExecutablePaths.begin(), defaultExecutablePaths.end());

        /*
         * Find the tool to execute.
         */
        ext::optional<std::string> executable = filesystem->findExecutable(options.tool(), executablePaths);
        if (!executable) {
            fprintf(stderr, "error: tool '%s' not found\n", options.tool().c_str());
            return 1;
        }
        if (verbose) {
            fprintf(stderr, "verbose: resolved tool '%s' to: %s\n", options.tool().c_str(), executable->c_str());
        }

        if (options.find()) {
            /*
             * Just find the tool; i.e. print its path.
             */
            printf("%s\n", executable->c_str());
            return 0;
        } else {
            /* Run is the default. */

            /*
             * Update effective environment to include the target path.
             */
            std::unordered_map<std::string, std::string> environment = SysUtil::EnvironmentVariables();
            environment["SDKROOT"] = target->path();

            if (log) {
                printf("env SDKROOT=%s %s\n", target->path().c_str(), executable->c_str());
            }

            /*
             * Execute the process!
             */
            if (verbose) {
                printf("verbose: executing tool: %s\n", executable->c_str());
            }
            Subprocess process;
            if (!process.execute(*executable, options.args(), environment)) {
                fprintf(stderr, "error: unable to execute tool '%s'\n", options.tool().c_str());
                return -1;
            }

            return process.exitcode();
        }
    }
}