📄 mingw.cpp
字号:
/*
* Copyright (C) 2005 Casper S. Hornstrup
* 2006 Christoph von Wittich
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "../../pch.h"
#include "mingw.h"
#include <assert.h>
#include "modulehandler.h"
#ifdef _MSC_VER
#define popen _popen
#define pclose _pclose
#endif//_MSC_VER
using std::string;
using std::vector;
using std::set;
using std::map;
typedef set<string> set_string;
string
v2s ( const string_list& v, int wrap_at )
{
if ( !v.size() )
return "";
string s;
int wrap_count = 0;
for ( size_t i = 0; i < v.size(); i++ )
{
if ( !v[i].size() )
continue;
if ( wrap_at > 0 && wrap_count++ == wrap_at )
s += " \\\n\t\t";
else if ( s.size() )
s += " ";
s += v[i];
}
return s;
}
static class MingwFactory : public Backend::Factory
{
public:
MingwFactory() : Factory ( "mingw", "Minimalist GNU Win32" ) {}
Backend* operator() ( Project& project,
Configuration& configuration )
{
return new MingwBackend ( project,
configuration );
}
} factory;
MingwBackend::MingwBackend ( Project& project,
Configuration& configuration )
: Backend ( project, configuration ),
manualBinutilsSetting( false ),
intermediateDirectory ( new Directory ("$(INTERMEDIATE)" ) ),
outputDirectory ( new Directory ( "$(OUTPUT)" ) ),
installDirectory ( new Directory ( "$(INSTALL)" ) )
{
compilerPrefix = "";
}
MingwBackend::~MingwBackend()
{
delete intermediateDirectory;
delete outputDirectory;
delete installDirectory;
}
string
MingwBackend::AddDirectoryTarget ( const string& directory,
Directory* directoryTree )
{
if ( directory.length () > 0)
directoryTree->Add ( directory.c_str() );
return directoryTree->name;
}
bool
MingwBackend::CanEnablePreCompiledHeaderSupportForModule ( const Module& module )
{
if ( !configuration.CompilationUnitsEnabled )
return true;
const vector<CompilationUnit*>& compilationUnits = module.non_if_data.compilationUnits;
size_t i;
for ( i = 0; i < compilationUnits.size (); i++ )
{
CompilationUnit& compilationUnit = *compilationUnits[i];
if ( compilationUnit.files.size () != 1 )
return false;
}
// intentionally make a copy so that we can append more work in
// the middle of processing without having to go recursive
vector<If*> v = module.non_if_data.ifs;
for ( i = 0; i < v.size (); i++ )
{
size_t j;
If& rIf = *v[i];
// check for sub-ifs to add to list
const vector<If*>& ifs = rIf.data.ifs;
for ( j = 0; j < ifs.size (); j++ )
v.push_back ( ifs[j] );
const vector<CompilationUnit*>& compilationUnits = rIf.data.compilationUnits;
for ( j = 0; j < compilationUnits.size (); j++ )
{
CompilationUnit& compilationUnit = *compilationUnits[j];
if ( compilationUnit.files.size () != 1 )
return false;
}
}
return true;
}
void
MingwBackend::ProcessModules ()
{
printf ( "Processing modules..." );
vector<MingwModuleHandler*> v;
size_t i;
for ( i = 0; i < ProjectNode.modules.size (); i++ )
{
Module& module = *ProjectNode.modules[i];
if ( !module.enabled )
continue;
MingwModuleHandler* h = MingwModuleHandler::InstanciateHandler (
module,
this );
h->AddImplicitLibraries ( module );
if ( use_pch && CanEnablePreCompiledHeaderSupportForModule ( module ) )
h->EnablePreCompiledHeaderSupport ();
if ( module.host == HostDefault )
{
module.host = h->DefaultHost();
assert ( module.host != HostDefault );
}
v.push_back ( h );
}
size_t iend = v.size ();
for ( i = 0; i < iend; i++ )
v[i]->GenerateObjectMacro();
fprintf ( fMakefile, "\n" );
for ( i = 0; i < iend; i++ )
v[i]->GenerateTargetMacro();
fprintf ( fMakefile, "\n" );
GenerateAllTarget ( v );
GenerateInitTarget ();
GenerateRegTestsRunTarget ();
for ( i = 0; i < iend; i++ )
v[i]->GenerateOtherMacros();
for ( i = 0; i < iend; i++ )
{
MingwModuleHandler& h = *v[i];
h.GeneratePreconditionDependencies ();
h.Process ();
h.GenerateInvocations ();
h.GenerateCleanTarget ();
h.GenerateInstallTarget ();
h.GenerateDependsTarget ();
delete v[i];
}
printf ( "done\n" );
}
void
MingwBackend::Process ()
{
if ( configuration.CheckDependenciesForModuleOnly )
CheckAutomaticDependenciesForModuleOnly ();
else
ProcessNormal ();
}
void
MingwBackend::CheckAutomaticDependenciesForModuleOnly ()
{
if ( configuration.AutomaticDependencies )
{
Module* module = ProjectNode.LocateModule ( configuration.CheckDependenciesForModuleOnlyModule );
if ( module == NULL )
{
printf ( "Module '%s' does not exist\n",
configuration.CheckDependenciesForModuleOnlyModule.c_str () );
return;
}
printf ( "Checking automatic dependencies for module '%s'...",
module->name.c_str () );
AutomaticDependency automaticDependency ( ProjectNode );
automaticDependency.CheckAutomaticDependenciesForModule ( *module,
configuration.Verbose );
printf ( "done\n" );
}
}
void
MingwBackend::ProcessNormal ()
{
DetectCompiler ();
DetectBinutils ();
DetectNetwideAssembler ();
DetectPipeSupport ();
DetectPCHSupport ();
CreateMakefile ();
GenerateHeader ();
GenerateGlobalVariables ();
GenerateXmlBuildFilesMacro ();
UnpackWineResources ();
ProcessModules ();
GenerateInstallTarget ();
GenerateTestTarget ();
GenerateDirectoryTargets ();
GenerateDirectories ();
GenerateTestSupportCode ();
GenerateCompilationUnitSupportCode ();
GenerateSysSetup ();
GenerateProxyMakefiles ();
CheckAutomaticDependencies ();
CloseMakefile ();
}
void
MingwBackend::CreateMakefile ()
{
fMakefile = fopen ( ProjectNode.makefile.c_str (), "w" );
if ( !fMakefile )
throw AccessDeniedException ( ProjectNode.makefile );
MingwModuleHandler::SetBackend ( this );
MingwModuleHandler::SetMakefile ( fMakefile );
}
void
MingwBackend::CloseMakefile () const
{
if (fMakefile)
fclose ( fMakefile );
}
void
MingwBackend::GenerateHeader () const
{
fprintf ( fMakefile, "# THIS FILE IS AUTOMATICALLY GENERATED, EDIT '%s' INSTEAD\n\n",
ProjectNode.GetProjectFilename ().c_str () );
}
string
MingwBackend::GenerateIncludesAndDefines ( IfableData& data ) const
{
string includeParameters = MingwModuleHandler::GenerateGccIncludeParametersFromVector ( data.includes );
string defineParameters = MingwModuleHandler::GenerateGccDefineParametersFromVector ( data.defines );
return includeParameters + " " + defineParameters;
}
void
MingwBackend::GenerateProjectCFlagsMacro ( const char* assignmentOperation,
IfableData& data ) const
{
fprintf (
fMakefile,
"PROJECT_CFLAGS %s",
assignmentOperation );
fprintf ( fMakefile,
" %s",
GenerateIncludesAndDefines ( data ).c_str() );
fprintf ( fMakefile, "\n" );
}
void
MingwBackend::GenerateGlobalCFlagsAndProperties (
const char* assignmentOperation,
IfableData& data ) const
{
size_t i;
for ( i = 0; i < data.properties.size(); i++ )
{
Property& prop = *data.properties[i];
fprintf ( fMakefile, "%s := %s\n",
prop.name.c_str(),
prop.value.c_str() );
}
if ( data.includes.size() || data.defines.size() )
{
GenerateProjectCFlagsMacro ( assignmentOperation,
data );
}
for ( i = 0; i < data.ifs.size(); i++ )
{
If& rIf = *data.ifs[i];
if ( rIf.data.defines.size()
|| rIf.data.includes.size()
|| rIf.data.ifs.size() )
{
fprintf (
fMakefile,
"ifeq (\"$(%s)\",\"%s\")\n",
rIf.property.c_str(),
rIf.value.c_str() );
GenerateGlobalCFlagsAndProperties (
"+=",
rIf.data );
fprintf (
fMakefile,
"endif\n\n" );
}
}
}
void
MingwBackend::GenerateProjectGccOptionsMacro ( const char* assignmentOperation,
IfableData& data ) const
{
size_t i;
fprintf (
fMakefile,
"PROJECT_GCCOPTIONS %s",
assignmentOperation );
for ( i = 0; i < data.compilerFlags.size(); i++ )
{
fprintf (
fMakefile,
" %s",
data.compilerFlags[i]->flag.c_str() );
}
fprintf ( fMakefile, "\n" );
}
void
MingwBackend::GenerateProjectGccOptions (
const char* assignmentOperation,
IfableData& data ) const
{
size_t i;
if ( data.compilerFlags.size() )
{
GenerateProjectGccOptionsMacro ( assignmentOperation,
data );
}
for ( i = 0; i < data.ifs.size(); i++ )
{
If& rIf = *data.ifs[i];
if ( rIf.data.compilerFlags.size()
|| rIf.data.ifs.size() )
{
fprintf (
fMakefile,
"ifeq (\"$(%s)\",\"%s\")\n",
rIf.property.c_str(),
rIf.value.c_str() );
GenerateProjectGccOptions (
"+=",
rIf.data );
fprintf (
fMakefile,
"endif\n\n" );
}
}
}
string
MingwBackend::GenerateProjectLFLAGS () const
{
string lflags;
for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
{
LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
if ( lflags.length () > 0 )
lflags += " ";
lflags += linkerFlag.flag;
}
return lflags;
}
void
MingwBackend::GenerateGlobalVariables () const
{
fprintf ( fMakefile,
"PREFIX := %s\n",
compilerPrefix.c_str () );
fprintf ( fMakefile,
"nasm := %s\n",
nasmCommand.c_str () );
GenerateGlobalCFlagsAndProperties ( "=", ProjectNode.non_if_data );
GenerateProjectGccOptions ( "=", ProjectNode.non_if_data );
fprintf ( fMakefile, "PROJECT_RCFLAGS := $(PROJECT_CFLAGS)\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -