📄 directcommands.cpp
字号:
// $-+link_objects
// $+-link_objects
//
// So, we first scan the command for this special case and, if found,
// set a flag so that the linkfiles array is filled with the correct options
Compiler* compiler = target ? CompilerFactory::Compilers[target->GetCompilerIndex()] : m_pCompiler;
wxString compilerCmd = compiler->GetCommand(ctLinkStaticCmd);
wxRegEx re(_T("\\$([-+]+)link_objects"));
if (re.Matches(compilerCmd))
prependHack = re.GetMatch(compilerCmd, 1);
}
// get all the linkable objects for the target
MyFilesArray files = GetProjectFilesSortedByWeight(target, false, true);
for (unsigned int i = 0; i < files.GetCount(); ++i)
{
ProjectFile* pf = files[i];
pfDetails pfd(this, target, pf);
if (FileTypeOf(pf->relativeFilename) == ftResource)
resfiles << pfd.object_file << _T(" ");
else
linkfiles << prependHack << pfd.object_file << _T(" "); // see QUICK HACK above (prependHack)
// timestamp check
if (!force)
{
time_t objtime;
depsTimeStamp(pfd.object_file_native.mb_str(), &objtime);
if (objtime > outputtime)
force = true;
}
}
if (!force)
return ret;
// create output dir
out.MakeAbsolute(m_pProject->GetBasePath());
wxString dstname = out.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(dstname);
if (!dstname.IsEmpty() && !wxDirExists(dstname))
{
if (!CreateDirRecursively(dstname, 0755))
wxMessageBox(_("Can't create output directory ") + dstname);
}
// add actual link command
wxString kind_of_output;
CommandType ct;
switch (target->GetTargetType())
{
case ttConsoleOnly:
ct = ctLinkConsoleExeCmd;
kind_of_output = _("console executable");
break;
case ttExecutable:
ct = ctLinkExeCmd;
kind_of_output = _("executable");
break;
case ttDynamicLib:
ct = ctLinkDynamicCmd;
kind_of_output = _("dynamic library");
break;
case ttStaticLib:
ct = ctLinkStaticCmd;
kind_of_output = _("static library");
break;
default: break;
}
wxString compilerCmd = mg.CreateSingleFileCompileCmd(ct, target, 0, _T(""), linkfiles, resfiles);
if (!compilerCmd.IsEmpty())
{
Compiler* compiler = target ? CompilerFactory::Compilers[target->GetCompilerIndex()] : m_pCompiler;
switch (compiler->GetSwitches().logging)
{
case clogFull:
ret.Add(wxString(COMPILER_SIMPLE_LOG) + compilerCmd);
break;
default: // linker always simple log (if not full)
ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Linking ") + kind_of_output + _T(": ") + target->GetOutputFilename());
break;
}
// for an explanation of the following, see GetTargetCompileCommands()
if (target && ret.GetCount() != 0)
ret.Add(wxString(COMPILER_TARGET_CHANGE) + target->GetTitle());
AddCommandsToArray(compilerCmd, ret);
}
return ret;
}
wxArrayString DirectCommands::GetCleanCommands(ProjectBuildTarget* target, bool distclean)
{
wxArrayString ret;
if (target)
ret = GetTargetCleanCommands(target);
else
{
for (int x = 0; x < m_pProject->GetBuildTargetsCount(); ++x)
{
ProjectBuildTarget* bt = m_pProject->GetBuildTarget(x);
wxArrayString targetclear = GetTargetCleanCommands(bt, distclean);
AppendArray(targetclear, ret);
}
}
return ret;
}
wxArrayString DirectCommands::GetTargetCleanCommands(ProjectBuildTarget* target, bool distclean)
{
wxArrayString ret;
// add object files
MyFilesArray files = GetProjectFilesSortedByWeight(target, true, false);
for (unsigned int i = 0; i < files.GetCount(); ++i)
{
ProjectFile* pf = files[i];
pfDetails pfd(this, target, pf);
ret.Add(pfd.object_file_absolute_native);
if (distclean)
ret.Add(pfd.dep_file_absolute_native);
}
// add target output
wxString outputfilename = target->GetOutputFilename();
if (target->GetTargetType() != ttCommandsOnly)
{
ret.Add(outputfilename);
}
if (target->GetTargetType() == ttDynamicLib)
{
// for dynamic libs, delete static lib
ret.Add(target->GetStaticLibFilename());
// .def exports file is not deleted, because it may be user-supplied
// ret.Add(target->GetDynamicLibDefFilename());
}
return ret;
}
/** external deps are manualy set by the user
* e.g. a static library linked to the project is an external dep (if set as such by the user)
* so that a re-linking is forced if the static lib is updated
*/
bool DirectCommands::AreExternalDepsOutdated(const wxString& buildOutput, const wxString& additionalFiles, const wxString& externalDeps)
{
// array is separated by ;
wxArrayString deps = GetArrayFromString(externalDeps, _T(";"));
wxArrayString files = GetArrayFromString(additionalFiles, _T(";"));
for (size_t i = 0; i < deps.GetCount(); ++i)
{
if (deps[i].IsEmpty())
continue;
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(deps[i]);
time_t timeSrc;
depsTimeStamp(deps[i].mb_str(), &timeSrc);
// if external dep doesn't exist, no need to relink
if (!timeSrc)
return false;
// let's check the additional output files
for (size_t x = 0; x < files.GetCount(); ++x)
{
if (files[i].IsEmpty())
continue;
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(files[i]);
time_t addT;
depsTimeStamp(files[i].mb_str(), &addT);
// if additional file doesn't exist, we can skip it
if (!addT)
continue;
// if external dep is newer than additional file, relink
if (timeSrc > addT)
return true;
}
// if no output, probably a commands-only target; nothing to relink
if (buildOutput.IsEmpty())
return false;
// now check the target's output
// this is moved last because, for "commands only" targets,
// it would return before we had a chance to check the
// additional output files (above)
wxString output = buildOutput;
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(output);
time_t timeExe;
depsTimeStamp(output.mb_str(), &timeExe);
// if build output doesn't exist, relink
if (!timeExe)
return true;
// if external dep is newer than build output, relink
if (timeSrc > timeExe)
return true;
}
return false; // no force relink
}
bool DirectCommands::IsObjectOutdated(const pfDetails& pfd)
{
// If the source file does not exist, then do not compile.
time_t timeSrc;
depsTimeStamp(pfd.source_file_absolute_native.mb_str(), &timeSrc);
if (!timeSrc)
return false;
// If the object file does not exist, then it must be built. In this case
// there is no need to scan the source file for headers.
time_t timeObj;
depsTimeStamp(pfd.object_file_absolute_native.mb_str(), &timeObj);
if (!timeObj)
return true;
// If the source file is newer than the object file, then the object file
// must be built. In this case there is no need to scan the source file
// for headers.
if (timeSrc > timeObj)
return true;
// Scan the source file for headers. Result is NULL if the file does
// not exist. If one of the descendent header files is newer than the
// object file, then the object file must be built.
depsRef ref = depsScanForHeaders(pfd.source_file_absolute_native.mb_str());
if (ref)
{
time_t timeNewest;
(void) depsGetNewest(ref, &timeNewest);
return (timeNewest > timeObj);
}
// Source file doesn't exist.
return false;
}
void DirectCommands::DepsSearchStart(ProjectBuildTarget* target)
{
depsSearchStart();
wxArrayString prj_incs = m_pProject->GetIncludeDirs();
wxArrayString tgt_incs = target->GetIncludeDirs();
// replace custom vars in include dirs
for (unsigned int i = 0; i < prj_incs.GetCount(); ++i)
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(prj_incs[i]);
for (unsigned int i = 0; i < tgt_incs.GetCount(); ++i)
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(tgt_incs[i]);
OptionsRelation relation = target->GetOptionRelation(ortIncludeDirs);
switch (relation)
{
case orUseParentOptionsOnly:
for (unsigned int i = 0; i < prj_incs.GetCount(); ++i)
depsAddSearchDir(prj_incs[i].mb_str());
break;
case orUseTargetOptionsOnly:
for (unsigned int i = 0; i < tgt_incs.GetCount(); ++i)
depsAddSearchDir(tgt_incs[i].mb_str());
break;
case orPrependToParentOptions:
for (unsigned int i = 0; i < tgt_incs.GetCount(); ++i)
depsAddSearchDir(tgt_incs[i].mb_str());
for (unsigned int i = 0; i < prj_incs.GetCount(); ++i)
depsAddSearchDir(prj_incs[i].mb_str());
break;
case orAppendToParentOptions:
for (unsigned int i = 0; i < prj_incs.GetCount(); ++i)
depsAddSearchDir(prj_incs[i].mb_str());
for (unsigned int i = 0; i < tgt_incs.GetCount(); ++i)
depsAddSearchDir(tgt_incs[i].mb_str());
break;
}
// We could add the "global" compiler directories too, but we normally
// don't care about the modification times of system include files.
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -