- Sync up Mm interface with WinLdr branch (introduce the concept of a memory type...
[reactos.git] / reactos / tools / rbuild / backend / codeblocks / codeblocks.cpp
1 /*
2 * Copyright (C) 2006 Christoph von Wittich
3 *
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.
8 *
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.
13 *
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.
17 */
18 #ifdef _MSC_VER
19 #pragma warning ( disable : 4786 )
20 #endif//_MSC_VER
21
22 #include <iostream>
23 #include <fstream>
24 #include <string>
25 #include <vector>
26
27 #include <stdio.h>
28
29 #include "codeblocks.h"
30 #include "../mingw/mingw.h"
31
32 using std::string;
33 using std::vector;
34 using std::ifstream;
35
36 #ifdef OUT
37 #undef OUT
38 #endif//OUT
39
40
41 static class CBFactory : public Backend::Factory
42 {
43 public:
44
45 CBFactory() : Factory("CB", "Code::Blocks") {}
46 Backend *operator() (Project &project,
47 Configuration& configuration)
48 {
49 return new CBBackend(project, configuration);
50 }
51
52 } factory;
53
54
55 CBBackend::CBBackend(Project &project,
56 Configuration& configuration) : Backend(project, configuration)
57 {
58 m_unitCount = 0;
59 }
60
61 void CBBackend::Process()
62 {
63
64 while ( m_configurations.size () > 0 )
65 {
66 const CBConfiguration* cfg = m_configurations.back();
67 m_configurations.pop_back();
68 delete cfg;
69 }
70
71 m_configurations.push_back ( new CBConfiguration( Debug ));
72 m_configurations.push_back ( new CBConfiguration( Release ));
73
74 string filename_wrkspace ( ProjectNode.name );
75 filename_wrkspace += "_auto.workspace";
76
77 printf ( "Creating Code::Blocks workspace: %s\n", filename_wrkspace.c_str() );
78
79 ProcessModules();
80 m_wrkspaceFile = fopen ( filename_wrkspace.c_str(), "wb" );
81
82 if ( !m_wrkspaceFile )
83 {
84 printf ( "Could not create file '%s'.\n", filename_wrkspace.c_str() );
85 return;
86 }
87
88 _generate_workspace ( m_wrkspaceFile );
89
90 fclose ( m_wrkspaceFile );
91 printf ( "Done.\n" );
92 }
93
94 void CBBackend::ProcessModules()
95 {
96 for(size_t i = 0; i < ProjectNode.modules.size(); i++)
97 {
98 Module &module = *ProjectNode.modules[i];
99 MingwAddImplicitLibraries( module );
100 _generate_cbproj ( module );
101 }
102 }
103
104 static std::string
105 GetExtension ( const std::string& filename )
106 {
107 size_t index = filename.find_last_of ( '/' );
108 if (index == string::npos) index = 0;
109 string tmp = filename.substr( index, filename.size() - index );
110 size_t ext_index = tmp.find_last_of( '.' );
111 if (ext_index != string::npos)
112 return filename.substr ( index + ext_index, filename.size() );
113 return "";
114 }
115
116 static bool FileExists(string &filename)
117 {
118 ifstream file(filename.c_str());
119
120 if(!file.is_open())
121 return false;
122
123 file.close();
124 return true;
125 }
126
127 void CBBackend::ProcessFile(string &filepath)
128 {
129 // Remove the .\ at the start of the filenames
130 if ( filepath[0] == '.' && strchr ( "/\\", filepath[1] ) )
131 filepath.erase(0, 2);
132
133 if(!FileExists(filepath))
134 return;
135
136 // Change the \ to /
137 for(size_t i = 0; i < filepath.length(); i++)
138 {
139 if(filepath[i] == '\\')
140 filepath[i] = '/';
141 }
142
143 // Remove the filename from the path
144 string folder = "";
145
146 size_t pos = filepath.rfind(string("/"), filepath.length() - 1);
147
148 if(pos != string::npos)
149 {
150 folder = filepath;
151 folder.erase(pos, folder.length() - pos);
152 }
153
154 FileUnit fileUnit;
155 fileUnit.filename = filepath;
156 fileUnit.folder = folder;
157
158 m_fileUnits.push_back(fileUnit);
159
160 if(folder != "")
161 AddFolders(folder);
162
163 m_unitCount++;
164 }
165
166 bool CBBackend::CheckFolderAdded(string &folder)
167 {
168 for(size_t i = 0; i < m_folders.size(); i++)
169 {
170 if(m_folders[i] == folder)
171 return true;
172 }
173
174 return false;
175 }
176
177 void CBBackend::AddFolders(string &folder)
178 {
179 // Check if this folder was already added. true if it was, false otherwise.
180 if(CheckFolderAdded(folder))
181 return;
182
183 m_folders.push_back(folder);
184
185 size_t pos = folder.rfind(string("/"), folder.length() - 1);
186
187 if(pos == string::npos)
188 return;
189
190 folder.erase(pos, folder.length() - pos);
191 AddFolders(folder);
192 }
193
194 void CBBackend::OutputFolders()
195 {
196 #if 0
197 m_devFile << "Folders=";
198
199 for(size_t i = 0; i < m_folders.size(); i++)
200 {
201 if(i > 0)
202 m_devFile << ",";
203
204 m_devFile << m_folders[i];
205 }
206 #endif
207 }
208
209 std::string
210 CBBackend::CbpFileName ( const Module& module ) const
211 {
212 return DosSeparator(
213 ReplaceExtension ( module.output->relative_path + "\\" + module.output->name, "_auto.cbp" )
214 );
215 }
216
217 std::string
218 CBBackend::LayoutFileName ( const Module& module ) const
219 {
220 return DosSeparator(
221 ReplaceExtension ( module.output->relative_path + "\\" + module.output->name, "_auto.layout" )
222 );
223 }
224
225 std::string
226 CBBackend::DependFileName ( const Module& module ) const
227 {
228 return DosSeparator(
229 ReplaceExtension ( module.output->relative_path + "\\" + module.output->name, "_auto.depend" )
230 );
231 }
232
233 void
234 CBBackend::_get_object_files ( const Module& module, vector<string>& out) const
235 {
236 string basepath = module.output->relative_path;
237 size_t i;
238 string intenv = Environment::GetIntermediatePath () + "\\" + basepath + "\\";
239 string outenv = Environment::GetOutputPath () + "\\" + basepath + "\\";
240
241 vector<string> cfgs;
242
243 if ( configuration.UseConfigurationInPath )
244 {
245 cfgs.push_back ( intenv + "Debug" );
246 cfgs.push_back ( intenv + "Release" );
247 cfgs.push_back ( outenv + "Debug" );
248 cfgs.push_back ( outenv + "Release" );
249 }
250 else
251 {
252 cfgs.push_back ( intenv );
253 cfgs.push_back ( outenv );
254 }
255
256 vector<const IfableData*> ifs_list;
257 ifs_list.push_back ( &module.project.non_if_data );
258 ifs_list.push_back ( &module.non_if_data );
259 while ( ifs_list.size () )
260 {
261 const IfableData& data = *ifs_list.back();
262 ifs_list.pop_back();
263 const vector<File*>& files = data.files;
264 for ( i = 0; i < files.size (); i++ )
265 {
266 string file = files[i]->file.relative_path + sSep + files[i]->file.name;
267 string::size_type pos = file.find_last_of ("\\");
268 if ( pos != string::npos )
269 file.erase ( 0, pos+1 );
270 if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )
271 file = ReplaceExtension ( file, ".res" );
272 else
273 file = ReplaceExtension ( file, ".obj" );
274 for ( size_t j = 0; j < cfgs.size () / 2; j++ )
275 out.push_back ( cfgs[j] + "\\" + file );
276 }
277
278 }
279 }
280
281 void
282 CBBackend::_clean_project_files ( void )
283 {
284 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
285 {
286 Module& module = *ProjectNode.modules[i];
287 vector<string> out;
288 printf("Cleaning project %s %s\n", module.name.c_str (), module.output->relative_path.c_str () );
289
290 string basepath = module.output->relative_path;
291 remove ( CbpFileName ( module ).c_str () );
292 remove ( DependFileName ( module ).c_str () );
293 remove ( LayoutFileName ( module ).c_str () );
294
295 _get_object_files ( module, out );
296 for ( size_t j = 0; j < out.size (); j++)
297 {
298 //printf("Cleaning file %s\n", out[j].c_str () );
299 remove ( out[j].c_str () );
300 }
301 }
302
303 string filename_wrkspace = ProjectNode.name + ".workspace";
304
305 remove ( filename_wrkspace.c_str () );
306 }
307
308 void
309 CBBackend::_generate_workspace ( FILE* OUT )
310 {
311 fprintf ( OUT, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\r\n" );
312 fprintf ( OUT, "<CodeBlocks_workspace_file>\r\n" );
313 fprintf ( OUT, "\t<Workspace title=\"ReactOS\">\r\n" );
314 for ( size_t i = 0; i < ProjectNode.modules.size(); i++ )
315 {
316 Module& module = *ProjectNode.modules[i];
317
318 if ((module.type != Iso) &&
319 (module.type != LiveIso) &&
320 (module.type != IsoRegTest) &&
321 (module.type != LiveIsoRegTest))
322 {
323 std::string Cbp_file = CbpFileName ( module );
324 fprintf ( OUT, "\t\t<Project filename=\"%s\">\r\n", Cbp_file.c_str());
325
326 /* dependencies */
327 vector<const IfableData*> ifs_list;
328 ifs_list.push_back ( &module.project.non_if_data );
329 ifs_list.push_back ( &module.non_if_data );
330 while ( ifs_list.size() )
331 {
332 const IfableData& data = *ifs_list.back();
333 ifs_list.pop_back();
334 const vector<Library*>& libs = data.libraries;
335 for ( size_t j = 0; j < libs.size(); j++ )
336 fprintf ( OUT, "\t\t\t<Depends filename=\"%s\\%s_auto.cbp\" />\r\n", libs[j]->importedModule->output->relative_path.c_str(), libs[j]->name.c_str() );
337 }
338 fprintf ( OUT, "\t\t</Project>\r\n" );
339 }
340 }
341 fprintf ( OUT, "\t</Workspace>\r\n" );
342 fprintf ( OUT, "</CodeBlocks_workspace_file>\r\n" );
343 }
344
345 void
346 CBBackend::_generate_cbproj ( const Module& module )
347 {
348
349 size_t i;
350
351 string cbproj_file = CbpFileName(module);
352 string outdir;
353 string intdir;
354 string path_basedir = module.GetPathToBaseDir ();
355 string intenv = Environment::GetIntermediatePath ();
356 string outenv = Environment::GetOutputPath ();
357 string module_type = GetExtension(*module.output);
358 string cbproj_path = module.output->relative_path;
359 string CompilerVar;
360 string baseaddr;
361 string windres_defines;
362 string widl_options;
363 string project_linker_flags = "-Wl,--enable-stdcall-fixup ";
364 project_linker_flags += GenerateProjectLinkerFlags();
365
366 bool lib = (module.type == ObjectLibrary) || (module.type == RpcClient) ||(module.type == RpcServer) || (module_type == ".lib") || (module_type == ".a");
367 bool dll = (module_type == ".dll") || (module_type == ".cpl");
368 bool exe = (module_type == ".exe") || (module_type == ".scr");
369 bool sys = (module_type == ".sys");
370
371 vector<string> source_files, resource_files, includes, libraries, libpaths;
372 vector<string> header_files, common_defines, compiler_flags;
373 vector<string> vars, values;
374
375 /* do not create project files for these targets
376 use virtual targets instead */
377 switch (module.type)
378 {
379 case Iso:
380 case LiveIso:
381 case IsoRegTest:
382 case LiveIsoRegTest:
383 return;
384 default:
385 break;
386 }
387
388 compiler_flags.push_back ( "-Wall" );
389
390 // Always force disabling of sibling calls optimisation for GCC
391 // (TODO: Move to version-specific once this bug is fixed in GCC)
392 compiler_flags.push_back ( "-fno-optimize-sibling-calls" );
393
394 if ( module.pch != NULL )
395 {
396 string pch_path = Path::RelativeFromDirectory (
397 module.pch->file.name,
398 module.output->relative_path );
399
400 header_files.push_back ( pch_path );
401 }
402
403 if ( intenv == "obj-i386" )
404 intdir = path_basedir + "obj-i386"; /* append relative dir from project dir */
405 else
406 intdir = intenv;
407
408 if ( outenv == "output-i386" )
409 outdir = path_basedir + "output-i386";
410 else
411 outdir = outenv;
412
413 vector<const IfableData*> ifs_list;
414 ifs_list.push_back ( &module.project.non_if_data );
415 ifs_list.push_back ( &module.non_if_data );
416 while ( ifs_list.size() )
417 {
418 const IfableData& data = *ifs_list.back();
419 ifs_list.pop_back();
420 for ( i = 0; i < data.ifs.size(); i++ )
421 {
422 const Property* property = _lookup_property( module, data.ifs[i]->property );
423 if ( property != NULL )
424 {
425 if ( data.ifs[i]->value == property->value && data.ifs[i]->negated == false ||
426 data.ifs[i]->value != property->value && data.ifs[i]->negated)
427 ifs_list.push_back ( &data.ifs[i]->data );
428 }
429 }
430 const vector<File*>& files = data.files;
431 for ( i = 0; i < files.size(); i++ )
432 {
433 string fullpath = files[i]->file.relative_path + sSep + files[i]->file.name;
434 string file = string(".") + &fullpath[cbproj_path.size()];
435
436 if ( !stricmp ( Right(file,3).c_str(), ".rc" ) )
437 resource_files.push_back ( file );
438 else
439 source_files.push_back ( file );
440 }
441 const vector<Include*>& incs = data.includes;
442 for ( i = 0; i < incs.size(); i++ )
443 {
444 string path = Path::RelativeFromDirectory (
445 incs[i]->directory->relative_path,
446 module.output->relative_path );
447
448 includes.push_back ( path );
449 widl_options += "-I" + path + " ";
450 }
451 const vector<Library*>& libs = data.libraries;
452 for ( i = 0; i < libs.size(); i++ )
453 {
454 string libpath = intdir + "\\" + libs[i]->importedModule->output->relative_path;
455 libraries.push_back ( libs[i]->name );
456 libpaths.push_back ( libpath );
457 }
458 const vector<CompilerFlag*>& cflags = data.compilerFlags;
459 for ( i = 0; i < cflags.size(); i++ )
460 {
461 compiler_flags.push_back ( cflags[i]->flag );
462 }
463 const vector<Define*>& defs = data.defines;
464 for ( i = 0; i < defs.size(); i++ )
465 {
466 if ( defs[i]->value[0] )
467 {
468 const string& escaped = _replace_str(defs[i]->value, "\"","&quot;");
469 common_defines.push_back( defs[i]->name + "=" + escaped );
470 windres_defines += "-D" + defs[i]->name + "=" + escaped + " ";
471 }
472 else
473 {
474 common_defines.push_back( defs[i]->name );
475 windres_defines += "-D" + defs[i]->name + " ";
476 }
477 }
478 /*const vector<Property*>& variables = data.properties;
479 for ( i = 0; i < variables.size(); i++ )
480 {
481 vars.push_back( variables[i]->name );
482 values.push_back( variables[i]->value );
483 }*/
484 for ( i = 0; i < data.properties.size(); i++ )
485 {
486 Property& prop = *data.properties[i];
487 if ( strstr ( module.baseaddress.c_str(), prop.name.c_str() ) )
488 baseaddr = prop.value;
489 }
490 }
491
492 if ( !module.allowWarnings )
493 compiler_flags.push_back ( "-Werror" );
494
495 if ( module.type == StaticLibrary && module.isStartupLib )
496 compiler_flags.push_back ( "-Wno-main" );
497
498
499 FILE* OUT = fopen ( cbproj_file.c_str(), "wb" );
500
501 fprintf ( OUT, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\r\n" );
502 fprintf ( OUT, "<CodeBlocks_project_file>\r\n" );
503 fprintf ( OUT, "\t<FileVersion major=\"1\" minor=\"6\" />\r\n" );
504 fprintf ( OUT, "\t<Project>\r\n" );
505 fprintf ( OUT, "\t\t<Option title=\"%s\" />\r\n", module.name.c_str() );
506 fprintf ( OUT, "\t\t<Option pch_mode=\"2\" />\r\n" );
507 fprintf ( OUT, "\t\t<Option default_target=\"\" />\r\n" );
508 fprintf ( OUT, "\t\t<Option compiler=\"gcc\" />\r\n" );
509 fprintf ( OUT, "\t\t<Option extended_obj_names=\"1\" />\r\n" );
510 fprintf ( OUT, "\t\t<Option virtualFolders=\"\" />\r\n" );
511 fprintf ( OUT, "\t\t<Build>\r\n" );
512
513 bool console = exe && (module.type == Win32CUI);
514
515 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
516 {
517 const CBConfiguration& cfg = *m_configurations[icfg];
518 fprintf ( OUT, "\t\t\t<Target title=\"%s\">\r\n", cfg.name.c_str() );
519
520 if ( configuration.UseConfigurationInPath )
521 {
522 if ( module.type == StaticLibrary ||module.type == ObjectLibrary )
523 fprintf ( OUT, "\t\t\t\t<Option output=\"%s\\%s%s\\%s%s\" prefix_auto=\"0\" extension_auto=\"0\" />\r\n", intdir.c_str (), module.output->relative_path.c_str (), cfg.name.c_str(), module.name.c_str(), module_type.c_str());
524 else
525 fprintf ( OUT, "\t\t\t\t<Option output=\"%s\\%s%s\\%s%s\" prefix_auto=\"0\" extension_auto=\"0\" />\r\n", outdir.c_str (), module.output->relative_path.c_str (), cfg.name.c_str(), module.name.c_str(), module_type.c_str());
526 fprintf ( OUT, "\t\t\t\t<Option object_output=\"%s\\%s%s\" />\r\n", intdir.c_str(), module.output->relative_path.c_str (), cfg.name.c_str() );
527 }
528 else
529 {
530 if ( module.type == StaticLibrary || module.type == ObjectLibrary )
531 fprintf ( OUT, "\t\t\t\t<Option output=\"%s\\%s\\%s%s\" prefix_auto=\"0\" extension_auto=\"0\" />\r\n", intdir.c_str (), module.output->relative_path.c_str (), module.name.c_str(), module_type.c_str() );
532 else
533 fprintf ( OUT, "\t\t\t\t<Option output=\"%s\\%s\\%s%s\" prefix_auto=\"0\" extension_auto=\"0\" />\r\n", outdir.c_str (), module.output->relative_path.c_str (), module.name.c_str(), module_type.c_str() );
534 fprintf ( OUT, "\t\t\t\t<Option object_output=\"%s\\%s\" />\r\n", intdir.c_str(), module.output->relative_path.c_str () );
535 }
536
537 if ( lib )
538 {
539 fprintf ( OUT, "\t\t\t\t<Option type=\"2\" />\r\n" );
540 }
541 else if ( dll )
542 fprintf ( OUT, "\t\t\t\t<Option type=\"3\" />\r\n" );
543 else if ( sys )
544 fprintf ( OUT, "\t\t\t\t<Option type=\"5\" />\r\n" );
545 else if ( exe )
546 {
547 if ( module.type == Kernel )
548 fprintf ( OUT, "\t\t\t\t<Option type=\"5\" />\r\n" );
549 else if ( module.type == NativeCUI )
550 fprintf ( OUT, "\t\t\t\t<Option type=\"5\" />\r\n" );
551 else if ( module.type == Win32CUI || module.type == Win32GUI || module.type == Win32SCR)
552 {
553 if ( console )
554 fprintf ( OUT, "\t\t\t\t<Option type=\"1\" />\r\n" );
555 else
556 fprintf ( OUT, "\t\t\t\t<Option type=\"0\" />\r\n" );
557 }
558 }
559
560 fprintf ( OUT, "\t\t\t\t<Option compiler=\"gcc\" />\r\n" );
561
562 if ( module_type == ".cpl" )
563 {
564 fprintf ( OUT, "\t\t\t\t<Option parameters=\"shell32,Control_RunDLL &quot;$exe_output&quot;,@\" />\r\n" );
565 fprintf ( OUT, "\t\t\t\t<Option host_application=\"rundll32.exe\" />\r\n" );
566 }
567 fprintf ( OUT, "\t\t\t\t<Compiler>\r\n" );
568
569 bool debug = ( cfg.optimization == Debug );
570
571 if ( debug )
572 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-g\" />\r\n" );
573
574 /* compiler flags */
575 for ( i = 0; i < compiler_flags.size(); i++ )
576 {
577 const string& cflag = compiler_flags[i];
578 fprintf ( OUT, "\t\t\t\t\t<Add option=\"%s\" />\r\n", cflag.c_str() );
579 }
580
581 /* defines */
582 for ( i = 0; i < common_defines.size(); i++ )
583 {
584 const string& define = common_defines[i];
585 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-D%s\" />\r\n", define.c_str() );
586 }
587 /* includes */
588 for ( i = 0; i < includes.size(); i++ )
589 {
590 const string& include = includes[i];
591 fprintf ( OUT, "\t\t\t\t\t<Add directory=\"%s\" />\r\n", include.c_str() );
592 }
593 fprintf ( OUT, "\t\t\t\t</Compiler>\r\n" );
594
595 /* includes */
596 fprintf ( OUT, "\t\t\t\t<ResourceCompiler>\r\n" );
597 for ( i = 0; i < includes.size(); i++ )
598 {
599 const string& include = includes[i];
600 fprintf ( OUT, "\t\t\t\t\t<Add directory=\"%s\" />\r\n", include.c_str() );
601 }
602 fprintf ( OUT, "\t\t\t\t</ResourceCompiler>\r\n" );
603
604 fprintf ( OUT, "\t\t\t\t<Linker>\r\n" );
605 fprintf ( OUT, "\t\t\t\t\t<Add option=\"%s\" />\r\n", project_linker_flags.c_str() );
606
607 if ( sys )
608 {
609 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--entry,%s%s\" />\r\n", "_", module.GetEntryPoint(false) == "" ? "DriverEntry@8" : module.GetEntryPoint(false).c_str ());
610 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--image-base,%s\" />\r\n", baseaddr == "" ? "0x10000" : baseaddr.c_str () );
611 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-nostartfiles -Wl,--nostdlib\" />\r\n" );
612 }
613 else if ( exe )
614 {
615 if ( module.type == Kernel )
616 {
617 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--entry,_KiSystemStartup\" />\r\n" );
618 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--image-base,%s\" />\r\n", baseaddr.c_str () );
619 }
620 else if ( module.type == NativeCUI )
621 {
622 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--entry,_NtProcessStartup@4\" />\r\n" );
623 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--image-base,%s\" />\r\n", baseaddr.c_str () );
624 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-nostartfiles -Wl,--nostdlib\" />\r\n" );
625 }
626 else
627 {
628 fprintf ( OUT, "\t\t\t\t\t<Add option=\"%s\" />\r\n", module.cplusplus ? "-nostartfiles" : "-nostartfiles -Wl,--nostdlib" );
629 fprintf ( OUT, "\t\t\t\t\t<Add library=\"gcc\" />\r\n" );
630 }
631 }
632 else if ( dll )
633 {
634 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--entry,%s%s\" />\r\n", "_", module.GetEntryPoint(false).c_str () );
635 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--image-base,%s\" />\r\n", baseaddr == "" ? "0x40000" : baseaddr.c_str () );
636
637 if ( module.type == Win32DLL )
638 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--shared\" />\r\n" );
639 else if ( module.type == NativeDLL)
640 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--shared\" />\r\n" );
641 else if ( module.type == NativeDLL)
642 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-nostartfiles -Wl,--shared\" />\r\n" );
643
644 fprintf ( OUT, "\t\t\t\t\t<Add option=\"%s\" />\r\n", module.cplusplus ? "-nostartfiles" : "-nostartfiles -Wl,--nostdlib" );
645 fprintf ( OUT, "\t\t\t\t\t<Add library=\"gcc\" />\r\n" );
646 }
647
648 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--file-alignment,0x1000\" />\r\n" );
649 fprintf ( OUT, "\t\t\t\t\t<Add option=\"-Wl,--section-alignment,0x1000\" />\r\n" );
650
651 if ( dll )
652 fprintf ( OUT, "\t\t\t\t\t<Add option=\"%s.temp.exp\" />\r\n", module.name.c_str() );
653
654 /* libraries */
655 for ( i = 0; i < libraries.size(); i++ )
656 {
657 const string& lib = libraries[i];
658 fprintf ( OUT, "\t\t\t\t\t<Add library=\"%s\" />\r\n", lib.c_str() );
659 }
660 for ( i = 0; i < libpaths.size(); i++ )
661 {
662 const string& lib = libpaths[i];
663 fprintf ( OUT, "\t\t\t\t\t<Add directory=\"%s\" />\r\n", lib.c_str() );
664 }
665 fprintf ( OUT, "\t\t\t\t</Linker>\r\n" );
666
667 fprintf ( OUT, "\t\t\t\t<ExtraCommands>\r\n" );
668
669 #if 0
670 if ( module.type == StaticLibrary && module.importLibrary )
671 fprintf ( OUT, "\t\t\t\t\t<Add after=\"dlltool --dllname %s --def %s --output-lib $exe_output; %s -U\" />\r\n", module.importLibrary->dllname.c_str (), module.importLibrary->definition.c_str(), module.mangledSymbols ? "" : "--kill-at" );
672 else if ( module.importLibrary != NULL )
673 fprintf ( OUT, "\t\t\t\t\t<Add after=\"dlltool --dllname %s --def %s --output-lib &quot;$(TARGET_OBJECT_DIR)lib$(TARGET_OUTPUT_BASENAME).a&quot; %s\" />\r\n", module.GetTargetName ().c_str(), module.importLibrary->definition.c_str(), module.mangledSymbols ? "" : "--kill-at" );
674 #endif
675
676
677 for ( i = 0; i < resource_files.size(); i++ )
678 {
679 const string& resource_file = resource_files[i];
680 #ifdef WIN32
681 fprintf ( OUT, "\t\t\t\t\t<Add after=\"cmd /c del $(TARGET_OBJECT_DIR)\\%s.rci.tmp 2&gt;NUL\" />\r\n", resource_file.c_str() );
682 fprintf ( OUT, "\t\t\t\t\t<Add after=\"cmd /c del $(TARGET_OBJECT_DIR)\\%s.res.tmp 2&gt;NUL\" />\r\n", resource_file.c_str() );
683 #else
684 fprintf ( OUT, "\t\t\t\t\t<Add after=\"rm $(TARGET_OBJECT_DIR)/%s.rci.tmp 2&gt;/dev/null\" />\r\n", resource_file.c_str() );
685 fprintf ( OUT, "\t\t\t\t\t<Add after=\"rm $(TARGET_OBJECT_DIR)/%s.res.tmp 2&gt;/dev/null\" />\r\n", resource_file.c_str() );
686 #endif
687 }
688
689 #if 0
690 if ( dll )
691 {
692 if (IsWineModule( module ))
693 fprintf ( OUT, "\t\t\t\t\t<Add before=\"%s\\tools\\winebuild\\winebuild.exe -o %s --def -E %s.spec\" />\r\n", outdir.c_str(), module.importLibrary->definition.c_str(), module.name.c_str());
694 fprintf ( OUT, "\t\t\t\t\t<Add before=\"dlltool --dllname %s --def %s --output-exp %s.temp.exp %s\" />\r\n", module.GetTargetName ().c_str(), module.importLibrary->definition.c_str(), module.name.c_str(), module.mangledSymbols ? "" : "--kill-at" );
695 fprintf ( OUT, "\t\t\t\t\t<Add after=\"%s\\tools\\pefixup $exe_output -exports\" />\r\n", outdir.c_str() );
696 #ifdef WIN32
697 fprintf ( OUT, "\t\t\t\t\t<Add after=\"cmd /c del %s.temp.exp 2&gt;NUL\" />\r\n", module.name.c_str() );
698 #else
699 fprintf ( OUT, "\t\t\t\t\t<Add after=\"rm %s.temp.exp 2&gt;/dev/null\" />\r\n", module.name.c_str() );
700 #endif
701 fprintf ( OUT, "\t\t\t\t\t<Mode after=\"always\" />\r\n" );
702 }
703 #endif
704
705 fprintf ( OUT, "\t\t\t\t</ExtraCommands>\r\n" );
706
707 fprintf ( OUT, "\t\t\t</Target>\r\n" );
708
709 }
710
711 /* vars
712 fprintf ( OUT, "\t\t\t<Environment>\r\n" );
713 for ( i = 0; i < vars.size(); i++ )
714 {
715 const string& var = vars[i];
716 const string& value = values[i];
717 fprintf ( OUT, "\t\t\t\t<Variable name=\"%s\" value=\"%s\" />\r\n", var.c_str(), value.c_str() );
718 }
719 fprintf ( OUT, "\t\t\t</Environment>\r\n" ); */
720
721 fprintf ( OUT, "\t\t</Build>\r\n" );
722
723 #ifdef FORCE_CPP
724 CompilerVar = "CPP"
725 #else
726 if ( module.cplusplus )
727 CompilerVar = "CPP";
728 else
729 CompilerVar = "CC";
730 #endif
731
732 /* header files */
733 for ( i = 0; i < header_files.size(); i++ )
734 {
735 const string& header_file = header_files[i];
736 fprintf ( OUT, "\t\t<Unit filename=\"%s\">\r\n", header_file.c_str() );
737 fprintf ( OUT, "\t\t\t<Option compilerVar=\"%s\" />\r\n", CompilerVar.c_str() );
738 fprintf ( OUT, "\t\t\t<Option compile=\"0\" />\r\n" );
739 fprintf ( OUT, "\t\t\t<Option link=\"0\" />\r\n" );
740 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
741 {
742 const CBConfiguration& cfg = *m_configurations[icfg];
743 fprintf ( OUT, "\t\t\t<Option target=\"%s\" />\r\n" , cfg.name.c_str() );
744 }
745 fprintf ( OUT, "\t\t</Unit>\r\n" );
746 }
747
748 /* source files */
749 for ( size_t isrcfile = 0; isrcfile < source_files.size(); isrcfile++ )
750 {
751 string source_file = DosSeparator(source_files[isrcfile]);
752 fprintf ( OUT, "\t\t<Unit filename=\"%s\">\r\n", source_file.c_str() );
753 fprintf ( OUT, "\t\t\t<Option compilerVar=\"%s\" />\r\n", CompilerVar.c_str() );
754
755 string extension = GetExtension ( source_file );
756 if ( extension == ".s" || extension == ".S" )
757 {
758 fprintf ( OUT, "\t\t\t<Option compile=\"1\" />\r\n" );
759 fprintf ( OUT, "\t\t\t<Option link=\"1\" />\r\n" );
760 fprintf ( OUT, "\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"gcc -x assembler-with-cpp -c $file -o $link_objects $includes -D__ASM__ $options\" />\r\n" );
761 }
762 else if ( extension == ".asm" || extension == ".ASM" )
763 {
764 fprintf ( OUT, "\t\t\t<Option compile=\"1\" />\r\n" );
765 fprintf ( OUT, "\t\t\t<Option link=\"1\" />\r\n" );
766 fprintf ( OUT, "\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"nasm -f win32 $file -o $link_objects\" />\r\n" );
767 }
768 else if ( extension == ".idl" || extension == ".IDL" )
769 {
770 fprintf ( OUT, "\t\t\t<Option compile=\"1\" />\r\n" );
771 fprintf ( OUT, "\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"%s\\tools\\widl\\widl.exe %s %s -h -H &quot;$(TARGET_OUTPUT_DIR)$filetitle_c.h&quot; -c -C &quot;$(TARGET_OUTPUT_DIR)$filetitle_c.c&quot; $file\\ngcc %s -c &quot;$(TARGET_OUTPUT_DIR)$filetitle_c.c&quot; -o &quot;$(TARGET_OUTPUT_DIR)$file_c.o&quot;\" />\r\n", outdir.c_str(), widl_options.c_str(), windres_defines.c_str(), widl_options.c_str() );
772 }
773 else if ( extension == ".spec" || extension == ".SPEC" )
774 {
775 fprintf ( OUT, "\t\t\t<Option compile=\"1\" />\r\n" );
776 fprintf ( OUT, "\t\t\t<Option link=\"1\" />\r\n" );
777 fprintf ( OUT, "\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"%s\\tools\\winebuild\\winebuild.exe -o $file.stubs.c --pedll $file\\n$compiler -c $options $includes $file.stubs.c -o $(TARGET_OBJECT_DIR)\\$file.o\" />\r\n", outdir.c_str() );
778 }
779
780 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
781 {
782 const CBConfiguration& cfg = *m_configurations[icfg];
783 fprintf ( OUT, "\t\t\t<Option target=\"%s\" />\r\n" , cfg.name.c_str() );
784 }
785 fprintf ( OUT, "\t\t</Unit>\r\n" );
786 }
787
788 /* resource files */
789 for ( i = 0; i < resource_files.size(); i++ )
790 {
791 const string& resource_file = resource_files[i];
792 fprintf ( OUT, "\t\t<Unit filename=\"%s\">\r\n", resource_file.c_str() );
793 fprintf ( OUT, "\t\t\t<Option compilerVar=\"WINDRES\" />\r\n" );
794 string extension = GetExtension ( resource_file );
795 fprintf ( OUT, "\t\t\t<Option compiler=\"gcc\" use=\"1\" buildCommand=\"gcc -xc -E -DRC_INVOKED $includes %s $file -o $(TARGET_OBJECT_DIR)\\$file.rci.tmp\\n%s\\tools\\wrc\\wrc.exe $includes %s $(TARGET_OBJECT_DIR)\\$file.rci.tmp $(TARGET_OBJECT_DIR)\\$file.res.tmp\\n$rescomp --output-format=coff $(TARGET_OBJECT_DIR)\\$file.res.tmp -o $resource_output\" />\r\n" , windres_defines.c_str(), outdir.c_str(), windres_defines.c_str() );
796 for ( size_t icfg = 0; icfg < m_configurations.size(); icfg++ )
797 {
798 const CBConfiguration& cfg = *m_configurations[icfg];
799 fprintf ( OUT, "\t\t\t<Option target=\"%s\" />\r\n" , cfg.name.c_str() );
800 }
801 fprintf ( OUT, "\t\t</Unit>\r\n" );
802 }
803
804 fprintf ( OUT, "\t\t<Extensions />\r\n" );
805 fprintf ( OUT, "\t</Project>\r\n" );
806 fprintf ( OUT, "</CodeBlocks_project_file>\r\n" );
807
808
809 fclose ( OUT );
810 }
811
812 CBConfiguration::CBConfiguration ( const OptimizationType optimization, const std::string &name )
813 {
814 this->optimization = optimization;
815 if ( name != "" )
816 this->name = name;
817 else
818 {
819 if ( optimization == Debug )
820 this->name = "Debug";
821 else if ( optimization == Release )
822 this->name = "Release";
823 else
824 this->name = "Unknown";
825 }
826 }
827
828 std::string
829 CBBackend::_replace_str(std::string string1, const std::string &find_str, const std::string &replace_str)
830 {
831 std::string::size_type pos = string1.find(find_str, 0);
832 int intLen = find_str.length();
833
834 while(std::string::npos != pos)
835 {
836 string1.replace(pos, intLen, replace_str);
837 pos = string1.find(find_str, intLen + pos);
838 }
839
840 return string1;
841 }
842
843 std::string
844 CBBackend::GenerateProjectLinkerFlags() const
845 {
846 std::string lflags;
847 for ( size_t i = 0; i < ProjectNode.linkerFlags.size (); i++ )
848 {
849 LinkerFlag& linkerFlag = *ProjectNode.linkerFlags[i];
850 if ( lflags.length () > 0 )
851 lflags += " ";
852 lflags += linkerFlag.flag;
853 }
854 return lflags;
855 }
856
857 void
858 CBBackend::MingwAddImplicitLibraries( Module &module )
859 {
860 Library* pLibrary;
861
862 if ( !module.isDefaultEntryPoint )
863 return;
864
865 if ( module.IsDLL () )
866 {
867 //pLibrary = new Library ( module, "__mingw_dllmain" );
868 //module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin(), pLibrary );
869 }
870 else
871 {
872 pLibrary = new Library ( module, module.isUnicode ? "mingw_wmain" : "mingw_main" );
873 module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin(), pLibrary );
874 }
875
876 pLibrary = new Library ( module, "mingw_common" );
877 module.non_if_data.libraries.insert ( module.non_if_data.libraries.begin() + 1, pLibrary );
878
879 if ( module.name != "msvcrt" )
880 {
881 // always link in msvcrt to get the basic routines
882 pLibrary = new Library ( module, "msvcrt" );
883 module.non_if_data.libraries.push_back ( pLibrary );
884 }
885 }
886
887 const Property*
888 CBBackend::_lookup_property ( const Module& module, const std::string& name ) const
889 {
890 /* Check local values */
891 for ( size_t i = 0; i < module.non_if_data.properties.size(); i++ )
892 {
893 const Property& property = *module.non_if_data.properties[i];
894 if ( property.name == name )
895 return &property;
896 }
897 // TODO FIXME - should we check local if-ed properties?
898 for ( size_t i = 0; i < module.project.non_if_data.properties.size(); i++ )
899 {
900 const Property& property = *module.project.non_if_data.properties[i];
901 if ( property.name == name )
902 return &property;
903 }
904 // TODO FIXME - should we check global if-ed properties?
905 return NULL;
906 }
907
908 bool
909 CBBackend::IsWineModule ( const Module& module ) const
910 {
911 if ( module.importLibrary == NULL)
912 return false;
913
914 size_t index = module.importLibrary->source->name.rfind ( ".spec.def" );
915 return ( index != string::npos );
916 }