clang: lib/Frontend/DependencyFile.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/ADT/StringSet.h"

24#include "llvm/Support/FileSystem.h"

25#include "llvm/Support/Path.h"

26#include "llvm/Support/raw_ostream.h"

27#include

28

29using namespace clang;

30

31namespace {

32struct DepCollectorPPCallbacks : public PPCallbacks {

33 DependencyCollector &DepCollector;

34 Preprocessor &PP;

35 DepCollectorPPCallbacks(DependencyCollector &L, Preprocessor &PP)

36 : DepCollector(L), PP(PP) {}

37

38 void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,

40 SourceLocation Loc) override {

41 if (Reason != PPCallbacks::LexedFileChangeReason::EnterFile)

42 return;

43

44

45

46

47 if (std::optional Filename =

48 PP.getSourceManager().getNonBuiltinFilenameForID(FID))

49 DepCollector.maybeAddDependency(

50 llvm::sys::path::remove_leading_dotslash(*Filename),

51 false, isSystem(FileType), false,

52 false);

53 }

54

55 void FileSkipped(const FileEntryRef &SkippedFile, const Token &FilenameTok,

57 StringRef Filename =

58 llvm::sys::path::remove_leading_dotslash(SkippedFile.getName());

59 DepCollector.maybeAddDependency(Filename, false,

61 false,

62 false);

63 }

64

65 void EmbedDirective(SourceLocation, StringRef, bool,

67 const LexEmbedParametersResult &) override {

68 assert(File && "expected to only be called when the file is found");

70 llvm::sys::path::remove_leading_dotslash(File->getName());

71 DepCollector.maybeAddDependency(FileName,

72 false,

73 false,

74 false,

75 false);

76 }

77

78 bool EmbedFileNotFound(StringRef FileName) override {

79 DepCollector.maybeAddDependency(

80 llvm::sys::path::remove_leading_dotslash(FileName),

81 false,

82 false,

83 false,

84 true);

85

86 return true;

87 }

88

89 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,

90 StringRef FileName, bool IsAngled,

91 CharSourceRange FilenameRange,

93 StringRef RelativePath, const Module *SuggestedModule,

94 bool ModuleImported,

97 DepCollector.maybeAddDependency(FileName, false,

98 false,

99 false,

100 true);

101

102 }

103

104 void HasEmbed(SourceLocation, StringRef, bool,

107 return;

108 StringRef Filename =

109 llvm::sys::path::remove_leading_dotslash(File->getName());

110 DepCollector.maybeAddDependency(Filename,

111 false, false,

112 false,

113 false);

114 }

115

116 void HasInclude(SourceLocation Loc, StringRef SpelledFilename, bool IsAngled,

120 return;

121 StringRef Filename =

122 llvm::sys::path::remove_leading_dotslash(File->getName());

123 DepCollector.maybeAddDependency(Filename, false,

125 false,

126 false);

127 }

128

129 void EndOfMainFile() override {

130 DepCollector.finishedMainFile(PP.getDiagnostics());

131 }

132};

133

135 DependencyCollector &DepCollector;

136 DepCollectorMMCallbacks(DependencyCollector &DC) : DepCollector(DC) {}

137

138 void moduleMapFileRead(SourceLocation Loc, FileEntryRef Entry,

139 bool IsSystem) override {

140 StringRef Filename = Entry.getName();

141 DepCollector.maybeAddDependency(Filename, false,

142 IsSystem,

143 false,

144 false);

145 }

146};

147

149 DependencyCollector &DepCollector;

150 FileManager &FileMgr;

151 DepCollectorASTListener(DependencyCollector &L, FileManager &FileMgr)

152 : DepCollector(L), FileMgr(FileMgr) {}

153 bool needsInputFileVisitation() override { return true; }

154 bool needsSystemInputFileVisitation() override {

155 return DepCollector.needSystemDependencies();

156 }

157 void visitModuleFile(StringRef Filename,

159 DepCollector.maybeAddDependency(Filename, true,

160 false, true,

161 false);

162 }

163 bool visitInputFile(StringRef Filename, bool IsSystem,

164 bool IsOverridden, bool IsExplicitModule) override {

165 if (IsOverridden || IsExplicitModule)

166 return true;

167

168

169

170 if (auto FE = FileMgr.getOptionalFileRef(Filename))

171 Filename = FE->getName();

172

173 DepCollector.maybeAddDependency(Filename, true, IsSystem,

174 false,

175 false);

176 return true;

177 }

178};

179}

180

182 bool FromModule, bool IsSystem,

183 bool IsModuleFile,

184 bool IsMissing) {

185 if (sawDependency(Filename, FromModule, IsSystem, IsModuleFile, IsMissing))

187}

188

190 StringRef SearchPath;

191#ifdef _WIN32

192

194 llvm::sys::path::native(TmpPath);

195 std::transform(TmpPath.begin(), TmpPath.end(), TmpPath.begin(), ::tolower);

196 SearchPath = TmpPath.str();

197#else

198 SearchPath = Filename;

199#endif

200

201 if (Seen.insert(SearchPath).second) {

202 Dependencies.push_back(std::string(Filename));

203 return true;

204 }

205 return false;

206}

207

209 return Filename == "";

210}

211

213 bool IsSystem, bool IsModuleFile,

214 bool IsMissing) {

217}

218

221 PP.addPPCallbacks(std::make_unique(*this, PP));

223 std::make_unique(*this));

224}

227 std::make_unique(*this, R.getFileManager()));

228}

229

232 : OutputFile(Opts.OutputFile), Targets(Opts.Targets),

233 IncludeSystemHeaders(Opts.IncludeSystemHeaders),

234 PhonyTarget(Opts.UsePhonyTargets),

235 AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), SeenMissingHeader(false),

236 IncludeModuleFiles(Opts.IncludeModuleFiles),

237 OutputFormat(Opts.OutputFormat), InputFileIndex(0) {

238 for (const auto &ExtraDep : Opts.ExtraDeps) {

239 if (addDependency(ExtraDep.first))

240 ++InputFileIndex;

241 }

242}

243

245

246 if (AddMissingHeaderDeps)

248

250}

251

253 bool IsSystem, bool IsModuleFile,

254 bool IsMissing) {

255 if (IsMissing) {

256

257 if (AddMissingHeaderDeps)

258 return true;

259 SeenMissingHeader = true;

260 return false;

261 }

262 if (IsModuleFile && !IncludeModuleFiles)

263 return false;

264

266 return false;

267

268 if (IncludeSystemHeaders)

269 return true;

270

271 return !IsSystem;

272}

273

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326static void PrintFilename(raw_ostream &OS, StringRef Filename,

328

330 llvm::sys::path::native(Filename.str(), NativePath);

331

333

334

335

336 if (NativePath.find_first_of(" #${}^!") != StringRef::npos)

337 OS << '\"' << NativePath << '\"';

338 else

339 OS << NativePath;

340 return;

341 }

343 for (unsigned i = 0, e = NativePath.size(); i != e; ++i) {

344 if (NativePath[i] == '#')

345 OS << '\\';

346 else if (NativePath[i] == ' ') {

347 OS << '\\';

348 unsigned j = i;

349 while (j > 0 && NativePath[--j] == '\\')

350 OS << '\\';

351 } else if (NativePath[i] == '$')

352 OS << '$';

353 OS << NativePath[i];

354 }

355}

356

358 if (SeenMissingHeader) {

359 llvm::sys::fs::remove(OutputFile);

360 return;

361 }

362

363 std::error_code EC;

364 llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::OF_TextWithCRLF);

365 if (EC) {

366 Diags.Report(diag::err_fe_error_opening) << OutputFile << EC.message();

367 return;

368 }

369

371}

372

374

375

376

377

378 const unsigned MaxColumns = 75;

379 unsigned Columns = 0;

380

381 for (StringRef Target : Targets) {

382 unsigned N = Target.size();

383 if (Columns == 0) {

384 Columns += N;

385 } else if (Columns + N + 2 > MaxColumns) {

386 Columns = N + 2;

387 OS << " \\\n ";

388 } else {

389 Columns += N + 1;

390 OS << ' ';

391 }

392

394 }

395

396 OS << ':';

397 Columns += 1;

398

399

400

402 for (StringRef File : Files) {

403 if (File == "")

404 continue;

405

406

407

408 unsigned N = File.size();

409 if (Columns + (N + 1) + 2 > MaxColumns) {

410 OS << " \\\n ";

411 Columns = 2;

412 }

413 OS << ' ';

415 Columns += N + 1;

416 }

417 OS << '\n';

418

419

420 if (PhonyTarget && !Files.empty()) {

421 unsigned Index = 0;

422 for (auto I = Files.begin(), E = Files.end(); I != E; ++I) {

423 if (Index++ == InputFileIndex)

424 continue;

426 OS << ":\n";

427 }

428 }

429}

static void PrintFilename(raw_ostream &OS, StringRef Filename, DependencyOutputFormat OutputFormat)

Print the filename, with escaping or quoting that accommodates the three most likely tools that use d...

Definition DependencyFile.cpp:326

static bool isSpecialFilename(StringRef Filename)

Definition DependencyFile.cpp:208

Defines the clang::FileManager interface and associated types.

llvm::MachO::FileType FileType

Defines the PPCallbacks interface.

Defines the clang::Preprocessor interface.

Defines the SourceManager interface.

Abstract interface for callback invocations by the ASTReader.

Reads an AST files chain containing the contents of a translation unit.

void addListener(std::unique_ptr< ASTReaderListener > L)

Add an AST callback listener.

FileManager & getFileManager() const

virtual void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)

Add a dependency Filename if it has not been seen before and sawDependency() returns true.

Definition DependencyFile.cpp:181

bool addDependency(StringRef Filename)

Return true if the filename was added to the list of dependencies, false otherwise.

Definition DependencyFile.cpp:189

virtual void attachToPreprocessor(Preprocessor &PP)

Definition DependencyFile.cpp:220

ArrayRef< std::string > getDependencies() const

virtual void attachToASTReader(ASTReader &R)

Definition DependencyFile.cpp:225

virtual ~DependencyCollector()

Definition DependencyFile.cpp:219

virtual bool needSystemDependencies()

Return true if system files should be passed to sawDependency().

virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing)

Called when a new file is seen.

Definition DependencyFile.cpp:212

void outputDependencyFile(llvm::raw_ostream &OS)

Definition DependencyFile.cpp:373

void attachToPreprocessor(Preprocessor &PP) override

Definition DependencyFile.cpp:244

void finishedMainFile(DiagnosticsEngine &Diags) override

Called when the end of the main file is reached.

Definition DependencyFile.cpp:274

bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) final

Called when a new file is seen.

Definition DependencyFile.cpp:252

DependencyFileGenerator(const DependencyOutputOptions &Opts)

Definition DependencyFile.cpp:230

DependencyOutputOptions - Options for controlling the compiler dependency file generation.

std::vector< std::pair< std::string, ExtraDepKind > > ExtraDeps

A list of extra dependencies (filename and kind) to be used for every target.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

StringRef getName() const

The name of this FileEntry.

A mechanism to observe the actions of the module map loader as it reads module map files.

void addModuleMapCallbacks(std::unique_ptr< ModuleMapCallbacks > Callback)

Add a module map callback.

This interface provides a way to observe the actions of the preprocessor as it does its thing.

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

void addPPCallbacks(std::unique_ptr< PPCallbacks > C)

HeaderSearch & getHeaderSearchInfo() const

void SetSuppressIncludeNotFoundError(bool Suppress)

CharacteristicKind

Indicates whether a file or directory holds normal user code, system code, or system code which is im...

bool isSystem(CharacteristicKind CK)

Determine whether a file / directory characteristic is for system code.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

ModuleKind

Specifies the kind of module that has been loaded.

The JSON file list parser is used to communicate input to InstallAPI.

CustomizableOptional< FileEntryRef > OptionalFileEntryRef

@ Module

Module linkage, which indicates that the entity can be referred to from other translation units withi...

DependencyOutputFormat

DependencyOutputFormat - Format for the compiler dependency file.