Moved header list loading to new class. This is staging for adding module map loading and checking support.

llvm-svn: 229108
This commit is contained in:
John Thompson 2015-02-13 14:29:22 +00:00
parent 48bc169f04
commit d845baecb4
4 changed files with 218 additions and 93 deletions

View File

@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
add_clang_executable(modularize
Modularize.cpp
ModuleAssistant.cpp
ModularizeUtilities.cpp
PreprocessorTracker.cpp
)

View File

@ -144,6 +144,7 @@
//===----------------------------------------------------------------------===//
#include "Modularize.h"
#include "ModularizeUtilities.h"
#include "PreprocessorTracker.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
@ -178,10 +179,10 @@ using namespace llvm::opt;
using namespace Modularize;
// Option to specify a file name for a list of header files to check.
cl::list<std::string>
ListFileNames(cl::Positional, cl::value_desc("list"),
cl::desc("<list of one or more header list files>"),
cl::CommaSeparated);
cl::list<std::string>
ListFileNames(cl::Positional, cl::value_desc("list"),
cl::desc("<list of one or more header list files>"),
cl::CommaSeparated);
// Collect all other arguments, which will be passed to the front end.
cl::list<std::string>
@ -224,80 +225,6 @@ const char *Argv0;
// Save the command line for comments.
std::string CommandLine;
// Read the header list file and collect the header file names and
// optional dependencies.
std::error_code
getHeaderFileNames(SmallVectorImpl<std::string> &HeaderFileNames,
DependencyMap &Dependencies, StringRef ListFileName,
StringRef HeaderPrefix) {
// By default, use the path component of the list file name.
SmallString<256> HeaderDirectory(ListFileName);
sys::path::remove_filename(HeaderDirectory);
SmallString<256> CurrentDirectory;
sys::fs::current_path(CurrentDirectory);
// Get the prefix if we have one.
if (HeaderPrefix.size() != 0)
HeaderDirectory = HeaderPrefix;
// Read the header list file into a buffer.
ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
MemoryBuffer::getFile(ListFileName);
if (std::error_code EC = listBuffer.getError())
return EC;
// Parse the header list into strings.
SmallVector<StringRef, 32> Strings;
listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);
// Collect the header file names from the string list.
for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
E = Strings.end();
I != E; ++I) {
StringRef Line = I->trim();
// Ignore comments and empty lines.
if (Line.empty() || (Line[0] == '#'))
continue;
std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
SmallString<256> HeaderFileName;
// Prepend header file name prefix if it's not absolute.
if (sys::path::is_absolute(TargetAndDependents.first))
llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
else {
if (HeaderDirectory.size() != 0)
HeaderFileName = HeaderDirectory;
else
HeaderFileName = CurrentDirectory;
sys::path::append(HeaderFileName, TargetAndDependents.first);
sys::path::native(HeaderFileName);
}
// Handle optional dependencies.
DependentsVector Dependents;
SmallVector<StringRef, 4> DependentsList;
TargetAndDependents.second.split(DependentsList, " ", -1, false);
int Count = DependentsList.size();
for (int Index = 0; Index < Count; ++Index) {
SmallString<256> Dependent;
if (sys::path::is_absolute(DependentsList[Index]))
Dependent = DependentsList[Index];
else {
if (HeaderDirectory.size() != 0)
Dependent = HeaderDirectory;
else
Dependent = CurrentDirectory;
sys::path::append(Dependent, DependentsList[Index]);
}
sys::path::native(Dependent);
Dependents.push_back(Dependent.str());
}
// Save the resulting header file path and dependencies.
HeaderFileNames.push_back(HeaderFileName.str());
Dependencies[HeaderFileName.str()] = Dependents;
}
return std::error_code();
}
// Helper function for finding the input file in an arguments list.
std::string findInputFile(const CommandLineArguments &CLArgs) {
std::unique_ptr<OptTable> Opts(createDriverOptTable());
@ -706,22 +633,20 @@ int main(int Argc, const char **Argv) {
return 1;
}
std::unique_ptr<ModularizeUtilities> ModUtil;
ModUtil.reset(
ModularizeUtilities::createModularizeUtilities(
ListFileNames, HeaderPrefix));
// Get header file names and dependencies.
SmallVector<std::string, 32> Headers;
DependencyMap Dependencies;
for (auto I : ListFileNames) {
if (std::error_code EC =
getHeaderFileNames(Headers, Dependencies, I, HeaderPrefix)) {
errs() << Argv[0] << ": error: Unable to get header list '" << I
<< "': " << EC.message() << '\n';
return 1;
}
}
ModUtil->loadAllHeaderListsAndDependencies();
// If we are in assistant mode, output the module map and quit.
if (ModuleMapPath.length() != 0) {
if (!createModuleMap(ModuleMapPath, Headers, Dependencies, HeaderPrefix,
RootModule))
if (!createModuleMap(ModuleMapPath, ModUtil->HeaderFileNames,
ModUtil->Dependencies, HeaderPrefix, RootModule))
return 1; // Failed.
return 0; // Success - Skip checks in assistant mode.
}
@ -735,12 +660,13 @@ int main(int Argc, const char **Argv) {
// Create preprocessor tracker, to watch for macro and conditional problems.
std::unique_ptr<PreprocessorTracker> PPTracker(
PreprocessorTracker::create(Headers, BlockCheckHeaderListOnly));
PreprocessorTracker::create(ModUtil->HeaderFileNames,
BlockCheckHeaderListOnly));
// Parse all of the headers, detecting duplicates.
EntityMap Entities;
ClangTool Tool(*Compilations, Headers);
Tool.appendArgumentsAdjuster(getAddDependenciesAdjuster(Dependencies));
ClangTool Tool(*Compilations, ModUtil->HeaderFileNames);
Tool.appendArgumentsAdjuster(getAddDependenciesAdjuster(ModUtil->Dependencies));
int HadErrors = 0;
ModularizeFrontendActionFactory Factory(Entities, *PPTracker, HadErrors);
HadErrors |= Tool.run(&Factory);

View File

@ -0,0 +1,124 @@
//===--- extra/modularize/ModularizeUtilities.cpp -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a class for loading and validating a module map or
// header list by checking that all headers in the corresponding directories
// are accounted for.
//
//===----------------------------------------------------------------------===//
#include "ModularizeUtilities.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace Modularize;
// ModularizeUtilities class implementation.
// Constructor.
ModularizeUtilities::ModularizeUtilities(std::vector<std::string> &InputPaths,
llvm::StringRef Prefix)
: InputFilePaths(InputPaths),
HeaderPrefix(Prefix) {}
// Create instance of ModularizeUtilities, to simplify setting up
// subordinate objects.
ModularizeUtilities *ModularizeUtilities::createModularizeUtilities(
std::vector<std::string> &InputPaths, llvm::StringRef Prefix) {
return new ModularizeUtilities(InputPaths, Prefix);
}
// Load all header lists and dependencies.
std::error_code ModularizeUtilities::loadAllHeaderListsAndDependencies() {
typedef std::vector<std::string>::iterator Iter;
for (Iter I = InputFilePaths.begin(), E = InputFilePaths.end(); I != E; ++I) {
if (std::error_code EC = loadSingleHeaderListsAndDependencies(*I)) {
errs() << "modularize: error: Unable to get header list '" << *I
<< "': " << EC.message() << '\n';
return EC;
}
}
return std::error_code();
}
// Load single header list and dependencies.
std::error_code ModularizeUtilities::loadSingleHeaderListsAndDependencies(
llvm::StringRef InputPath) {
// By default, use the path component of the list file name.
SmallString<256> HeaderDirectory(InputPath);
llvm::sys::path::remove_filename(HeaderDirectory);
SmallString<256> CurrentDirectory;
llvm::sys::fs::current_path(CurrentDirectory);
// Get the prefix if we have one.
if (HeaderPrefix.size() != 0)
HeaderDirectory = HeaderPrefix;
// Read the header list file into a buffer.
ErrorOr<std::unique_ptr<MemoryBuffer>> listBuffer =
MemoryBuffer::getFile(InputPath);
if (std::error_code EC = listBuffer.getError())
return EC;
// Parse the header list into strings.
SmallVector<StringRef, 32> Strings;
listBuffer.get()->getBuffer().split(Strings, "\n", -1, false);
// Collect the header file names from the string list.
for (SmallVectorImpl<StringRef>::iterator I = Strings.begin(),
E = Strings.end();
I != E; ++I) {
StringRef Line = I->trim();
// Ignore comments and empty lines.
if (Line.empty() || (Line[0] == '#'))
continue;
std::pair<StringRef, StringRef> TargetAndDependents = Line.split(':');
SmallString<256> HeaderFileName;
// Prepend header file name prefix if it's not absolute.
if (llvm::sys::path::is_absolute(TargetAndDependents.first))
llvm::sys::path::native(TargetAndDependents.first, HeaderFileName);
else {
if (HeaderDirectory.size() != 0)
HeaderFileName = HeaderDirectory;
else
HeaderFileName = CurrentDirectory;
llvm::sys::path::append(HeaderFileName, TargetAndDependents.first);
llvm::sys::path::native(HeaderFileName);
}
// Handle optional dependencies.
DependentsVector Dependents;
SmallVector<StringRef, 4> DependentsList;
TargetAndDependents.second.split(DependentsList, " ", -1, false);
int Count = DependentsList.size();
for (int Index = 0; Index < Count; ++Index) {
SmallString<256> Dependent;
if (llvm::sys::path::is_absolute(DependentsList[Index]))
Dependent = DependentsList[Index];
else {
if (HeaderDirectory.size() != 0)
Dependent = HeaderDirectory;
else
Dependent = CurrentDirectory;
llvm::sys::path::append(Dependent, DependentsList[Index]);
}
llvm::sys::path::native(Dependent);
Dependents.push_back(Dependent.str());
}
// Save the resulting header file path and dependencies.
HeaderFileNames.push_back(HeaderFileName.str());
Dependencies[HeaderFileName.str()] = Dependents;
}
return std::error_code();
}

View File

@ -0,0 +1,74 @@
//=====-- ModularizeUtilities.h - Utilities for modularize -*- C++ -*-======//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===--------------------------------------------------------------------===//
///
/// \file
/// \brief ModularizeUtilities class definition.
///
//===--------------------------------------------------------------------===//
#ifndef MODULARIZEUTILITIES_H
#define MODULARIZEUTILITIES_H
#include "Modularize.h"
#include <string>
#include <vector>
namespace Modularize {
/// Modularize utilities class.
/// Support functions and data for modularize.
class ModularizeUtilities {
public:
// Input arguments.
/// The input file paths.
std::vector<std::string> InputFilePaths;
/// The header prefix.
llvm::StringRef HeaderPrefix;
// Output data.
// List of top-level header files.
llvm::SmallVector<std::string, 32> HeaderFileNames;
// Map of top-level header file dependencies.
DependencyMap Dependencies;
// Functions.
/// Constructor.
/// You can use the static createModularizeUtilities to create an instance
/// of this object.
/// \param InputPaths The input file paths.
/// \param Prefix The headear path prefix.
ModularizeUtilities(std::vector<std::string> &InputPaths,
llvm::StringRef Prefix);
/// Create instance of ModularizeUtilities.
/// \param InputPaths The input file paths.
/// \param Prefix The headear path prefix.
/// \returns Initialized ModularizeUtilities object.
static ModularizeUtilities *createModularizeUtilities(
std::vector<std::string> &InputPaths,
llvm::StringRef Prefix);
/// Load header list and dependencies.
/// \returns std::error_code.
std::error_code loadAllHeaderListsAndDependencies();
protected:
/// Load single header list and dependencies.
/// \param InputPath The input file path.
/// \returns std::error_code.
std::error_code loadSingleHeaderListsAndDependencies(
llvm::StringRef InputPath);
};
} // end namespace Modularize
#endif // MODULARIZEUTILITIES_H