目标
类似《为代码中的类继承关系生成Mermaid图》
我想为代码文件的include关系生成Mermaid图。
为了排除不感兴趣的其他文件,我将从一个“根文件”出发,找出其include的文件,再递归依次找出他们的include文件。
概括思路
- 递归的方式找到一个文件夹下的所有代码文件,记为
files
。 - 遍历
files
,读取每一行line
。 - 对于
line
做下面处理:(1)先看是否包含 #include ,如果不包含则跳过。(2)然后截取两个引号之间的字符串作为文件路径,处理后变为文件名。这样便能最终得到所有include关系数据
。 - 最后,根据
include关系数据
,从一个“根文件”出发,找出其include的文件,再递归依次找出他们的include文件。然后用Mermaid的格式打印出这些关系。
具体代码
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <io.h>
#include <map>
using namespace std;
//递归地方式找到所有的文件
void GetFilesInFolder_recursion(string folder, vector<string>& files)
{
_finddata_t fileInfo; //储存得到的文件信息
//找第一个
auto findResult = _findfirst((folder + "\\*").c_str(), &fileInfo);
if (findResult == -1)
{
_findclose(findResult);
return;
}
//找之后的
do
{
string fileName = fileInfo.name;
if ((fileInfo.attrib == _A_NORMAL) || (fileInfo.attrib == _A_ARCH)) //是文件
{
files.push_back(folder + "/" + fileName);
}
else if (fileInfo.attrib == _A_SUBDIR)//是文件夹
{
if (fileName == ".") //跳过得到的这个路径
continue;
if (fileName == "..") //跳过得到的这个路径
continue;
GetFilesInFolder_recursion(folder + "/" + fileName, files);
}
} while (_findnext(findResult, &fileInfo) == 0);
_findclose(findResult);
}
//将路径转换为文件名
string GetFileNameFromPath(string filePath)
{
//最后一个斜杠的位置:
const int LastSlashIndex = filePath.find_last_of('/');
if (LastSlashIndex == -1)//没找到
return filePath;
else
return filePath.substr(LastSlashIndex + 1, filePath.size() - LastSlashIndex);
}
//递归的方式收集所有文件
void ColectIncludeFile_recursion(map<string, vector<string>>& InlcudeRelationships, const string fileName, set<string >& Collection)
{
Collection.insert(fileName);
for (string includeFile : InlcudeRelationships[fileName])
ColectIncludeFile_recursion(InlcudeRelationships, includeFile, Collection);
}
int main()
{
//搜寻的文件夹:
const string Folder = "D:/0_WorkSpace/UnrealEngine-release/Engine/Shaders/Private";
//查询的文件:
const string RootFileName = "MaterialTemplate.ush";
//包含关系:
map<string, vector<string>> InlcudeRelationships;
//找到所有文件:
vector<string> files;
GetFilesInFolder_recursion(Folder, files);
//收集所有的信息
for (auto filePath : files)
{
//cout << "读取文件" << filePath << endl;
//读取文件
fstream fileStream(filePath);
//文件名
const string fileName = GetFileNameFromPath(filePath);
//一行的内容字符串
char line[1024] = { 0 };
//读取每一行
while (fileStream.getline(line, 1024))
{
//转换为std::string类型
string content = line;
if (content.find("#include")!=-1)//如果存在include字样
{
//cout << content << endl;
//第一个引号的位置:
const int FirstIndex = content.find_first_of('"');
//第二个引号的位置:
const int SecondIndex = content.find_last_of('"');
//文件路径就是两个引号之间的内容
const string includePath = content.substr(FirstIndex + 1, SecondIndex - FirstIndex - 1);
//cout << includePath << endl;
//文件名字
const string IncludeFile = GetFileNameFromPath(includePath);
//cout << IncludeFile << endl;
//添加进一个关系:
InlcudeRelationships[fileName].push_back(IncludeFile);
}
}
}
//递归收集出所有Include关系
set<string > Collection;
ColectIncludeFile_recursion(InlcudeRelationships, RootFileName, Collection);
//打印出所有的关系
for (string f : Collection)
for (string include : InlcudeRelationships[f])
cout << f << "-->" << include << endl;
}
使用时:
- 将
main()
中的Folder
变量设置为所有相关代码所在的文件夹。 - 将
main()
中的RootFileName
变量设置为想要查询的“根”文件。
试用
尝试打印出UE4的shader文件中,MaterialTemplate.ush
所include的文件关系:
Common.ush-->Platform.ush
Common.ush-->GeneratedUniformBuffers.ush
Common.ush-->CommonViewUniformBuffer.ush
Common.ush-->InstancedStereo.ush
Common.ush-->Definitions.usf
Common.ush-->FastMath.ush
Common.ush-->Random.ush
DeferredShadingCommon.ush-->ShadingCommon.ush
DeferredShadingCommon.ush-->LightAccumulator.ush
DeferredShadingCommon.ush-->SceneTexturesCommon.ush
InstancedStereo.ush-->View.ush
InstancedStereo.ush-->InstancedView.ush
InstancedStereo.ush-->GeneratedInstancedStereo.ush
MaterialTemplate.ush-->SceneTexturesCommon.ush
MaterialTemplate.ush-->Random.ush
MaterialTemplate.ush-->SobolRandom.ush
MaterialTemplate.ush-->MonteCarlo.ush
MaterialTemplate.ush-->Material.ush
MaterialTemplate.ush-->DepthOfFieldCommon.ush
MaterialTemplate.ush-->CircleDOFCommon.ush
MaterialTemplate.ush-->GlobalDistanceFieldShared.ush
MaterialTemplate.ush-->SceneData.ush
MaterialTemplate.ush-->SpeedTreeCommon.ush
MaterialTemplate.ush-->VirtualTextureCommon.ush
MaterialTemplate.ush-->MinMaterialTexCoords.ush
MaterialTemplate.ush-->AtmosphereCommon.ush
MaterialTemplate.ush-->SkyAtmosphereCommon.ush
MaterialTemplate.ush-->PaniniProjection.ush
MaterialTemplate.ush-->DeferredShadingCommon.ush
MonteCarlo.ush-->Common.ush
SceneTexturesCommon.ush-->Common.ush
SpeedTreeCommon.ush-->SpeedTreeData.ush
VirtualTextureCommon.ush-->Common.ush
VirtualTextureCommon.ush-->Random.ush
生成Mermaid图: