Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}