wxArrayString DirectCommands::GetTargetCompileCommands(ProjectBuildTarget* target, bool force) const { wxArrayString ret; // set list of #include directories DepsSearchStart(target); // iterate all files of the project/target and add them to the build process size_t counter = ret.GetCount(); MyFilesArray files = GetProjectFilesSortedByWeight(target, true, false); size_t fcount = files.GetCount(); bool hasWeight = false; unsigned short int lastWeight = 0; for (unsigned int i = 0; i < fcount; ++i) { ProjectFile* pf = files[i]; // auto-generated files are handled automatically in GetCompileFileCommand() if (pf->AutoGeneratedBy()) continue; const pfDetails& pfd = pf->GetFileDetails(target); wxString err; if (force || IsObjectOutdated(target, pfd, &err)) { // Add a wait command if the weight of the current file is different from the previous one // Because GetCompileFileCommand() already adds a wait command if it compiled a PCH we // check the last command to prevent two consecutive wait commands if (hasWeight && lastWeight != pf->weight && (ret.IsEmpty() || ret.Last() != COMPILER_WAIT)) ret.Add(COMPILER_WAIT); // compile file wxArrayString filecmd = GetCompileFileCommand(target, pf); AppendArray(filecmd, ret); // Update the weight if (!hasWeight) hasWeight = true; lastWeight = pf->weight; } else { if (!err.IsEmpty()) ret.Add(COMPILER_WARNING_LOG + err); } if (m_doYield) Manager::Yield(); } // add link command wxArrayString link = GetLinkCommands(target, ret.GetCount() != counter); AppendArray(link, ret); return ret; }
SStringArray& SStringArray::operator=(const SStringArray &array) { MakeEmpty(); return AppendArray(array); }
wxArrayString DirectCommands::CompileFile(ProjectBuildTarget* target, ProjectFile* pf, bool force) const { wxArrayString ret; // is it compilable? if (!pf || !pf->compile || pf->compilerVar.IsEmpty()) return ret; // might happen for single file compilation if user chose a target the file does NOT belong to: if (target && pf->GetBuildTargets().Index(target->GetTitle()) == wxNOT_FOUND) { Manager::Get()->GetLogManager()->DebugLog(_("Invalid target selected to compile project file for: File does not belong to this target.")); return ret; } if (!force) { DepsSearchStart(target); const pfDetails& pfd = pf->GetFileDetails(target); wxString err; if ( !IsObjectOutdated(target, pfd, &err) ) { if ( !err.IsEmpty() ) ret.Add(COMPILER_WARNING_LOG + err); return ret; } } if (target) ret.Add(COMPILER_TARGET_CHANGE + target->GetTitle()); AppendArray(GetCompileFileCommand(target, pf), ret); return ret; }
wxArrayString DirectCommands::CompileFile(ProjectBuildTarget* target, ProjectFile* pf, bool force) { wxArrayString ret; // is it compilable? if (!pf->compile || pf->compilerVar.IsEmpty()) return ret; if (!force) { DepsSearchStart(target); const pfDetails& pfd = pf->GetFileDetails(target); wxString err; if (!IsObjectOutdated(target, pfd, &err)) { if (!err.IsEmpty()) ret.Add(wxString(COMPILER_SIMPLE_LOG) + err); return ret; } } if (target) ret.Add(wxString(COMPILER_TARGET_CHANGE) + target->GetTitle()); AppendArray(GetCompileFileCommand(target, pf), 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::GetCompileCommands(ProjectBuildTarget* target, bool force) { wxArrayString ret; if (target) ret = GetTargetCompileCommands(target, force); else { for (int x = 0; x < m_pProject->GetBuildTargetsCount(); ++x) { ProjectBuildTarget* bt = m_pProject->GetBuildTarget(x); if (bt->GetIncludeInTargetAll()) // only if target gets build with "all" { wxArrayString targetcompile = GetTargetCompileCommands(bt, force); AppendArray(targetcompile, ret); } } } return ret; }
wxArrayString DirectCommands::GetTargetLinkCommands(ProjectBuildTarget* target, bool force) { wxArrayString ret; wxString output = target->GetOutputFilename(); Manager::Get()->GetMacrosManager()->ReplaceMacros(output, target); wxFileName out = UnixFilename(output); wxString linkfiles; wxString FlatLinkFiles; wxString resfiles; bool IsOpenWatcom = target->GetCompilerID().IsSameAs(_T("ow")); time_t outputtime; depsTimeStamp(output.mb_str(), &outputtime); if (!outputtime) force = true; if (AreExternalDepsOutdated(out.GetFullPath(), target->GetAdditionalOutputFiles(), target->GetExternalDeps())) force = true; Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; wxString prependHack; // part of the following hack if (target->GetTargetType() == ttStaticLib) { // QUICK HACK: some linkers (e.g. bcc, dmc) require a - or + in front of // object files for static library. What we 'll do here until we redesign // the thing, is to accept this symbol as part of the $link_objects macro // like this: // $+link_objects // $-link_objects // $-+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 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); wxString allfile; if (files.GetCount() == 0) { ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Linking stage skipped (build target has no object files to link)")); return ret; } if (IsOpenWatcom && target->GetTargetType() != ttStaticLib) linkfiles << _T("file "); for (unsigned int i = 0; i < files.GetCount(); ++i) { ProjectFile* pf = files[i]; // we have to test again for each file if it is to be compiled // and we can't check the file for existence because we 're still // generating the command lines that will create the files... wxString macro = _T("$compiler"); if(m_pCompiler->GetParentID().Matches(_T("lcy"))) { if(pf->file.GetExt().Lower().IsSameAs(FileFilters::LD_EXT)) continue; } // allfile = allfile + _T(" ") + pf->GetObjName().BeforeLast(_T('.'))+_T('.')+pf->file.GetExt(); compiler->GenerateCommandLine(macro, target, pf, wxEmptyString, wxEmptyString, wxEmptyString, wxEmptyString); if (macro.IsEmpty()) continue; const pfDetails& pfd = pf->GetFileDetails(target); wxString Object = (target->GetUseFlatObjects())?pfd.object_file_flat:pfd.object_file; if (FileTypeOf(pf->relativeFilename) == ftResource) { // ----------------------------------------- // Following lines have been modified for OpenWatcom if (IsOpenWatcom) resfiles << _T("option resource=") << Object << _T(" "); else resfiles << Object << _T(" "); // ------------------------------------------ } else { // ----------------------------------------- // Following lines have been modified for OpenWatcom if (IsOpenWatcom && target->GetTargetType() != ttStaticLib) { linkfiles << prependHack << Object << _T(","); // see QUICK HACK above (prependHack) FlatLinkFiles << prependHack << pfd.object_file_flat << _T(","); // see QUICK HACK above (prependHack) } else { linkfiles << prependHack << Object << _T(" "); // see QUICK HACK above (prependHack) FlatLinkFiles << prependHack << pfd.object_file_flat << _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; } // Why was this here? // if(m_doYield) // Manager::Yield(); } if (IsOpenWatcom) { linkfiles.Trim(); if (linkfiles.Right(1).IsSameAs(_T(","))) linkfiles = linkfiles.BeforeLast(_T(',')); } if (!force) return ret; if(target->GetCompilerID().Lower().Matches(_T("dsp"))) /// 2012-8-29 lcy { // FlatLinkFiles.Replace(_T(".obj"),_T(".cln")); FlatLinkFiles.Replace(_T("\\"),_T(" ")); // linkfiles.Replace(_T(".obj"),_T(".cln")); linkfiles.Replace(_T("\\"),_T(" ")); } // create output dir out.MakeAbsolute(m_pProject->GetBasePath()); wxString dstname = out.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); Manager::Get()->GetMacrosManager()->ReplaceMacros(dstname, target); if (!dstname.IsEmpty() && !CreateDirRecursively(dstname, 0755)) { cbMessageBox(_("Can't create output directory ") + dstname); } // add actual link command wxString kind_of_output; CommandType ct = ctCount; // get rid of compiler warning 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; case ttNative: ct = ctLinkNativeCmd; kind_of_output = _("native"); break; case ttCommandsOnly: // add target post-build commands ret.Clear(); AppendArray(GetPostBuildCommands(target), ret); return ret; break; default: wxString ex; ex.Printf(_T("Encountered invalid TargetType (value = %d)"), target->GetTargetType()); cbThrow(ex); break; } wxString compilerCmd = compiler->GetCommand(ct); compiler->GenerateCommandLine(compilerCmd, target, 0, _T(""), linkfiles, FlatLinkFiles, resfiles); if(target->GetCompilerID().Lower().Matches(_T("dsp"))) /// 2012-8-29 lcy { compilerCmd.Replace(_("#allfile"),allfile); } if (!compilerCmd.IsEmpty()) { 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(": ") + output); break; } // for an explanation of the following, see GetTargetCompileCommands() if (target && ret.GetCount() != 0) ret.Add(wxString(COMPILER_TARGET_CHANGE) + target->GetTitle()); // the 'true' will make sure all commands will be prepended by // COMPILER_WAIT signal AddCommandsToArray(compilerCmd, ret, true, true); } else ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping linking (no linker program set): ") + output); return ret; }
wxArrayString DirectCommands::GetTargetCompileCommands(ProjectBuildTarget* target, bool force) { // Manager::Get()->GetLogManager()->DebugLog(wxString("-----GetTargetCompileCommands-----")); wxArrayString ret; // ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Switching to target: ") + target->GetTitle()); // NOTE: added this to notify compiler about the active target. // this is needed when targets use different compiler each // and C::B tries to parse the compiler's output. // previous behaviour, used the project's compiler for parsing // all targets output, which failed when a target's compiler // was different than the project's... // ret.Add(wxString(COMPILER_TARGET_CHANGE) + target->GetTitle()); m_pCurrTarget = target; // set list of #include directories DepsSearchStart(target); // iterate all files of the project/target and add them to the build process size_t counter = ret.GetCount(); MyFilesArray files = GetProjectFilesSortedByWeight(target, true, false); size_t fcount = files.GetCount(); bool ldcheck = false; for (unsigned int i = 0; i < fcount; ++i) { ProjectFile* pf = files[i]; // auto-generated files are handled automatically in GetCompileFileCommand() if (pf->AutoGeneratedBy()) { continue; } const pfDetails& pfd = pf->GetFileDetails(target); wxString err; if (force || IsObjectOutdated(target, pfd, &err)) { // compile file if(m_pCompiler->GetParentID().Matches(_T("lcy"))) { if(pf->file.GetExt().Lower().IsSameAs(_T("ld"))) { ldcheck= true; } } wxArrayString filecmd = GetCompileFileCommand(target, pf); AppendArray(filecmd, ret); } else { if (!err.IsEmpty()) ret.Add(wxString(COMPILER_SIMPLE_LOG) + err); } if(m_doYield) Manager::Yield(); } // add link command wxArrayString link = GetLinkCommands(target, ldcheck ? ldcheck : ret.GetCount() != counter); AppendArray(link, ret); // remove "switching to target" message if no compile needed // bool needPost = ret.GetCount() != counter; // if (!needPost) // ret.Clear(); return ret; }
wxArrayString DirectCommands::GetCompileFileCommand(ProjectBuildTarget* target, ProjectFile* pf) { wxArrayString ret; wxArrayString retGenerated; // is it compilable? if (!pf->compile || pf->compilerVar.IsEmpty()) return ret; const pfDetails& pfd = pf->GetFileDetails(target); Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; // wxString Object = (compiler->GetSwitches().UseFlatObjects)?pfd.object_file_flat:pfd.object_file; wxString Object = (target->GetUseFlatObjects())?pfd.object_file_flat:pfd.object_file; // lookup file's type FileType ft = FileTypeOf(pf->relativeFilename); // create output dir if (!pfd.object_dir_native.IsEmpty() && !CreateDirRecursively(pfd.object_dir_native, 0755)) { cbMessageBox(_("Can't create object output directory ") + pfd.object_dir_native); } bool isResource = ft == ftResource; bool isHeader = ft == ftHeader; // allowed resources under all platforms: makes sense when cross-compiling for // windows under linux. // and anyway, if the user is dumb enough to try to compile resources without // having a resource compiler, (s)he deserves the upcoming build error ;) //#ifndef __WXMSW__ // // not supported under non-win32 platforms // if (isResource) // return ret; //#endif wxString compilerCmd,source_file,tempCompilerCmd(wxEmptyString); if (!isHeader || compiler->GetSwitches().supportsPCH) { const CompilerTool& tool = compiler->GetCompilerTool(isResource ? ctCompileResourceCmd : ctCompileObjectCmd, pf->file.GetExt()); // does it generate other files to compile? for (size_t i = 0; i < pf->generatedFiles.size(); ++i) { AppendArray(GetCompileFileCommand(target, pf->generatedFiles[i]), retGenerated); // recurse } pfCustomBuild& pcfb = pf->customBuild[compiler->GetID()]; compilerCmd = pcfb.useCustomBuildCommand ? pcfb.buildCommand : tool.command; if (target->GetUseFullSourcePaths()) { source_file = UnixFilename(pfd.source_file_absolute_native); // for resource files, use short from if path because if windres bug with spaces-in-paths if (isResource) source_file = pf->file.GetShortPath(); } else source_file = pfd.source_file; QuoteStringIfNeeded(source_file); compiler->GenerateCommandLine(compilerCmd, target, pf, source_file, Object, pfd.object_file_flat, pfd.dep_file); } if (!compilerCmd.IsEmpty()) // my lcy 1 { switch (compiler->GetSwitches().logging) { case clogFull: ret.Add(wxString(COMPILER_SIMPLE_LOG) + compilerCmd); break; case clogSimple: if (isHeader) ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Precompiling header: ") + pfd.source_file_native); else ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Compiling: ") + pfd.source_file_native); break; default: break; } AddCommandsToArray(compilerCmd, ret); if(m_pCurrTarget->GetGenerateEachLit()) AddCommandsToArray(GenerateLitForEachObj(Object,compiler->GetPrograms().OBJDUMP),ret); if (isHeader) ret.Add(wxString(COMPILER_WAIT)); if (retGenerated.GetCount()) { // not only append commands for (any) generated files to be compiled // but also insert a "pause" to allow this file to generate its files first if (!isHeader) // if isHeader, the "pause" has already been added ret.Add(wxString(COMPILER_WAIT)); AppendArray(retGenerated, ret); } // if it's a PCH, delete the previously generated PCH to avoid problems // (it 'll be recreated anyway) if (FileTypeOf(pf->relativeFilename) == ftHeader && pf->compile) { wxString ObjectAbs = (m_pCurrTarget->GetUseFlatObjects())?pfd.object_file_flat_absolute_native:pfd.object_file_absolute_native; wxRemoveFile(ObjectAbs); } } else // lcy skip { ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping file (no compiler program set): ") + pfd.source_file_native); } return ret; }
AreaChangeData::AreaChangeData() { AppendArray(); }
SprayData::SprayData() { AppendArray(); }
SStringArray& SStringArray::operator+=(const SStringArray &array) { return AppendArray(array); }
wxArrayString DirectCommands::GetCompileFileCommand(ProjectBuildTarget* target, ProjectFile* pf) const { wxArrayString ret; wxArrayString ret_generated; // is it compilable? if (!pf || !pf->compile) return ret; if (pf->compilerVar.IsEmpty()) { Manager::Get()->GetLogManager()->DebugLog(_("Cannot resolve compiler var for project file.")); return ret; } Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; if (!compiler) { Manager::Get()->GetLogManager()->DebugLog(_("Can't access compiler for file.")); return ret; } const pfDetails& pfd = pf->GetFileDetails(target); wxString object = (compiler->GetSwitches().UseFlatObjects) ? pfd.object_file_flat : pfd.object_file; wxString object_dir = (compiler->GetSwitches().UseFlatObjects) ? pfd.object_dir_flat_native : pfd.object_dir_native; // create output dir if (!object_dir.IsEmpty() && !CreateDirRecursively(object_dir, 0755)) Manager::Get()->GetLogManager()->DebugLog(_("Can't create object output directory:\n") + object_dir); // lookup file's type const FileType ft = FileTypeOf(pf->relativeFilename); bool is_resource = ft == ftResource; bool is_header = ft == ftHeader; // allowed resources under all platforms: makes sense when cross-compiling for // windows under linux. // and anyway, if the user is dumb enough to try to compile resources without // having a resource compiler, (s)he deserves the upcoming build error ;) wxString compiler_cmd; if (!is_header || compiler->GetSwitches().supportsPCH) { const CompilerTool* tool = compiler->GetCompilerTool(is_resource ? ctCompileResourceCmd : ctCompileObjectCmd, pf->file.GetExt()); // does it generate other files to compile? for (size_t i = 0; i < pf->generatedFiles.size(); ++i) AppendArray(GetCompileFileCommand(target, pf->generatedFiles[i]), ret_generated); // recurse pfCustomBuild& pcfb = pf->customBuild[compiler->GetID()]; if (pcfb.useCustomBuildCommand) compiler_cmd = pcfb.buildCommand; else if (tool) compiler_cmd = tool->command; else compiler_cmd = wxEmptyString; wxString source_file; if (compiler->GetSwitches().UseFullSourcePaths) source_file = UnixFilename(pfd.source_file_absolute_native); else source_file = pfd.source_file; #ifdef command_line_generation Manager::Get()->GetLogManager()->DebugLog(F(_T("GetCompileFileCommand[1]: compiler_cmd='%s', source_file='%s', object='%s', object_dir='%s'."), compiler_cmd.wx_str(), source_file.wx_str(), object.wx_str(), object_dir.wx_str())); #endif // for resource files, use short from if path because if windres bug with spaces-in-paths if (is_resource && compiler->GetSwitches().UseFullSourcePaths) source_file = pf->file.GetShortPath(); QuoteStringIfNeeded(source_file); #ifdef command_line_generation Manager::Get()->GetLogManager()->DebugLog(F(_T("GetCompileFileCommand[2]: source_file='%s'."), source_file.wx_str())); #endif m_pGenerator->GenerateCommandLine(compiler_cmd, target, pf, source_file, object, pfd.object_file_flat, pfd.dep_file); } if (!is_header && compiler_cmd.IsEmpty()) { ret.Add(COMPILER_SIMPLE_LOG + _("Skipping file (no compiler program set): ") + pfd.source_file_native ); return ret; } switch (compiler->GetSwitches().logging) { case clogFull: ret.Add(COMPILER_SIMPLE_LOG + compiler_cmd); break; case clogSimple: if (is_header) ret.Add(COMPILER_SIMPLE_LOG + _("Pre-compiling header: ") + pfd.source_file_native ); else ret.Add(COMPILER_SIMPLE_LOG + _("Compiling: ") + pfd.source_file_native ); break; case clogNone: // fall-through default: break; } AddCommandsToArray(compiler_cmd, ret); if (is_header) ret.Add(COMPILER_WAIT); if (ret_generated.GetCount()) { // not only append commands for (any) generated files to be compiled // but also insert a "pause" to allow this file to generate its files first if (!is_header) // if is_header, the "pause" has already been added ret.Add(COMPILER_WAIT); AppendArray(ret_generated, ret); } // if it's a PCH, delete the previously generated PCH to avoid problems // (it 'll be recreated anyway) if ( (ft == ftHeader) && pf->compile ) { wxString object_abs = (compiler->GetSwitches().UseFlatObjects) ? pfd.object_file_flat_absolute_native : pfd.object_file_absolute_native; if ( wxFileExists(object_abs) && !wxRemoveFile(object_abs) ) Manager::Get()->GetLogManager()->DebugLog(_("Cannot remove old PCH file:\n") + object_abs); } return ret; }
ReserviorData::ReserviorData() { AppendArray(); }
DeadEndData::DeadEndData() { AppendArray(); }
ReliefData::ReliefData() { AppendArray(); }
BreckerData::BreckerData() { AppendArray(); }
void JsonDb::AppendArray(TransactionHandle &transaction, std::string const &path, double value) { AppendArray(transaction, path, ValuePointer(new ValueNumberReal(transaction->GenerateKey(), value))); }
wxArrayString DirectCommands::GetTargetLinkCommands(ProjectBuildTarget* target, bool force) const { wxArrayString ret; wxString output = target->GetOutputFilename(); Manager::Get()->GetMacrosManager()->ReplaceMacros(output, target); wxFileName out = UnixFilename(output); wxString linkfiles; wxString FlatLinkFiles; wxString resfiles; bool IsOpenWatcom = target->GetCompilerID().IsSameAs(_T("ow")); time_t outputtime; depsTimeStamp(output.mb_str(), &outputtime); if (!outputtime) force = true; wxArrayString fileMissing; if ( AreExternalDepsOutdated(target, out.GetFullPath(), &fileMissing) ) force = true; if (!fileMissing.IsEmpty()) { wxString warn; #ifdef NO_TRANSLATION warn.Printf(wxT("WARNING: Target '%s': Unable to resolve %lu external dependenc%s:"), target->GetFullTitle().wx_str(), static_cast<unsigned long>(fileMissing.Count()), wxString(fileMissing.Count() == 1 ? wxT("y") : wxT("ies")).wx_str()); #else warn.Printf(_("WARNING: Target '%s': Unable to resolve %lu external dependency/ies:"), target->GetFullTitle().wx_str(), static_cast<unsigned long>(fileMissing.Count())); #endif // NO_TRANSLATION ret.Add(COMPILER_WARNING_LOG + warn); for (size_t i = 0; i < fileMissing.Count(); ++i) ret.Add(COMPILER_NOTE_LOG + wxString(wxT(' '), 8) + fileMissing[i]); } Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; wxString prependHack; // part of the following hack if (target->GetTargetType() == ttStaticLib) { // QUICK HACK: some linkers (e.g. bcc, dmc) require a - or + in front of // object files for static library. What we 'll do here until we redesign // the thing, is to accept this symbol as part of the $link_objects macro // like this: // $+link_objects // $-link_objects // $-+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 wxString compilerCmd = compiler ? compiler->GetCommand(ctLinkStaticCmd) : wxString(wxEmptyString); 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); if (files.GetCount() == 0) { if (target->GetTargetType() != ttCommandsOnly) ret.Add(COMPILER_SIMPLE_LOG + _("Linking stage skipped (build target has no object files to link)")); return ret; } if (IsOpenWatcom && target->GetTargetType() != ttStaticLib) linkfiles << _T("file "); bool subseq(false); for (unsigned int i = 0; i < files.GetCount(); ++i) { ProjectFile* pf = files[i]; // we have to test again for each file if it is to be compiled // and we can't check the file for existence because we 're still // generating the command lines that will create the files... wxString macro = _T("$compiler"); m_pGenerator->GenerateCommandLine(macro, target, pf, wxEmptyString, wxEmptyString, wxEmptyString, wxEmptyString); if (macro.IsEmpty()) continue; const pfDetails& pfd = pf->GetFileDetails(target); wxString Object = (compiler->GetSwitches().UseFlatObjects) ? pfd.object_file_flat : pfd.object_file; if (FileTypeOf(pf->relativeFilename) == ftResource) { if (subseq) resfiles << _T(" "); // ----------------------------------------- // Following lines have been modified for OpenWatcom if (IsOpenWatcom) resfiles << _T("option resource=") << Object; else resfiles << Object; // ------------------------------------------ } else { // ----------------------------------------- // Following lines have been modified for OpenWatcom if (IsOpenWatcom && target->GetTargetType() == ttStaticLib) { if (subseq) { linkfiles << _T(" "); FlatLinkFiles << _T(" "); } linkfiles << prependHack << Object; // see QUICK HACK above (prependHack) FlatLinkFiles << prependHack << pfd.object_file_flat; // see QUICK HACK above (prependHack) } else { if (subseq) { linkfiles << compiler->GetSwitches().objectSeparator; FlatLinkFiles << compiler->GetSwitches().objectSeparator; } linkfiles << prependHack << Object; // see QUICK HACK above (prependHack) FlatLinkFiles << prependHack << pfd.object_file_flat; // see QUICK HACK above (prependHack) } // ----------------------------------------- } subseq = true; // timestamp check if (!force) { time_t objtime; depsTimeStamp(pfd.object_file_native.mb_str(), &objtime); // Honor compiler request to Use Flat Objects // (Settings/compiler/otherSettings/advancedOptions/Others/UseFlatObjects) if (compiler->GetSwitches().UseFlatObjects) depsTimeStamp(pfd.object_file_flat.mb_str(), &objtime); if (!objtime) force = true; if (objtime > outputtime) force = true; } } if (IsOpenWatcom) { linkfiles.Trim(); } 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()->ReplaceMacros(dstname, target); if (!dstname.IsEmpty() && !CreateDirRecursively(dstname, 0755)) { cbMessageBox(_("Can't create output directory ") + dstname); } // add actual link command wxString kind_of_output; CommandType ct = ctCount; // get rid of compiler warning 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; case ttNative: ct = ctLinkNativeCmd; kind_of_output = _("native"); break; case ttCommandsOnly: // add target post-build commands ret.Clear(); AppendArray(GetPostBuildCommands(target), ret); return ret; break; default: wxString ex; ex.Printf(_T("Encountered invalid TargetType (value = %d)"), target->GetTargetType()); cbThrow(ex); break; } wxString compilerCmd = compiler->GetCommand(ct); m_pGenerator->GenerateCommandLine(compilerCmd, target, 0, _T(""), linkfiles, FlatLinkFiles, resfiles); if (!compilerCmd.IsEmpty()) { switch (compiler->GetSwitches().logging) { case clogFull: ret.Add(COMPILER_SIMPLE_LOG + compilerCmd); break; case clogSimple: // fall-through case clogNone: // fall-through default: // linker always simple log (if not full) ret.Add(COMPILER_SIMPLE_LOG + _("Linking ") + kind_of_output + _T(": ") + output); break; } // for an explanation of the following, see GetTargetCompileCommands() if (target && ret.GetCount() != 0) ret.Add(COMPILER_TARGET_CHANGE + target->GetTitle()); // the 'true' will make sure all commands will be prepended by // COMPILER_WAIT signal AddCommandsToArray(compilerCmd, ret, true, true); } else ret.Add(COMPILER_SIMPLE_LOG + _("Skipping linking (no linker program set): ") + output); return ret; }
/** external deps are manually 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(ProjectBuildTarget* target, const wxString& buildOutput, wxArrayString* filesMissing) const { Compiler* compiler = CompilerFactory::GetCompiler(target->GetCompilerID()); // if no output, probably a commands-only target; nothing to relink // but we have to check other dependencies time_t timeOutput = 0; if (!buildOutput.IsEmpty()) { wxString output = buildOutput; Manager::Get()->GetMacrosManager()->ReplaceMacros(output); depsTimeStamp(output.mb_str(), &timeOutput); // if build output exists, check for updated static libraries if (timeOutput) { // look for static libraries in target/project library dirs wxArrayString libs = target->GetLinkLibs(); const wxArrayString& prjLibs = target->GetParentProject()->GetLinkLibs(); const wxArrayString& cmpLibs = compiler->GetLinkLibs(); AppendArray(prjLibs, libs); AppendArray(cmpLibs, libs); const wxArrayString& prjLibDirs = target->GetParentProject()->GetLibDirs(); const wxArrayString& cmpLibDirs = compiler->GetLibDirs(); wxArrayString libDirs = target->GetLibDirs(); AppendArray(prjLibDirs, libDirs); AppendArray(cmpLibDirs, libDirs); for (size_t i = 0; i < libs.GetCount(); ++i) { wxString lib = libs[i]; // if user manually pointed to a library, without using the lib dirs, // then just check the file directly w/out involving the search dirs... if (lib.Contains(_T("/")) || lib.Contains(_T("\\"))) { Manager::Get()->GetMacrosManager()->ReplaceMacros(lib, target); lib = UnixFilename(lib); time_t timeExtDep; depsTimeStamp(lib.mb_str(), &timeExtDep); if (timeExtDep > timeOutput) { // force re-link Manager::Get()->GetLogManager()->DebugLog(F(_T("Forcing re-link of '%s/%s' because '%s' is newer"), target->GetParentProject()->GetTitle().wx_str(), target->GetTitle().wx_str(), lib.wx_str())); return true; } continue; } if (!lib.StartsWith(compiler->GetSwitches().libPrefix)) lib = compiler->GetSwitches().libPrefix + lib; if (!lib.EndsWith(_T(".") + compiler->GetSwitches().libExtension)) lib += _T(".") + compiler->GetSwitches().libExtension; for (size_t l = 0; l < libDirs.GetCount(); ++l) { wxString dir = libDirs[l] + wxFILE_SEP_PATH + lib; Manager::Get()->GetMacrosManager()->ReplaceMacros(dir, target); dir = UnixFilename(dir); time_t timeExtDep; depsTimeStamp(dir.mb_str(), &timeExtDep); if (timeExtDep > timeOutput) { // force re-link Manager::Get()->GetLogManager()->DebugLog(F(_T("Forcing re-link of '%s/%s' because '%s' is newer"), target->GetParentProject()->GetTitle().wx_str(), target->GetTitle().wx_str(), dir.wx_str())); return true; } } } } } // array is separated by ; wxArrayString extDeps = GetArrayFromString(target->GetExternalDeps(), _T(";")); wxArrayString addFiles = GetArrayFromString(target->GetAdditionalOutputFiles(), _T(";")); for (size_t i = 0; i < extDeps.GetCount(); ++i) { if (extDeps[i].IsEmpty()) continue; Manager::Get()->GetMacrosManager()->ReplaceMacros(extDeps[i]); time_t timeExtDep; depsTimeStamp(extDeps[i].mb_str(), &timeExtDep); // if external dep doesn't exist, no need to relink // but we have to check other dependencies if (!timeExtDep) { if (filesMissing) filesMissing->Add(extDeps[i]); continue; } // let's check the additional output files for (size_t j = 0; j < addFiles.GetCount(); ++j) { if (addFiles[j].IsEmpty()) continue; Manager::Get()->GetMacrosManager()->ReplaceMacros(addFiles[j]); time_t timeAddFile; depsTimeStamp(addFiles[j].mb_str(), &timeAddFile); // if additional file doesn't exist, we can skip it if (!timeAddFile) { if (filesMissing) filesMissing->Add(addFiles[j]); continue; } // if external dep is newer than additional file, relink if (timeExtDep > timeAddFile) return true; } // if no output, probably a commands-only target; nothing to relink // but we have to check other dependencies if (buildOutput.IsEmpty()) continue; // 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) // if build output doesn't exist, relink if (!timeOutput) return true; // if external dep is newer than build output, relink if (timeExtDep > timeOutput) return true; } return false; // no force relink }
AssignPressData::AssignPressData() { AppendArray(); }
CheckValveData::CheckValveData() { AppendArray(); }