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; }
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]; const pfDetails& pfd = pf->GetFileDetails(target); Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler; wxString ObjectAbs = (target->GetUseFlatObjects())?pfd.object_file_flat_absolute_native:pfd.object_file_absolute_native; ret.Add(ObjectAbs); // if this is an auto-generated file, delete it if (pf->AutoGeneratedBy()) { ret.Add(pf->file.GetFullPath()); } if (distclean) { ret.Add(pfd.dep_file_absolute_native); } // if(m_doYield) // Manager::Yield(); } // add target output wxString outputfilename = target->GetOutputFilename(); if (target->GetTargetType() != ttCommandsOnly) { Manager::Get()->GetMacrosManager()->ReplaceMacros(outputfilename, target); ret.Add(outputfilename); } if (target->GetTargetType() == ttDynamicLib) { // for dynamic libs, delete static lib outputfilename = target->GetStaticLibFilename(); Manager::Get()->GetMacrosManager()->ReplaceMacros(outputfilename, target); ret.Add(outputfilename); // .def exports file is not deleted, because it may be user-supplied // ret.Add(target->GetDynamicLibDefFilename()); } return ret; }
bool cbMGMakefile::reLoadDependecies(const wxString &p_DepsFileName,ProjectBuildTarget *p_pTarget,Compiler* p_pCompiler) { m_Deps.Clear(); if ( !wxFileExists( p_DepsFileName ) ) return false; wxString l_Buf; wxString l_VarName; wxTextFile l_DepFile; bool IsSkipThisFile = true; if (l_DepFile.Open( p_DepsFileName, wxConvFile )) { for ( unsigned long i = 0; i < l_DepFile.GetLineCount(); i++ ) { l_Buf = l_DepFile[i]; l_Buf.Trim(true); // Wrong! Don't uncomment it! Being deleted '\t' symbol! l_Buf.Trim(false); if ( l_Buf.IsEmpty() ) { l_VarName.Clear(); IsSkipThisFile = true; continue; } if ( _T('#') == l_Buf[0] ) continue; if ( _T('\t') == l_Buf[0] ) { if ( !IsSkipThisFile ) { if ( _T('"') == l_Buf[1] ) { wxString l_TmpName = l_Buf.AfterFirst( _T('\t') ); if (!l_TmpName.IsEmpty() && l_TmpName.GetChar(0) == _T('"') && l_TmpName.Last() == _T('"')) l_TmpName = l_TmpName.Mid(1, l_TmpName.Length() - 2); QuoteStringIfNeeded( l_TmpName ); m_Deps.AppendValue( l_VarName, l_TmpName ); } } } else { l_VarName = l_Buf.AfterFirst(_T(' ')); bool IsSource = l_VarName.Matches( _T("source:*") ); if ( IsSource ) { l_VarName = l_VarName.AfterFirst( _T(':') ); } /* * You would MUST found source file and get his filename from project * !!! .depend file content lowcase filenames */ wxFileName l_DepFileName = l_VarName; ProjectFile *pf = m_pProj->GetFileByFilename( l_DepFileName.GetFullPath(), l_DepFileName.IsRelative(), false ); if ( pf ) { const pfDetails& pfd = pf->GetFileDetails( p_pTarget ); if ( p_pCompiler->GetSwitches().UseFullSourcePaths ) { l_VarName = UnixFilename( pfd.source_file_absolute_native ); } else { l_VarName = pfd.source_file; } QuoteStringIfNeeded( l_VarName ); IsSkipThisFile = false; } else { IsSkipThisFile = true; } } } } /* FIXME (kisoftcb#1#): Next code for debug only! wxTextFile l_DebFile; l_DebFile.Create( _T("D:/DepsFile.log") ); m_Deps.SaveAllVars( l_DebFile ); l_DebFile.Write(); l_DebFile.Close(); */ }
bool cbMGMakefile::SaveMakefile() { bool l_Ret = false; wxString l_FullFilename = m_Path + m_Filename; if ( m_Overwrite && wxFileExists( l_FullFilename ) ) wxRemoveFile( l_FullFilename ); wxTextFile l_File; if ( !l_File.Create( l_FullFilename ) ) { wxString lMsg = _( "File " ) + l_FullFilename + _(" is exists!\nOverwrite?" ); if (wxID_YES == cbMessageBox(lMsg, _("Warning"), wxICON_EXCLAMATION | wxYES_NO, (wxWindow *)Manager::Get()->GetAppWindow())) { wxRemoveFile( l_FullFilename ); } else { return l_Ret; } } // for active target only! wxString l_ActiveTargetName = m_pProj->GetActiveBuildTarget(); ProjectBuildTarget* l_pTarget = m_pProj->GetBuildTarget( l_ActiveTargetName ); if ( !l_pTarget ) { wxString l_Msg = _( "Can't found an active target!\n" "C::B MakefileGen could not complete the operation." ); cbMessageBox( l_Msg, _( "Error" ), wxICON_ERROR | wxOK, (wxWindow *)Manager::Get()->GetAppWindow() ); Manager::Get()->GetMessageManager()->DebugLog( l_Msg ); return l_Ret; } const wxString& l_CompilerId = l_pTarget->GetCompilerID(); Compiler* l_pCompiler = CompilerFactory::GetCompiler( l_CompilerId ); if ( !getDependencies( l_pTarget, l_pCompiler ) ) return false; m_Variables.AddVariable(_T("CPP"),l_pCompiler->GetPrograms().CPP); m_Variables.AddVariable(_T("CC"),l_pCompiler->GetPrograms().C); m_Variables.AddVariable(_T("LD"),l_pCompiler->GetPrograms().LD); m_Variables.AddVariable(_T("LIB"),l_pCompiler->GetPrograms().LIB); m_Variables.AddVariable(_T("WINDRES"),l_pCompiler->GetPrograms().WINDRES); const wxArrayString& l_CommandsBeforeBuild = l_pTarget->GetCommandsBeforeBuild(); const wxArrayString& l_CommandsAfterBuild = l_pTarget->GetCommandsAfterBuild(); wxString l_TargetFileName = l_pTarget->GetOutputFilename(); Manager::Get()->GetMacrosManager()->ReplaceMacros(l_TargetFileName, l_pTarget); wxFileName l_OutFileName = UnixFilename(l_TargetFileName); cbMGRule l_Rule; if ( 0 == l_ActiveTargetName.CmpNoCase( _T( "default" ) ) ) { l_Rule.SetTarget( _T( "all" ) ); } else { l_Rule.SetTarget( l_ActiveTargetName ); } wxString l_Pre; if ( l_CommandsBeforeBuild.GetCount() > 0 ) { l_Pre = cmdbefore + _T(" "); } l_Pre += l_OutFileName.GetFullPath(); if ( l_CommandsAfterBuild.GetCount() > 0 ) { l_Pre += _T(" ") + cmdafter; } l_Rule.SetPrerequisites( l_Pre ); m_Rules.Add( l_Rule ); if ( l_CommandsBeforeBuild.GetCount() > 0 ) { l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( cmdbefore ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( cmdbefore ); for ( unsigned long idx = 0; idx < l_CommandsBeforeBuild.GetCount(); idx ++ ) { l_Rule.AddCommand( l_CommandsBeforeBuild[ idx ] ); } m_Rules.Add( l_Rule ); } if ( l_CommandsAfterBuild.GetCount() > 0 ) { l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( cmdafter ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( cmdafter ); for ( unsigned long idx = 0; idx < l_CommandsAfterBuild.GetCount(); idx ++ ) { l_Rule.AddCommand( l_CommandsAfterBuild[ idx ] ); } m_Rules.Add( l_Rule ); } l_Rule.Clear(); l_Rule.SetTarget( l_OutFileName.GetFullPath() ); l_Rule.SetPrerequisites( objs ); wxString kind_of_output = _T( "unknown" ); CommandType ct = ctInvalid; // get rid of compiler warning switch ( l_pTarget->GetTargetType() ) { case ttConsoleOnly: ct = ctLinkConsoleExeCmd; kind_of_output = _T( "console executable" ); break; case ttExecutable: ct = ctLinkExeCmd; kind_of_output = _T( "executable" ); break; case ttDynamicLib: ct = ctLinkDynamicCmd; kind_of_output = _T( "dynamic library" ); break; case ttStaticLib: ct = ctLinkStaticCmd; kind_of_output = _T( "static library" ); break; case ttNative: ct = ctLinkNativeCmd; kind_of_output = _T( "native" ); break; case ttCommandsOnly: ct = ctLinkConsoleExeCmd; kind_of_output = _T( "commands only" ); break; // case ttCommandsOnly: // // add target post-build commands // ret.Clear(); // AppendArray(GetPostBuildCommands(target), ret); // return ret; // break; break; } /*if(ttCommandsOnly == lTarget->GetTargetType()) { GetPostBuildCommands(lTarget); } else*/ { l_Rule.AddCommand( _T( "echo Building " ) + kind_of_output + _T( " " ) + l_OutFileName.GetFullPath() ); wxString l_LinkerCmd = l_pCompiler->GetCommand( ct ); l_pCompiler->GenerateCommandLine( l_LinkerCmd, l_pTarget, NULL, l_OutFileName.GetFullPath(), oobjs, wxEmptyString, wxEmptyString ); l_Rule.AddCommand( l_LinkerCmd ); } m_Rules.Add( l_Rule ); // Form rules wxString l_Tmp; unsigned long ii; wxString macro; wxString file; wxString object; wxString FlatObject; wxString deps; cbMGSortFilesArray files = GetProjectFilesSortedByWeight(l_pTarget,true,false); unsigned long lnb_files = files.GetCount(); for ( ii = 0; ii < lnb_files; ii++ ) { l_Rule.Clear(); ProjectFile* pf = files[ ii ]; const pfDetails& pfd = pf->GetFileDetails( l_pTarget ); wxString l_Object = ( l_pCompiler->GetSwitches().UseFlatObjects )?pfd.object_file_flat:pfd.object_file; wxString l_CompilerCmd; // lookup file's type FileType ft = FileTypeOf( pf->relativeFilename ); bool isResource = ft == ftResource; bool isHeader = ft == ftHeader; if ( !isHeader || l_pCompiler->GetSwitches().supportsPCH ) { pfCustomBuild& pcfb = pf->customBuild[l_pCompiler->GetID()]; l_CompilerCmd = pcfb.useCustomBuildCommand ? pcfb.buildCommand : l_pCompiler->GetCommand( isResource ? ctCompileResourceCmd : ctCompileObjectCmd ); wxString l_SourceFile; if ( l_pCompiler->GetSwitches().UseFullSourcePaths ) { l_SourceFile = UnixFilename( pfd.source_file_absolute_native ); // for resource files, use short from if path because if windres bug with spaces-in-paths if ( isResource ) { l_SourceFile = pf->file.GetShortPath(); } } else { l_SourceFile = pfd.source_file; } QuoteStringIfNeeded( l_SourceFile ); l_pCompiler->GenerateCommandLine( l_CompilerCmd, l_pTarget, pf, l_SourceFile, l_Object, pfd.object_file_flat, pfd.dep_file ); m_Variables.AppendValue( _T( "OBJS" ), l_Object ); l_Rule.SetTarget( l_Object ); l_Rule.SetPrerequisites( l_SourceFile ); l_Rule.AddCommand( _T( "echo Compiling: " ) + l_SourceFile ); l_Rule.AddCommand( l_CompilerCmd ); m_Rules.Add( l_Rule ); } } for ( unsigned long i=0; i < m_Deps.Count(); i++ ) { l_Rule.Clear(); l_Rule.SetTarget( m_Deps.GetVarName( i ) ); l_Rule.SetPrerequisites( m_Deps.GetVariable( i ) ); m_Rules.Add( l_Rule ); } l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( cmdclean ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( cmdclean ); l_Rule.AddCommand( _T( "echo Delete $(OBJS) " ) + l_OutFileName.GetFullPath() ); #ifdef __WXMSW__ l_Rule.AddCommand( _T( "del /f $(OBJS) " ) + l_OutFileName.GetFullPath() ); #else l_Rule.AddCommand( _T( "rm -f $(OBJS) " ) + l_OutFileName.GetFullPath() ); #endif m_Rules.Add( l_Rule ); // save header l_File.AddLine( sHeader ); l_File.AddLine( wxEmptyString ); m_Variables.SaveAllVars( l_File ); SaveAllRules( l_File ); l_File.Write(); l_File.Close(); l_Ret = true; return l_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::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; }
bool cbMGMakefile::formFileForTarget( ProjectBuildTarget *p_BuildTarget, wxTextFile &p_File ) { bool l_Ret = false; if ( !p_BuildTarget ) { wxString l_Msg = _( "Can't found an active target!\n" "C::B MakefileGen could not complete the operation." ); cbMessageBox( l_Msg, _( "Error" ), wxICON_ERROR | wxOK, (wxWindow *)Manager::Get()->GetAppWindow() ); Manager::Get()->GetLogManager()->DebugLog( l_Msg ); return l_Ret; } wxString l_TargetName = p_BuildTarget->GetTitle(); l_TargetName.Replace( _T( " " ), _T( "_" ) ); wxString l_ObjsName = _T("OBJS_") + l_TargetName.Upper(); wxString l_CmdBefore = cmdbefore + _T('_') + l_TargetName; wxString l_CmdAfter = cmdafter + _T('_') + l_TargetName; wxString l_CmdClean = cmdclean + _T('_') + l_TargetName; m_Rules.Clear(); const wxString& l_CompilerId = p_BuildTarget->GetCompilerID(); Compiler* l_pCompiler = CompilerFactory::GetCompiler( l_CompilerId ); if( !l_pCompiler ) { wxString l_Msg = _( "Can't found an compiler settings!\n" "C::B MakefileGen could not complete the operation." ); cbMessageBox( l_Msg, _( "Error" ), wxICON_ERROR | wxOK, (wxWindow *)Manager::Get()->GetAppWindow() ); Manager::Get()->GetLogManager()->DebugLog( l_Msg ); return false; } if ( !getDependencies( p_BuildTarget, l_pCompiler ) ) return false; if ( !m_VariablesIsSaved ) { m_Variables.AddVariable(_T("CPP"),l_pCompiler->GetPrograms().CPP); m_Variables.AddVariable(_T("CC"),l_pCompiler->GetPrograms().C); m_Variables.AddVariable(_T("LD"),l_pCompiler->GetPrograms().LD); m_Variables.AddVariable(_T("LIB"),l_pCompiler->GetPrograms().LIB); m_Variables.AddVariable(_T("WINDRES"),l_pCompiler->GetPrograms().WINDRES); } const wxArrayString& l_CommandsBeforeBuild = p_BuildTarget->GetCommandsBeforeBuild(); const wxArrayString& l_CommandsAfterBuild = p_BuildTarget->GetCommandsAfterBuild(); wxString l_TargetFileName = p_BuildTarget->GetOutputFilename(); Manager::Get()->GetMacrosManager()->ReplaceMacros(l_TargetFileName, p_BuildTarget); #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::formFileForTarget" ), l_TargetFileName ); #endif wxFileName l_OutFileName = UnixFilename(l_TargetFileName); wxString l_OutFileNameFullPath = l_OutFileName.GetFullPath(); QuoteStringIfNeeded( l_OutFileNameFullPath ); wxString l_OutFileNameFullPathMakefileFriendly = l_OutFileNameFullPath; ConvertToMakefileFriendly( l_OutFileNameFullPathMakefileFriendly ); cbMGRule l_Rule; if ( 0 == l_TargetName.CmpNoCase( _T( "default" ) ) ) { l_Rule.SetTarget( _T( "all" ) ); } else { l_Rule.SetTarget( l_TargetName ); } wxString l_Pre; if ( l_CommandsBeforeBuild.GetCount() > 0 ) { l_Pre = l_CmdBefore; } l_Pre += l_OutFileNameFullPathMakefileFriendly; if ( l_CommandsAfterBuild.GetCount() > 0 ) { l_Pre += _T(" ") + l_CmdAfter; } l_Rule.SetPrerequisites( l_Pre ); m_Rules.Add( l_Rule ); if ( l_CommandsBeforeBuild.GetCount() > 0 ) { l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( l_CmdBefore ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( l_CmdBefore ); for ( unsigned long idx = 0; idx < l_CommandsBeforeBuild.GetCount(); idx ++ ) { l_Rule.AddCommand( l_CommandsBeforeBuild[ idx ] ); } m_Rules.Add( l_Rule ); } if ( l_CommandsAfterBuild.GetCount() > 0 ) { l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( l_CmdAfter ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( l_CmdAfter ); for ( unsigned long idx = 0; idx < l_CommandsAfterBuild.GetCount(); idx ++ ) { l_Rule.AddCommand( l_CommandsAfterBuild[ idx ] ); } m_Rules.Add( l_Rule ); } l_Rule.Clear(); l_Rule.SetTarget( l_OutFileNameFullPathMakefileFriendly ); l_Rule.SetPrerequisites( _T("$(") + l_ObjsName + _T(")") ); wxString kind_of_output = _T( "unknown" ); CommandType ct = ctCount; bool l_TargetTypeValid = true; switch ( p_BuildTarget->GetTargetType() ) { case ttConsoleOnly: ct = ctLinkConsoleExeCmd; kind_of_output = _T( "console executable" ); break; case ttExecutable: ct = ctLinkExeCmd; kind_of_output = _T( "executable" ); break; case ttDynamicLib: ct = ctLinkDynamicCmd; kind_of_output = _T( "dynamic library" ); break; case ttStaticLib: ct = ctLinkStaticCmd; kind_of_output = _T( "static library" ); break; case ttNative: ct = ctLinkNativeCmd; kind_of_output = _T( "native" ); break; case ttCommandsOnly: ct = ctLinkConsoleExeCmd; kind_of_output = _T( "commands only" ); break; default: l_TargetTypeValid = false; break; // case ttCommandsOnly: // // add target post-build commands // ret.Clear(); // AppendArray(GetPostBuildCommands(target), ret); // return ret; // break; break; } /*if(ttCommandsOnly == lTarget->GetTargetType()) { GetPostBuildCommands(lTarget); } else*/ { l_Rule.AddCommand( _T( "echo Building " ) + kind_of_output + _T( " " ) + l_OutFileNameFullPath ); if( l_TargetTypeValid ) { wxString l_LinkerCmd = l_pCompiler->GetCommand( ct ); #if wxCHECK_VERSION(2, 9, 0) Manager::Get()->GetLogManager()->DebugLog(wxString::Format( _("LinkerCmd: %s"), l_LinkerCmd.wx_str()) ); #else Manager::Get()->GetLogManager()->DebugLog(wxString::Format( _("LinkerCmd: %s"), l_LinkerCmd.c_str()) ); #endif l_pCompiler->GenerateCommandLine( l_LinkerCmd, p_BuildTarget, NULL, l_OutFileNameFullPath, // _T("$$(") + l_TargetName + _T(")"), /* fix by oBFusCATed */ _T("$$(") + l_ObjsName + _T(")"), wxEmptyString, wxEmptyString ); l_Rule.AddCommand( l_LinkerCmd ); } } m_Rules.Add( l_Rule ); // Form rules wxString l_Tmp; unsigned long ii; wxString macro; wxString file; wxString object; wxString FlatObject; wxString deps; cbMGSortFilesArray files = GetProjectFilesSortedByWeight(p_BuildTarget,true,false); unsigned long lnb_files = files.GetCount(); // fix by Sasquatch_47 //need to clear the m_Objs string for cases where one is generating a makefile for more than one configuration m_Objs.clear(); for ( ii = 0; ii < lnb_files; ii++ ) { l_Rule.Clear(); ProjectFile* pf = files[ ii ]; const pfDetails& pfd = pf->GetFileDetails( p_BuildTarget ); wxString l_Object = ( l_pCompiler->GetSwitches().UseFlatObjects )?pfd.object_file_flat:pfd.object_file; wxString l_CompilerCmd; // lookup file's type FileType ft = FileTypeOf( pf->relativeFilename ); bool isResource = ft == ftResource; bool isHeader = ft == ftHeader; if ( !isHeader || l_pCompiler->GetSwitches().supportsPCH ) { pfCustomBuild& pcfb = pf->customBuild[l_pCompiler->GetID()]; l_CompilerCmd = pcfb.useCustomBuildCommand ? pcfb.buildCommand : l_pCompiler->GetCommand( isResource ? ctCompileResourceCmd : ctCompileObjectCmd ); wxString l_SourceFile; wxString l_SourceFileMakefileFriendly; if ( l_pCompiler->GetSwitches().UseFullSourcePaths ) { wxString l_fName = pfd.source_file_absolute_native; if( l_fName != wxEmptyString ) { #ifdef USE_DEBUGSAVE p_File.AddLine( _T("# File: ") + pfd.source_file_absolute_native ); p_File.AddLine( _T("# File: ") + l_fName ); p_File.AddLine( wxEmptyString ); #endif #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::formFileForTarget" ), l_fName ); #endif l_SourceFile = UnixFilename( l_fName ); // for resource files, use short from if path because if windres bug with spaces-in-paths if ( isResource ) { l_SourceFile = pf->file.GetShortPath(); } } } else { l_SourceFile = pfd.source_file; } l_SourceFileMakefileFriendly = l_SourceFile; ConvertToMakefileFriendly( l_SourceFileMakefileFriendly ); QuoteStringIfNeeded( l_SourceFile ); #if wxCHECK_VERSION(2, 9, 0) Manager::Get()->GetLogManager()->DebugLog(wxString::Format( _("CompilerCmd: %s"), l_CompilerCmd.wx_str()) ); #else Manager::Get()->GetLogManager()->DebugLog(wxString::Format( _("CompilerCmd: %s"), l_CompilerCmd.c_str()) ); #endif /* FIXME: traps after next command */ l_pCompiler->GenerateCommandLine( l_CompilerCmd, p_BuildTarget, pf, l_SourceFile, l_Object, pfd.object_file_flat, pfd.dep_file ); if ( m_Objs.size() ) { m_Objs += _T(' '); } m_Objs += l_Object; l_Rule.SetTarget( l_Object ); l_Rule.SetPrerequisites( l_SourceFileMakefileFriendly ); l_Rule.AddCommand( _T( "echo Compiling: " ) + l_SourceFile ); l_Rule.AddCommand( l_CompilerCmd ); m_Rules.Add( l_Rule ); } } for ( unsigned long i=0; i < m_Deps.Count(); i++ ) { l_Rule.Clear(); l_Rule.SetTarget( m_Deps.GetVarName( i ) ); l_Rule.SetPrerequisites( m_Deps.GetVariable( i ) ); m_Rules.Add( l_Rule ); } l_Rule.Clear(); l_Rule.SetTarget( cmdphony ); l_Rule.SetPrerequisites( l_CmdClean ); m_Rules.Add( l_Rule ); l_Rule.Clear(); l_Rule.SetTarget( l_CmdClean ); l_Rule.AddCommand( _T( "echo Delete $(" ) + l_ObjsName + _T( ") " ) + l_OutFileNameFullPath ); #ifdef __WXMSW__ l_Rule.AddCommand( _T( "-del /f $(" ) + l_ObjsName + _T( ") " ) + l_OutFileNameFullPath ); #else l_Rule.AddCommand( _T( "-rm -f $(" ) + l_ObjsName + _T( ") " ) + l_OutFileNameFullPath ); #endif m_Rules.Add( l_Rule ); if ( !m_VariablesIsSaved ) { m_Variables.SaveAllVars( p_File ); m_VariablesIsSaved = true; } p_File.AddLine( _T("# Target: ") + l_TargetName ); p_File.AddLine( wxEmptyString ); p_File.AddLine( l_ObjsName + _T("=") + m_Objs ); p_File.AddLine( wxEmptyString ); SaveAllRules( p_File ); p_File.AddLine( wxEmptyString ); p_File.AddLine( wxEmptyString ); l_Ret = true; return l_Ret; }
bool cbMGMakefile::reLoadDependecies(const wxString &p_DepsFileName,ProjectBuildTarget *p_pTarget,Compiler* p_pCompiler) { #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, Start" ), p_pTarget->GetTitle() ); #endif m_Deps.Clear(); if ( !wxFileExists( p_DepsFileName ) ) { wxString l_Msg = _( "Dependencies file (.depend) is absent!\n" "C::B MakefileGen could not complete the operation." ); cbMessageBox( l_Msg, _( "Error" ), wxICON_ERROR | wxOK, (wxWindow *)Manager::Get()->GetAppWindow() ); Manager::Get()->GetLogManager()->DebugLog( l_Msg ); #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies" ), _T( "End false" ) ); #endif return false; } wxString l_Buf; wxString l_VarName; wxTextFile l_DepFile; wxString l_TargetName = p_pTarget->GetTitle(); bool IsSkipThisFile = true; if (l_DepFile.Open( p_DepsFileName, wxConvFile )) { for ( unsigned long i = 0; i < l_DepFile.GetLineCount(); i++ ) { l_Buf = l_DepFile[i]; l_Buf.Trim(true); // Wrong! Don't uncomment it! Being deleted '\t' symbol! l_Buf.Trim(false); if ( l_Buf.IsEmpty() ) { l_VarName.Clear(); IsSkipThisFile = true; continue; } if ( _T('#') == l_Buf[0] ) continue; if ( _T('\t') == l_Buf[0] ) { if ( !IsSkipThisFile ) { if ( _T('"') == l_Buf[1] ) { wxString l_TmpName = l_Buf.AfterFirst( _T('\t') ); if (!l_TmpName.IsEmpty() && l_TmpName.GetChar(0) == _T('"') && l_TmpName.Last() == _T('"')) l_TmpName = l_TmpName.Mid(1, l_TmpName.Length() - 2); QuoteStringIfNeeded( l_TmpName ); m_Deps.AppendValue( l_VarName, l_TmpName ); } } } else { l_VarName = l_Buf.AfterFirst(_T(' ')); bool IsSource = l_VarName.Matches( _T("source:*") ); if ( IsSource ) { l_VarName = l_VarName.AfterFirst( _T(':') ); } /* * You would MUST found source file and get his filename from project * !!! .depend file content lowcase filenames */ wxFileName l_DepFileName = l_VarName; #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, depfilename" ), l_VarName.wc_str() ); #endif ProjectFile *pf = m_pProj->GetFileByFilename( l_DepFileName.GetFullPath(), l_DepFileName.IsRelative(), false ); if ( pf ) { #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, pf readed" ), pf->GetObjName() ); #endif if( pf->buildTargets.Index( l_TargetName ) != wxNOT_FOUND ) { #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, before pfd read, target" ), l_TargetName ); #endif const pfDetails& pfd = pf->GetFileDetails( p_pTarget ); #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, pfd readed" ), pfd.dep_dir ); #endif if ( p_pCompiler->GetSwitches().UseFullSourcePaths ) { l_VarName = UnixFilename( pfd.source_file_absolute_native ); } else { l_VarName = pfd.source_file; } QuoteStringIfNeeded( l_VarName ); IsSkipThisFile = false; } else { #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies, pf skip" ), pf->GetObjName() ); #endif IsSkipThisFile = true; } } else { IsSkipThisFile = true; } } } } /* FIXME (kisoftcb#1#): Next code for debug only! wxTextFile l_DebFile; l_DebFile.Create( _T("D:/DepsFile.log") ); m_Deps.SaveAllVars( l_DebFile ); l_DebFile.Write(); l_DebFile.Close(); */ /* return was absent here! */ #ifdef USE_PRINTLOG printLog( _T( "cbMGMakefile::reLoadDependecies" ), _T( "End true" ) ); #endif return true; }