* 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.
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "pch.h"
#include <assert.h>
{
}
-void IfableData::ExtractModules( std::vector<Module*> &modules )
+void IfableData::ExtractModules( std::map<std::string, Module*> &modules )
{
size_t i;
for ( i = 0; i < this->modules.size (); i++ )
- modules.push_back(this->modules[i]);
+ modules.insert(std::make_pair(this->modules[i]->name, this->modules[i]));
}
IfableData::~IfableData()
delete defines[i];
for ( i = 0; i < libraries.size (); i++ )
delete libraries[i];
- for ( i = 0; i < properties.size (); i++ )
- delete properties[i];
+ for ( std::map<std::string, Property*>::const_iterator p = properties.begin(); p != properties.end(); ++ p )
+ delete p->second;
for ( i = 0; i < compilerFlags.size (); i++ )
delete compilerFlags[i];
for ( i = 0; i < modules.size(); i++ )
defines[i]->ProcessXML ();
for ( i = 0; i < libraries.size (); i++ )
libraries[i]->ProcessXML ();
- for ( i = 0; i < properties.size(); i++ )
- properties[i]->ProcessXML ();
+ for ( std::map<std::string, Property*>::const_iterator p = properties.begin(); p != properties.end(); ++ p )
+ p->second->ProcessXML ();
for ( i = 0; i < compilerFlags.size(); i++ )
compilerFlags[i]->ProcessXML ();
for ( i = 0; i < compilationUnits.size (); i++ )
compilationUnits[i]->ProcessXML ();
}
+bool Module::GetBooleanAttribute ( const XMLElement& moduleNode, const char * name, bool default_value )
+{
+ const XMLAttribute* att = moduleNode.GetAttribute ( name, false );
+ if ( att != NULL )
+ {
+ const char* p = att->value.c_str();
+ if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
+ return true;
+ else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
+ return false;
+ else
+ {
+ throw InvalidAttributeValueException (
+ moduleNode.location,
+ name,
+ att->value );
+ }
+ }
+ else
+ return default_value;
+}
+
Module::Module ( const Project& project,
const XMLElement& moduleNode,
const string& modulePath )
: project (project),
node (moduleNode),
importLibrary (NULL),
+ delayImportLibrary (NULL),
metadata (NULL),
bootSector (NULL),
bootstrap (NULL),
else
extension = GetDefaultModuleExtension ();
- att = moduleNode.GetAttribute ( "unicode", false );
- if ( att != NULL )
- {
- const char* p = att->value.c_str();
- if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
- isUnicode = true;
- else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
- isUnicode = false;
- else
- {
- throw InvalidAttributeValueException (
- moduleNode.location,
- "unicode",
- att->value );
- }
- }
- else
- isUnicode = false;
+ isUnicode = GetBooleanAttribute ( moduleNode, "unicode" );
if (isUnicode)
{
else
baseaddress = GetDefaultModuleBaseaddress ();
- att = moduleNode.GetAttribute ( "mangledsymbols", false );
- if ( att != NULL )
+ isStartupLib = GetBooleanAttribute ( moduleNode, "isstartuplib" );
+ isCRT = GetBooleanAttribute ( moduleNode, "iscrt", GetDefaultModuleIsCRT () );
+
+ att = moduleNode.GetAttribute ( "crt", false );
+ if ( att != NULL)
{
- const char* p = att->value.c_str();
- if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
- mangledSymbols = true;
- else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
- mangledSymbols = false;
- else
- {
- throw InvalidAttributeValueException (
- moduleNode.location,
- "mangledsymbols",
- att->value );
- }
+ CRT = att->value;
+
+ if ( stricmp ( CRT.c_str (), "auto" ) == 0 )
+ CRT = GetDefaultModuleCRT ();
}
else
- mangledSymbols = false;
-
- att = moduleNode.GetAttribute ( "underscoresymbols", false );
- if ( att != NULL )
- underscoreSymbols = att->value == "true";
+ CRT = GetDefaultModuleCRT ();
+
+ const char * crtAttr = CRT.c_str ();
+ if ( crtAttr == NULL || stricmp ( crtAttr, "none" ) == 0 )
+ dynamicCRT = false;
+ else if ( stricmp ( crtAttr, "libc" ) == 0 )
+ dynamicCRT = false;
+ else if ( stricmp ( crtAttr, "msvcrt" ) == 0 )
+ dynamicCRT = true;
+ else if ( stricmp ( crtAttr, "libcntpr" ) == 0 )
+ dynamicCRT = false;
+ else if ( stricmp ( crtAttr, "ntdll" ) == 0 )
+ dynamicCRT = true;
+ else if ( stricmp ( crtAttr, "static" ) == 0 )
+ dynamicCRT = false;
+ else if ( stricmp ( crtAttr, "dll" ) == 0 )
+ dynamicCRT = true;
else
- underscoreSymbols = false;
+ {
+ throw InvalidAttributeValueException (
+ moduleNode.location,
+ "crt",
+ std::string ( crtAttr ) );
+ }
- att = moduleNode.GetAttribute ( "isstartuplib", false );
- if ( att != NULL )
+ if ( isCRT && dynamicCRT )
{
- const char* p = att->value.c_str();
- if ( !stricmp ( p, "true" ) || !stricmp ( p, "yes" ) )
- isStartupLib = true;
- else if ( !stricmp ( p, "false" ) || !stricmp ( p, "no" ) )
- isStartupLib = false;
- else
- {
- throw InvalidAttributeValueException (
- moduleNode.location,
- "isstartuplib",
- att->value );
- }
+ throw XMLInvalidBuildFileException (
+ moduleNode.location,
+ "C runtime module '%s' cannot be compiled for a dynamically-linked C runtime",
+ name.c_str() );
}
- else
- isStartupLib = false;
att = moduleNode.GetAttribute ( "prefix", false );
if ( att != NULL )
}
if ( att != NULL )
allowWarnings = att->value == "true";
+ else if ( project.allowWarningsSet )
+ allowWarnings = project.allowWarnings;
else
allowWarnings = false;
delete linkerFlags[i];
for ( i = 0; i < stubbedComponents.size(); i++ )
delete stubbedComponents[i];
+ for ( i = 0; i < cdfiles.size (); i++ )
+ delete cdfiles[i];
if ( linkerScript )
delete linkerScript;
if ( pch )
if ( autoRegister )
delete autoRegister;
if ( output )
- delete output;
+ delete output;
}
void
const string& relative_path,
ParseContext& parseContext )
{
+ const XMLAttribute* att;
+
+ att = e.GetAttribute ( "compilerset", false );
+
+ if ( att )
+ {
+ CompilerSet compilerSet;
+
+ if ( att->value == "msc" )
+ compilerSet = MicrosoftC;
+ else if ( att->value == "gcc" )
+ compilerSet = GnuGcc;
+ else
+ throw InvalidAttributeValueException (
+ e.location,
+ "compilerset",
+ att->value );
+
+ if ( compilerSet != project.configuration.Compiler )
+ return;
+ }
+
+ att = e.GetAttribute ( "linkerset", false );
+
+ if ( att )
+ {
+ LinkerSet linkerSet;
+
+ if ( att->value == "mslink" )
+ linkerSet = MicrosoftLink;
+ else if ( att->value == "ld" )
+ linkerSet = GnuLd;
+ else
+ throw InvalidAttributeValueException (
+ e.location,
+ "linkerset",
+ att->value );
+
+ if ( linkerSet != project.configuration.Linker )
+ return;
+ }
+
CompilationUnit* pOldCompilationUnit = parseContext.compilationUnit;
bool subs_invalid = false;
string subpath ( relative_path );
}
else if ( e.name == "library" && e.value.size () )
{
+ const XMLAttribute* att = e.GetAttribute ( "delayimport", false );
Library* pLibrary = new Library ( e, *this, e.value );
+ if ( att && !stricmp ( att->value.c_str(), "true" ) )
+ pLibrary->delayimp = true;
non_if_data.libraries.push_back ( pLibrary );
subs_invalid = true;
}
non_if_data.includes.push_back ( include );
subs_invalid = true;
}
- else if ( e.name == "define" )
+ else if ( e.name == "define" || e.name == "redefine" )
{
Define* pDefine = new Define ( project, this, e );
non_if_data.defines.push_back ( pDefine );
e.location,
"Only one <importlibrary> is valid per module" );
}
- SetImportLibrary ( new ImportLibrary ( project, e, this ) );
+ SetImportLibrary ( new ImportLibrary ( project, e, this, false ) );
+ SetDelayImportLibrary ( new ImportLibrary ( project, e, this, true ) );
subs_invalid = true;
}
else if ( e.name == "if" || e.name == "ifnot" )
name = e.GetAttribute ( "property", true );
assert( name );
const Property *property = project.LookupProperty( name->value );
- if ( !property )
+ const string *PropertyValue;
+ const string EmptyString;
+
+ if (property)
{
- // Property not found
- throw InvalidOperationException ( __FILE__,
- __LINE__,
- "Test on unknown property '%s' at %s",
- name->value.c_str (), e.location.c_str () );
+ PropertyValue = &property->value;
+ }
+ else
+ {
+ // Property does not exist, treat it as being empty
+ PropertyValue = &EmptyString;
}
const XMLAttribute* value;
assert( value );
bool negate = ( e.name == "ifnot" );
- bool equality = ( property->value == value->value );
+ bool equality = ( *PropertyValue == value->value );
if ( equality == negate )
{
// Failed, skip this element
autoRegister = new AutoRegister ( project, this, e );
subs_invalid = true;
}
+ else if ( e.name == "cdfile" )
+ {
+ CDFile* cdfile = new CDFile ( project, e, subpath );
+ cdfiles.push_back ( cdfile );
+ subs_invalid = true;
+ }
if ( subs_invalid && e.subElements.size() > 0 )
{
throw XMLInvalidBuildFileException (
"<%s> cannot have sub-elements",
e.name.c_str() );
}
+ for ( size_t i = 0; i < cdfiles.size (); i++ )
+ cdfiles[i]->ProcessXML ();
for ( size_t i = 0; i < e.subElements.size (); i++ )
ProcessXMLSubElement ( *e.subElements[i], subdirectory, subpath, parseContext );
parseContext.compilationUnit = pOldCompilationUnit;
return Iso;
if ( attribute.value == "liveiso" )
return LiveIso;
- if ( attribute.value == "isoregtest" )
- return IsoRegTest;
- if ( attribute.value == "liveisoregtest" )
- return LiveIsoRegTest;
if ( attribute.value == "test" )
return Test;
if ( attribute.value == "rpcserver" )
return Alias;
if ( attribute.value == "idlheader" )
return IdlHeader;
+ if ( attribute.value == "idlinterface" )
+ return IdlInterface;
if ( attribute.value == "embeddedtypelib" )
return EmbeddedTypeLib;
if ( attribute.value == "elfexecutable" )
case BootProgram:
case Iso:
case LiveIso:
- case IsoRegTest:
- case LiveIsoRegTest:
case ElfExecutable:
case Cabinet:
return OutputDirectory;
case RpcProxy:
case Alias:
case IdlHeader:
+ case IdlInterface:
case MessageHeader:
return IntermediateDirectory;
case TypeDontCare:
return ".o";
case Iso:
case LiveIso:
- case IsoRegTest:
- case LiveIsoRegTest:
return ".iso";
case Test:
return ".exe";
case RpcServer:
case RpcClient:
case RpcProxy:
+ case IdlInterface:
return ".o";
case Alias:
case ElfExecutable:
switch ( type )
{
case Kernel:
- return "KiSystemStartup";
+ if (Environment::GetArch() == "arm") return "KiSystemStartup";
+ return "KiSystemStartup@4";
case KeyboardLayout:
case KernelModeDLL:
case KernelModeDriver:
return "DllMainCRTStartup@12";
case NativeCUI:
if (Environment::GetArch() == "arm") return "NtProcessStartup";
- return "NtProcessStartup@4";
+ return "NtProcessStartup@4";
case Win32DLL:
case Win32OCX:
if (Environment::GetArch() == "arm") return "DllMain";
return "DllMain@12";
case Win32CUI:
case Test:
- if ( isUnicode )
- return "wmainCRTStartup";
- else
- return "mainCRTStartup";
+ return "mainCRTStartup";
case Win32SCR:
case Win32GUI:
- if ( isUnicode )
- return "wWinMainCRTStartup";
- else
- return "WinMainCRTStartup";
+ return "WinMainCRTStartup";
case BuildTool:
case StaticLibrary:
case HostStaticLibrary:
case BootSector:
case Iso:
case LiveIso:
- case IsoRegTest:
- case LiveIsoRegTest:
case RpcServer:
case RpcClient:
case RpcProxy:
case Alias:
case BootProgram:
case IdlHeader:
+ case IdlInterface:
case MessageHeader:
case ElfExecutable:
case EmbeddedTypeLib:
case BootSector:
case Iso:
case LiveIso:
- case IsoRegTest:
- case LiveIsoRegTest:
case RpcServer:
case RpcClient:
case RpcProxy:
case Alias:
case BootProgram:
case IdlHeader:
+ case IdlInterface:
case MessageHeader:
case EmbeddedTypeLib:
case Cabinet:
__LINE__ );
}
+std::string
+Module::GetDefaultModuleCRT () const
+{
+ if ( isCRT )
+ return "static";
+
+ switch ( type )
+ {
+ case Kernel:
+ return "static";
+ case Win32DLL:
+ case Win32OCX:
+ return "ntdll";
+ case NativeDLL:
+ case NativeCUI:
+ return "ntdll";
+ case Win32CUI:
+ case Win32SCR:
+ case Win32GUI:
+ return "msvcrt";
+ case Test:
+ return "msvcrt"; // BUGBUG: not sure about this
+ case KeyboardLayout:
+ return "none";
+ case KernelModeDLL:
+ case KernelModeDriver:
+ return "dll";
+ case BootLoader:
+ return "libcntpr";
+ case ElfExecutable:
+ case BuildTool:
+ case StaticLibrary:
+ case HostStaticLibrary:
+ case ObjectLibrary:
+ case BootSector:
+ case Iso:
+ case LiveIso:
+ case RpcServer:
+ case RpcClient:
+ case RpcProxy:
+ case Alias:
+ case BootProgram:
+ case IdlHeader:
+ case IdlInterface:
+ case MessageHeader:
+ case EmbeddedTypeLib:
+ case Cabinet:
+ case TypeDontCare:
+ return "none";
+ }
+ throw InvalidOperationException ( __FILE__,
+ __LINE__ );
+}
+
+bool
+Module::GetDefaultModuleIsCRT () const
+{
+ return type == Kernel;
+}
+
bool
Module::HasImportLibrary () const
{
case BootProgram:
case Iso:
case LiveIso:
- case IsoRegTest:
- case LiveIsoRegTest:
case RpcServer:
case RpcClient:
case RpcProxy:
case Alias:
case IdlHeader:
+ case IdlInterface:
case MessageHeader:
case EmbeddedTypeLib:
case ElfExecutable:
}
string
-Module::GetEntryPoint(bool leadingUnderscore) const
+Module::GetEntryPoint() const
{
string result = "";
if (entrypoint == "0" || entrypoint == "0x0")
return "0";
- if (leadingUnderscore)
+
+ if (Environment::GetArch() != "arm" && Environment::GetArch() != "amd64")
result = "_";
result += entrypoint;
+
+ if (Environment::GetArch() == "amd64")
+ {
+ size_t at_index = result.find_last_of( '@' );
+ if ( at_index != result.npos )
+ return result.substr (0, at_index );
+ }
+
return result;
}
HasImportLibrary () ? "lib" + name + ".a" : output->name );
}
+void
+Module::SetDelayImportLibrary ( ImportLibrary* importLibrary )
+{
+ this->delayImportLibrary = importLibrary;
+}
+
+std::string
+Module::GetDllName () const
+{
+ if ( importLibrary && !importLibrary->dllname.empty() )
+ return importLibrary->dllname;
+ else if ( output )
+ return output->name;
+ else
+ throw new InvalidOperationException ( __FILE__, __LINE__, "Module %s has no dllname." );
+}
+
+SpecFileType
+Module::IsSpecDefinitionFile () const
+{
+ if(!importLibrary)
+ return None;
+
+ std::string ext = GetExtension ( *importLibrary->source );
+
+ if ( ext == ".spec" )
+ return Spec;
+
+ if ( ext == ".pspec" )
+ return PSpec;
+
+ return None;
+}
+
File::File ( DirectoryLocation directory,
const string& relative_path,
: node(&_node),
module(_module),
name(_name),
- importedModule(_module.project.LocateModule(_name))
+ importedModule(_module.project.LocateModule(_name)),
+ delayimp(false)
{
if ( module.name == name )
{
: node(NULL),
module(_module),
name(_name),
- importedModule(_module.project.LocateModule(_name))
+ importedModule(_module.project.LocateModule(_name)),
+ delayimp(false)
{
+ if ( !importedModule )
+ {
+ throw XMLInvalidBuildFileException (
+ "<internal>",
+ "module '%s' trying to import non-existant module '%s'",
+ module.name.c_str(),
+ name.c_str() );
+ }
}
void
Bootsector::IsSupportedModuleType ( ModuleType type )
{
if ( type == Iso ||
- type == LiveIso ||
- type == IsoRegTest ||
- type == LiveIsoRegTest )
+ type == LiveIso )
{
return true;
}
ImportLibrary::~ImportLibrary ()
{
delete source;
+ delete target;
}
ImportLibrary::ImportLibrary ( const Project& project,
const XMLElement& node,
- const Module* module )
+ const Module* module,
+ bool delayimp )
: XmlNode ( project, node ),
module (module)
{
"root",
att->value );
}
- else
- {
- size_t index = definition->value.rfind ( ".spec.def" );
- if ( index != string::npos )
- directory = IntermediateDirectory;
- }
if ( dllname )
this->dllname = dllname->value;
- else if ( module->type == StaticLibrary || module->type == HostStaticLibrary )
- throw XMLInvalidBuildFileException (
- node.location,
- "<importlibrary> dllname attribute required." );
size_t index = definition->value.find_last_of ( "/\\" );
if ( index == string::npos )
name,
&node );
}
+
+ target = new FileLocation ( IntermediateDirectory,
+ base->output->relative_path,
+ "lib" + module->name + (delayimp ? ".delayimp.a" : ".a" ));
+
}