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
)
76 FileLocation::FileLocation ( Directory
* directory
,
77 std::string filename
)
78 : directory (directory
),
84 Project::Project ( const Configuration
& configuration
,
85 const string
& filename
)
89 configuration (configuration
)
97 for ( i
= 0; i
< modules
.size (); i
++ )
99 for ( i
= 0; i
< linkerFlags
.size (); i
++ )
100 delete linkerFlags
[i
];
101 for ( i
= 0; i
< cdfiles
.size (); i
++ )
103 for ( i
= 0; i
< installfiles
.size (); i
++ )
104 delete installfiles
[i
];
109 Project::LookupProperty ( const string
& name
) const
111 for ( size_t i
= 0; i
< non_if_data
.properties
.size (); i
++ )
113 const Property
* property
= non_if_data
.properties
[i
];
114 if ( property
->name
== name
)
121 Project::ResolveNextProperty ( string
& s
) const
123 size_t i
= s
.find ( "${" );
124 if ( i
== string::npos
)
126 if ( i
!= string::npos
)
129 if ( s
[i
+ 1] == '{' )
133 size_t j
= s
.find ( endCharacter
);
134 if ( j
!= string::npos
)
136 int propertyNameLength
= j
- i
- 2;
137 string propertyName
= s
.substr ( i
+ 2, propertyNameLength
);
138 const Property
* property
= LookupProperty ( propertyName
);
139 if ( property
!= NULL
)
140 return s
.replace ( i
, propertyNameLength
+ 3, property
->value
);
147 Project::ResolveProperties ( const string
& s
) const
154 s2
= ResolveNextProperty ( s3
);
155 } while ( s2
!= s3
);
160 Project::SetConfigurationOption ( char* s
,
162 string
* alternativeName
)
164 const Property
* property
= LookupProperty ( name
);
165 if ( property
!= NULL
&& property
->value
.length () > 0 )
169 property
->name
.c_str (),
170 property
->value
.c_str () );
172 else if ( property
!= NULL
)
176 property
->name
.c_str () );
178 else if ( alternativeName
!= NULL
)
182 alternativeName
->c_str () );
187 Project::SetConfigurationOption ( char* s
,
190 SetConfigurationOption ( s
, name
, NULL
);
194 Project::WriteConfigurationFile ()
199 buf
= (char*) malloc ( 10*1024 );
201 throw OutOfMemoryException ();
204 s
= s
+ sprintf ( s
, "/* Automatically generated. " );
205 s
= s
+ sprintf ( s
, "Edit config.xml to change configuration */\n" );
206 s
= s
+ sprintf ( s
, "#ifndef __INCLUDE_CONFIG_H\n" );
207 s
= s
+ sprintf ( s
, "#define __INCLUDE_CONFIG_H\n" );
209 SetConfigurationOption ( s
, "ARCH" );
210 SetConfigurationOption ( s
, "OPTIMIZED" );
211 SetConfigurationOption ( s
, "MP", new string ( "UP" ) );
212 SetConfigurationOption ( s
, "ACPI" );
213 SetConfigurationOption ( s
, "_3GB" );
215 s
= s
+ sprintf ( s
, "#endif /* __INCLUDE_CONFIG_H */\n" );
217 FileSupportCode::WriteIfChanged ( buf
, "include" + sSep
+ "roscfg.h" );
223 Project::ExecuteInvocations ()
225 for ( size_t i
= 0; i
< modules
.size (); i
++ )
226 modules
[i
]->InvokeModule ();
233 head
= XMLLoadFile ( xmlfile
, path
, xmlbuildfiles
);
235 for ( size_t i
= 0; i
< head
->subElements
.size (); i
++ )
237 if ( head
->subElements
[i
]->name
== "project" )
239 node
= head
->subElements
[i
];
241 this->ProcessXML ( path
);
247 node
= head
->subElements
[0];
249 throw XMLInvalidBuildFileException (
251 "Document contains no 'project' tag." );
255 Project::ProcessXML ( const string
& path
)
257 const XMLAttribute
*att
;
258 if ( node
->name
!= "project" )
259 throw Exception ( "internal tool error: Project::ProcessXML() called with non-<project> node" );
261 att
= node
->GetAttribute ( "name", false );
267 att
= node
->GetAttribute ( "makefile", true );
269 makefile
= att
->value
;
272 for ( i
= 0; i
< node
->subElements
.size (); i
++ )
274 ParseContext parseContext
;
275 ProcessXMLSubElement ( *node
->subElements
[i
], path
, parseContext
);
277 for ( i
= 0; i
< modules
.size (); i
++ )
278 modules
[i
]->ProcessXML ();
279 for ( i
= 0; i
< linkerFlags
.size (); i
++ )
280 linkerFlags
[i
]->ProcessXML ();
281 non_if_data
.ProcessXML ();
282 for ( i
= 0; i
< cdfiles
.size (); i
++ )
283 cdfiles
[i
]->ProcessXML ();
284 for ( i
= 0; i
< installfiles
.size (); i
++ )
285 installfiles
[i
]->ProcessXML ();
289 Project::ProcessXMLSubElement ( const XMLElement
& e
,
291 ParseContext
& parseContext
)
293 bool subs_invalid
= false;
294 string
subpath(path
);
295 if ( e
.name
== "module" )
297 if ( parseContext
.ifData
)
298 throw XMLInvalidBuildFileException (
300 "<module> is not a valid sub-element of <if>" );
301 Module
* module
= new Module ( *this, e
, path
);
302 if ( LocateModule ( module
->name
) )
303 throw XMLInvalidBuildFileException (
305 "module name conflict: '%s' (originally defined at %s)",
306 module
->name
.c_str(),
307 module
->node
.location
.c_str() );
308 modules
.push_back ( module
);
309 return; // defer processing until later
311 else if ( e
.name
== "cdfile" )
313 CDFile
* cdfile
= new CDFile ( *this, e
, path
);
314 cdfiles
.push_back ( cdfile
);
317 else if ( e
.name
== "installfile" )
319 InstallFile
* installfile
= new InstallFile ( *this, e
, path
);
320 installfiles
.push_back ( installfile
);
323 else if ( e
.name
== "directory" )
325 const XMLAttribute
* att
= e
.GetAttribute ( "name", true );
327 subpath
= GetSubPath ( e
.location
, path
, att
->value
);
329 else if ( e
.name
== "include" )
331 Include
* include
= new Include ( *this, &e
);
332 if ( parseContext
.ifData
)
333 parseContext
.ifData
->data
.includes
.push_back ( include
);
335 non_if_data
.includes
.push_back ( include
);
338 else if ( e
.name
== "define" )
340 Define
* define
= new Define ( *this, e
);
341 if ( parseContext
.ifData
)
342 parseContext
.ifData
->data
.defines
.push_back ( define
);
344 non_if_data
.defines
.push_back ( define
);
347 else if ( e
.name
== "compilerflag" )
349 CompilerFlag
* pCompilerFlag
= new CompilerFlag ( *this, e
);
350 if ( parseContext
.ifData
)
351 parseContext
.ifData
->data
.compilerFlags
.push_back ( pCompilerFlag
);
353 non_if_data
.compilerFlags
.push_back ( pCompilerFlag
);
356 else if ( e
.name
== "linkerflag" )
358 linkerFlags
.push_back ( new LinkerFlag ( *this, e
) );
361 else if ( e
.name
== "if" )
363 If
* pOldIf
= parseContext
.ifData
;
364 parseContext
.ifData
= new If ( e
, *this, NULL
);
366 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
368 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
369 subs_invalid
= false;
371 else if ( e
.name
== "ifnot" )
373 If
* pOldIf
= parseContext
.ifData
;
374 parseContext
.ifData
= new If ( e
, *this, NULL
, true );
376 pOldIf
->data
.ifs
.push_back ( parseContext
.ifData
);
378 non_if_data
.ifs
.push_back ( parseContext
.ifData
);
379 subs_invalid
= false;
381 else if ( e
.name
== "property" )
383 Property
* property
= new Property ( e
, *this, NULL
);
384 if ( parseContext
.ifData
)
385 parseContext
.ifData
->data
.properties
.push_back ( property
);
387 non_if_data
.properties
.push_back ( property
);
389 if ( subs_invalid
&& e
.subElements
.size() )
391 throw XMLInvalidBuildFileException (
393 "<%s> cannot have sub-elements",
396 for ( size_t i
= 0; i
< e
.subElements
.size (); i
++ )
397 ProcessXMLSubElement ( *e
.subElements
[i
], subpath
, parseContext
);
401 Project::LocateModule ( const string
& name
)
403 for ( size_t i
= 0; i
< modules
.size (); i
++ )
405 if (modules
[i
]->name
== name
)
413 Project::LocateModule ( const string
& name
) const
415 for ( size_t i
= 0; i
< modules
.size (); i
++ )
417 if ( modules
[i
]->name
== name
)
425 Project::GetProjectFilename () const