64,665
社区成员
发帖
与我相关
我的任务
分享
int _tmain(int argc, TCHAR* argv[])
{
// 处理运行参数
OptData od;
od.onlyMak = false;
GetOptToData(argc, argv, od);
if ((od.onlyMak && (od.baseDir.empty() || od.projType.empty())) || (!od.onlyMak && od.baseDir.empty()))
{
PrintHelpInfo();
return -2;
}
// 创建Makefile
if (od.onlyMak)
{
CreateMakefile(od.baseDir, od.projType);
return 0;
}
// 获得源文件与头文件对应的依赖文件,即基本依赖
DependBase depBase;
depBase.psr.SetBasePath(od.baseDir);
depBase.psr.SetIncludePath(od.incDir);
depBase.pch = qp::Path::Append(od.baseDir, od.pchSrc);
qp::Search s;
s.RegisterNotify(&SearchCorCppFiles);
s.Run(od.baseDir, &depBase);
// 递归得到源文件对应的所有依赖,即完整依赖
Depend dep(depBase.header, depBase.src);
dep.Parser();
// 输出到文件
qp::File file;
qp::String depFile(qp::Path::Append(od.baseDir, _T("Depends.mk")));
if (!file.Create(depFile, GENERIC_WRITE, FILE_SHARE_WRITE, CREATE_ALWAYS))
return -3;
#ifdef _UNICODE
WORD bom = 0xFEFF; // 添加Unicode BOM
file.Write(&bom, sizeof(WORD));
#endif
// 添加版权声明
qp::String toFile;
toFile.reserve(1000 * 1000);
toFile += _T("#----------------------------------------------\r\n")
_T("# Copyright (C) QPSOFT.COM All rights reserved.\r\n")
_T("#----------------------------------------------\r\n")
_T("\r\nOBJS = \\\r\n");
// 添加OBJ列表,将OBJ文件保存在Vector中,为后面写编译规则时提速
VecString obj;
for (auto it = depBase.src.begin(); it != depBase.src.end(); ++it)
{
const qp::String& src = (*it).first;
qp::String tmp(_T("\"$(OUT)"));
tmp += src.substr(1, src.rfind(_T('.')));
tmp += _T("obj\"");
toFile += _T("\t") + tmp + _T(" \\\r\n");
qp::String cc(_T("SRC=" + src + _T("\r\n")) + tmp + _T(" : $(SRC) \"$(OUT)\""));
if (!od.pchSrc.empty()) cc += _T(" \"$(PCH)\"");
cc += _T("\r\n");
const qp::String::size_type pos = src.rfind(_T('\\'));
if (pos > 2)
{
cc += _T("\t$(CC) $(CFLAGS) /Fo$(OUT)");
cc += src.substr(1, pos) + _T(" $(SRC)\r\n");
}
cc += _T("\r\n");
obj.push_back(cc);
}
// 添加编译规则
toFile += _T("\r\n");
for (auto it = obj.begin(); it != obj.end(); ++it)
{
toFile += *it;
}
// 添加依赖关系
for (auto it = depBase.src.begin(); it != depBase.src.end(); ++it)
{
toFile += (*it).first + _T(" : \\\r\n");
for (auto i = ((*it).second).begin(); i < ((*it).second).end(); ++i)
{
toFile += _T("\t\"") + *i + _T("\" \\\r\n");
}
toFile += _T("\r\n");
}
// 写入文件
file.Write(toFile.c_str(), toFile.size() * sizeof(TCHAR));
qp::Cmd::Printf(_T("NMaker: Created '%s' !\n"), depFile.c_str());
return 0;
}
Parser::Parser(const qp::String& basePath, const VecString& searchPath) :
m_basePath(basePath), m_incPath(searchPath)
{}
void Parser::ParserFile(const qp::String& file)
{
m_fileName = qp::Path::RelativePathTo(m_basePath, file);
m_filePath = file;
qp::Path::RemoveFileSpec(m_filePath);
m_depFile.clear();
std::vector<TCHAR> buf;
if (ReadFileToBuffer(file, buf))
ParserBuffer(buf);
}
bool Parser::ReadFileToBuffer(const qp::String& filePath, std::vector<TCHAR>& buf)
{
qp::File file;
if (!file.Create(filePath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING))
return false;
DWORD size = static_cast<DWORD> (file.GetSize());
// 最大只处理4K,为了效率
if (size > 4096)
size = 4096;
buf.resize(size);
file.Read(&buf[0], size);
return true;
}
void Parser::ParserBuffer(std::vector<TCHAR>& buf)
{
buf[buf.size() - 1] = '\0';
std::vector<TCHAR>::size_type max = buf.size() - 8;
for (std::vector<TCHAR>::size_type i = 0; i < max; ++i)
{
TCHAR* p = &buf[i];
if (*p == '#' && *++p == 'i' && *++p == 'n' && *++p == 'c' && *++p == 'l' && *++p == 'u' && *++p
== 'd' && *++p == 'e')
{
i += 7;
// 不是第一行代码,则#include之前必须是换行符
if (i > 8 && buf[i - 8] != '\n')
continue;
// 去除#include与"或<之间的空格、Tab
do ++p;
while (*p == ' ' || *p == '\t');
// 获取包含文件的长度
int len = 0;
if (*p == '"' || *p == '<')
{
++p;
while (*(p + len) != '"' && *(p + len) != '>')
{
if (++len > 100) break;
}
}
// 判断文件是否存在,如果不存在,则到搜索目录中查找,只匹配第一个符合条件的文件
qp::String fileName(p, len);
qp::String filePath = qp::Path::Append(m_filePath, fileName);
if (!qp::Path::FileExists(filePath))
{
bool finded = false;
for (auto it = m_incPath.begin(); it < m_incPath.end(); ++it)
{
filePath = qp::Path::Append(*it, fileName);
if (qp::Path::FileExists(filePath))
{
finded = true;
break;
}
}
if (!finded) filePath.clear();
}
// 判断相对路径
if (!filePath.empty())
{
fileName = qp::Path::RelativePathTo(m_basePath, filePath);
if (!fileName.empty())
{
qp::StringEx::Replace(fileName, '/', '\\');
m_depFile.push_back(fileName);
}
}
}
}
}
Depend::Depend(DependMap& header, DependMap& src) : m_depHeader(header), m_depSrc(src)
{}
void Depend::GetDependFromHeader(VecString& srcDep, qp::String& header)
{
auto iter = m_depHeader.find(header);
if (iter != m_depHeader.end())
{
AddDependToSrcVector(srcDep, (*iter).second);
m_fileIsParser.push_back((*iter).first);
for (auto it = ((*iter).second).begin(); it < ((*iter).second).end(); ++it)
{
bool isParser = false;
for (auto i = m_fileIsParser.begin(); i < m_fileIsParser.end(); ++i)
{
if (*i == *it)
{
isParser = true;
break;
}
}
if (!isParser)
GetDependFromHeader(srcDep, *it);
}
}
}
void Depend::AddDependToSrcVector(VecString& srcDep, VecString& headerDep)
{
for (VecString::size_type i = 0; i < headerDep.size(); ++i)
{
bool isExist = false;
for (VecString::size_type j = 0; j < srcDep.size(); ++j)
{
if (headerDep[i] == srcDep[j])
{
isExist = true;
break;
}
}
if (!isExist)
srcDep.push_back(headerDep[i]);
}
}
void Depend::Parser()
{
for (auto it = m_depSrc.begin(); it != m_depSrc.end(); ++it)
{
m_fileIsParser.clear();
VecString& srcDep = (*it).second;
VecString::size_type max = srcDep.size();
for (VecString::size_type i = 0; i < max; ++i)
{
GetDependFromHeader(srcDep, srcDep[i]);
}
}
}
set old=G:
set new=Z:
for /f %%i in ('mountvol %old% /l') do set "vol=%%i"
mountvol %old% /d
mountvol %new% %vol%
popd
#include "someheader.h"
#include "otherh.h"
...