diff --git uppsrc/ide/Builders/Builders.h uppsrc/ide/Builders/Builders.h --- uppsrc/ide/Builders/Builders.h +++ uppsrc/ide/Builders/Builders.h @@ -77,6 +77,16 @@ struct GccBuilder : CppBuilder { String Info_plist; // apple bundle Info.plist }; +struct ClangTidyBuilder : CppBuilder { + virtual void AddFlags(Index& cfg); + virtual bool BuildPackage(const String& package, Vector& linkfile, Vector& immfile, + String& linkoptions, const Vector& all_uses, const Vector& all_libraries, int optimize); + virtual bool Link(const Vector& linkfile, const String& linkoptions, bool createmap); + virtual bool Preprocess(const String& package, const String& file, const String& target, bool asmout); + + String CompilerName() const; +}; + struct OwcBuilder : CppBuilder { typedef OwcBuilder CLASSNAME; @@ -166,6 +176,7 @@ INITIALIZE(GccBuilder) INITIALIZE(MscBuilder) INITIALIZE(JavaBuilder) INITIALIZE(AndroidBuilder) +INITIALIZE(ClangTidyBuilder) INITIALIZE(ScriptBuilder) #endif diff --git uppsrc/ide/Builders/Builders.upp uppsrc/ide/Builders/Builders.upp --- uppsrc/ide/Builders/Builders.upp +++ uppsrc/ide/Builders/Builders.upp @@ -19,6 +19,7 @@ file GccBuilder.cpp, MscBuilder.cpp, JavaBuilder.cpp, + ClangTidyBuilder.cpp, ScriptBuilder.cpp, Cocoa.cpp, Android readonly separator, diff --git uppsrc/ide/Builders/ClangTidyBuilder.cpp uppsrc/ide/Builders/ClangTidyBuilder.cpp --- /dev/null +++ uppsrc/ide/Builders/ClangTidyBuilder.cpp @@ -0,0 +1,199 @@ +#include "Builders.h" + +void ClangTidyBuilder::AddFlags(Index& cfg) +{ + cfg.FindAdd("CLANG"); +} + +String ClangTidyBuilder::CompilerName() const +{ + if(!IsNull(compiler)) return compiler; + return "clang-tidy"; +} + +bool ClangTidyBuilder::BuildPackage(const String& package, Vector& linkfile, Vector& immfile, String& linkoptions, const Vector& all_uses, const Vector& all_libraries, int optimize) +{ + SaveBuildInfo(package); + + int i; + String packagepath = PackagePath(package); + Package pkg; + pkg.Load(packagepath); + String packagedir = GetFileFolder(packagepath); + ChDir(packagedir); + PutVerbose("cd " + packagedir); + IdeConsoleBeginGroup(package); + Vector obj; + + bool is_shared = HasFlag("SO"); + String shared_ext = (HasFlag("WIN32") ? ".dll" : ".so"); + + Vector sfile, isfile; + Vector soptions, isoptions; + bool error = false; + + Index noblitz; + + bool blitz = HasFlag("BLITZ"); + bool release = !HasFlag("DEBUG"); + bool objectivec = HasFlag("OBJC"); +#ifdef PLATFORM_MACOS + objectivec = true; +#endif + + for(i = 0; i < pkg.GetCount(); i++) { + if(!IdeIsBuilding()) + return false; + if(!pkg[i].separator) { + String gop = Gather(pkg[i].option, config.GetKeys()); + Vector srcfile = CustomStep(pkg[i], package, error); + if(srcfile.GetCount() == 0) + error = true; + for(int j = 0; j < srcfile.GetCount(); j++) { + String fn = srcfile[j]; + String ext = GetSrcType(fn); + if(findarg(ext, ".c", ".cpp", ".cc", ".cxx") >= 0 || + objectivec && findarg(ext, ".mm", ".m") >= 0 || + + + (!release && blitz && ext == ".icpp")) { + sfile.Add(fn); + soptions.Add(gop); + } + else + if(ext == ".icpp") { + isfile.Add(fn); + isoptions.Add(gop); + } + else + if(ext == ".o") + obj.Add(fn); + else + if(ext == ".a" || ext == ".so") + linkfile.Add(fn); + if(pkg[i].noblitz) + noblitz.Add(fn); + } + } + } + + String cc(" -- -c"); + for(String s : pkg_config) + cc << " `pkg-config --cflags " << s << "`"; + cc << ' ' << IncludesDefinesTargetTime(package, pkg); + + if(HasFlag("WIN32")/* && HasFlag("MT")*/) + cc << " -mthreads"; + if(HasFlag("DEBUG_MINIMAL")) + cc << (HasFlag("WIN32") ? " -g1" : " -ggdb -g1"); + if(HasFlag("DEBUG_FULL")) + cc << (HasFlag("WIN32") ? " -g2" : " -ggdb -g2"); + String fuse_cxa_atexit; + if(is_shared /*&& !HasFlag("MAIN")*/) { + cc << " -shared -fPIC"; + fuse_cxa_atexit = " -fuse-cxa-atexit"; + } + if(!HasFlag("SHARED") && !is_shared) + cc << " -static "; + cc << ' ' << Gather(pkg.option, config.GetKeys()); + cc << " -fexceptions"; + + if(!release) + cc << " -D_DEBUG " << debug_options; + else + cc << ' ' << release_options; + + if(pkg.nowarnings) + cc << " -w"; + + Blitz b; + if(blitz) { + BlitzBuilderComponent bc(this); + b = bc.MakeBlitzStep(sfile, soptions, obj, immfile, ".o", noblitz, package); + } + + if(blitz && b.build) { + PutConsole("BLITZ:" + b.info); + int slot = AllocSlot(); + String exec = CompilerName(); + exec << " " << GetHostPathQ(b.path) << cc; + if(slot < 0 || !Run(String().Cat() << Join(exec, cpp_options) << ' ' + << GetHostPathQ(b.path) + << " -o " << GetHostPathQ(b.object), slot, GetHostPath(b.object), b.count)) + error = true; + } + + int first_ifile = sfile.GetCount(); + sfile.AppendPick(pick(isfile)); + soptions.AppendPick(pick(isoptions)); + + for(i = 0; i < sfile.GetCount(); i++) { + if(!IdeIsBuilding()) + return false; + String fn = sfile[i]; + String ext = ToLower(GetFileExt(fn)); + bool init = (i >= first_ifile); + String objfile = CatAnyPath(outdir, GetFileTitle(fn) + ".o"); + if(HdependFileTime(fn) > GetFileTime(GetHostPath(objfile))) { + PutConsole(GetFileName(fn)); + int time = msecs(); + bool execerr = false; + String exec = CompilerName(); + exec << " " << GetHostPathQ(fn) << cc; + if(ext == ".c") + exec << Join(" -x c", c_options) << ' '; + else if(ext == ".s" || ext == ".S") + exec << " -x assembler-with-cpp "; + else + if (ext == ".m") + exec << fuse_cxa_atexit << " -x objective-c "; + else + if (ext == ".mm") + exec << fuse_cxa_atexit << Join(" -x objective-c++ ", cpp_options) << ' '; + else + exec << fuse_cxa_atexit << Join(" -x c++", cpp_options) << ' '; + exec << soptions[i] << " -o " << GetHostPathQ(objfile); + PutVerbose(exec); + int slot = AllocSlot(); + execerr = (slot < 0 || !Run(exec, slot, GetHostPath(objfile), 1)); + if(execerr) + DeleteFile(objfile); + error |= execerr; + PutVerbose("compiled in " + GetPrintTime(time)); + } + immfile.Add(objfile); + if(init) + linkfile.Add(objfile); + else + obj.Add(objfile); + } + + if(error) { + IdeConsoleEndGroup(); + return false; + } + + return true; +} + +bool ClangTidyBuilder::Link(const Vector& linkfile, const String& linkoptions, bool createmap) +{ + if(!Wait()) + return false; + + return true; +} + +bool ClangTidyBuilder::Preprocess(const String& package, const String& file, const String& target, bool asmout) +{ + return true; +} + +Builder *CreateClangTidyBuilder() +{ + return new ClangTidyBuilder; +} + +INITIALIZER(ClangTidyBuilder) +{ + RegisterBuilder("CLANGTIDY", CreateClangTidyBuilder); +}