1 #include "Builders.h"
2 #include "BuilderUtils.h"
3 
AddFlags(Index<String> & cfg)4 void   GccBuilder::AddFlags(Index<String>& cfg)
5 {
6 }
7 
CompilerName() const8 String GccBuilder::CompilerName() const
9 {
10 	if(!IsNull(compiler)) return compiler;
11 	return "c++";
12 }
13 
CmdLine(const String & package,const Package & pkg)14 String GccBuilder::CmdLine(const String& package, const Package& pkg)
15 {
16 	String cc = CompilerName();
17 	cc << " -c";
18 	for(String s : pkg_config)
19 		cc << " `pkg-config --cflags " << s << "`";
20 	cc << ' ' << IncludesDefinesTargetTime(package, pkg);
21 	return cc;
22 }
23 
BinaryToObject(String objfile,CParser & binscript,String basedir,const String & package,const Package & pkg)24 void GccBuilder::BinaryToObject(String objfile, CParser& binscript, String basedir,
25                                 const String& package, const Package& pkg)
26 {
27 	String fo = BrcToC(binscript, basedir);
28 	String tmpfile = ForceExt(objfile, ".c");
29 	SaveFile(tmpfile, fo);
30 	String cc = CmdLine(package, pkg);
31 	cc << " -c -o " << GetHostPathQ(objfile) << " -x c " << GetHostPathQ(tmpfile);
32 	int slot = AllocSlot();
33 	if(slot < 0 || !Run(cc, slot, objfile, 1))
34 		throw Exc(Format("Error compiling binary object '%s'.", objfile));
35 }
36 
BuildPackage(const String & package,Vector<String> & linkfile,Vector<String> & immfile,String & linkoptions,const Vector<String> & all_uses,const Vector<String> & all_libraries,int opt)37 bool GccBuilder::BuildPackage(const String& package, Vector<String>& linkfile, Vector<String>& immfile,
38 	String& linkoptions, const Vector<String>& all_uses, const Vector<String>& all_libraries,
39 	int opt)
40 {
41 	if(HasFlag("OSX") && HasFlag("GUI")) {
42 		String folder;
43 		String name = GetFileName(target);
44 		if(GetFileExt(target) == ".app")
45 			target = target + "/Contents/MacOS/" + GetFileTitle(target);
46 		else
47 			target = target + ".app/Contents/MacOS/" + GetFileName(target);
48 		RealizePath(target);
49 	}
50 
51 	SaveBuildInfo(package);
52 
53 	int i;
54 	String packagepath = PackagePath(package);
55 	Package pkg;
56 	pkg.Load(packagepath);
57 	String packagedir = GetFileFolder(packagepath);
58 	ChDir(packagedir);
59 	PutVerbose("cd " + packagedir);
60 	IdeConsoleBeginGroup(package);
61 	Vector<String> obj;
62 
63 	bool is_shared = HasFlag("SO");
64 	String shared_ext = (HasFlag("WIN32") ? ".dll" : ".so");
65 
66 	Vector<String> sfile, isfile;
67 	Vector<String> soptions, isoptions;
68 	bool           error = false;
69 
70 	String pch_header;
71 
72 	Index<String> nopch, noblitz;
73 
74 	bool blitz = HasFlag("BLITZ");
75 	bool release = !HasFlag("DEBUG");
76 	bool objectivec = HasFlag("OBJC");
77 
78 	if(HasFlag("OSX"))
79 		objectivec = true;
80 
81 	for(i = 0; i < pkg.GetCount(); i++) {
82 		if(!IdeIsBuilding())
83 			return false;
84 		if(!pkg[i].separator) {
85 			String gop = Gather(pkg[i].option, config.GetKeys());
86 			Vector<String> srcfile = CustomStep(pkg[i], package, error);
87 			if(srcfile.GetCount() == 0)
88 				error = true;
89 			for(int j = 0; j < srcfile.GetCount(); j++) {
90 				String fn = srcfile[j];
91 				String ext = GetSrcType(fn);
92 				if(findarg(ext, ".c", ".cpp", ".cc", ".cxx", ".brc", ".s", ".ss") >= 0 ||
93 				   objectivec && findarg(ext, ".mm", ".m") >= 0 ||
94 				   +
95 				   (!release && blitz && ext == ".icpp") ||
96 				   ext == ".rc" && HasFlag("WIN32")) {
97 					sfile.Add(fn);
98 					soptions.Add(gop);
99 				}
100 				else
101 				if(ext == ".icpp") {
102 					isfile.Add(fn);
103 					isoptions.Add(gop);
104 				}
105 				else
106 				if(ext == ".o")
107 					obj.Add(fn);
108 				else
109 				if(ext == ".a" || ext == ".so")
110 					linkfile.Add(fn);
111 				else
112 				if(IsHeaderExt(ext) && pkg[i].pch && allow_pch && !blitz) {
113 					if(pch_header.GetCount())
114 						PutConsole(GetFileName(fn) + ": multiple PCHs are not allowed. Check your package configuration");
115 					else
116 						pch_header = fn;
117 				}
118 				if(pkg[i].nopch) {
119 					nopch.Add(fn);
120 					if(allow_pch && release)
121 						noblitz.Add(fn);
122 				}
123 				if(pkg[i].noblitz)
124 					noblitz.Add(fn);
125 				if(ext == ".c")
126 					nopch.Add(fn);
127 			}
128 		}
129 	}
130 
131 	String cc = CmdLine(package, pkg);
132 
133 //	if(IsVerbose())
134 //		cc << " -v";
135 	if(HasFlag("WIN32")/* && HasFlag("MT")*/)
136 		cc << " -mthreads";
137 
138 	if(HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL")) {
139 		cc << (HasFlag("WIN32") && HasFlag("CLANG") ? " -gcodeview -fno-limit-debug-info" : " -ggdb");
140 		cc << (HasFlag("DEBUG_FULL") ? " -g2" : " -g1");
141 	}
142 	String fuse_cxa_atexit;
143 	if(is_shared /*&& !HasFlag("MAIN")*/) {
144 		cc << " -shared -fPIC";
145 		fuse_cxa_atexit = " -fuse-cxa-atexit";
146 	}
147 	if(!HasFlag("SHARED") && !is_shared)
148 		cc << " -static ";
149 //	else if(!HasFlag("WIN32")) // TRC 05/03/08: dynamic fPIC doesn't seem to work in MinGW
150 //		cc << " -dynamic -fPIC "; // TRC 05/03/30: dynamic fPIC doesn't seem to work in GCC either :-)
151 	cc << ' ' << Gather(pkg.option, config.GetKeys());
152 	cc << " -fexceptions";
153 
154 #if 0
155 	if (HasFlag("OSX")) {
156 	  if (HasFlag("POWERPC"))
157 		cc << " -arch ppc";
158 	  if (HasFlag("X86"))
159 		cc << " -arch i386";
160 	}
161 #endif
162 //	if(HasFlag("SSE2")) {
163 //		cc << " -msse2";
164 //		if(!HasFlag("CLANG"))
165 //			cc << " -mfpmath=sse";
166 //	}
167 
168 	if(!release)
169 		cc << " -D_DEBUG " << debug_options;
170 	else
171 		cc << ' ' << release_options;
172 
173 	if(pkg.nowarnings)
174 		cc << " -w";
175 
176 	int recompile = 0;
177 	Blitz b;
178 	if(blitz) {
179 		BlitzBuilderComponent bc(this);
180 		b = bc.MakeBlitzStep(sfile, soptions, obj, immfile, ".o", noblitz, package);
181 		recompile = b.build;
182 	}
183 
184 	for(i = 0; i < sfile.GetCount(); i++) {
185 		String fn = sfile[i];
186 		String ext = ToLower(GetFileExt(fn));
187 		if(findarg(ext, ".rc", ".brc", ".c") < 0 && HdependFileTime(sfile[i]) > GetFileTime(CatAnyPath(outdir, GetFileTitle(fn) + ".o")))
188 			recompile++;
189 	}
190 
191 	String pch_use;
192 	String pch_file;
193 
194 	if(recompile > 2 && pch_header.GetCount()) {
195 		String pch_header2 = CatAnyPath(outdir, GetFileTitle(pch_header) + "$pch.h");
196 		pch_file = pch_header2 + ".gch";
197 		SaveFile(pch_header2, "#include <" + pch_header + ">"); // CLANG needs a copy of header
198 
199 		int pch_slot = AllocSlot();
200 		StringBuffer sb;
201 
202 		sb << Join(cc, cpp_options) << " -x c++-header " << GetHostPathQ(pch_header) << " -o " << GetHostPathQ(pch_file);
203 
204 		PutConsole("Precompiling header: " + GetFileName(pch_header));
205 		if(pch_slot < 0 || !Run(~sb, pch_slot, GetHostPath(pch_file), 1))
206 			error = true;
207 		Wait();
208 
209 		pch_use = " -I" + GetHostPathQ(outdir) + " -include " + GetFileName(pch_header2) + " -Winvalid-pch ";
210 	}
211 
212 	if(blitz && b.build) {
213 		PutConsole("BLITZ:" + b.info);
214 		int slot = AllocSlot();
215 		if(slot < 0 || !Run(String().Cat() << Join(cc, cpp_options) << ' '
216 		                    << GetHostPathQ(b.path)
217 		                    << " -o " << GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count))
218 			error = true;
219 	}
220 
221 	int first_ifile = sfile.GetCount();
222 	sfile.AppendPick(pick(isfile));
223 	soptions.AppendPick(pick(isoptions));
224 
225 	int ccount = 0;
226 	for(i = 0; i < sfile.GetCount(); i++) {
227 		if(!IdeIsBuilding())
228 			return false;
229 		String fn = sfile[i];
230 		String ext = ToLower(GetFileExt(fn));
231 		bool rc = (ext == ".rc");
232 		bool brc = (ext == ".brc");
233 		bool init = (i >= first_ifile);
234 		String objfile = CatAnyPath(outdir, GetFileTitle(fn) + (rc ? "$rc.o" : brc ? "$brc.o" : ".o"));
235 		if(GetFileName(fn) == "Info.plist")
236 			Info_plist = LoadFile(fn);
237 		if(HdependFileTime(fn) > GetFileTime(GetHostPath(objfile))) {
238 			PutConsole(GetFileName(fn));
239 			int time = msecs();
240 			bool execerr = false;
241 			if(rc) {
242 				String exec;
243 				String windres = "windres.exe";
244 				int q = compiler.ReverseFind('-'); // clang32 windres name is i686-w64-mingw32-windres.exe
245 				if(q > 0)
246 					windres = compiler.Mid(0, q + 1) + windres;
247 				exec << GetHostPath(FindInDirs(host->GetExecutablesDirs(), windres)) << " -i " << GetHostPathQ(fn);
248 				if(cc.Find(" -m32 ") >= 0)
249 					exec << " --target=pe-i386 ";
250 				exec << " -o " << GetHostPathQ(objfile) << Includes(" --include-dir=", package, pkg)
251 				     << DefinesTargetTime(" -D", package, pkg) + (HasFlag("DEBUG")?" -D_DEBUG":"");
252 				PutVerbose(exec);
253 				int slot = AllocSlot();
254 				execerr = (slot < 0 || !Run(exec, slot, GetHostPath(objfile), 1));
255 			}
256 			else if(brc) {
257 				try {
258 					String brcdata = LoadFile(fn);
259 					if(brcdata.IsVoid())
260 						throw Exc(Format("error reading file '%s'", fn));
261 					CParser parser(brcdata, fn);
262 					BinaryToObject(GetHostPath(objfile), parser, GetFileDirectory(fn), package, pkg);
263 				}
264 				catch(Exc e) {
265 					PutConsole(e);
266 					execerr = true;
267 				}
268 			}
269 			else {
270 				String exec = cc;
271 				if(ext == ".c")
272 					exec << Join(" -x c", c_options) << ' ';
273 				else if(ext == ".s" || ext == ".S")
274 					exec << " -x assembler-with-cpp ";
275 				else
276 				if (ext == ".m")
277 					exec << fuse_cxa_atexit << " -x objective-c ";
278 				else
279 				if (ext == ".mm")
280 					exec << fuse_cxa_atexit << Join(" -x objective-c++ ", cpp_options) << ' ';
281 				else {
282 					exec << fuse_cxa_atexit << Join(" -x c++", cpp_options) << ' ';
283 					exec << pch_use;
284 				}
285 				exec << GetHostPathQ(fn)  << " " << soptions[i] << " -o " << GetHostPathQ(objfile);
286 				PutVerbose(exec);
287 				int slot = AllocSlot();
288 				execerr = (slot < 0 || !Run(exec, slot, GetHostPath(objfile), 1));
289 			}
290 			if(execerr)
291 				DeleteFile(objfile);
292 			error |= execerr;
293 			PutVerbose("compiled in " + GetPrintTime(time));
294 			ccount++;
295 		}
296 		immfile.Add(objfile);
297 		if(init)
298 			linkfile.Add(objfile);
299 		else
300 			obj.Add(objfile);
301 	}
302 
303 	if(error) {
304 //		if(ccount)
305 //			PutCompileTime(time, ccount);
306 		IdeConsoleEndGroup();
307 		return false;
308 	}
309 
310 	MergeWith(linkoptions, " ", Gather(pkg.link, config.GetKeys()));
311 	if(linkoptions.GetCount())
312 		linkoptions << ' ';
313 
314 	Vector<String> libs = Split(Gather(pkg.library, config.GetKeys()), ' ');
315 	linkfile.Append(libs);
316 
317 	if(pch_file.GetCount())
318 		OnFinish(callback1(DeletePCHFile, pch_file));
319 
320 	int libtime = msecs();
321 	if(!HasFlag("MAIN")) {
322 		if(HasFlag("BLITZ") && !HasFlag("SO")  || HasFlag("NOLIB")) {
323 			linkfile.Append(obj); // Simply link everything as .o files...
324 			IdeConsoleEndGroup();
325 //			if(ccount)
326 //				PutCompileTime(time, ccount);
327 			return true;
328 		}
329 		IdeConsoleEndGroup();
330 		if(!Wait())
331 			return false;
332 		String product;
333 		if(is_shared)
334 			product = GetSharedLibPath(package);
335 		else
336 			product = CatAnyPath(outdir, GetAnyFileName(package) + ".a");
337 		String hproduct = GetHostPath(product);
338 		Time producttime = GetFileTime(hproduct);
339 //		LOG("hproduct = " << hproduct << ", time = " << producttime);
340 		if(obj.GetCount()) {
341 			linkfile.Add(GetHostPath(product));
342 			immfile.Add(GetHostPath(product));
343 		}
344 		for(int i = 0; i < obj.GetCount(); i++)
345 			if(GetFileTime(obj[i]) > producttime) {
346 				String lib;
347 				if(is_shared) {
348 					lib = CompilerName();
349 					lib << " -shared -fPIC -fuse-cxa-atexit";
350 					if(!HasFlag("SHARED") && !is_shared)
351 						lib << " -static";
352 //					else if(!HasFlag("WIN32")) // TRC 05/03/08: dynamic fPIC causes trouble in MinGW
353 //						lib << " -dynamic -fPIC"; // TRC 05/03/30: dynamic fPIC doesn't seem to work in GCC either :-)
354 					if(HasFlag("GCC32"))
355 						lib << " -m32";
356 					Point p = ExtractVersion();
357 					if(!IsNull(p.x) && HasFlag("WIN32")) {
358 						lib << " -Xlinker --major-image-version -Xlinker " << p.x;
359 						if(!IsNull(p.y))
360 							lib << " -Xlinker --minor-image-version -Xlinker " << p.y;
361 					}
362 					lib << ' ' << Gather(pkg.link, config.GetKeys());
363 
364 					lib << " -o ";
365 				}
366 				else
367 					lib = "ar -sr ";
368 				lib << GetHostPathQ(product);
369 
370 
371 				String llib;
372 				for(int i = 0; i < obj.GetCount(); i++)
373 					llib << ' ' << GetHostPathQ(obj[i]);
374 				PutConsole("Creating library...");
375 				DeleteFile(hproduct);
376 				if(is_shared) {
377 					for(int i = 0; i < libpath.GetCount(); i++)
378 						llib << " -L" << GetHostPathQ(libpath[i]);
379 					for(int i = 0; i < all_uses.GetCount(); i++)
380 						llib << ' ' << GetHostPathQ(GetSharedLibPath(all_uses[i]));
381 					for(int i = 0; i < all_libraries.GetCount(); i++)
382 						llib << " -l" << GetHostPathQ(all_libraries[i]);
383 
384 					if(HasFlag("POSIX"))
385 						llib << " -Wl,-soname," << GetSoname(product);
386 				}
387 
388 				String tmpFileName;
389 				if(HasFlag("LINUX") || HasFlag("WIN32")) {
390 					if(lib.GetCount() + llib.GetCount() >= 8192)
391 					{
392 						tmpFileName = GetTempFileName();
393 						// we can't simply put all data on a single line
394 						// as it has a limit of around 130000 chars too, so we split
395 						// in multiple lines
396 						FileOut f(tmpFileName);
397 						while(llib != "")
398 						{
399 							int found = 0;
400 							bool quotes = false;
401 							int lim = min(8192, llib.GetCount());
402 							for(int i = 0; i < lim; i++)
403 							{
404 								char c = llib[i];
405 								if(isspace(c) && !quotes)
406 									found = i;
407 								else if(c == '"')
408 									quotes = !quotes;
409 							}
410 							if(!found)
411 								found = llib.GetCount();
412 
413 							// replace all '\' with '/'`
414 							llib = UnixPath(llib);
415 
416 							f.PutLine(llib.Left(found));
417 							llib.Remove(0, found);
418 						}
419 						f.Close();
420 						lib << " @" << tmpFileName;
421 					}
422 					else
423 						lib << llib;
424 				}
425 				else
426 					lib << llib;
427 
428 				int res = Execute(lib);
429 				if(tmpFileName.GetCount())
430 					FileDelete(tmpFileName);
431 				String folder, libF, soF, linkF;
432 				if(HasFlag("POSIX")) {
433 					if(is_shared)
434 					{
435 						folder = GetFileFolder(hproduct);
436 						libF = GetFileName(hproduct);
437 						soF = AppendFileName(folder, GetSoname(hproduct));
438 						linkF = AppendFileName(folder, GetSoLinkName(hproduct));
439 					}
440 				}
441 				if(res) {
442 					DeleteFile(hproduct);
443 					if(HasFlag("POSIX")) {
444 						if(is_shared) {
445 							DeleteFile(libF);
446 							DeleteFile(linkF);
447 						}
448 					}
449 					return false;
450 				}
451 #ifdef PLATFORM_POSIX // we do not have symlink in Win32....
452 				if(HasFlag("POSIX")) {
453 					if(is_shared)
454 					{
455 						int r;
456 						r = symlink(libF, soF);
457 						r = symlink(libF, linkF);
458 						(void)r;
459 					}
460 				}
461 #endif
462 				PutConsole(String().Cat() << hproduct << " (" << GetFileInfo(hproduct).length
463 				           << " B) created in " << GetPrintTime(libtime));
464 				break;
465 			}
466 		return true;
467 	}
468 
469 	IdeConsoleEndGroup();
470 	obj.Append(linkfile);
471 	linkfile = pick(obj);
472 	return true;
473 }
474 
475 
Link(const Vector<String> & linkfile,const String & linkoptions,bool createmap)476 bool GccBuilder::Link(const Vector<String>& linkfile, const String& linkoptions, bool createmap)
477 {
478 	if(!Wait())
479 		return false;
480 	PutLinking();
481 	int time = msecs();
482 #ifdef PLATFORM_OSX
483 	CocoaAppBundle();
484 #endif
485 	for(int i = 0; i < linkfile.GetCount(); i++)
486 		if(GetFileTime(linkfile[i]) > targettime) {
487 			Vector<String> lib;
488 			String lnk = CompilerName();
489 //			if(IsVerbose())
490 //				lnk << " -v";
491 			if(HasFlag("GCC32"))
492 				lnk << " -m32";
493 			if(HasFlag("DLL"))
494 				lnk << " -shared";
495 			if(!HasFlag("SHARED") && !HasFlag("SO"))
496 				lnk << " -static";
497 			if(HasFlag("WINCE"))
498 				lnk << " -mwindowsce";
499 			else if(HasFlag("WIN32")) {
500 				lnk << " -mthreads";
501 				if(HasFlag("CLANG")) {
502 					if(HasFlag("GUI"))
503 						lnk << " -mwindows";
504 					else
505 						lnk << " -mconsole";
506 				}
507 				else {
508 					lnk << " -mwindows";
509 					// if(HasFlag("MT"))
510 					if(!HasFlag("GUI"))
511 						lnk << " -mconsole";
512 				}
513 			}
514 			lnk << " -o " << GetHostPathQ(target);
515 			if(createmap)
516 				lnk << " -Wl,-Map," << GetHostPathQ(GetFileDirectory(target) + GetFileTitle(target) + ".map");
517 			if(HasFlag("DEBUG_MINIMAL") || HasFlag("DEBUG_FULL"))
518 				lnk << (HasFlag("CLANG") && HasFlag("WIN32") ? " -Wl,-pdb=" : " -ggdb");
519 			else
520 				lnk << (!HasFlag("OSX") ? " -Wl,-s" : "");
521 			for(i = 0; i < libpath.GetCount(); i++)
522 				lnk << " -L" << GetHostPathQ(libpath[i]);
523 			MergeWith(lnk, " ", linkoptions);
524 			String lfilename;
525 			if(HasFlag("OBJC")) {
526 				String lfilename;
527 				String linklist;
528 				for(i = 0; i < linkfile.GetCount(); i++)
529 					if(ToLower(GetFileExt(linkfile[i])) == ".o" || ToLower(GetFileExt(linkfile[i])) == ".a")
530 						linklist << GetHostPath(linkfile[i]) << '\n';
531 
532 				String linklistM = "Producing link file list ...\n";
533 				String odir = GetFileDirectory(linkfile[0]);
534 				lfilename << GetHostPath(GetFileFolder(linkfile[0])) << ".LinkFileList";
535 
536 				linklistM  << lfilename;
537 				UPP::SaveFile(lfilename, linklist);
538 				lnk << " -L" << GetHostPathQ(odir)
539 				    << " -F" << GetHostPathQ(odir)
540 				          << " -filelist " << lfilename << " ";
541 				PutConsole( linklistM );
542 			}
543 			else
544 				for(i = 0; i < linkfile.GetCount(); i++) {
545 					if(ToLower(GetFileExt(linkfile[i])) == ".o")
546 						lnk  << ' ' << GetHostPathQ(linkfile[i]);
547 					else
548 						lib.Add(linkfile[i]);
549 				}
550 			if(!HasFlag("SOLARIS") && !HasFlag("OSX") && !HasFlag("OBJC"))
551 				lnk << " -Wl,--start-group ";
552 			for(String s : pkg_config)
553 				lnk << " `pkg-config --libs " << s << "`";
554 			for(int pass = 0; pass < 2; pass++) {
555 				for(i = 0; i < lib.GetCount(); i++) {
556 					String ln = lib[i];
557 					String ext = ToLower(GetFileExt(ln));
558 
559 					// unix shared libs shall have version number AFTER .so (sic)
560 					// so we shall find the true extension....
561 					if(HasFlag("POSIX") && ext != ".so")
562 					{
563 						const char *c = ln.Last();
564 						while(--c >= ~ln)
565 							if(!IsDigit(*c) && *c != '.')
566 								break;
567 						int pos = int(c - ~ln - 2);
568 						if(pos >= 0 && ToLower(ln.Mid(pos, 3)) == ".so")
569 							ext = ".so";
570 					}
571 
572 					if(pass == 0) {
573 						if(ext == ".a")
574 							lnk << ' ' << GetHostPathQ(FindInDirs(libpath, lib[i]));
575 					}
576 					else
577 						if(ext != ".a") {
578 							if(ext == ".so" || ext == ".dll" || ext == ".lib")
579 								lnk << ' ' << GetHostPathQ(FindInDirs(libpath, lib[i]));
580 							else
581 								lnk << " -l" << ln;
582 						}
583 				}
584 				if(pass == 1 && !HasFlag("SOLARIS") && !HasFlag("OSX"))
585 					lnk << " -Wl,--end-group";
586 			}
587 			PutConsole("Linking...");
588 			bool error = false;
589 			CustomStep(".pre-link", Null, error);
590 			if(!error && Execute(lnk) == 0) {
591 				CustomStep(".post-link", Null, error);
592 				PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
593 				           << " B) linked in " << GetPrintTime(time));
594 				return !error;
595 			}
596 			else {
597 				DeleteFile(target);
598 				return false;
599 			}
600 		}
601 
602 	PutConsole(String().Cat() << GetHostPath(target) << " (" << GetFileInfo(target).length
603 	           << " B) is up to date.");
604 	return true;
605 }
606 
Preprocess(const String & package,const String & file,const String & target,bool asmout)607 bool GccBuilder::Preprocess(const String& package, const String& file, const String& target, bool asmout)
608 {
609 	Package pkg;
610 	String packagePath = PackagePath(package);
611 	pkg.Load(packagePath);
612 	String packageDir = GetFileFolder(packagePath);
613 	ChDir(packageDir);
614 	PutVerbose("cd " + packageDir);
615 
616 	String cmd = CmdLine(package, pkg);
617 	cmd << " " << Gather(pkg.option, config.GetKeys());
618 	cmd << " -o " << target;
619 	cmd << (asmout ? " -S " : " -E ") << GetHostPathQ(file);
620 	if(BuilderUtils::IsCFile(file))
621 		cmd << " " << c_options;
622 	else
623 	if(BuilderUtils::IsCppFile(file))
624 		cmd << " " << cpp_options;
625 	return Execute(cmd);
626 }
627 
CreateGccBuilder()628 Builder *CreateGccBuilder()
629 {
630 	return new GccBuilder;
631 }
632 
INITIALIZER(GccBuilder)633 INITIALIZER(GccBuilder)
634 {
635 	RegisterBuilder("GCC", CreateGccBuilder);
636 	RegisterBuilder("CLANG", CreateGccBuilder);
637 }
638