⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 makefilegenerator.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*
* This file is part of Code::Blocks Studio, an open-source cross-platform IDE
* Copyright (C) 2003  Yiannis An. Mandravellos
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
* Contact e-mail: Yiannis An. Mandravellos <mandrav@codeblocks.org>
* Program URL   : http://www.codeblocks.org
*
* $Id: makefilegenerator.cpp,v 1.60.2.1 2005/10/25 07:59:01 mandrav Exp $
* $Date: 2005/10/25 07:59:01 $
*/

#include <sdk.h>
#include "makefilegenerator.h" // class's header file
#include <manager.h>
#include <macrosmanager.h>
#include <messagemanager.h>
#include <wx/file.h>
#include <compilerfactory.h>
#include <customvars.h>

// TODO (mandrav#1#): Fix Makefile for targets using different compilers

// class constructor
MakefileGenerator::MakefileGenerator(CompilerGCC* compiler, cbProject* project, const wxString& makefile, int logIndex)
    : m_Compiler(compiler),
    m_CompilerSet(CompilerFactory::Compilers[compiler->GetCurrentCompilerIndex()]),
	m_Project(project),
    m_Makefile(makefile),
    m_LogIndex(logIndex),
    m_GeneratingMakefile(false)
{
}

// class destructor
MakefileGenerator::~MakefileGenerator()
{
}

void MakefileGenerator::UpdateCompiler(ProjectBuildTarget* target)
{
    int idx = target
                ? target->GetCompilerIndex()
                : (m_Project ? m_Project->GetCompilerIndex() : -1);
    if (idx != -1)
        m_CompilerSet = CompilerFactory::Compilers[idx];
    else
        m_CompilerSet = CompilerFactory::GetDefaultCompiler();
}

wxString MakefileGenerator::ReplaceCompilerMacros(CommandType et,
                                                const wxString& compilerVar,
                                                ProjectBuildTarget* target,
                                                const wxString& file,
                                                const wxString& object,
                                                const wxString& deps)
{
    wxString compilerCmd;
    UpdateCompiler(target);
    compilerCmd = m_CompilerSet->GetCommand(et);

    compilerCmd.Replace(_T("$compiler"), _T("$(") + target->GetTitle() + _T("_") + compilerVar + _T(")"));
    compilerCmd.Replace(_T("$linker"), _T("$(") + target->GetTitle() + _T("_LD)"));
    compilerCmd.Replace(_T("$lib_linker"), _T("$(") + target->GetTitle() + _T("_LIB)"));
    compilerCmd.Replace(_T("$rescomp"), _T("$(") + target->GetTitle() + _T("_RESCOMP)"));
    compilerCmd.Replace(_T("$options"), _T("$(") + target->GetTitle() + _T("_CFLAGS)"));
    compilerCmd.Replace(_T("$link_options"), _T("$(") + target->GetTitle() + _T("_LDFLAGS)"));
    compilerCmd.Replace(_T("$includes"), _T("$(") + target->GetTitle() + _T("_INCS)"));
    compilerCmd.Replace(_T("$libdirs"), _T("$(") + target->GetTitle() + _T("_LIBDIRS)"));
    compilerCmd.Replace(_T("$libs"), _T("$(") + target->GetTitle() + _T("_LIBS)"));
    compilerCmd.Replace(_T("$file"), file);
    compilerCmd.Replace(_T("$objects"), _T("$(") + target->GetTitle() + _T("_OBJS)"));
    compilerCmd.Replace(_T("$dep_object"), deps);
    compilerCmd.Replace(_T("$object"), object);
    compilerCmd.Replace(_T("$link_objects"), _T("$(") + target->GetTitle() + _T("_LINKOBJS)"));
    compilerCmd.Replace(_T("$link_resobjects"), _T("$(") + target->GetTitle() + _T("_RESOURCE)"));
    compilerCmd.Replace(_T("$exe_output"), _T("$(") + target->GetTitle() + _T("_BIN)"));
    if (target->GetTargetType() == ttStaticLib)
        compilerCmd.Replace(_T("$static_output"), _T("$(") + target->GetTitle() + _T("_BIN)"));
    else if (target->GetTargetType() == ttDynamicLib && target->GetCreateStaticLib())
        compilerCmd.Replace(_T("$static_output"), _T("$(") + target->GetTitle() + _T("_STATIC_LIB)"));
    else
        compilerCmd.Replace(_T("-Wl,--out-implib=$static_output"), _T(""));
    if (target->GetTargetType() == ttDynamicLib && target->GetCreateStaticLib())
        compilerCmd.Replace(_T("$def_output"), _T("$(") + target->GetTitle() + _T("_LIB_DEF)"));
    else
        compilerCmd.Replace(_T("-Wl,--output-def=$def_output"), _T(""));
    compilerCmd.Replace(_T("$resource_output"), _T("$(") + target->GetTitle() + _T("_RESOURCE)"));

    int idx = compilerCmd.Find(_T("$res_includes"));
    if (idx != -1)
    {
        wxString incs;
        DoAppendResourceIncludeDirs(incs, 0L, m_CompilerSet->GetSwitches().includeDirs, true);
        DoAppendResourceIncludeDirs(incs, 0L, m_CompilerSet->GetSwitches().includeDirs);
        DoAppendResourceIncludeDirs(incs, target, m_CompilerSet->GetSwitches().includeDirs);
        compilerCmd.Replace(_T("$res_includes"), incs);
    }

    return compilerCmd;
}

wxString MakefileGenerator::CreateSingleFileCompileCmd(CommandType et,
                                                        ProjectBuildTarget* target,
                                                        ProjectFile* pf,
                                                        const wxString& file,
                                                        const wxString& object,
                                                        const wxString& deps)
{
    UpdateCompiler(target);
    return CreateSingleFileCompileCmd(m_CompilerSet->GetCommand(et), target, pf, file, object, deps);
}

wxString MakefileGenerator::CreateSingleFileCompileCmd(const wxString& command,
                                                        ProjectBuildTarget* target,
                                                        ProjectFile* pf,
                                                        const wxString& file,
                                                        const wxString& object,
                                                        const wxString& deps)
{
    // in case of linking command, deps has resource objects
    UpdateCompiler(target);

    wxString compilerStr;
    if (pf)
    {
        if (pf->compilerVar.Matches(_T("CPP")))
            compilerStr = m_CompilerSet->GetPrograms().CPP;
        else if (pf->compilerVar.Matches(_T("CC")))
            compilerStr = m_CompilerSet->GetPrograms().C;
        else if (pf->compilerVar.Matches(_T("WINDRES")))
            compilerStr = m_CompilerSet->GetPrograms().WINDRES;
        else
            return wxEmptyString; // unknown compiler var
    }
    else
    {
    	wxFileName fname(file);
    	if (fname.GetExt().Lower().Matches(_T("c")))
            compilerStr = m_CompilerSet->GetPrograms().C;
        else
            compilerStr = m_CompilerSet->GetPrograms().CPP;
    }

    wxString cflags;
    wxString global_cflags;
	wxString prj_cflags;
	DoAppendCompilerOptions(global_cflags, 0L, true);
	DoAppendCompilerOptions(prj_cflags, 0L);
    DoGetMakefileCFlags(cflags, target);
    if (target)
    {
        cflags.Replace(_T("$(") + target->GetTitle() + _T("_GLOBAL_CFLAGS)"), global_cflags);
        cflags.Replace(_T("$(") + target->GetTitle() + _T("_PROJECT_CFLAGS)"), prj_cflags);
    }
    else if (!target && !pf) // probably single file compilation
        cflags = global_cflags;

    wxString ldflags;
	wxString global_ldflags;
	wxString prj_ldflags;
	DoAppendLinkerOptions(global_ldflags, 0L, true);
	DoAppendLinkerOptions(prj_ldflags, 0L);
	DoGetMakefileLDFlags(ldflags, target);
    if (target)
    {
        ldflags.Replace(_T("$(") + target->GetTitle() + _T("_GLOBAL_LDFLAGS)"), global_ldflags);
        ldflags.Replace(_T("$(") + target->GetTitle() + _T("_PROJECT_LDFLAGS)"), prj_ldflags);
    }
    else if (!target && !pf) // probably single file compilation
        ldflags = global_ldflags;

    wxString ldadd;
	wxString global_ldadd;
	wxString prj_ldadd;
	DoAppendLinkerLibs(global_ldadd, 0L, true);
	DoAppendLinkerLibs(prj_ldadd, 0L);
	DoGetMakefileLibs(ldadd, target);
    if (target)
    {
        ldadd.Replace(_T("$(") + target->GetTitle() + _T("_GLOBAL_LIBS)"), global_ldadd);
        ldadd.Replace(_T("$(") + target->GetTitle() + _T("_PROJECT_LIBS)"), prj_ldadd);
    }
    else if (!target && !pf) // probably single file compilation
        ldadd = global_ldadd;

	wxString global_res_incs;
	wxString prj_res_incs;
	wxString res_incs;
	DoAppendResourceIncludeDirs(global_res_incs, 0L, m_CompilerSet->GetSwitches().includeDirs, true);
	DoAppendResourceIncludeDirs(prj_res_incs, 0L, m_CompilerSet->GetSwitches().includeDirs);
	res_incs << global_res_incs << _T(" ") << prj_res_incs << _T(" ");
	DoAppendResourceIncludeDirs(res_incs, target, m_CompilerSet->GetSwitches().includeDirs);

    wxString incs;
	wxString global_incs;
	wxString prj_incs;
	DoAppendIncludeDirs(global_incs, 0L, m_CompilerSet->GetSwitches().includeDirs, true);
	DoAppendIncludeDirs(prj_incs, 0L, m_CompilerSet->GetSwitches().includeDirs);
	DoGetMakefileIncludes(incs, target);
    if (target)
    {
        incs.Replace(_T("$(") + target->GetTitle() + _T("_GLOBAL_INCS)"), global_incs);
        incs.Replace(_T("$(") + target->GetTitle() + _T("_PROJECT_INCS)"), prj_incs);
    }
    else if (!target && !pf) // probably single file compilation
        incs = global_incs;

    wxString libs;
	wxString global_libs;
	wxString prj_libs;
	DoAppendLibDirs(global_libs, 0L, m_CompilerSet->GetSwitches().libDirs, true);
	DoAppendLibDirs(prj_libs, 0L, m_CompilerSet->GetSwitches().libDirs);
	DoGetMakefileLibDirs(libs, target);
    if (target)
    {
        libs.Replace(_T("$(") + target->GetTitle() + _T("_GLOBAL_LIBDIRS)"), global_libs);
        libs.Replace(_T("$(") + target->GetTitle() + _T("_PROJECT_LIBDIRS)"), prj_libs);
    }
    else if (!target && !pf) // probably single file compilation
        libs = global_libs;

    wxString output;
    if (target)
        output = UnixFilename(target->GetOutputFilename());
    else
    {
        wxString object_unquoted(object);
        if (!object_unquoted.IsEmpty() && object_unquoted.GetChar(0) == '"')
            object_unquoted.Replace(_T("\""), _T(""));
        wxFileName fname(object_unquoted);
        fname.SetExt(EXECUTABLE_EXT);
        output = fname.GetFullPath();
    }
    Manager::Get()->GetMacrosManager()->ReplaceEnvVars(output);
    ConvertToMakefileFriendly(output);
    QuoteStringIfNeeded(output);

    wxString linkobjs;

    wxString compilerCmd = command;
    compilerCmd.Replace(_T("$compiler"), compilerStr);
    compilerCmd.Replace(_T("$linker"), m_CompilerSet->GetPrograms().LD);
    compilerCmd.Replace(_T("$lib_linker"), m_CompilerSet->GetPrograms().LIB);
    compilerCmd.Replace(_T("$rescomp"), m_CompilerSet->GetPrograms().WINDRES);
    compilerCmd.Replace(_T("$options"), cflags);
    compilerCmd.Replace(_T("$link_options"), ldflags);
    compilerCmd.Replace(_T("$includes"), incs);
    compilerCmd.Replace(_T("$res_includes"), res_incs);
    compilerCmd.Replace(_T("$libdirs"), libs);
    compilerCmd.Replace(_T("$libs"), ldadd);
    compilerCmd.Replace(_T("$file"), file);
    compilerCmd.Replace(_T("$dep_object"), deps);
    compilerCmd.Replace(_T("$object"), object);
    compilerCmd.Replace(_T("$exe_output"), output);
    compilerCmd.Replace(_T("$resource_output"), object);
    compilerCmd.Replace(_T("$link_resobjects"), deps);
    compilerCmd.Replace(_T("$link_objects"), object);
    // the following were added to support the QUICK HACK
    // at directcommands.cpp:576
    compilerCmd.Replace(_T("$+link_objects"), object);
    compilerCmd.Replace(_T("$-link_objects"), object);
    compilerCmd.Replace(_T("$-+link_objects"), object);
    compilerCmd.Replace(_T("$+-link_objects"), object);

    if (target && (target->GetTargetType() == ttStaticLib || target->GetTargetType() == ttDynamicLib))
    {
        wxFileName fname(target->GetOutputFilename());
        if (!fname.GetName().StartsWith(m_CompilerSet->GetSwitches().libPrefix))
            fname.SetName(m_CompilerSet->GetSwitches().libPrefix + fname.GetName());
        fname.SetExt(m_CompilerSet->GetSwitches().libExtension);
        wxString out = UnixFilename(fname.GetFullPath());
        ConvertToMakefileFriendly(out);
        QuoteStringIfNeeded(out);
        if (target->GetTargetType() == ttStaticLib || target->GetCreateStaticLib())
            compilerCmd.Replace(_T("$static_output"), out);
        else
        {
            compilerCmd.Replace(_T("-Wl,--out-implib=$static_output"), _T("")); // special gcc case
            compilerCmd.Replace(_T("$static_output"), _T(""));
        }
        if (target->GetCreateDefFile())
        {
            fname.SetExt(_T("def"));
            out = UnixFilename(fname.GetFullPath());
            ConvertToMakefileFriendly(out);
            QuoteStringIfNeeded(out);
            compilerCmd.Replace(_T("$def_output"), out);
        }
        else
        {
            compilerCmd.Replace(_T("-Wl,--output-def=$def_output"), _T("")); // special gcc case
            compilerCmd.Replace(_T("$def_output"), _T(""));
        }
    }
    return compilerCmd;
}

void MakefileGenerator::DoAppendCompilerOptions(wxString& cmd, ProjectBuildTarget* target, bool useGlobalOptions)
{
    wxArrayString opts;
    if (!m_CompilerSet)
        return;
	if (useGlobalOptions)
		opts = m_CompilerSet->GetCompilerOptions();
	else
	{
		if (target)
			opts = target->GetCompilerOptions();
		else
			opts = m_Project ? m_Project->GetCompilerOptions() : m_CompilerSet->GetCompilerOptions();
	}

    for (unsigned int x = 0; x < opts.GetCount(); ++x)
    {
    	if (!m_GeneratingMakefile)
            Manager::Get()->GetMacrosManager()->ReplaceEnvVars(opts[x]);
        cmd << _T(" ") << opts[x];
    }
}

void MakefileGenerator::DoAppendLinkerOptions(wxString& cmd, ProjectBuildTarget* target, bool useGlobalOptions)
{
    CompileOptionsBase* obj;
    if (!m_CompilerSet)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -