wxArrayString DirectCommands::GetPostBuildCommands(ProjectBuildTarget* target) { Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; wxArrayString buildcmds = target ? target->GetCommandsAfterBuild() : m_pProject->GetCommandsAfterBuild(); if (!buildcmds.IsEmpty()) { wxString title = target ? target->GetTitle() : m_pProject->GetTitle(); wxArrayString tmp; for (size_t i = 0; i < buildcmds.GetCount(); ++i) { if(target) compiler->GenerateCommandLine(buildcmds[i], target, 0, wxEmptyString, wxEmptyString, wxEmptyString, wxEmptyString); else compiler->GenerateCommandLine(buildcmds[i], m_pProject->GetCurrentlyCompilingTarget(), 0, wxEmptyString, wxEmptyString, wxEmptyString, wxEmptyString); tmp.Add(wxString(COMPILER_WAIT)); // all commands should wait for queue to empty first tmp.Add(wxString(COMPILER_SIMPLE_LOG) + buildcmds[i]); tmp.Add(buildcmds[i]); } buildcmds = tmp; if (target) buildcmds.Insert(wxString(COMPILER_SIMPLE_LOG) + _("Running target post-build steps"), 0); else buildcmds.Insert(wxString(COMPILER_SIMPLE_LOG) + _("Running project post-build steps"), 0); if(m_doYield) Manager::Yield(); } return buildcmds; }
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; }
/// This is to be used *only* for files not belonging to a project!!! wxArrayString DirectCommands::GetCompileSingleFileCommand(const wxString& filename) { wxArrayString ret; // lookup file's type FileType ft = FileTypeOf(filename); // is it compilable? if (ft != ftSource) return ret; wxFileName fname(filename); fname.SetExt(m_pCompiler->GetSwitches().objectExtension); wxString o_filename = fname.GetFullPath(); wxString srcExt = fname.GetExt(); // if(m_pCompiler->GetName().Matches(_T("dsp"))) /// 2012-8-27 lcy // fname.SetExt(FileFilters::DSP563_EXT); // else if(m_pCompiler->GetName().Matches(_T("mc"))) // fname.SetExt(FileFilters::OR32_EXT); // else fname.SetExt(FileFilters::EXECUTABLE_EXT); wxString exe_filename = fname.GetFullPath(); wxString s_filename = filename; QuoteStringIfNeeded(s_filename); QuoteStringIfNeeded(o_filename); Compiler* compiler = CompilerFactory::GetDefaultCompiler(); wxString compilerCmd = compiler->GetCommand(ctCompileObjectCmd, srcExt); compiler->GenerateCommandLine(compilerCmd, 0, 0, s_filename, o_filename, o_filename, wxEmptyString); wxString linkerCmd = compiler->GetCommand(ctLinkConsoleExeCmd, fname.GetExt()); compiler->GenerateCommandLine(linkerCmd, 0, 0, wxEmptyString, o_filename, o_filename, wxEmptyString); // wxString asmCmd = compiler->GetCommand(ctCompileAsmCmd, _T("asm")); /// 2012-8-27 lcy // compiler->GenerateCommandLine(asmCmd, // 0, // 0, // wxEmptyString, // o_filename, // o_filename, // wxEmptyString); if (!compilerCmd.IsEmpty()) // my 2 { switch (m_pCompiler->GetSwitches().logging) { case clogFull: ret.Add(wxString(COMPILER_SIMPLE_LOG) + compilerCmd); break; case clogSimple: ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Compiling: ") + filename); break; default: break; } AddCommandsToArray(compilerCmd, ret); } else ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping file (no compiler program set): ") + filename); if (!linkerCmd.IsEmpty()) { switch (m_pCompiler->GetSwitches().logging) { case clogFull: ret.Add(wxString(COMPILER_SIMPLE_LOG) + linkerCmd); break; default: ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Linking console executable: ") + exe_filename); break; } AddCommandsToArray(linkerCmd, ret, true); } else ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping linking (no linker program set): ") + exe_filename); // if (!asmCmd.IsEmpty()) // { // switch (m_pCompiler->GetSwitches().logging) // { // case clogFull: // ret.Add(wxString(COMPILER_SIMPLE_LOG) + asmCmd); // break; // // default: // ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Linking console executable: ") + exe_filename); // break; // } // AddCommandsToArray(asmCmd, ret, true); // } // else // ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping linking (no linker program set): ") + exe_filename); 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; }