mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-03-25 01:13:57 +08:00
212 lines
6.3 KiB
C++
212 lines
6.3 KiB
C++
#include "Codepack.h"
|
|
|
|
FilePath GetCommonFolder(
|
|
const List<FilePath>& paths
|
|
)
|
|
{
|
|
auto folder = paths[0].GetFolder();
|
|
while (true)
|
|
{
|
|
if (From(paths).All([&](const FilePath& path)
|
|
{
|
|
return INVLOC.StartsWith(path.GetFullPath(), folder.GetFullPath() + WString::FromChar(folder.Delimiter), Locale::IgnoreCase);
|
|
}))
|
|
{
|
|
return folder;
|
|
}
|
|
folder = folder.GetFolder();
|
|
}
|
|
CHECK_FAIL(L"Cannot process files across multiple drives.");
|
|
}
|
|
|
|
void CollectConditions(
|
|
Group<WString, WString>& categorizedConditions,
|
|
Group<FilePath, Tuple<WString, FilePath>>& conditions,
|
|
const FilePath& file,
|
|
const Dictionary<FilePath, WString>& inputFileToOutputFiles
|
|
)
|
|
{
|
|
vint index = conditions.Keys().IndexOf(file);
|
|
if (index != -1)
|
|
{
|
|
for (auto [condition, path] : conditions.GetByIndex(index))
|
|
{
|
|
auto includeFile = inputFileToOutputFiles[path];
|
|
if (!categorizedConditions.Contains(condition, includeFile))
|
|
{
|
|
categorizedConditions.Add(condition, includeFile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CombineWriteHeader(
|
|
List<WString>& lines,
|
|
const Dictionary<FilePath, WString>& inputFileToOutputFiles,
|
|
Group<FilePath, Tuple<WString, FilePath>>& conditionOns,
|
|
Group<FilePath, Tuple<WString, FilePath>>& conditionOffs,
|
|
const List<FilePath>& files,
|
|
LazyList<WString> externalIncludes
|
|
)
|
|
{
|
|
lines.Add(L"/***********************************************************************");
|
|
lines.Add(L"THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY");
|
|
lines.Add(L"DEVELOPER: Zihan Chen(vczh)");
|
|
lines.Add(L"***********************************************************************/");
|
|
for (auto path : externalIncludes)
|
|
{
|
|
lines.Add(L"#include \"" + path + L"\"");
|
|
}
|
|
{
|
|
Group<WString, WString> categorizedConditionOns, categorizedConditionOffs;
|
|
for (auto file : files)
|
|
{
|
|
CollectConditions(categorizedConditionOns, conditionOns, file, inputFileToOutputFiles);
|
|
CollectConditions(categorizedConditionOffs, conditionOffs, file, inputFileToOutputFiles);
|
|
}
|
|
|
|
for (vint i = 0; i < categorizedConditionOns.Count(); i++)
|
|
{
|
|
lines.Add(L"#ifdef " + categorizedConditionOns.Keys()[i]);
|
|
const auto& onFiles = categorizedConditionOns.GetByIndex(i);
|
|
for (auto onFile : onFiles)
|
|
{
|
|
lines.Add(L"#include \"" + inputFileToOutputFiles[onFile] + L"\"");
|
|
}
|
|
lines.Add(L"#endif");
|
|
}
|
|
|
|
for (vint i = 0; i < categorizedConditionOffs.Count(); i++)
|
|
{
|
|
lines.Add(L"#ifndef " + categorizedConditionOffs.Keys()[i]);
|
|
const auto& offFiles = categorizedConditionOffs.GetByIndex(i);
|
|
for (auto offFile : offFiles)
|
|
{
|
|
lines.Add(L"#include \"" + offFile + L".h\"");
|
|
}
|
|
lines.Add(L"#endif");
|
|
}
|
|
}
|
|
}
|
|
|
|
void Combine(
|
|
const Dictionary<FilePath, WString>& inputFileToOutputFiles, // (in)
|
|
const Dictionary<WString, FilePath>& skippedImportFiles, // (in)
|
|
Dictionary<FilePath, LazyList<FilePath>>& cachedFileToIncludes, // (cache)
|
|
Group<FilePath, Tuple<WString, FilePath>>& conditionOns, // (out)
|
|
Group<FilePath, Tuple<WString, FilePath>>& conditionOffs, // (out)
|
|
const List<FilePath>& files, // (in)
|
|
FilePath outputFilePath, //
|
|
FilePath outputIncludeFilePath, //
|
|
SortedList<WString>& systemIncludes, //
|
|
LazyList<WString> externalIncludes //
|
|
)
|
|
{
|
|
auto workingDir = outputFilePath.GetFolder();
|
|
|
|
List<FilePath> sortedFiles;
|
|
{
|
|
PartialOrderingProcessor popFiles;
|
|
Group<FilePath, FilePath> depGroup;
|
|
for (auto file : files)
|
|
{
|
|
for (auto dep : GetIncludedFiles(file, skippedImportFiles, cachedFileToIncludes, conditionOns, conditionOffs))
|
|
{
|
|
if (files.Contains(dep))
|
|
{
|
|
depGroup.Add(file, dep);
|
|
}
|
|
}
|
|
}
|
|
|
|
popFiles.InitWithGroup(files, depGroup);
|
|
popFiles.Sort();
|
|
|
|
bool needExit = false;
|
|
for (vint i = 0; i < popFiles.components.Count(); i++)
|
|
{
|
|
auto& component = popFiles.components[i];
|
|
sortedFiles.Add(files[component.firstNode[0]]);
|
|
|
|
if (component.nodeCount > 1)
|
|
{
|
|
Console::SetColor(true, false, false, true);
|
|
Console::WriteLine(
|
|
L"Error: Cycle dependency found in categories: "
|
|
+ From(component.firstNode, component.firstNode + component.nodeCount)
|
|
.Select([&](vint nodeIndex) { return L"\r\n" + files[nodeIndex].GetFullPath(); })
|
|
.Aggregate([](const WString& a, const WString& b) {return a + b; })
|
|
+ L"\r\n.");
|
|
Console::SetColor(true, true, true, false);
|
|
needExit = true;
|
|
}
|
|
}
|
|
CHECK_ERROR(!needExit, L"Cycle dependency is not allowed");
|
|
}
|
|
{
|
|
List<WString> lines;
|
|
CombineWriteHeader(lines, inputFileToOutputFiles, conditionOns, conditionOffs, files, externalIncludes);
|
|
{
|
|
auto prefix = GetCommonFolder(files);
|
|
for (auto file : From(sortedFiles).Intersect(files))
|
|
{
|
|
lines.Add(L"");
|
|
lines.Add(L"/***********************************************************************");
|
|
lines.Add(wupper(prefix.GetRelativePathFor(file)));
|
|
lines.Add(L"***********************************************************************/");
|
|
|
|
StringReader reader(ReadFile(file));
|
|
bool skip = false;
|
|
while (!reader.IsEnd())
|
|
{
|
|
auto line = reader.ReadLine();
|
|
Ptr<RegexMatch> match;
|
|
if ((match = regexInstruction.MatchHead(line)))
|
|
{
|
|
auto name = match->Groups()[instruction_name][0].Value();
|
|
if (name == L"BeginIgnore")
|
|
{
|
|
skip = true;
|
|
}
|
|
else if (name == L"EndIgnore")
|
|
{
|
|
skip = false;
|
|
}
|
|
}
|
|
else if (!skip)
|
|
{
|
|
if ((match = regexSystemInclude.MatchHead(line)))
|
|
{
|
|
auto systemFile = match->Groups()[systemInclude_path][0].Value();
|
|
if (skippedImportFiles.Keys().Contains(systemFile)) continue;
|
|
if (systemIncludes.Contains(systemFile)) continue;
|
|
systemIncludes.Add(systemFile);
|
|
lines.Add(line);
|
|
}
|
|
else if (!regexInclude.MatchHead(line))
|
|
{
|
|
lines.Add(line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
File(outputFilePath).WriteAllLines(lines, true, BomEncoder::Utf8);
|
|
}
|
|
{
|
|
List<WString> lines;
|
|
CombineWriteHeader(lines, inputFileToOutputFiles, conditionOns, conditionOffs, files, externalIncludes);
|
|
lines.Add(L"");
|
|
{
|
|
auto prefix = outputIncludeFilePath.GetFolder();
|
|
for (auto file : From(sortedFiles).Intersect(files))
|
|
{
|
|
lines.Add(L"#include \"" + prefix.GetRelativePathFor(file) + L"\"");
|
|
}
|
|
}
|
|
File(outputIncludeFilePath).WriteAllLines(lines, true, BomEncoder::Utf8);
|
|
}
|
|
Console::SetColor(false, true, false, true);
|
|
Console::WriteLine(L"Succeeded to write: " + outputFilePath.GetFullPath());
|
|
Console::SetColor(true, true, true, false);
|
|
} |