1 | /* |
2 | * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com) |
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 3 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, see <https://www.gnu.org/licenses/>. |
16 | */ |
17 | #include "projectcompiler.h" |
18 | #include "../project.h" |
19 | #include "compilermanager.h" |
20 | #include "../systemconsts.h" |
21 | #include "qt_utils/charsetinfo.h" |
22 | #include "../editor.h" |
23 | |
24 | #include <QDir> |
25 | |
26 | ProjectCompiler::ProjectCompiler(std::shared_ptr<Project> project, bool silent, bool onlyCheckSyntax): |
27 | Compiler("" ,silent,onlyCheckSyntax), |
28 | mOnlyClean(false) |
29 | { |
30 | setProject(project); |
31 | } |
32 | |
33 | void ProjectCompiler::buildMakeFile() |
34 | { |
35 | //we are using custom make file, don't overwrite it |
36 | if (!mProject->options().customMakefile.isEmpty()) |
37 | return; |
38 | |
39 | switch(mProject->options().type) { |
40 | case ProjectType::StaticLib: |
41 | createStaticMakeFile(); |
42 | break; |
43 | case ProjectType::DynamicLib: |
44 | createDynamicMakeFile(); |
45 | break; |
46 | default: |
47 | createStandardMakeFile(); |
48 | } |
49 | } |
50 | |
51 | void ProjectCompiler::createStandardMakeFile() |
52 | { |
53 | QFile file(mProject->makeFileName()); |
54 | newMakeFile(file); |
55 | file.write("$(BIN): $(OBJ)\n" ); |
56 | if (!mOnlyCheckSyntax) { |
57 | if (mProject->options().isCpp) { |
58 | writeln(file,"\t$(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)" ); |
59 | } else |
60 | writeln(file,"\t$(CC) $(LINKOBJ) -o $(BIN) $(LIBS)" ); |
61 | } |
62 | writeMakeObjFilesRules(file); |
63 | } |
64 | |
65 | void ProjectCompiler::createStaticMakeFile() |
66 | { |
67 | QFile file(mProject->makeFileName()); |
68 | newMakeFile(file); |
69 | writeln(file,"$(BIN): $(LINKOBJ)" ); |
70 | if (!mOnlyCheckSyntax) { |
71 | writeln(file,"\tar r $(BIN) $(LINKOBJ)" ); |
72 | writeln(file,"\tranlib $(BIN)" ); |
73 | } |
74 | writeMakeObjFilesRules(file); |
75 | } |
76 | |
77 | void ProjectCompiler::createDynamicMakeFile() |
78 | { |
79 | QFile file(mProject->makeFileName()); |
80 | newMakeFile(file); |
81 | writeln(file,"$(BIN): $(LINKOBJ)" ); |
82 | if (!mOnlyCheckSyntax) { |
83 | if (mProject->options().isCpp) { |
84 | file.write("\t$(CPP) -mdll $(LINKOBJ) -o $(BIN) $(LIBS) -Wl,--output-def,$(DEF),--out-implib,$(STATIC)" ); |
85 | } else { |
86 | file.write("\t$(CC) -mdll $(LINKOBJ) -o $(BIN) $(LIBS) -Wl,--output-def,$(DEF),--out-implib,$(STATIC)" ); |
87 | } |
88 | } |
89 | writeMakeObjFilesRules(file); |
90 | } |
91 | |
92 | void ProjectCompiler::newMakeFile(QFile& file) |
93 | { |
94 | // Create OBJ output directory |
95 | if (!mProject->options().objectOutput.isEmpty()) { |
96 | QDir(mProject->directory()).mkpath(mProject->options().objectOutput); |
97 | } |
98 | |
99 | // Write more information to the log file than before |
100 | log(tr("Building makefile..." )); |
101 | log("--------" ); |
102 | log(tr("- Filename: %1" ).arg(mProject->makeFileName())); |
103 | |
104 | // Create the actual file |
105 | if (!file.open(QFile::WriteOnly | QFile::Truncate)) |
106 | throw CompileError(tr("Can't open '%1' for write!" ).arg(mProject->makeFileName())); |
107 | |
108 | // Write header |
109 | writeMakeHeader(file); |
110 | |
111 | // Writes definition list |
112 | writeMakeDefines(file); |
113 | |
114 | // Write PHONY and all targets |
115 | writeMakeTarget(file); |
116 | |
117 | // Write list of includes |
118 | writeMakeIncludes(file); |
119 | |
120 | // Write clean command |
121 | writeMakeClean(file); |
122 | } |
123 | |
124 | void ProjectCompiler::(QFile &file) |
125 | { |
126 | writeln(file,"# Project: " + mProject->name()); |
127 | writeln(file,QString("# Makefile created by Red Panda C++ " ) + REDPANDA_CPP_VERSION); |
128 | writeln(file); |
129 | if (mOnlyCheckSyntax) { |
130 | writeln(file,"# This Makefile is written for syntax check!" ); |
131 | writeln(file,"# Regenerate it if you want to use this Makefile to build." ); |
132 | writeln(file); |
133 | } |
134 | } |
135 | |
136 | void ProjectCompiler::writeMakeDefines(QFile &file) |
137 | { |
138 | // Get list of object files |
139 | QString Objects; |
140 | QString LinkObjects; |
141 | QString cleanObjects; |
142 | |
143 | // Create a list of object files |
144 | for (int i=0;i<mProject->units().count();i++) { |
145 | PProjectUnit unit = mProject->units()[i]; |
146 | if (!unit->compile() && !unit->link()) |
147 | continue; |
148 | |
149 | // Only process source files |
150 | QString RelativeName = extractRelativePath(mProject->directory(), unit->fileName()); |
151 | FileType fileType = getFileType(RelativeName); |
152 | if (fileType == FileType::CSource || fileType == FileType::CppSource) { |
153 | if (!mProject->options().objectOutput.isEmpty()) { |
154 | // ofile = C:\MyProgram\obj\main.o |
155 | QString fullObjFile = includeTrailingPathDelimiter(mProject->options().objectOutput) |
156 | + extractFileName(unit->fileName()); |
157 | QString relativeObjFile = extractRelativePath(mProject->directory(), changeFileExt(fullObjFile, OBJ_EXT)); |
158 | QString ObjFile = genMakePath2(relativeObjFile); |
159 | Objects += ' ' + ObjFile; |
160 | #ifdef Q_OS_WIN |
161 | cleanObjects += ' ' + genMakePath1(relativeObjFile).replace("/" ,QDir::separator()); |
162 | #else |
163 | cleanObjects += ' ' + genMakePath1(relativeObjFile); |
164 | #endif |
165 | if (unit->link()) { |
166 | LinkObjects += ' ' + genMakePath1(relativeObjFile); |
167 | } |
168 | } else { |
169 | Objects += ' ' + genMakePath2(changeFileExt(RelativeName, OBJ_EXT)); |
170 | #ifdef Q_OS_WIN |
171 | cleanObjects += ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT)).replace("/" ,QDir::separator()); |
172 | #else |
173 | cleanObjects += ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT)); |
174 | #endif |
175 | if (unit->link()) |
176 | LinkObjects = LinkObjects + ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT)); |
177 | } |
178 | } |
179 | } |
180 | |
181 | Objects = Objects.trimmed(); |
182 | LinkObjects = LinkObjects.trimmed(); |
183 | |
184 | // Get windres file |
185 | QString ObjResFile; |
186 | #ifdef Q_OS_WIN |
187 | if (!mProject->options().privateResource.isEmpty()) { |
188 | if (!mProject->options().objectOutput.isEmpty()) { |
189 | ObjResFile = includeTrailingPathDelimiter(mProject->options().objectOutput) + |
190 | changeFileExt(mProject->options().privateResource, RES_EXT); |
191 | } else |
192 | ObjResFile = changeFileExt(mProject->options().privateResource, RES_EXT); |
193 | } |
194 | #endif |
195 | |
196 | // Mention progress in the logs |
197 | if (!ObjResFile.isEmpty()) { |
198 | log(tr("- Resource File: %1" ).arg(QDir(mProject->directory()).absoluteFilePath(ObjResFile))); |
199 | } |
200 | log("" ); |
201 | |
202 | // Get list of applicable flags |
203 | QString cCompileArguments = getCCompileArguments(mOnlyCheckSyntax); |
204 | QString cppCompileArguments = getCppCompileArguments(mOnlyCheckSyntax); |
205 | QString libraryArguments = getLibraryArguments(FileType::Project); |
206 | QString cIncludeArguments = getCIncludeArguments() + " " + getProjectIncludeArguments(); |
207 | QString cppIncludeArguments = getCppIncludeArguments() + " " +getProjectIncludeArguments(); |
208 | |
209 | if (cCompileArguments.indexOf(" -g3" )>=0 |
210 | || cCompileArguments.startsWith("-g3" )) { |
211 | cCompileArguments += " -D__DEBUG__" ; |
212 | cppCompileArguments+= " -D__DEBUG__" ; |
213 | } |
214 | writeln(file,"CPP = " + extractFileName(compilerSet()->cppCompiler())); |
215 | writeln(file,"CC = " + extractFileName(compilerSet()->CCompiler())); |
216 | #ifdef Q_OS_WIN |
217 | writeln(file,"WINDRES = " + extractFileName(compilerSet()->resourceCompiler())); |
218 | #endif |
219 | if (!ObjResFile.isEmpty()) { |
220 | writeln(file,"RES = " + genMakePath1(ObjResFile)); |
221 | writeln(file,"OBJ = " + Objects + " $(RES)" ); |
222 | writeln(file,"LINKOBJ = " + LinkObjects + " $(RES)" ); |
223 | #ifdef Q_OS_WIN |
224 | writeln(file,"CLEANOBJ = " + cleanObjects + |
225 | " " + genMakePath1(ObjResFile).replace("/" ,QDir::separator()) |
226 | + " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())).replace("/" ,QDir::separator()) ); |
227 | #else |
228 | writeln(file,"CLEANOBJ = " + cleanObjects + |
229 | " " + genMakePath1(ObjResFile) |
230 | + " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable()))); |
231 | #endif |
232 | } else { |
233 | writeln(file,"OBJ = " + Objects); |
234 | writeln(file,"LINKOBJ = " + LinkObjects); |
235 | #ifdef Q_OS_WIN |
236 | writeln(file,"CLEANOBJ = " + cleanObjects + |
237 | + " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())).replace("/" ,QDir::separator()) ); |
238 | #else |
239 | writeln(file,"CLEANOBJ = " + cleanObjects + |
240 | + " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable()))); |
241 | #endif |
242 | }; |
243 | libraryArguments.replace('\\', '/'); |
244 | writeln(file,"LIBS = " + libraryArguments); |
245 | cIncludeArguments.replace('\\', '/'); |
246 | writeln(file,"INCS = " + cIncludeArguments); |
247 | cppIncludeArguments.replace('\\', '/'); |
248 | writeln(file,"CXXINCS = " + cppIncludeArguments); |
249 | writeln(file,"BIN = " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable()))); |
250 | cppCompileArguments.replace('\\', '/'); |
251 | writeln(file,"CXXFLAGS = $(CXXINCS) " + cppCompileArguments); |
252 | //writeln(file,"ENCODINGS = -finput-charset=utf-8 -fexec-charset='+GetSystemCharsetName); |
253 | cCompileArguments.replace('\\', '/'); |
254 | writeln(file,"CFLAGS = $(INCS) " + cCompileArguments); |
255 | writeln(file, QString("RM = " ) + CLEAN_PROGRAM ); |
256 | if (mProject->options().usePrecompiledHeader){ |
257 | writeln(file,"PCH_H = " + mProject->options().precompiledHeader ); |
258 | writeln(file,"PCH = " + changeFileExt(mProject->options().precompiledHeader, GCH_EXT)); |
259 | } |
260 | |
261 | |
262 | // This needs to be put in before the clean command. |
263 | if (mProject->options().type == ProjectType::DynamicLib) { |
264 | QString OutputFileDir = extractFilePath(mProject->executable()); |
265 | QString libOutputFile = includeTrailingPathDelimiter(OutputFileDir) + "lib" + extractFileName(mProject->executable()); |
266 | if (QFileInfo(libOutputFile).absoluteFilePath() |
267 | == mProject->directory()) |
268 | libOutputFile = extractFileName(libOutputFile); |
269 | else |
270 | libOutputFile = extractRelativePath(mProject->makeFileName(), libOutputFile); |
271 | writeln(file,"DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT))); |
272 | writeln(file,"STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT))); |
273 | #ifdef Q_OS_WIN |
274 | writeln(file,"CLEAN_DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT)).replace("/" ,QDir::separator())); |
275 | writeln(file,"CLEAN_STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT)).replace("/" ,QDir::separator())); |
276 | #else |
277 | writeln(file,"CLEAN_DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT))); |
278 | writeln(file,"CLEAN_STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT))); |
279 | #endif |
280 | } |
281 | writeln(file); |
282 | } |
283 | |
284 | void ProjectCompiler::writeMakeTarget(QFile &file) |
285 | { |
286 | if (mOnlyCheckSyntax) |
287 | writeln(file, ".PHONY: all all-before all-after clean clean-custom $(OBJ) $(BIN)" ); |
288 | else |
289 | writeln(file, ".PHONY: all all-before all-after clean clean-custom" ); |
290 | writeln(file); |
291 | writeln(file, "all: all-before $(BIN) all-after" ); |
292 | writeln(file); |
293 | if (mProject->options().usePrecompiledHeader) { |
294 | writeln(file, "$(PCH) : $(PCH_H)" ); |
295 | writeln(file, " $(CPP) -x c++-header \"$(PCH_H)\" -o \"$(PCH)\" $(CXXFLAGS)" ); |
296 | writeln(file); |
297 | } |
298 | } |
299 | |
300 | void ProjectCompiler::writeMakeIncludes(QFile &file) |
301 | { |
302 | foreach(const QString& s, mProject->options().makeIncludes) { |
303 | writeln(file, "include " + genMakePath1(s)); |
304 | } |
305 | if (!mProject->options().makeIncludes.isEmpty()) { |
306 | writeln(file); |
307 | } |
308 | } |
309 | |
310 | void ProjectCompiler::writeMakeClean(QFile &file) |
311 | { |
312 | writeln(file, "clean: clean-custom" ); |
313 | if (mProject->options().type == ProjectType::DynamicLib) |
314 | writeln(file, QString("\t${RM} $(CLEANOBJ) $(CLEAN_DEF) $(CLEAN_STATIC) > %1 2>&1" ).arg(NULL_FILE)); |
315 | else |
316 | writeln(file, QString("\t${RM} $(CLEANOBJ) > %1 2>&1" ).arg(NULL_FILE)); |
317 | writeln(file); |
318 | } |
319 | |
320 | void ProjectCompiler::writeMakeObjFilesRules(QFile &file) |
321 | { |
322 | PCppParser parser = mProject->cppParser(); |
323 | QString precompileStr; |
324 | if (mProject->options().usePrecompiledHeader) |
325 | precompileStr = " $(PCH) " ; |
326 | |
327 | for (int i = 0;i<mProject->units().count();i++) { |
328 | PProjectUnit unit = mProject->units()[i]; |
329 | FileType fileType = getFileType(unit->fileName()); |
330 | // Only process source files |
331 | if (fileType!=FileType::CSource && fileType!=FileType::CppSource) |
332 | continue; |
333 | |
334 | QString shortFileName = extractRelativePath(mProject->makeFileName(),unit->fileName()); |
335 | |
336 | writeln(file); |
337 | QString objStr=genMakePath2(shortFileName); |
338 | // if we have scanned it, use scanned info |
339 | if (parser && parser->scannedFiles().contains(unit->fileName())) { |
340 | QSet<QString> fileIncludes = parser->getFileIncludes(unit->fileName()); |
341 | foreach (const QString& , fileIncludes) { |
342 | if (headerName == unit->fileName()) |
343 | continue; |
344 | if (!parser->isSystemHeaderFile(headerName) |
345 | && ! parser->isProjectHeaderFile(headerName)) { |
346 | for (int j = 0;j<mProject->units().count();j++) { |
347 | PProjectUnit unit2 = mProject->units()[j]; |
348 | if (unit2->fileName()==headerName) { |
349 | objStr = objStr + ' ' + genMakePath2(extractRelativePath(mProject->makeFileName(),headerName)); |
350 | break; |
351 | } |
352 | } |
353 | } |
354 | } |
355 | } else { |
356 | foreach (const PProjectUnit& u, mProject->units()) { |
357 | FileType fileType = getFileType(u->fileName()); |
358 | if (fileType == FileType::CHeader || fileType==FileType::CppHeader) |
359 | objStr = objStr + ' ' + genMakePath2(extractRelativePath(mProject->makeFileName(),u->fileName())); |
360 | } |
361 | } |
362 | QString ObjFileName; |
363 | QString ObjFileName2; |
364 | if (!mProject->options().objectOutput.isEmpty()) { |
365 | ObjFileName = includeTrailingPathDelimiter(mProject->options().objectOutput) + |
366 | extractFileName(unit->fileName()); |
367 | ObjFileName = genMakePath2(extractRelativePath(mProject->makeFileName(), changeFileExt(ObjFileName, OBJ_EXT))); |
368 | ObjFileName2 = genMakePath1(extractRelativePath(mProject->makeFileName(), changeFileExt(ObjFileName, OBJ_EXT))); |
369 | // if (!extractFileDir(ObjFileName).isEmpty()) { |
370 | // objStr = genMakePath2(includeTrailingPathDelimiter(extractFileDir(ObjFileName))) + objStr; |
371 | // } |
372 | } else { |
373 | ObjFileName = genMakePath2(changeFileExt(shortFileName, OBJ_EXT)); |
374 | ObjFileName2 = genMakePath1(changeFileExt(shortFileName, OBJ_EXT)); |
375 | } |
376 | |
377 | objStr = ObjFileName + ": " +objStr+precompileStr; |
378 | |
379 | writeln(file,objStr); |
380 | |
381 | // Write custom build command |
382 | if (unit->overrideBuildCmd() && !unit->buildCmd().isEmpty()) { |
383 | QString BuildCmd = unit->buildCmd(); |
384 | BuildCmd.replace("<CRTAB>" , "\n\t" ); |
385 | writeln(file, '\t' + BuildCmd); |
386 | // Or roll our own |
387 | } else { |
388 | QString encodingStr; |
389 | if (compilerSet()->compilerType() != COMPILER_CLANG && mProject->options().addCharset) { |
390 | QByteArray defaultSystemEncoding=pCharsetInfoManager->getDefaultSystemEncoding(); |
391 | QByteArray encoding = mProject->options().execEncoding; |
392 | QByteArray targetEncoding; |
393 | QByteArray sourceEncoding; |
394 | if ( encoding == ENCODING_SYSTEM_DEFAULT || encoding.isEmpty()) { |
395 | targetEncoding = defaultSystemEncoding; |
396 | } else if (encoding == ENCODING_UTF8_BOM) { |
397 | targetEncoding = "UTF-8" ; |
398 | } else { |
399 | targetEncoding = encoding; |
400 | } |
401 | |
402 | if (unit->encoding() == ENCODING_AUTO_DETECT) { |
403 | Editor* editor = mProject->unitEditor(unit); |
404 | if (editor && editor->fileEncoding()!=ENCODING_ASCII |
405 | && editor->fileEncoding()!=targetEncoding) { |
406 | sourceEncoding = editor->fileEncoding(); |
407 | } else { |
408 | sourceEncoding = targetEncoding; |
409 | } |
410 | } else if (unit->encoding()==ENCODING_SYSTEM_DEFAULT) { |
411 | sourceEncoding = defaultSystemEncoding; |
412 | } else if (unit->encoding()!=ENCODING_ASCII && !unit->encoding().isEmpty() |
413 | && unit->encoding()!=targetEncoding) { |
414 | sourceEncoding = unit->encoding(); |
415 | } |
416 | |
417 | if (sourceEncoding!=targetEncoding) { |
418 | encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2" ) |
419 | .arg(QString(sourceEncoding), |
420 | QString(targetEncoding)); |
421 | } |
422 | } |
423 | |
424 | if (mOnlyCheckSyntax) { |
425 | if (unit->compileCpp()) |
426 | writeln(file, "\t$(CPP) -c " + genMakePath1(unit->fileName()) + " $(CXXFLAGS) " + encodingStr); |
427 | else |
428 | writeln(file, "\t(CC) -c " + genMakePath1(unit->fileName()) + " $(CFLAGS) " + encodingStr); |
429 | } else { |
430 | if (unit->compileCpp()) |
431 | writeln(file, "\t$(CPP) -c " + genMakePath1(unit->fileName()) + " -o " + ObjFileName2 + " $(CXXFLAGS) " + encodingStr); |
432 | else |
433 | writeln(file, "\t$(CC) -c " + genMakePath1(unit->fileName()) + " -o " + ObjFileName2 + " $(CFLAGS) " + encodingStr); |
434 | } |
435 | } |
436 | } |
437 | |
438 | #ifdef Q_OS_WIN |
439 | if (!mProject->options().privateResource.isEmpty()) { |
440 | |
441 | // Concatenate all resource include directories |
442 | QString ResIncludes(" " ); |
443 | for (int i=0;i<mProject->options().resourceIncludes.count();i++) { |
444 | QString filename = mProject->options().resourceIncludes[i]; |
445 | if (!filename.isEmpty()) |
446 | ResIncludes = ResIncludes + " --include-dir " + genMakePath1(filename); |
447 | } |
448 | |
449 | QString ResFiles; |
450 | // Concatenate all resource filenames (not created when syntax checking) |
451 | if (!mOnlyCheckSyntax) { |
452 | foreach(const PProjectUnit& unit, mProject->units()) { |
453 | if (getFileType(unit->fileName())!=FileType::WindowsResourceSource) |
454 | continue; |
455 | if (fileExists(unit->fileName())) { |
456 | QString ResFile = extractRelativePath(mProject->makeFileName(), unit->fileName()); |
457 | ResFiles = ResFiles + genMakePath2(ResFile) + ' '; |
458 | } |
459 | } |
460 | ResFiles = ResFiles.trimmed(); |
461 | } |
462 | |
463 | // Determine resource output file |
464 | QString ObjFileName; |
465 | if (!mProject->options().objectOutput.isEmpty()) { |
466 | ObjFileName = includeTrailingPathDelimiter(mProject->options().objectOutput) + |
467 | changeFileExt(mProject->options().privateResource, RES_EXT); |
468 | } else { |
469 | ObjFileName = changeFileExt(mProject->options().privateResource, RES_EXT); |
470 | } |
471 | ObjFileName = genMakePath1(extractRelativePath(mProject->filename(), ObjFileName)); |
472 | QString PrivResName = genMakePath1(extractRelativePath(mProject->filename(), mProject->options().privateResource)); |
473 | |
474 | // Build final cmd |
475 | QString WindresArgs; |
476 | if (getCCompileArguments(mOnlyCheckSyntax).contains("-m32" )) |
477 | WindresArgs = " -F pe-i386" ; |
478 | |
479 | if (mOnlyCheckSyntax) { |
480 | writeln(file); |
481 | writeln(file, ObjFileName + ':'); |
482 | writeln(file, "\t$(WINDRES) -i " + PrivResName + WindresArgs + " --input-format=rc -o nul -O coff" + ResIncludes); |
483 | } else { |
484 | writeln(file); |
485 | writeln(file, ObjFileName + ": " + PrivResName + ' ' + ResFiles); |
486 | writeln(file, "\t$(WINDRES) -i " + PrivResName + WindresArgs + " --input-format=rc -o " + ObjFileName + " -O coff" |
487 | + ResIncludes); |
488 | } |
489 | writeln(file); |
490 | } |
491 | #endif |
492 | } |
493 | |
494 | void ProjectCompiler::writeln(QFile &file, const QString &s) |
495 | { |
496 | if (!s.isEmpty()) |
497 | file.write(s.toLocal8Bit()); |
498 | file.write("\n" ); |
499 | } |
500 | |
501 | bool ProjectCompiler::onlyClean() const |
502 | { |
503 | return mOnlyClean; |
504 | } |
505 | |
506 | void ProjectCompiler::setOnlyClean(bool newOnlyClean) |
507 | { |
508 | mOnlyClean = newOnlyClean; |
509 | } |
510 | |
511 | bool ProjectCompiler::prepareForRebuild() |
512 | { |
513 | //we use make argument to clean |
514 | return true; |
515 | } |
516 | |
517 | bool ProjectCompiler::prepareForCompile() |
518 | { |
519 | if (!mProject) |
520 | return false; |
521 | //initProgressForm(); |
522 | log(tr("Compiling project changes..." )); |
523 | log("--------" ); |
524 | log(tr("- Project Filename: %1" ).arg(mProject->filename())); |
525 | log(tr("- Compiler Set Name: %1" ).arg(compilerSet()->name())); |
526 | log("" ); |
527 | |
528 | buildMakeFile(); |
529 | |
530 | mCompiler = compilerSet()->make(); |
531 | if (mOnlyClean) { |
532 | mArguments = QString("-f \"%1\" clean" ).arg(extractRelativePath( |
533 | mProject->directory(), |
534 | mProject->makeFileName())); |
535 | } else if (mRebuild) { |
536 | mArguments = QString("-f \"%1\" clean all" ).arg(extractRelativePath( |
537 | mProject->directory(), |
538 | mProject->makeFileName())); |
539 | } else { |
540 | mArguments = QString("-f \"%1\" all" ).arg(extractRelativePath( |
541 | mProject->directory(), |
542 | mProject->makeFileName())); |
543 | } |
544 | mDirectory = mProject->directory(); |
545 | |
546 | log(tr("Processing makefile:" )); |
547 | log("--------" ); |
548 | log(tr("- makefile processer: %1" ).arg(mCompiler)); |
549 | log(tr("- Command: %1 %2" ).arg(extractFileName(mCompiler)).arg(mArguments)); |
550 | log("" ); |
551 | |
552 | return true; |
553 | } |
554 | |