深入研究Clang(十八) Clang Driver库的job

Posted snsn1984

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入研究Clang(十八) Clang Driver库的job相关的知识,希望对你有一定的参考价值。

Clang的Tool最终会调用ConstructJob来为Compilation添加job。根据源码中的注释,Tool中保存的是一个特定编译工具的信息(Tool - Information on a specific compilation tool.,clang/include/clang/Driver/Tool.h)。而job则是通过Command类去进行具体实现,同时还有一个相关类JobList。本文将分析Command和JobList的实现,以及其相关的调用关系。

一、Command和JobList的实现

1、Command和JobList的定义和实现都位于clang/include/clang/Driver/Job.h和clang/lib/Driver/Job.cpp。

2、Command类其实是job概念的对应实现。它表示的是一个将要执行的可执行路径/名字和参数。源码中的注释为: Command - An executable path/name and argument vector to execute.(clang/include/clang/Driver/Job.h)

3、Command类中包含了其所对应的Tool、Action以及可执行文件。从其源码中可以明确看出(clang/include/clang/Driver/Job.h):

/// Command - An executable path/name and argument vector to
/// execute.
class Command 
  /// Source - The action which caused the creation of this job.
  const Action &Source;

  /// Tool - The tool which caused the creation of this job.
  const Tool &Creator;

  /// The executable to run.
  const char *Executable;

  /// The list of program arguments (not including the implicit first
  /// argument, which will be the executable).
  llvm::opt::ArgStringList Arguments;

  /// The list of program arguments which are inputs.
  llvm::opt::ArgStringList InputFilenames;

Command有其对应的Tool和Action。成员变量Creator,就是导致这个job(Command)被创建的Tool。成员变量Source,是导致这个job(Command)被创建的Action,有关Action的内容,在后续的部分进行介绍。成员变量Executable是要运行的可执行文件。

同时,Command还有一个重要的成员函数Execute,它的子类都会重载该函数,该函数为:

  virtual int Execute(ArrayRef<Optional<StringRef>> Redirects,
                      std::string *ErrMsg, bool *ExecutionFailed) const;

4、Command类有两个子类:CC1Command、FallbackCommand和ForceSuccessCommand。CC1Command是在可能的情况下使用CC1 tool进行回调,而避免新建一个进程。FallbackCommand比Command多提供一个回退,是为了万一出现最初的Command崩溃的时候使用。ForceSuccessCommand总是假装wrapped command succeeded。具体代码为(clang/include/clang/Driver/Job.h):

/// Use the CC1 tool callback when available, to avoid creating a new process
class CC1Command : public Command 

/// Like Command, but with a fallback which is executed in case
/// the primary command crashes.
class FallbackCommand : public Command 

/// Like Command, but always pretends that the wrapped command succeeded.
class ForceSuccessCommand : public Command 

5、JobList类是用来表示一系列的job,也就是用来表示Command列表。其具体实现如下:

(clang/include/clang/Driver/Job.h)

/// JobList - A sequence of jobs to perform.
class JobList 
public:
  using list_type = SmallVector<std::unique_ptr<Command>, 4>;
  using size_type = list_type::size_type;
  using iterator = llvm::pointee_iterator<list_type::iterator>;
  using const_iterator = llvm::pointee_iterator<list_type::const_iterator>;

private:
  list_type Jobs;

public:
  void Print(llvm::raw_ostream &OS, const char *Terminator,
             bool Quote, CrashReportInfo *CrashInfo = nullptr) const;

  /// Add a job to the list (taking ownership).
  void addJob(std::unique_ptr<Command> J)  Jobs.push_back(std::move(J)); 

JobList的实现,主要就是维护了Jobs这个列表,并且提供了对该列表的相关操作,包括添加、清空、迭代器等。

二、Command和JobList的调用关系

1、Clang的Tool最终会调用ConstructJob来为Compilation添加job(Command)。以RISCV::Linker::ConstructJob(clang/lib/Driver/ToolChains/RISCVToolchain.cpp)为例,其最终调用了Compilation的addCommand来为Compilation添加job(Command),具体源码如下(clang/lib/Driver/ToolChains/RISCVToolchain.cpp):

  C.addCommand(std::make_unique<Command>(JA, *this, Args.MakeArgString(Linker),
                                          CmdArgs, Inputs));

这里其实是构建除了一个Command对象,并且通过addCommand来为Compilation添加job(Command)。

Compilation的addCommand实现如下(clang/include/clang/Driver/Compilation.h):

  void addCommand(std::unique_ptr<Command> C)  Jobs.addJob(std::move(C)); 

其中Jobs的定义为(clang/include/clang/Driver/Compilation.h):

  /// The root list of jobs.
  JobList Jobs;

至此,Tool对于Command以及JobList的调用及其关系就已经就很清晰了。

发布于 2020-05-14

以上是关于深入研究Clang(十八) Clang Driver库的job的主要内容,如果未能解决你的问题,请参考以下文章

深入研究Clang(十六) Clang Driver库的ToolChain

深入研究Clang(十六) Clang Driver库的ToolChain

深入研究Clang(十四) clang-tidy的使用

深入研究Clang(十七) Clang Driver库的Tool

深入研究Clang(十七) Clang Driver库的Tool

深入研究Clang(十九) Clang的RISCV支持2