2021-12-26 23:18:28 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2021-09-13 07:49:36 +08:00
|
|
|
#include "projectcompiler.h"
|
2021-09-13 22:45:50 +08:00
|
|
|
#include "../project.h"
|
2021-09-13 10:48:44 +08:00
|
|
|
#include "compilermanager.h"
|
|
|
|
#include "../systemconsts.h"
|
2022-09-26 12:01:45 +08:00
|
|
|
#include "qt_utils/charsetinfo.h"
|
2021-09-13 22:45:50 +08:00
|
|
|
#include "../editor.h"
|
2021-09-13 10:48:44 +08:00
|
|
|
|
|
|
|
#include <QDir>
|
2021-09-13 07:49:36 +08:00
|
|
|
|
|
|
|
ProjectCompiler::ProjectCompiler(std::shared_ptr<Project> project, bool silent, bool onlyCheckSyntax):
|
2021-11-23 10:32:33 +08:00
|
|
|
Compiler("",silent,onlyCheckSyntax),
|
|
|
|
mOnlyClean(false)
|
2021-09-13 07:49:36 +08:00
|
|
|
{
|
|
|
|
setProject(project);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::buildMakeFile()
|
|
|
|
{
|
2021-09-13 10:48:44 +08:00
|
|
|
//we are using custom make file, don't overwrite it
|
2022-10-23 10:40:00 +08:00
|
|
|
if (mProject->options().useCustomMakefile && !mProject->options().customMakefile.isEmpty())
|
2021-09-13 10:48:44 +08:00
|
|
|
return;
|
2021-09-13 07:49:36 +08:00
|
|
|
|
|
|
|
switch(mProject->options().type) {
|
|
|
|
case ProjectType::StaticLib:
|
|
|
|
createStaticMakeFile();
|
|
|
|
break;
|
|
|
|
case ProjectType::DynamicLib:
|
|
|
|
createDynamicMakeFile();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
createStandardMakeFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
void ProjectCompiler::createStandardMakeFile()
|
|
|
|
{
|
|
|
|
QFile file(mProject->makeFileName());
|
|
|
|
newMakeFile(file);
|
|
|
|
file.write("$(BIN): $(OBJ)\n");
|
|
|
|
if (!mOnlyCheckSyntax) {
|
2022-02-01 16:17:28 +08:00
|
|
|
if (mProject->options().isCpp) {
|
2021-09-17 09:56:52 +08:00
|
|
|
writeln(file,"\t$(CPP) $(LINKOBJ) -o $(BIN) $(LIBS)");
|
2021-09-13 10:48:44 +08:00
|
|
|
} else
|
2021-09-17 09:56:52 +08:00
|
|
|
writeln(file,"\t$(CC) $(LINKOBJ) -o $(BIN) $(LIBS)");
|
2021-09-13 10:48:44 +08:00
|
|
|
}
|
|
|
|
writeMakeObjFilesRules(file);
|
|
|
|
}
|
|
|
|
|
2021-09-13 22:45:50 +08:00
|
|
|
void ProjectCompiler::createStaticMakeFile()
|
|
|
|
{
|
|
|
|
QFile file(mProject->makeFileName());
|
|
|
|
newMakeFile(file);
|
2021-10-05 23:30:34 +08:00
|
|
|
writeln(file,"$(BIN): $(LINKOBJ)");
|
2021-09-13 22:45:50 +08:00
|
|
|
if (!mOnlyCheckSyntax) {
|
|
|
|
writeln(file,"\tar r $(BIN) $(LINKOBJ)");
|
|
|
|
writeln(file,"\tranlib $(BIN)");
|
|
|
|
}
|
|
|
|
writeMakeObjFilesRules(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::createDynamicMakeFile()
|
|
|
|
{
|
|
|
|
QFile file(mProject->makeFileName());
|
|
|
|
newMakeFile(file);
|
2021-10-05 23:30:34 +08:00
|
|
|
writeln(file,"$(BIN): $(LINKOBJ)");
|
2021-09-13 22:45:50 +08:00
|
|
|
if (!mOnlyCheckSyntax) {
|
2022-02-01 16:17:28 +08:00
|
|
|
if (mProject->options().isCpp) {
|
2021-09-17 09:56:52 +08:00
|
|
|
file.write("\t$(CPP) -mdll $(LINKOBJ) -o $(BIN) $(LIBS) -Wl,--output-def,$(DEF),--out-implib,$(STATIC)");
|
2021-09-13 22:45:50 +08:00
|
|
|
} else {
|
2021-09-17 09:56:52 +08:00
|
|
|
file.write("\t$(CC) -mdll $(LINKOBJ) -o $(BIN) $(LIBS) -Wl,--output-def,$(DEF),--out-implib,$(STATIC)");
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
writeMakeObjFilesRules(file);
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
void ProjectCompiler::newMakeFile(QFile& file)
|
|
|
|
{
|
|
|
|
// Create OBJ output directory
|
|
|
|
if (!mProject->options().objectOutput.isEmpty()) {
|
|
|
|
QDir(mProject->directory()).mkpath(mProject->options().objectOutput);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write more information to the log file than before
|
|
|
|
log(tr("Building makefile..."));
|
|
|
|
log("--------");
|
|
|
|
log(tr("- Filename: %1").arg(mProject->makeFileName()));
|
|
|
|
|
|
|
|
// Create the actual file
|
|
|
|
if (!file.open(QFile::WriteOnly | QFile::Truncate))
|
2021-09-13 22:45:50 +08:00
|
|
|
throw CompileError(tr("Can't open '%1' for write!").arg(mProject->makeFileName()));
|
2021-09-13 10:48:44 +08:00
|
|
|
|
|
|
|
// Write header
|
|
|
|
writeMakeHeader(file);
|
|
|
|
|
|
|
|
// Writes definition list
|
|
|
|
writeMakeDefines(file);
|
|
|
|
|
|
|
|
// Write PHONY and all targets
|
|
|
|
writeMakeTarget(file);
|
|
|
|
|
|
|
|
// Write list of includes
|
|
|
|
writeMakeIncludes(file);
|
|
|
|
|
|
|
|
// Write clean command
|
|
|
|
writeMakeClean(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::writeMakeHeader(QFile &file)
|
|
|
|
{
|
|
|
|
writeln(file,"# Project: " + mProject->name());
|
2022-01-05 09:08:44 +08:00
|
|
|
writeln(file,QString("# Makefile created by Red Panda C++ ") + REDPANDA_CPP_VERSION);
|
2021-09-13 10:48:44 +08:00
|
|
|
writeln(file);
|
|
|
|
if (mOnlyCheckSyntax) {
|
|
|
|
writeln(file,"# This Makefile is written for syntax check!");
|
|
|
|
writeln(file,"# Regenerate it if you want to use this Makefile to build.");
|
|
|
|
writeln(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::writeMakeDefines(QFile &file)
|
|
|
|
{
|
|
|
|
// Get list of object files
|
|
|
|
QString Objects;
|
|
|
|
QString LinkObjects;
|
2021-09-17 19:58:37 +08:00
|
|
|
QString cleanObjects;
|
2021-09-13 10:48:44 +08:00
|
|
|
|
|
|
|
// Create a list of object files
|
2022-10-01 08:54:44 +08:00
|
|
|
foreach(const PProjectUnit &unit, mProject->unitList()) {
|
2021-09-13 10:48:44 +08:00
|
|
|
if (!unit->compile() && !unit->link())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Only process source files
|
|
|
|
QString RelativeName = extractRelativePath(mProject->directory(), unit->fileName());
|
|
|
|
FileType fileType = getFileType(RelativeName);
|
|
|
|
if (fileType == FileType::CSource || fileType == FileType::CppSource) {
|
|
|
|
if (!mProject->options().objectOutput.isEmpty()) {
|
|
|
|
// ofile = C:\MyProgram\obj\main.o
|
2021-09-17 19:58:37 +08:00
|
|
|
QString fullObjFile = includeTrailingPathDelimiter(mProject->options().objectOutput)
|
2021-09-13 10:48:44 +08:00
|
|
|
+ extractFileName(unit->fileName());
|
2021-09-17 19:58:37 +08:00
|
|
|
QString relativeObjFile = extractRelativePath(mProject->directory(), changeFileExt(fullObjFile, OBJ_EXT));
|
|
|
|
QString ObjFile = genMakePath2(relativeObjFile);
|
2021-09-13 10:48:44 +08:00
|
|
|
Objects += ' ' + ObjFile;
|
2022-04-08 22:14:18 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
cleanObjects += ' ' + genMakePath1(relativeObjFile).replace("/",QDir::separator());
|
|
|
|
#else
|
2021-09-17 19:58:37 +08:00
|
|
|
cleanObjects += ' ' + genMakePath1(relativeObjFile);
|
2022-04-08 22:14:18 +08:00
|
|
|
#endif
|
2021-09-17 19:58:37 +08:00
|
|
|
if (unit->link()) {
|
|
|
|
LinkObjects += ' ' + genMakePath1(relativeObjFile);
|
|
|
|
}
|
2021-09-13 10:48:44 +08:00
|
|
|
} else {
|
2021-09-17 19:58:37 +08:00
|
|
|
Objects += ' ' + genMakePath2(changeFileExt(RelativeName, OBJ_EXT));
|
2022-04-08 22:14:18 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
cleanObjects += ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT)).replace("/",QDir::separator());
|
|
|
|
#else
|
2021-09-17 19:58:37 +08:00
|
|
|
cleanObjects += ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT));
|
2022-04-08 22:14:18 +08:00
|
|
|
#endif
|
2021-09-13 10:48:44 +08:00
|
|
|
if (unit->link())
|
|
|
|
LinkObjects = LinkObjects + ' ' + genMakePath1(changeFileExt(RelativeName, OBJ_EXT));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Objects = Objects.trimmed();
|
|
|
|
LinkObjects = LinkObjects.trimmed();
|
|
|
|
|
|
|
|
// Get windres file
|
|
|
|
QString ObjResFile;
|
2022-01-15 12:25:30 +08:00
|
|
|
#ifdef Q_OS_WIN
|
2021-09-13 10:48:44 +08:00
|
|
|
if (!mProject->options().privateResource.isEmpty()) {
|
|
|
|
if (!mProject->options().objectOutput.isEmpty()) {
|
|
|
|
ObjResFile = includeTrailingPathDelimiter(mProject->options().objectOutput) +
|
|
|
|
changeFileExt(mProject->options().privateResource, RES_EXT);
|
|
|
|
} else
|
|
|
|
ObjResFile = changeFileExt(mProject->options().privateResource, RES_EXT);
|
|
|
|
}
|
2022-01-15 12:25:30 +08:00
|
|
|
#endif
|
2021-09-13 10:48:44 +08:00
|
|
|
|
|
|
|
// Mention progress in the logs
|
|
|
|
if (!ObjResFile.isEmpty()) {
|
2022-10-24 17:23:37 +08:00
|
|
|
log(tr("- Resource File: %1").arg(absolutePath(mProject->directory(),ObjResFile)));
|
2021-09-13 10:48:44 +08:00
|
|
|
}
|
|
|
|
log("");
|
|
|
|
|
|
|
|
// Get list of applicable flags
|
2022-06-22 17:08:35 +08:00
|
|
|
QString cCompileArguments = getCCompileArguments(mOnlyCheckSyntax);
|
2021-09-13 10:48:44 +08:00
|
|
|
QString cppCompileArguments = getCppCompileArguments(mOnlyCheckSyntax);
|
2021-09-13 19:09:15 +08:00
|
|
|
QString libraryArguments = getLibraryArguments(FileType::Project);
|
|
|
|
QString cIncludeArguments = getCIncludeArguments() + " " + getProjectIncludeArguments();
|
|
|
|
QString cppIncludeArguments = getCppIncludeArguments() + " " +getProjectIncludeArguments();
|
|
|
|
|
|
|
|
if (cCompileArguments.indexOf(" -g3")>=0
|
|
|
|
|| cCompileArguments.startsWith("-g3")) {
|
|
|
|
cCompileArguments += " -D__DEBUG__";
|
|
|
|
cppCompileArguments+= " -D__DEBUG__";
|
|
|
|
}
|
2021-09-13 22:45:50 +08:00
|
|
|
writeln(file,"CPP = " + extractFileName(compilerSet()->cppCompiler()));
|
|
|
|
writeln(file,"CC = " + extractFileName(compilerSet()->CCompiler()));
|
2022-01-15 12:25:30 +08:00
|
|
|
#ifdef Q_OS_WIN
|
2021-09-13 22:45:50 +08:00
|
|
|
writeln(file,"WINDRES = " + extractFileName(compilerSet()->resourceCompiler()));
|
2022-01-15 12:25:30 +08:00
|
|
|
#endif
|
2021-09-13 19:09:15 +08:00
|
|
|
if (!ObjResFile.isEmpty()) {
|
|
|
|
writeln(file,"RES = " + genMakePath1(ObjResFile));
|
|
|
|
writeln(file,"OBJ = " + Objects + " $(RES)");
|
|
|
|
writeln(file,"LINKOBJ = " + LinkObjects + " $(RES)");
|
2022-04-08 22:14:18 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
writeln(file,"CLEANOBJ = " + cleanObjects +
|
|
|
|
" " + genMakePath1(ObjResFile).replace("/",QDir::separator())
|
|
|
|
+ " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())).replace("/",QDir::separator()) );
|
|
|
|
#else
|
|
|
|
writeln(file,"CLEANOBJ = " + cleanObjects +
|
|
|
|
" " + genMakePath1(ObjResFile)
|
|
|
|
+ " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())));
|
|
|
|
#endif
|
2021-09-13 19:09:15 +08:00
|
|
|
} else {
|
|
|
|
writeln(file,"OBJ = " + Objects);
|
|
|
|
writeln(file,"LINKOBJ = " + LinkObjects);
|
2022-04-08 22:14:18 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
writeln(file,"CLEANOBJ = " + cleanObjects +
|
|
|
|
+ " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())).replace("/",QDir::separator()) );
|
|
|
|
#else
|
|
|
|
writeln(file,"CLEANOBJ = " + cleanObjects +
|
|
|
|
+ " " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())));
|
|
|
|
#endif
|
2021-09-13 19:09:15 +08:00
|
|
|
};
|
|
|
|
libraryArguments.replace('\\', '/');
|
|
|
|
writeln(file,"LIBS = " + libraryArguments);
|
|
|
|
cIncludeArguments.replace('\\', '/');
|
|
|
|
writeln(file,"INCS = " + cIncludeArguments);
|
|
|
|
cppIncludeArguments.replace('\\', '/');
|
|
|
|
writeln(file,"CXXINCS = " + cppIncludeArguments);
|
|
|
|
writeln(file,"BIN = " + genMakePath1(extractRelativePath(mProject->makeFileName(), mProject->executable())));
|
|
|
|
cppCompileArguments.replace('\\', '/');
|
|
|
|
writeln(file,"CXXFLAGS = $(CXXINCS) " + cppCompileArguments);
|
|
|
|
//writeln(file,"ENCODINGS = -finput-charset=utf-8 -fexec-charset='+GetSystemCharsetName);
|
|
|
|
cCompileArguments.replace('\\', '/');
|
|
|
|
writeln(file,"CFLAGS = $(INCS) " + cCompileArguments);
|
|
|
|
writeln(file, QString("RM = ") + CLEAN_PROGRAM );
|
|
|
|
if (mProject->options().usePrecompiledHeader){
|
|
|
|
writeln(file,"PCH_H = " + mProject->options().precompiledHeader );
|
|
|
|
writeln(file,"PCH = " + changeFileExt(mProject->options().precompiledHeader, GCH_EXT));
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
|
|
|
|
// This needs to be put in before the clean command.
|
2021-09-13 19:09:15 +08:00
|
|
|
if (mProject->options().type == ProjectType::DynamicLib) {
|
|
|
|
QString OutputFileDir = extractFilePath(mProject->executable());
|
|
|
|
QString libOutputFile = includeTrailingPathDelimiter(OutputFileDir) + "lib" + extractFileName(mProject->executable());
|
|
|
|
if (QFileInfo(libOutputFile).absoluteFilePath()
|
|
|
|
== mProject->directory())
|
|
|
|
libOutputFile = extractFileName(libOutputFile);
|
|
|
|
else
|
|
|
|
libOutputFile = extractRelativePath(mProject->makeFileName(), libOutputFile);
|
|
|
|
writeln(file,"DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT)));
|
|
|
|
writeln(file,"STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT)));
|
2022-04-08 22:14:18 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
writeln(file,"CLEAN_DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT)).replace("/",QDir::separator()));
|
|
|
|
writeln(file,"CLEAN_STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT)).replace("/",QDir::separator()));
|
|
|
|
#else
|
|
|
|
writeln(file,"CLEAN_DEF = " + genMakePath1(changeFileExt(libOutputFile, DEF_EXT)));
|
|
|
|
writeln(file,"CLEAN_STATIC = " + genMakePath1(changeFileExt(libOutputFile, LIB_EXT)));
|
|
|
|
#endif
|
2021-09-13 19:09:15 +08:00
|
|
|
}
|
|
|
|
writeln(file);
|
2021-09-13 10:48:44 +08:00
|
|
|
}
|
|
|
|
|
2021-09-13 22:45:50 +08:00
|
|
|
void ProjectCompiler::writeMakeTarget(QFile &file)
|
|
|
|
{
|
|
|
|
if (mOnlyCheckSyntax)
|
|
|
|
writeln(file, ".PHONY: all all-before all-after clean clean-custom $(OBJ) $(BIN)");
|
|
|
|
else
|
|
|
|
writeln(file, ".PHONY: all all-before all-after clean clean-custom");
|
|
|
|
writeln(file);
|
|
|
|
writeln(file, "all: all-before $(BIN) all-after");
|
|
|
|
writeln(file);
|
|
|
|
if (mProject->options().usePrecompiledHeader) {
|
|
|
|
writeln(file, "$(PCH) : $(PCH_H)");
|
|
|
|
writeln(file, " $(CPP) -x c++-header \"$(PCH_H)\" -o \"$(PCH)\" $(CXXFLAGS)");
|
|
|
|
writeln(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::writeMakeIncludes(QFile &file)
|
|
|
|
{
|
|
|
|
foreach(const QString& s, mProject->options().makeIncludes) {
|
|
|
|
writeln(file, "include " + genMakePath1(s));
|
|
|
|
}
|
|
|
|
if (!mProject->options().makeIncludes.isEmpty()) {
|
|
|
|
writeln(file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::writeMakeClean(QFile &file)
|
|
|
|
{
|
|
|
|
writeln(file, "clean: clean-custom");
|
|
|
|
if (mProject->options().type == ProjectType::DynamicLib)
|
2022-04-08 22:14:18 +08:00
|
|
|
writeln(file, QString("\t${RM} $(CLEANOBJ) $(CLEAN_DEF) $(CLEAN_STATIC) > %1 2>&1").arg(NULL_FILE));
|
2021-09-13 22:45:50 +08:00
|
|
|
else
|
2022-04-08 22:14:18 +08:00
|
|
|
writeln(file, QString("\t${RM} $(CLEANOBJ) > %1 2>&1").arg(NULL_FILE));
|
2021-09-13 22:45:50 +08:00
|
|
|
writeln(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::writeMakeObjFilesRules(QFile &file)
|
|
|
|
{
|
|
|
|
PCppParser parser = mProject->cppParser();
|
|
|
|
QString precompileStr;
|
|
|
|
if (mProject->options().usePrecompiledHeader)
|
|
|
|
precompileStr = " $(PCH) ";
|
|
|
|
|
2022-10-25 19:09:46 +08:00
|
|
|
QList<PProjectUnit> projectUnits=mProject->unitList();
|
2022-10-01 08:54:44 +08:00
|
|
|
foreach(const PProjectUnit &unit, projectUnits) {
|
2021-09-13 22:45:50 +08:00
|
|
|
FileType fileType = getFileType(unit->fileName());
|
|
|
|
// Only process source files
|
|
|
|
if (fileType!=FileType::CSource && fileType!=FileType::CppSource)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
QString shortFileName = extractRelativePath(mProject->makeFileName(),unit->fileName());
|
|
|
|
|
|
|
|
writeln(file);
|
|
|
|
QString objStr=genMakePath2(shortFileName);
|
|
|
|
// if we have scanned it, use scanned info
|
|
|
|
if (parser && parser->scannedFiles().contains(unit->fileName())) {
|
|
|
|
QSet<QString> fileIncludes = parser->getFileIncludes(unit->fileName());
|
|
|
|
foreach (const QString& headerName, fileIncludes) {
|
|
|
|
if (headerName == unit->fileName())
|
|
|
|
continue;
|
|
|
|
if (!parser->isSystemHeaderFile(headerName)
|
|
|
|
&& ! parser->isProjectHeaderFile(headerName)) {
|
2022-10-01 08:54:44 +08:00
|
|
|
foreach(const PProjectUnit &unit2, projectUnits) {
|
2022-04-09 09:35:17 +08:00
|
|
|
if (unit2->fileName()==headerName) {
|
|
|
|
objStr = objStr + ' ' + genMakePath2(extractRelativePath(mProject->makeFileName(),headerName));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2022-10-01 08:54:44 +08:00
|
|
|
foreach(const PProjectUnit &unit2, projectUnits) {
|
|
|
|
FileType fileType = getFileType(unit2->fileName());
|
2021-09-13 22:45:50 +08:00
|
|
|
if (fileType == FileType::CHeader || fileType==FileType::CppHeader)
|
2022-10-01 08:54:44 +08:00
|
|
|
objStr = objStr + ' ' + genMakePath2(extractRelativePath(mProject->makeFileName(),unit2->fileName()));
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
QString ObjFileName;
|
2021-09-17 19:58:37 +08:00
|
|
|
QString ObjFileName2;
|
2021-09-13 22:45:50 +08:00
|
|
|
if (!mProject->options().objectOutput.isEmpty()) {
|
|
|
|
ObjFileName = includeTrailingPathDelimiter(mProject->options().objectOutput) +
|
|
|
|
extractFileName(unit->fileName());
|
2021-09-17 19:58:37 +08:00
|
|
|
ObjFileName = genMakePath2(extractRelativePath(mProject->makeFileName(), changeFileExt(ObjFileName, OBJ_EXT)));
|
|
|
|
ObjFileName2 = genMakePath1(extractRelativePath(mProject->makeFileName(), changeFileExt(ObjFileName, OBJ_EXT)));
|
2022-04-08 22:14:18 +08:00
|
|
|
// if (!extractFileDir(ObjFileName).isEmpty()) {
|
|
|
|
// objStr = genMakePath2(includeTrailingPathDelimiter(extractFileDir(ObjFileName))) + objStr;
|
|
|
|
// }
|
2021-09-13 22:45:50 +08:00
|
|
|
} else {
|
2021-09-17 19:58:37 +08:00
|
|
|
ObjFileName = genMakePath2(changeFileExt(shortFileName, OBJ_EXT));
|
|
|
|
ObjFileName2 = genMakePath1(changeFileExt(shortFileName, OBJ_EXT));
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
objStr = ObjFileName + ": "+objStr+precompileStr;
|
|
|
|
|
|
|
|
writeln(file,objStr);
|
|
|
|
|
|
|
|
// Write custom build command
|
|
|
|
if (unit->overrideBuildCmd() && !unit->buildCmd().isEmpty()) {
|
|
|
|
QString BuildCmd = unit->buildCmd();
|
|
|
|
BuildCmd.replace("<CRTAB>", "\n\t");
|
|
|
|
writeln(file, '\t' + BuildCmd);
|
|
|
|
// Or roll our own
|
|
|
|
} else {
|
|
|
|
QString encodingStr;
|
2022-05-02 21:47:01 +08:00
|
|
|
if (compilerSet()->compilerType() != COMPILER_CLANG && mProject->options().addCharset) {
|
2022-06-22 17:08:35 +08:00
|
|
|
QByteArray defaultSystemEncoding=pCharsetInfoManager->getDefaultSystemEncoding();
|
|
|
|
QByteArray encoding = mProject->options().execEncoding;
|
|
|
|
QByteArray targetEncoding;
|
|
|
|
QByteArray sourceEncoding;
|
|
|
|
if ( encoding == ENCODING_SYSTEM_DEFAULT || encoding.isEmpty()) {
|
|
|
|
targetEncoding = defaultSystemEncoding;
|
|
|
|
} else if (encoding == ENCODING_UTF8_BOM) {
|
|
|
|
targetEncoding = "UTF-8";
|
|
|
|
} else {
|
|
|
|
targetEncoding = encoding;
|
|
|
|
}
|
|
|
|
|
2021-09-13 22:45:50 +08:00
|
|
|
if (unit->encoding() == ENCODING_AUTO_DETECT) {
|
2022-03-21 09:08:05 +08:00
|
|
|
Editor* editor = mProject->unitEditor(unit);
|
2022-03-27 11:44:52 +08:00
|
|
|
if (editor && editor->fileEncoding()!=ENCODING_ASCII
|
2022-06-22 17:08:35 +08:00
|
|
|
&& editor->fileEncoding()!=targetEncoding) {
|
|
|
|
sourceEncoding = editor->fileEncoding();
|
|
|
|
} else {
|
|
|
|
sourceEncoding = targetEncoding;
|
|
|
|
}
|
2021-11-15 19:30:24 +08:00
|
|
|
} else if (unit->encoding()==ENCODING_SYSTEM_DEFAULT) {
|
2022-06-22 17:08:35 +08:00
|
|
|
sourceEncoding = defaultSystemEncoding;
|
2022-03-27 11:44:52 +08:00
|
|
|
} else if (unit->encoding()!=ENCODING_ASCII && !unit->encoding().isEmpty()
|
2022-06-22 17:08:35 +08:00
|
|
|
&& unit->encoding()!=targetEncoding) {
|
|
|
|
sourceEncoding = unit->encoding();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sourceEncoding!=targetEncoding) {
|
2021-09-14 14:05:43 +08:00
|
|
|
encodingStr = QString(" -finput-charset=%1 -fexec-charset=%2")
|
2022-06-22 17:08:35 +08:00
|
|
|
.arg(QString(sourceEncoding),
|
|
|
|
QString(targetEncoding));
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mOnlyCheckSyntax) {
|
|
|
|
if (unit->compileCpp())
|
2021-10-25 09:16:00 +08:00
|
|
|
writeln(file, "\t$(CPP) -c " + genMakePath1(unit->fileName()) + " $(CXXFLAGS) " + encodingStr);
|
2021-09-13 22:45:50 +08:00
|
|
|
else
|
2021-10-25 09:16:00 +08:00
|
|
|
writeln(file, "\t(CC) -c " + genMakePath1(unit->fileName()) + " $(CFLAGS) " + encodingStr);
|
2021-09-13 22:45:50 +08:00
|
|
|
} else {
|
|
|
|
if (unit->compileCpp())
|
2021-10-25 09:16:00 +08:00
|
|
|
writeln(file, "\t$(CPP) -c " + genMakePath1(unit->fileName()) + " -o " + ObjFileName2 + " $(CXXFLAGS) " + encodingStr);
|
2021-09-13 22:45:50 +08:00
|
|
|
else
|
2021-10-25 09:16:00 +08:00
|
|
|
writeln(file, "\t$(CC) -c " + genMakePath1(unit->fileName()) + " -o " + ObjFileName2 + " $(CFLAGS) " + encodingStr);
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-15 12:25:30 +08:00
|
|
|
#ifdef Q_OS_WIN
|
2021-09-13 22:45:50 +08:00
|
|
|
if (!mProject->options().privateResource.isEmpty()) {
|
|
|
|
|
|
|
|
// Concatenate all resource include directories
|
|
|
|
QString ResIncludes(" ");
|
|
|
|
for (int i=0;i<mProject->options().resourceIncludes.count();i++) {
|
|
|
|
QString filename = mProject->options().resourceIncludes[i];
|
|
|
|
if (!filename.isEmpty())
|
|
|
|
ResIncludes = ResIncludes + " --include-dir " + genMakePath1(filename);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString ResFiles;
|
|
|
|
// Concatenate all resource filenames (not created when syntax checking)
|
|
|
|
if (!mOnlyCheckSyntax) {
|
2022-10-01 08:54:44 +08:00
|
|
|
foreach(const PProjectUnit& unit, mProject->unitList()) {
|
2021-09-13 22:45:50 +08:00
|
|
|
if (getFileType(unit->fileName())!=FileType::WindowsResourceSource)
|
|
|
|
continue;
|
2021-09-28 10:01:13 +08:00
|
|
|
if (fileExists(unit->fileName())) {
|
2021-09-13 22:45:50 +08:00
|
|
|
QString ResFile = extractRelativePath(mProject->makeFileName(), unit->fileName());
|
|
|
|
ResFiles = ResFiles + genMakePath2(ResFile) + ' ';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ResFiles = ResFiles.trimmed();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine resource output file
|
|
|
|
QString ObjFileName;
|
|
|
|
if (!mProject->options().objectOutput.isEmpty()) {
|
|
|
|
ObjFileName = includeTrailingPathDelimiter(mProject->options().objectOutput) +
|
|
|
|
changeFileExt(mProject->options().privateResource, RES_EXT);
|
|
|
|
} else {
|
|
|
|
ObjFileName = changeFileExt(mProject->options().privateResource, RES_EXT);
|
|
|
|
}
|
|
|
|
ObjFileName = genMakePath1(extractRelativePath(mProject->filename(), ObjFileName));
|
|
|
|
QString PrivResName = genMakePath1(extractRelativePath(mProject->filename(), mProject->options().privateResource));
|
|
|
|
|
|
|
|
// Build final cmd
|
|
|
|
QString WindresArgs;
|
|
|
|
if (getCCompileArguments(mOnlyCheckSyntax).contains("-m32"))
|
|
|
|
WindresArgs = " -F pe-i386";
|
|
|
|
|
|
|
|
if (mOnlyCheckSyntax) {
|
|
|
|
writeln(file);
|
|
|
|
writeln(file, ObjFileName + ':');
|
|
|
|
writeln(file, "\t$(WINDRES) -i " + PrivResName + WindresArgs + " --input-format=rc -o nul -O coff" + ResIncludes);
|
|
|
|
} else {
|
|
|
|
writeln(file);
|
|
|
|
writeln(file, ObjFileName + ": " + PrivResName + ' ' + ResFiles);
|
|
|
|
writeln(file, "\t$(WINDRES) -i " + PrivResName + WindresArgs + " --input-format=rc -o " + ObjFileName + " -O coff"
|
|
|
|
+ ResIncludes);
|
|
|
|
}
|
|
|
|
writeln(file);
|
|
|
|
}
|
2022-01-15 12:25:30 +08:00
|
|
|
#endif
|
2021-09-13 22:45:50 +08:00
|
|
|
}
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
void ProjectCompiler::writeln(QFile &file, const QString &s)
|
|
|
|
{
|
|
|
|
if (!s.isEmpty())
|
|
|
|
file.write(s.toLocal8Bit());
|
|
|
|
file.write("\n");
|
|
|
|
}
|
|
|
|
|
2021-09-17 21:33:19 +08:00
|
|
|
bool ProjectCompiler::onlyClean() const
|
|
|
|
{
|
|
|
|
return mOnlyClean;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectCompiler::setOnlyClean(bool newOnlyClean)
|
|
|
|
{
|
|
|
|
mOnlyClean = newOnlyClean;
|
|
|
|
}
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
bool ProjectCompiler::prepareForRebuild()
|
|
|
|
{
|
|
|
|
//we use make argument to clean
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-09-13 07:49:36 +08:00
|
|
|
bool ProjectCompiler::prepareForCompile()
|
|
|
|
{
|
|
|
|
if (!mProject)
|
|
|
|
return false;
|
|
|
|
//initProgressForm();
|
|
|
|
log(tr("Compiling project changes..."));
|
|
|
|
log("--------");
|
|
|
|
log(tr("- Project Filename: %1").arg(mProject->filename()));
|
|
|
|
log(tr("- Compiler Set Name: %1").arg(compilerSet()->name()));
|
|
|
|
log("");
|
|
|
|
|
|
|
|
buildMakeFile();
|
|
|
|
|
2021-09-13 10:48:44 +08:00
|
|
|
mCompiler = compilerSet()->make();
|
2021-09-17 21:33:19 +08:00
|
|
|
if (mOnlyClean) {
|
|
|
|
mArguments = QString("-f \"%1\" clean").arg(extractRelativePath(
|
|
|
|
mProject->directory(),
|
|
|
|
mProject->makeFileName()));
|
2021-11-23 10:32:33 +08:00
|
|
|
} else if (mRebuild) {
|
2021-09-13 22:45:50 +08:00
|
|
|
mArguments = QString("-f \"%1\" clean all").arg(extractRelativePath(
|
|
|
|
mProject->directory(),
|
|
|
|
mProject->makeFileName()));
|
2021-09-13 10:48:44 +08:00
|
|
|
} else {
|
2021-09-13 22:45:50 +08:00
|
|
|
mArguments = QString("-f \"%1\" all").arg(extractRelativePath(
|
|
|
|
mProject->directory(),
|
|
|
|
mProject->makeFileName()));
|
2021-09-13 10:48:44 +08:00
|
|
|
}
|
2021-09-13 22:45:50 +08:00
|
|
|
mDirectory = mProject->directory();
|
|
|
|
|
|
|
|
log(tr("Processing makefile:"));
|
|
|
|
log("--------");
|
|
|
|
log(tr("- makefile processer: %1").arg(mCompiler));
|
2021-09-14 12:10:43 +08:00
|
|
|
log(tr("- Command: %1 %2").arg(extractFileName(mCompiler)).arg(mArguments));
|
2021-09-13 22:45:50 +08:00
|
|
|
log("");
|
|
|
|
|
|
|
|
return true;
|
2021-09-13 07:49:36 +08:00
|
|
|
}
|