Skip to content

添加最小化生成支持 #5

@mingkuang-Chuyu

Description

@mingkuang-Chuyu

目前我们需要支持三部分:

  • 最小化Compile任务生成(最小化编译)
  • 最小化Ld任务生成(最小化链接)
  • 最小化Ar任务生成(最小化Lib打包)

支持最小化生成这个显然是非常有价值的,否则每次重新生成这将导致极大重复时间开销。

1. 背景调查

1.1. 微软CL的最小化编译原理

初步的想法是移植微软的最小化生成机制,以CL为例,完成最小化生成需要这三个文件:

  • CL.command.1.tlog
  • CL.read.1.tlog
  • CL.write.1.tlog

CL.command.1.tlog示例,看样子是记录了处理此文件时的命令行参数。

^D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1.CPP
/c /Zi /nologo /W3 /WX- /diagnostics:column /sdl /O2 /Oi /Oy- /GL /D WIN32 /D NDEBUG /D _CONSOLE /D _UNICODE /D UNICODE /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /std:c++17 /permissive- /Fo"RELEASE\\" /Fd"RELEASE\VC143.PDB" /external:W3 /Gd /TP /analyze- /FC D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1.CPP

CL.read.1.tlog示例,看起来是记录了处理此文件时,额外读取的文件,也可以理解为依赖项。

^D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1.CPP
C:\PROGRAM FILES (X86)\WINDOWS KITS\10\INCLUDE\10.0.22000.0\UM\SHLOBJ.H
C:\PROGRAM FILES (X86)\WINDOWS KITS\10\INCLUDE\10.0.22000.0\SHARED\WINAPIFAMILY.H
C:\PROGRAM FILES (X86)\WINDOWS KITS\10\INCLUDE\10.0.22000.0\SHARED\WINPACKAGEFAMILY.H

CL.write.1.tlog,处理这个文件时,生成了哪些产物。

^D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1.CPP
D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\RELEASE\VC143.PDB
D:\SOURCESCODE\YY\CONSOLEAPPLICATION1\CONSOLEAPPLICATION1\RELEASE\CONSOLEAPPLICATION1.OBJ

除了command文件在TrackedVCToolTask中直接生成,read与write二个文件由SDK目录下的Tracker.exe辅助生成。但是很显然Linux中没有Tracker.exe所以目前的想法是在任务中自行生成read与write二个文件

此外微软的文件中路径似乎故意转换为了大小,Windows中默认文件名大小写不敏感,但是Linux中默认是敏感的。路径上我们不能跟Windows一样,强行转换为大写。

2. 实现构想

2.1. command文件生成

由于command文件由TrackedVCToolTask任务直接生成,这个文件也只是记录了启动的命令行参数而已,这是通用逻辑,所以我们把当场微软的TrackedVCToolTask移植过来即可。当然我们需要去掉转路径默认转大写的工作。

2.2. write文件生成

Windows下write由Tracker.exe生成,在Linux中很显然不行,不过考虑到write文件只是记录了任务生成了什么文件,这往往是明确的。我们自己在完成命令行调用后,将我们关注的产物信息写入write文件。

2.3. read文件生成

Windows下write由Tracker.exe生成,在Linux显然没有这个程序。这个任务是最复杂的,比如Compile任务,编译时仅关注源代码文件本身是远远不够的,还需要关心额外include的文件是否发生变化。

2.3.1. 最小化Compile任务read生成

研究了gcc以后发现GCC支持-MD -MF OutMapFilePath参数,这可以在编译时同时生成MapFile。
生成的MapFile结构如下:

/home/john/Desktop/ConsoleApplication2/obj/x86/Debug/main.o: main.cpp \
 /usr/include/stdc-predef.h /usr/include/c++/11/cstdio \
 /usr/include/x86_64-linux-gnu/c++/11/bits/c++config\ .h \

MapFile文件详细的输出了main.cpp额外include的文件,对于这个文件的格式。稍微做个总结,每个条目以' '(空格)分割。'\'是发挥了转义符或者连接符的作用。

所以我们在Compile中,调用gcc完成编译后,使用这个MapFile转换出read文件就可以了。

2.3.2. 最小化Ld任务read生成

暂时没有良好的选项。虽然-Map可以输出类似的信息,但是信息过于繁杂。是否拥有更好的选项,还需要研究。

目前发现,-Wl,--trace可以完整的输出依赖信息:

其结果大致如下:

/lib/x86_64-linux-gnu/Scrt1.o
/lib/x86_64-linux-gnu/crti.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/crtbeginS.o
/home/john/Desktop/ConsoleApplication2/obj/x86/Release/main.o
/home/john/Desktop/ConsoleApplication2/obj/x86/Release/Test2.o
/usr/bin/../lib/gcc/x86_64-linux-gnu/11/libstdc++.so

从输出结果看,它可以正确的识别lib的引用指针,而不仅仅来自命令行参数。从需求上符合预期。但是它似乎不能输出到文件,目前从管道中读取这些信息。并记录为Read文件。

2.3.3. 最小化Ar任务read生成

暂时未找到类似于 g++ -MF -MF的选项,不过打包时需要需要向 Ar传递要打包的所有Obj,Lib,所以我们可以直接使用此信息。手工生成read文件。

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions