blob: b99a8abc3012369ae740de50a5dbd12a7e21abd1 [file] [log] [blame]
//===--- ArgsToFrontendOutputsConverter.h -----------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
#define SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H
#include "swift/AST/DiagnosticConsumer.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/Basic/LLVM.h"
#include "swift/Basic/SupplementaryOutputPaths.h"
#include "swift/Frontend/FrontendOptions.h"
#include "swift/Option/Options.h"
#include "llvm/Option/ArgList.h"
#include <vector>
namespace swift {
class OutputFileMap;
/// Given the command line arguments and information about the inputs,
/// Fill in all the information in FrontendInputsAndOutputs.
class ArgsToFrontendOutputsConverter {
const llvm::opt::ArgList &Args;
StringRef ModuleName;
FrontendInputsAndOutputs &InputsAndOutputs;
DiagnosticEngine &Diags;
public:
ArgsToFrontendOutputsConverter(const llvm::opt::ArgList &args,
StringRef moduleName,
FrontendInputsAndOutputs &inputsAndOutputs,
DiagnosticEngine &diags)
: Args(args), ModuleName(moduleName), InputsAndOutputs(inputsAndOutputs),
Diags(diags) {}
bool convert(std::vector<std::string> &mainOutputs,
std::vector<SupplementaryOutputPaths> &supplementaryOutputs);
/// Try to read an output file list file.
/// \returns `None` if it could not open the filelist.
static Optional<std::vector<std::string>>
readOutputFileList(StringRef filelistPath, DiagnosticEngine &diags);
};
class OutputFilesComputer {
DiagnosticEngine &Diags;
const FrontendInputsAndOutputs &InputsAndOutputs;
const std::vector<std::string> OutputFileArguments;
const std::string OutputDirectoryArgument;
const std::string FirstInput;
const FrontendOptions::ActionType RequestedAction;
const llvm::opt::Arg *const ModuleNameArg;
const StringRef Suffix;
const bool HasTextualOutput;
OutputFilesComputer(DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs,
std::vector<std::string> outputFileArguments,
StringRef outputDirectoryArgument, StringRef firstInput,
FrontendOptions::ActionType requestedAction,
const llvm::opt::Arg *moduleNameArg, StringRef suffix,
bool hasTextualOutput);
public:
static Optional<OutputFilesComputer>
create(const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs);
/// \return the output filenames on the command line or in the output
/// filelist. If there
/// were neither -o's nor an output filelist, returns an empty vector.
static Optional<std::vector<std::string>>
getOutputFilenamesFromCommandLineOrFilelist(const llvm::opt::ArgList &args,
DiagnosticEngine &diags);
Optional<std::vector<std::string>> computeOutputFiles() const;
private:
Optional<std::string> computeOutputFile(StringRef outputArg,
const InputFile &input) const;
/// \return the correct output filename when none was specified.
///
/// Such an absence should only occur when invoking the frontend
/// without the driver,
/// because the driver will always pass -o with an appropriate filename
/// if output is required for the requested action.
Optional<std::string> deriveOutputFileFromInput(const InputFile &input) const;
/// \return the correct output filename when a directory was specified.
///
/// Such a specification should only occur when invoking the frontend
/// directly, because the driver will always pass -o with an appropriate
/// filename if output is required for the requested action.
Optional<std::string>
deriveOutputFileForDirectory(const InputFile &input) const;
std::string determineBaseNameOfOutput(const InputFile &input) const;
std::string deriveOutputFileFromParts(StringRef dir, StringRef base) const;
};
class SupplementaryOutputPathsComputer {
const llvm::opt::ArgList &Args;
DiagnosticEngine &Diags;
const FrontendInputsAndOutputs &InputsAndOutputs;
ArrayRef<std::string> OutputFiles;
StringRef ModuleName;
const FrontendOptions::ActionType RequestedAction;
public:
SupplementaryOutputPathsComputer(
const llvm::opt::ArgList &args, DiagnosticEngine &diags,
const FrontendInputsAndOutputs &inputsAndOutputs,
ArrayRef<std::string> outputFiles, StringRef moduleName);
Optional<std::vector<SupplementaryOutputPaths>> computeOutputPaths() const;
private:
/// \Return a set of supplementary output paths for each input that might
/// produce supplementary outputs, or None to signal an error.
/// \note
/// Batch-mode supports multiple primary inputs.
/// \par
/// The paths are derived from arguments
/// such as -emit-module-path. These are not the final computed paths,
/// merely the ones passed in via the command line.
/// \note
/// In the future, these will also include those passed in via whatever
/// filelist scheme gets implemented to handle cases where the command line
/// arguments become burdensome.
Optional<std::vector<SupplementaryOutputPaths>>
getSupplementaryOutputPathsFromArguments() const;
/// Read a supplementary output file map file.
/// \returns `None` if it could not open the file map.
Optional<std::vector<SupplementaryOutputPaths>>
readSupplementaryOutputFileMap() const;
/// Given an ID corresponding to supplementary output argument
/// (e.g. -emit-module-path), collect all such paths, and ensure
/// there are the right number of them.
Optional<std::vector<std::string>>
getSupplementaryFilenamesFromArguments(options::ID pathID) const;
Optional<SupplementaryOutputPaths> computeOutputPathsForOneInput(
StringRef outputFilename,
const SupplementaryOutputPaths &pathsFromFilelists,
const InputFile &) const;
StringRef deriveDefaultSupplementaryOutputPathExcludingExtension(
StringRef outputFilename, const InputFile &) const;
/// \return empty string if no output file.
std::string determineSupplementaryOutputFilename(
options::ID emitOpt, std::string pathFromArgumentsOrFilelists,
StringRef extension, StringRef mainOutputIfUsable,
StringRef defaultSupplementaryOutputPathExcludingExtension) const;
void deriveModulePathParameters(options::ID &emitOption,
std::string &extension,
std::string &mainOutputIfUsable) const;
};
} // namespace swift
#endif /* SWIFT_FRONTEND_ARGSTOFRONTENDOUTPUTSCONVERTER_H */