📄 makefilegenerator.cpp
字号:
/*
* 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 + -