2 * Copyright (C) 2005 Casper S. Hornstrup
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 Environment::GetVariable ( const string
& name
)
29 char* value
= getenv ( name
.c_str () );
30 if ( value
!= NULL
&& strlen ( value
) > 0 )
31 return ssprintf ( "%s",
38 Environment::GetEnvironmentVariablePathOrDefault ( const string
& name
,
39 const string
& defaultValue
)
41 const string
& environmentVariableValue
= Environment::GetVariable ( name
);
42 if ( environmentVariableValue
.length () > 0 )
43 return NormalizeFilename ( environmentVariableValue
);
49 Environment::GetIntermediatePath ()
51 return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
56 Environment::GetOutputPath ()
58 return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
63 Environment::GetInstallPath ()
65 return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
69 ParseContext::ParseContext ()
71 compilationUnit (NULL
)
75 Project::Project ( const string
& filename
)
86 for ( i
= 0; i
< modules
.size (); i
++ )
88 for ( i
= 0; i
< linkerFlags
.size (); i
++ )
89 delete linkerFlags
[i
];
90 for ( i
= 0; i
< cdfiles
.size (); i
++ )
92 for ( i
= 0; i
< installfiles
.size (); i
++ )
93 delete installfiles
[i
];
98 Project::LookupProperty ( const string
& name
) const
100 for ( size_t i
= 0; i
< non_if_data
.properties
.size (); i
++ )
102 const Property
* property
= non_if_data
.properties
[i
];
103 if ( property
->name
== name
)
110 Project::ResolveNextProperty ( string
& s
) const
112 size_t i
= s
.find ( "${" );
113 if ( i
== string::npos
)
115 if ( i
!= string::npos
)
118 if ( s
[i
+ 1] == '{' )
122 size_t j
= s
.find ( endCharacter
);
123 if ( j
!= string::npos
)
125 int propertyNameLength
= j
- i
- 2;
126 string propertyName
= s
.substr ( i
+ 2, propertyNameLength
);
127 const Property
* property
= LookupProperty ( propertyName
);
128 if ( property
!= NULL
)
129 return s
.replace ( i
, propertyNameLength
+ 3, property
->value
);
136 Project::ResolveProperties ( const string
& s
) const
143 s2
= ResolveNextProperty ( s3
);
144 } while ( s2
!= s3
);
149 Project::SetConfigurationOption ( char* s
,
151 string
* alternativeName
)
153 const Property
* property
= LookupProperty ( name
);
154 if ( property
!= NULL
&& property
->value
.length () > 0 )
158 property
->name
.c_str (),
159 property
->value
.c_str () );
161 else if ( property
!= NULL
)
165 property
->name
.c_str () );
167 else if ( alternativeName
!= NULL
)
171 alternativeName
->c_str () );
176 Project::SetConfigurationOption ( char* s
,
179 SetConfigurationOption ( s
, name
, NULL
);
183 Project::WriteConfigurationFile ()
188 buf
= (char*) malloc ( 10*1024 );
190 throw OutOfMemoryException ();
193 s
= s
+ sprintf ( s
, "/* Automatically generated. " );
194 s
= s
+ sprintf ( s
, "Edit config.xml to change configuration */\n" );
195 s
= s
+ sprintf ( s
, "#ifndef __INCLUDE_CONFIG_H\n" );
196 s
= s
+ sprintf ( s
, "#define __INCLUDE_CONFIG_H\n" );
198 SetConfigurationOption ( s
, "ARCH" );
199 SetConfigurationOption ( s
, "OPTIMIZED" );
200 SetConfigurationOption ( s
, "MP", new string ( "UP" ) );
201 SetConfigurationOption ( s
, "ACPI" );
202 SetConfigurationOption ( s
, "_3GB" );
204 s
= s
+ sprintf ( s
, "#endif /* __INCLUDE_CONFIG_H */\n" );
206 FileSupportCode::WriteIfChanged ( buf
, "include" + sSep
+ "roscfg.h" );
212 Project::ExecuteInvocations ()
214 for ( size_t i
= 0; i
< modules
.size (); i
++ )
215 modules
[i
]->InvokeModule ();
222 head
= XMLLoadFile ( xmlfile
, path
, xmlbuildfiles
);
224 for ( size_t i
= 0; i
< head
->subElements
.size (); i
++ )
226 if ( head
->subElements
[i
]->name
== "project" )
228 node
= head
->subElements
[i
];
230 this->ProcessXML ( path
);
236 node
= head
->subElements
[0];
238 throw InvalidBuildFileException (
240 "Document contains no 'project' tag." );
244 Project::ProcessXML ( const string
& path
)
246 const XMLAttribute
*att
;
247 if ( node
->name
!= "project" )
248 throw Exception ( "internal tool error: Project::ProcessXML() called with non-<project> node" );
250 att
= node
->GetAttribute ( "name", false );
256 att
= node
->GetAttribute ( "makefile", true );
258 makefile
= att
->value
;
261 for ( i
= 0; i
< node
->subElements
.size (); i
++ )
263 ParseContext parseContext
;
264 ProcessXMLSubElement ( *node
->subElements
[i
], path
, parseContext
);
266 for ( i
= 0; i
< modules
.size (); i
++ )
267 modules
[i
]->ProcessXML ();
268 for ( i
= 0; i
< linkerFlags
.size (); i
++ )
269 linkerFlags
[i
]->ProcessXML ();
270 non_if_data
.ProcessXML ();
271 for ( i
= 0; i
< cdfiles
.size (); i
++ )
272 cdfiles
[i
]->ProcessXML ();
273 for ( i
= 0; i
< installfiles
.size (); i
++ )
274 installfiles
[i
]->ProcessXML ();
278 Project::ProcessXMLSubElement ( const XMLElement
& e
,
280 ParseContext
& parseContext
)
282 bool subs_invalid
= false;
283 string
subpath(path
);
284 if ( e
.name
== "module" )
286 if ( parseContext
.ifData
)
287 throw InvalidBuildFileException (
289 "<module> is not a valid sub-element of <if>" );
290 Module
* module
= new Module ( *this, e
, path
);
291 if ( LocateModule ( module
->name
) )
292 throw InvalidBuildFileException (
294 "module name conflict: '%s' (originally defined at %s)",
295 module
->name
.c_str(),
296 module
->node
.location
.c_str() );
297 modules
.push_back ( module
);
298 return; // defer processing until later
300 else if ( e
.name
== "cdfile" )
302 CDFile
* cdfile
= new CDFile ( *this, e
, path
);
303 cdfiles
.push_back ( cdfile
);
306 else if ( e
.name
== "installfile" )
308 InstallFile
* installfile
= new InstallFile ( *this, e
, path
);
309 installfiles
.push_back ( installfile
);
312 else if ( e
.name
== "directory" )
314 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
316 subpath
= GetSubPath ( e
.location
, path
, att
->value
);
318 else if ( e
.name
== "include" )
320 Include
* include
= new Include ( *this, &e
);
321 if ( parseContext
.ifData
)
322 parseContext
.ifData
->data
.includes
.push_back ( include
);
324 non_if_data
.includes
.push_back ( include
);
327 else if ( e
.name
== "define" )
329 Define
* define
= new Define ( *this, e
);
330 if ( parseContext
.ifData
)
331 parseContext
.ifData
->data
.defines
.push_back ( define
);
333 non_if_data
.defines
.push_back ( define
);
336 else if ( e
.name
== "compilerflag" )
338 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( *this, e
);
339 if ( parseContext
.ifData
)
340 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
342 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
345 else if ( e
.name
== "linkerflag" )
347 linkerFlags
.push_back ( new LinkerFlag ( *this, e
) );
350 else if ( e
.name
== "if" )
352 If
* pOldIf
= parseContext
.ifData
;
353 parseContext
.ifData
= new If ( e
, *this, NULL
);
355 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
357 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
358 subs_invalid
= false;
360 else if ( e
.name
== "ifnot" )
362 If
* pOldIf
= parseContext
.ifData
;
363 parseContext
.ifData
= new If ( e
, *this, NULL
, true );
365 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
367 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
368 subs_invalid
= false;
370 else if ( e
.name
== "property" )
372 Property
* property
= new Property ( e
, *this, NULL
);
373 if ( parseContext
.ifData
)
374 parseContext
.ifData
->data
.properties
.push_back ( property
);
376 non_if_data
.properties
.push_back ( property
);
378 if ( subs_invalid
&& e
.subElements
.size() )
379 throw InvalidBuildFileException (
381 "<%s> cannot have sub-elements",
383 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
384 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, parseContext
);
388 Project::LocateModule ( const string
& name
)
390 for ( size_t i
= 0; i
< modules
.size (); i
++ )
392 if (modules
[i
]->name
== name
)
400 Project::LocateModule ( const string
& name
) const
402 for ( size_t i
= 0; i
< modules
.size (); i
++ )
404 if ( modules
[i
]->name
== name
)
412 Project::GetProjectFilename () const