📄 makefilegenerator.cpp
字号:
if (!IsTargetValid(target))
continue;
buffer << target->GetTitle() << _T("_DIRS:") << _T('\n');
DoAddMakefileCreateDirs(buffer, target, true, false, true);
buffer << _T('\n');
buffer << target->GetTitle() << _T(": depend_") << target->GetTitle() << _T(" ") << target->GetTitle() << _T("_DIRS ") << target->GetTitle() << _T("-before ");
if (IsTargetValid(target))
{
buffer << _T("$(") << target->GetTitle() << _T("_BIN) ");
// add all custom-built files that do *not* link
int filesCount = (int)m_Files.GetCount();
for (int i = 0; i < filesCount; ++i)
{
ProjectFile* pf = m_Files[i];
if (pf->useCustomBuildCommand && !pf->link)
buffer << pf->relativeFilename << _T(" ");
}
}
buffer << target->GetTitle() << _T("-after") << _T('\n');
buffer << _T('\n');
// create target's options only if it has at least one linkable file
if (!IsTargetValid(target))
continue;
buffer << _T("$(") << target->GetTitle() << _T("_BIN): ") << _T("$(") << target->GetTitle() << _T("_LINKOBJS) $(") << target->GetTitle() << _T("_RESOURCE)");
// add external deps
wxArrayString array = GetArrayFromString(target->GetExternalDeps());
for (unsigned int i = 0; i < array.GetCount(); ++i)
{
buffer << _T(' ') << UnixFilename(array[i]);
}
buffer << _T('\n');
// change link stage command based on target type
switch (target->GetTargetType())
{
case ttConsoleOnly:
case ttExecutable:
{
CommandType ct = target->GetTargetType() == ttConsoleOnly ? ctLinkConsoleExeCmd : ctLinkExeCmd;
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Linking executable \"") << target->GetOutputFilename() << _T("\"...") << _T('\n');
wxString compilerCmd = ReplaceCompilerMacros(ct, _T(""), target, _T(""), _T(""), _T(""));
buffer << _T('\t') << m_Quiet << compilerCmd<< _T('\n');
break;
}
case ttStaticLib:
{
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Linking static library \"") << target->GetOutputFilename() << _T("\"...") << _T('\n');
wxString compilerCmd = ReplaceCompilerMacros(ctLinkStaticCmd, _T(""), target, _T(""), _T(""), _T(""));
buffer << _T('\t') << m_Quiet << compilerCmd<< _T('\n');
break;
}
case ttDynamicLib:
{
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Linking shared library \"") << target->GetOutputFilename() << _T("\"...") << _T('\n');
wxString compilerCmd = ReplaceCompilerMacros(ctLinkDynamicCmd, _T(""), target, _T(""), _T(""), _T(""));
buffer << _T('\t') << m_Quiet << compilerCmd<< _T('\n');
break;
}
default: break;
}
buffer << _T('\n');
}
buffer << _T('\n');
}
void MakefileGenerator::ConvertToMakefileFriendly(wxString& str, bool force)
{
if (!force && !m_GeneratingMakefile)
return;
if (str.IsEmpty())
return;
str.Replace(_T("\\"), _T("/"));
for (unsigned int i = 0; i < str.Length(); ++i)
{
if (str[i] == _T(' ') && (i > 0 && str[i - 1] != _T('\\')))
str.insert(i, _T('\\'));
}
// str.Replace("\\\\", "/");
}
void MakefileGenerator::QuoteStringIfNeeded(wxString& str, bool force)
{
if (!force && m_GeneratingMakefile)
return;
if (m_CompilerSet->GetSwitches().forceCompilerUseQuotes ||
m_CompilerSet->GetSwitches().forceLinkerUseQuotes ||
(str.Find(' ') != -1 && str.GetChar(0) != '"'))
{
str = _T('"') + str + _T('"');
}
}
wxString MakefileGenerator::GetObjectFile(ProjectFile* pf, ProjectBuildTarget* target)
{
wxFileName o_filename_tmp = UnixFilename(pf->GetObjName());
wxFileName o_filename = target->GetObjectOutput() + wxFILE_SEP_PATH + o_filename_tmp.GetFullPath();
// vars to make easier reading the following code
wxString o_file = UnixFilename(o_filename.GetFullPath());
ConvertToMakefileFriendly(o_file);
QuoteStringIfNeeded(o_file);
return o_file;
}
wxString MakefileGenerator::GetDependencyFile(ProjectFile* pf, ProjectBuildTarget* target)
{
wxFileName d_filename_tmp = UnixFilename(pf->GetObjName());
wxFileName d_filename = target->GetDepsOutput() + wxFILE_SEP_PATH + d_filename_tmp.GetFullPath();
d_filename.SetExt(_T("d"));
wxString d_file;
UpdateCompiler(target);
if (!m_CompilerSet)
return d_file;
if (m_CompilerSet->GetSwitches().needDependencies)
{
d_file = UnixFilename(d_filename.GetFullPath());
ConvertToMakefileFriendly(d_file);
QuoteStringIfNeeded(d_file);
}
return d_file;
}
void MakefileGenerator::DoAddMakefileTarget_Objs(wxString& buffer)
{
m_ObjectFiles.Clear();
wxString tmp;
wxArrayString depfiles; // one occurrence per dep (case where the same file is used in more than one target)
int targetsCount = m_Project->GetBuildTargetsCount();
for (int x = 0; x < targetsCount; ++x)
{
ProjectBuildTarget* target = m_Project->GetBuildTarget(x);
if (!target)
break;
UpdateCompiler(target);
if (!IsTargetValid(target))
continue;
#ifdef __WXMSW__
wxString resources;
#endif // __WXMSW__
int filesCount = (int)m_Files.GetCount();
for (int i = 0; i < filesCount; ++i)
{
ProjectFile* pf = m_Files[i];
if (pf->compile &&
!pf->compilerVar.IsEmpty() &&
pf->buildTargets.Index(target->GetTitle()) >= 0)
{
// vars to make easier reading the following code
wxString o_file = GetObjectFile(pf, target);
wxString d_file = GetDependencyFile(pf, target);
wxString c_file = UnixFilename(pf->relativeFilename);
ConvertToMakefileFriendly(c_file);
QuoteStringIfNeeded(c_file);
wxString targetName = target->GetTitle();
bool isResource = FileTypeOf(pf->relativeFilename) == ftResource;
if (!isResource)
{
if (m_CompilerSet->GetSwitches().needDependencies &&
depfiles.Index(d_file) == wxNOT_FOUND)
{
depfiles.Add(d_file);
if (pf->autoDeps)
{
// depend rule
buffer << d_file << _T(": ") << c_file << _T('\n');
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Calculating dependencies for \"") << pf->relativeFilename << _T("\"...") << _T('\n');
// gather all object files generated from this source file (multiple targets case)
wxString tmpdep;
for (unsigned int i = 0; i < pf->buildTargets.GetCount(); ++i)
{
ProjectBuildTarget* tmptarget = m_Project->GetBuildTarget(pf->buildTargets[i]);
if (tmptarget)
tmpdep << GetObjectFile(pf, tmptarget) << _T(',');
}
if (tmpdep.Last() == _T(','))
tmpdep.RemoveLast();
wxString compilerCmd = ReplaceCompilerMacros(ctGenDependenciesCmd, pf->compilerVar, target, c_file, tmpdep, d_file);
if (!compilerCmd.IsEmpty())
buffer << _T('\t') << m_Quiet << compilerCmd << _T('\n');
buffer << _T('\n');
}
else if (!pf->customDeps.IsEmpty())
{
// custom depend rule
wxString customDeps = pf->customDeps;
ReplaceMacros(target, pf, customDeps);
buffer << d_file << _T(": ") << c_file << _T('\n');
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Generating dependencies for \"") << pf->relativeFilename << _T("\"... (custom dependencies)") << _T('\n');
buffer << _T('\t') << m_Quiet << customDeps << _T('\n');
buffer << _T('\n');
}
}
else
d_file = UnixFilename(pf->relativeFilename); // for compilers that don't need deps, use .cpp file
if (pf->useCustomBuildCommand)
{
// custom build command
wxString customBuild = pf->buildCommand;
ReplaceMacros(target, pf, customBuild);
wxString obj_file = target->GetObjectOutput() + wxFILE_SEP_PATH + pf->GetObjName();
ConvertToMakefileFriendly(obj_file);
buffer << obj_file << _T(": ") << d_file << _T('\n');
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Compiling \"") << pf->relativeFilename << _T("\" (custom command)...") << _T('\n');
buffer << _T('\t') << m_Quiet << customBuild << _T('\n');
buffer << _T('\n');
}
else
{
// compile rule
buffer << o_file << _T(": ") << d_file << _T('\n');
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Compiling \"") << pf->relativeFilename << _T("\"...") << _T('\n');
// AddCreateSubdir(buffer, target->GetBasePath(), pf->GetObjName(), target->GetObjectOutput());
wxString compilerCmd = ReplaceCompilerMacros(ctCompileObjectCmd, pf->compilerVar, target, c_file, o_file, d_file);
if (!compilerCmd.IsEmpty())
buffer << _T('\t') << m_Quiet << compilerCmd << _T('\n');
buffer << _T('\n');
}
}
else
{
#ifdef __WXMSW__
if (pf->compile && FileTypeOf(pf->relativeFilename) == ftResource)
{
wxString out = pf->relativeFilename;
ConvertToMakefileFriendly(out);
resources << out << _T(" ");
}
#endif // __WXMSW__
}
}
}
#ifdef __WXMSW__
if (!resources.IsEmpty())
{
wxFileName resFile;
resFile.SetName(target->GetTitle() + _T("_private"));
resFile.SetExt(RESOURCE_EXT);
resFile.MakeRelativeTo(m_Project->GetBasePath());
buffer << _T("$(") << target->GetTitle() << _T("_RESOURCE): ");
if (m_CompilerSet->GetSwitches().needDependencies)
buffer << resources;
buffer << _T('\n');
if (m_CompilerSet->GetSwitches().logging == clogSimple)
buffer << _T('\t') << _T("@echo Compiling resources...") << _T('\n');
wxString compilerCmd = ReplaceCompilerMacros(ctCompileResourceCmd, _T(""), target, UnixFilename(resFile.GetFullPath()), _T(""), _T(""));
if (!compilerCmd.IsEmpty())
buffer << _T('\t') << m_Quiet << compilerCmd << _T('\n');
/*buffer << _T('\t') << m_Quiet << _T("$(RESCOMP) -i ") << UnixFilename(resFile.GetFullPath()) << _T(" -J rc ");
buffer << _T("-o $(") << target->GetTitle() << _T("_RESOURCE) -O coff ");
DoAppendIncludeDirs(buffer, 0L, _T("--include-dir="), true);
DoAppendIncludeDirs(buffer, 0L, _T("--include-dir=");
DoAppendIncludeDirs(buffer, target, _T("--include-dir=");*/
buffer << _T('\n');
}
buffer << _T('\n');
#endif // __WXMSW__
}
buffer << _T('\n');
}
int SortProjectFilesByWeight(ProjectFile** one, ProjectFile** two)
{
return (*one)->weight - (*two)->weight;
}
void MakefileGenerator::DoPrepareFiles()
{
m_Files.Clear();
for (int i = 0; i < m_Project->GetFilesCount(); ++i)
{
ProjectFile* pf = m_Project->GetFile(i);
m_Files.Add(pf);
}
m_Files.Sort(SortProjectFilesByWeight);
}
void MakefileGenerator::DoPrepareValidTargets()
{
m_LinkableTargets.Clear();
int targetsCount = m_Project->GetBuildTargetsCount();
for (int x = 0; x < targetsCount; ++x)
{
ProjectBuildTarget* target = m_Project->GetBuildTarget(x);
if (!target)
continue;
// create link target only if it has at least one linkable file
bool hasFiles = false;
for (unsigned int i = 0; i < m_Files.GetCount(); ++i)
{
ProjectFile* pf = m_Files[i];
if (pf->link && pf->buildTargets.Index(target->GetTitle()) >= 0)
{
hasFiles = true;
break;
}
}
if (hasFiles)
m_LinkableTargets.Add(target);
}
}
bool MakefileGenerator::IsTargetValid(ProjectBuildTarget* target)
{
UpdateCompiler(target);
if (!m_CompilerSet || !target)
return false;
bool hasBin = target->GetTargetType() != ttCommandsOnly; // is not "commands-only" target
bool hasCmds = !target->GetCommandsAfterBuild().IsEmpty() ||
!target->GetCommandsBeforeBuild().IsEmpty();
return hasBin && (hasCmds || m_LinkableTargets.Index(target) != -1);
}
void MakefileGenerator::ReplaceMacros(ProjectBuildTarget* bt, ProjectFile* pf, wxString& text)
{
wxString o_dir = bt ? bt->GetObjectOutput() + wxFILE_SEP_PATH : _T("");
wxString d_dir =
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -