Skip to content

Commit

Permalink
Keep configuration file search directories in ExpansionContext. NFC
Browse files Browse the repository at this point in the history
Class ExpansionContext encapsulates options for search and expansion of
response files, including configuration files. With this change the
directories which are searched for configuration files are also stored
in ExpansionContext.

Differential Revision: https://reviews.llvm.org/D135439
  • Loading branch information
spavloff committed Oct 19, 2022
1 parent 42230ef commit 0dec5e1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 52 deletions.
8 changes: 6 additions & 2 deletions clang/include/clang/Driver/Driver.h
Expand Up @@ -36,6 +36,9 @@ class Triple;
namespace vfs {
class FileSystem;
}
namespace cl {
class ExpansionContext;
}
} // namespace llvm

namespace clang {
Expand Down Expand Up @@ -677,13 +680,14 @@ class Driver {
/// executable filename).
///
/// \returns true if error occurred.
bool loadDefaultConfigFiles(ArrayRef<StringRef> CfgFileSearchDirs);
bool loadDefaultConfigFiles(llvm::cl::ExpansionContext &ExpCtx);

/// Read options from the specified file.
///
/// \param [in] FileName File to read.
/// \param [in] Search and expansion options.
/// \returns true, if error occurred while reading.
bool readConfigFile(StringRef FileName);
bool readConfigFile(StringRef FileName, llvm::cl::ExpansionContext &ExpCtx);

/// Set the driver mode (cl, gcc, etc) from the value of the `--driver-mode`
/// option.
Expand Down
74 changes: 24 additions & 50 deletions clang/lib/Driver/Driver.cpp
Expand Up @@ -922,35 +922,6 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
//
}

/// Looks the given directories for the specified file.
///
/// \param[out] FilePath File path, if the file was found.
/// \param[in] Dirs Directories used for the search.
/// \param[in] FileName Name of the file to search for.
/// \return True if file was found.
///
/// Looks for file specified by FileName sequentially in directories specified
/// by Dirs.
///
static bool searchForFile(SmallVectorImpl<char> &FilePath,
ArrayRef<StringRef> Dirs, StringRef FileName,
llvm::vfs::FileSystem &FS) {
SmallString<128> WPath;
for (const StringRef &Dir : Dirs) {
if (Dir.empty())
continue;
WPath.clear();
llvm::sys::path::append(WPath, Dir, FileName);
llvm::sys::path::native(WPath);
auto Status = FS.status(WPath);
if (Status && Status->getType() == llvm::sys::fs::file_type::regular_file) {
FilePath = std::move(WPath);
return true;
}
}
return false;
}

static void appendOneArg(InputArgList &Args, const Arg *Opt,
const Arg *BaseArg) {
// The args for config files or /clang: flags belong to different InputArgList
Expand All @@ -967,11 +938,10 @@ static void appendOneArg(InputArgList &Args, const Arg *Opt,
Args.append(Copy);
}

bool Driver::readConfigFile(StringRef FileName) {
bool Driver::readConfigFile(StringRef FileName,
llvm::cl::ExpansionContext &ExpCtx) {
// Try reading the given file.
SmallVector<const char *, 32> NewCfgArgs;
llvm::cl::ExpansionContext ExpCtx(Alloc, llvm::cl::tokenizeConfigFile);
ExpCtx.setVFS(&getVFS());
if (!ExpCtx.readConfigFile(FileName, NewCfgArgs)) {
Diag(diag::err_drv_cannot_read_config_file) << FileName;
return true;
Expand Down Expand Up @@ -1012,6 +982,10 @@ bool Driver::readConfigFile(StringRef FileName) {
}

bool Driver::loadConfigFiles() {
llvm::cl::ExpansionContext ExpCtx(Saver.getAllocator(),
llvm::cl::tokenizeConfigFile);
ExpCtx.setVFS(&getVFS());

// Process options that change search path for config files.
if (CLOptions) {
if (CLOptions->hasArg(options::OPT_config_system_dir_EQ)) {
Expand All @@ -1036,19 +1010,20 @@ bool Driver::loadConfigFiles() {

// Prepare list of directories where config file is searched for.
StringRef CfgFileSearchDirs[] = {UserConfigDir, SystemConfigDir, Dir};
ExpCtx.setSearchDirs(CfgFileSearchDirs);

// First try to load configuration from the default files, return on error.
if (loadDefaultConfigFiles(CfgFileSearchDirs))
if (loadDefaultConfigFiles(ExpCtx))
return true;

// Then load configuration files specified explicitly.
llvm::SmallString<128> CfgFilePath;
SmallString<128> CfgFilePath;
if (CLOptions) {
for (auto CfgFileName : CLOptions->getAllArgValues(options::OPT_config)) {
// If argument contains directory separator, treat it as a path to
// configuration file.
if (llvm::sys::path::has_parent_path(CfgFileName)) {
CfgFilePath = CfgFileName;
CfgFilePath.assign(CfgFileName);
if (llvm::sys::path::is_relative(CfgFilePath)) {
if (getVFS().makeAbsolute(CfgFilePath))
return true;
Expand All @@ -1059,8 +1034,7 @@ bool Driver::loadConfigFiles() {
return true;
}
}
} else if (!searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName,
getVFS())) {
} else if (!ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {
// Report an error that the config file could not be found.
Diag(diag::err_drv_config_file_not_found) << CfgFileName;
for (const StringRef &SearchDir : CfgFileSearchDirs)
Expand All @@ -1070,7 +1044,7 @@ bool Driver::loadConfigFiles() {
}

// Try to read the config file, return on error.
if (readConfigFile(CfgFilePath))
if (readConfigFile(CfgFilePath, ExpCtx))
return true;
}
}
Expand All @@ -1079,7 +1053,7 @@ bool Driver::loadConfigFiles() {
return false;
}

bool Driver::loadDefaultConfigFiles(ArrayRef<StringRef> CfgFileSearchDirs) {
bool Driver::loadDefaultConfigFiles(llvm::cl::ExpansionContext &ExpCtx) {
// Disable default config if CLANG_NO_DEFAULT_CONFIG is set to a non-empty
// value.
if (const char *NoConfigEnv = ::getenv("CLANG_NO_DEFAULT_CONFIG")) {
Expand Down Expand Up @@ -1123,36 +1097,36 @@ bool Driver::loadDefaultConfigFiles(ArrayRef<StringRef> CfgFileSearchDirs) {
// (e.g. i386-pc-linux-gnu.cfg + clang-g++.cfg for *clang-g++).

// Try loading <triple>-<mode>.cfg, and return if we find a match.
llvm::SmallString<128> CfgFilePath;
SmallString<128> CfgFilePath;
std::string CfgFileName = Triple + '-' + RealMode + ".cfg";
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
return readConfigFile(CfgFilePath);
if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
return readConfigFile(CfgFilePath, ExpCtx);

bool TryModeSuffix = !ClangNameParts.ModeSuffix.empty() &&
ClangNameParts.ModeSuffix != RealMode;
if (TryModeSuffix) {
CfgFileName = Triple + '-' + ClangNameParts.ModeSuffix + ".cfg";
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
return readConfigFile(CfgFilePath);
if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
return readConfigFile(CfgFilePath, ExpCtx);
}

// Try loading <mode>.cfg, and return if loading failed. If a matching file
// was not found, still proceed on to try <triple>.cfg.
CfgFileName = RealMode + ".cfg";
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS())) {
if (readConfigFile(CfgFilePath))
if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath)) {
if (readConfigFile(CfgFilePath, ExpCtx))
return true;
} else if (TryModeSuffix) {
CfgFileName = ClangNameParts.ModeSuffix + ".cfg";
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()) &&
readConfigFile(CfgFilePath))
if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath) &&
readConfigFile(CfgFilePath, ExpCtx))
return true;
}

// Try loading <triple>.cfg and return if we find a match.
CfgFileName = Triple + ".cfg";
if (searchForFile(CfgFilePath, CfgFileSearchDirs, CfgFileName, getVFS()))
return readConfigFile(CfgFilePath);
if (ExpCtx.findConfigFile(CfgFileName, CfgFilePath))
return readConfigFile(CfgFilePath, ExpCtx);

// If we were unable to find a config file deduced from executable name,
// that is not an error.
Expand Down
19 changes: 19 additions & 0 deletions llvm/include/llvm/Support/CommandLine.h
Expand Up @@ -2140,6 +2140,9 @@ class ExpansionContext {
/// current directory is used instead.
StringRef CurrentDir;

/// Directories used for search of config files.
ArrayRef<StringRef> SearchDirs;

/// True if names of nested response files must be resolved relative to
/// including file.
bool RelativeNames = false;
Expand Down Expand Up @@ -2172,11 +2175,27 @@ class ExpansionContext {
return *this;
}

ExpansionContext &setSearchDirs(ArrayRef<StringRef> X) {
SearchDirs = X;
return *this;
}

ExpansionContext &setVFS(vfs::FileSystem *X) {
FS = X;
return *this;
}

/// Looks for the specified configuration file.
///
/// \param[in] FileName Name of the file to search for.
/// \param[out] FilePath File absolute path, if it was found.
/// \return True if file was found.
///
/// If the specified file name contains a directory separator, it is searched
/// for by its absolute path. Otherwise looks for file sequentially in
/// directories specified by SearchDirs field.
bool findConfigFile(StringRef FileName, SmallVectorImpl<char> &FilePath);

/// Reads command line options from the given configuration file.
///
/// \param [in] CfgFile Path to configuration file.
Expand Down
37 changes: 37 additions & 0 deletions llvm/lib/Support/CommandLine.cpp
Expand Up @@ -1350,6 +1350,43 @@ bool cl::expandResponseFiles(int Argc, const char *const *Argv,
ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T)
: Saver(A), Tokenizer(T), FS(vfs::getRealFileSystem().get()) {}

bool ExpansionContext::findConfigFile(StringRef FileName,
SmallVectorImpl<char> &FilePath) {
SmallString<128> CfgFilePath;
const auto FileExists = [this](SmallString<128> Path) -> bool {
auto Status = FS->status(Path);
return Status &&
Status->getType() == llvm::sys::fs::file_type::regular_file;
};

// If file name contains directory separator, treat it as a path to
// configuration file.
if (llvm::sys::path::has_parent_path(FileName)) {
CfgFilePath = FileName;
if (llvm::sys::path::is_relative(FileName) && FS->makeAbsolute(CfgFilePath))
return false;
if (!FileExists(CfgFilePath))
return false;
FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
return true;
}

// Look for the file in search directories.
for (const StringRef &Dir : SearchDirs) {
if (Dir.empty())
continue;
CfgFilePath.assign(Dir);
llvm::sys::path::append(CfgFilePath, FileName);
llvm::sys::path::native(CfgFilePath);
if (FileExists(CfgFilePath)) {
FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
return true;
}
}

return false;
}

bool ExpansionContext::readConfigFile(StringRef CfgFile,
SmallVectorImpl<const char *> &Argv) {
SmallString<128> AbsPath;
Expand Down

0 comments on commit 0dec5e1

Please sign in to comment.