diff --git a/Ide/LgiIdeProj.xml b/Ide/LgiIdeProj.xml --- a/Ide/LgiIdeProj.xml +++ b/Ide/LgiIdeProj.xml @@ -1,279 +1,280 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - + + + + + + - + - .\win\Makefile.windows + win\Makefile.windows ./linux/Makefile.linux ./MacCocoa/LgiIde.xcodeproj Makefile.haiku ./lgiide ./lgiide LgiIde.exe LgiIde.exe WINDOWS WINNATIVE WINDOWS WINNATIVE POSIX POSIX LIBPNG_VERSION=\"1.2\" LIBPNG_VERSION=\"1.2\" MingW /home/matthew/Code/Lgi/trunk/Ide/Code/IdeProjectSettings.cpp ./src ./resources ../include ./src ./resources ../include ..\include\lgi\win ..\include\lgi\win ../include/lgi/linux ../include/lgi/linux/Gtk ../../../../codelib/openssl/include ../include/lgi/linux ../include/lgi/linux/Gtk ../../../../codelib/openssl/include ../include/lgi/haiku ../include/lgi/haiku ../include/lgi/mac/cocoa ../include/lgi/mac/cocoa imm32 imm32 magic pthread `pkg-config --libs gtk+-3.0` -static-libgcc magic pthread `pkg-config --libs gtk+-3.0` -static-libgcc -static-libgcc gnu network be -static-libgcc gnu network be - + Executable lgiide lgiide LgiIde.exe LgiIde.exe lgiide lgiide `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gtk+-3.0` + POSIX _GNU_SOURCE POSIX _GNU_SOURCE - + 4 4 0 1 SOME_TEST=testing /home/matthew/code/i.Hex/trunk/iHexProject.xml - + diff --git a/Ide/src/AddFtpFile.h b/Ide/src/AddFtpFile.h --- a/Ide/src/AddFtpFile.h +++ b/Ide/src/AddFtpFile.h @@ -1,23 +1,24 @@ #ifndef _ADD_FTP_FILE_H_ #define _ADD_FTP_FILE_H_ +#include "lgi/common/Uri.h" #include "FtpThread.h" class AddFtpFile : public LDialog, public FtpCallback { LUri *Base; LList *Files; LList *Log; FtpThread *Thread; public: LArray Uris; AddFtpFile(LViewI *p, char *ftp); ~AddFtpFile(); void OnCmdComplete(FtpCmd *Cmd); int OnNotify(LViewI *c, LNotification n); }; #endif \ No newline at end of file diff --git a/Ide/src/FtpThread.cpp b/Ide/src/FtpThread.cpp --- a/Ide/src/FtpThread.cpp +++ b/Ide/src/FtpThread.cpp @@ -1,422 +1,423 @@ #include #include "lgi/common/Lgi.h" +#include "lgi/common/Uri.h" #include "FtpThread.h" static FtpThread *Ftp = 0; class Line : public LListItem { LColour c; public: Line(const char *s, COLOUR col) { SetText(s); c.Set(col, 24); } void OnPaint(LItem::ItemPaintCtx &Ctx) { if (!Select()) Ctx.Fore = c; LListItem::OnPaint(Ctx); } }; class LogSock : public LSocket { LStringPipe r, w; void Pop(LStringPipe &p, COLOUR c) { char s[256]; while (p.Pop(s, sizeof(s))) { char *e = s + strlen(s) - 1; while (e > s && strchr(" \t\r\n", e[-1])) { e--; *e = 0; } if (Log) { LListItem *i; Log->Insert(i = new Line(s, c)); i->ScrollTo(); } } } public: LList *Log; LogSock(LList *log) { Log = log; } void OnRead(char *Data, ssize_t Len) { r.Write(Data, Len); Pop(r, Rgb24(0, 0xc0, 0)); } void OnWrite(const char *Data, ssize_t Len) { w.Write(Data, Len); Pop(w, Rgb24(0, 0, 0xc0)); } void OnError(int ErrorCode, const char *ErrorDescription) { char s[256]; snprintf(s, sizeof(s), "Error(%i): %s", ErrorCode, ErrorDescription); Log->Insert(new Line(s, Rgb24(255, 0, 0))); } }; struct FtpConn { LUri *Base; LogSock *Sock; IFtp Ftp; FtpConn(char *u) { Base = new LUri(u); Sock = 0; } void SetLog(LList *l) { if (Sock) Sock->Log = l; } bool Match (char *Uri) { LUri u(Uri); if (Base && u.sHost && Base->sHost && u.sUser && Base->sUser && u.sPass && Base->sPass) { return stricmp(u.sHost, Base->sHost) == 0 && strcmp(u.sUser, Base->sUser) == 0 && strcmp(u.sPass, Base->sPass) == 0; } return false; } bool Open(LList *Watch) { if (Base) { if ( Ftp.Open ( Sock = new LogSock(Watch), Base->sHost, Base->Port ? Base->Port : 21, Base->sUser, Base->sPass ) == FO_Connected ) return true; } return false; } }; //////////////////////////////////////////////////////////////////////////////////// FtpCmd::FtpCmd(FtpCommand c, FtpCallback *cb) { Cmd = c; Callback = cb; Uri = 0; File = 0; Watch = 0; Status = false; View = 0; } FtpCmd::~FtpCmd() { DeleteArray(Uri); DeleteArray(File); Dir.DeleteObjects(); } void FtpCmd::Error(const char *e) { if (Watch) { Watch->Insert(new Line(e, Rgb24(255, 0, 0))); } } //////////////////////////////////////////////////////////////////////////////////// #define M_FTP_CMD (M_USER + 0x4000) class FtpRedir : public LWindow { public: FtpRedir() { LRect r(-20001, -20001, -20000, -20000); SetPos(r); Attach(0); } LMessage::Result OnEvent(LMessage *m) { if (m->Msg() == M_FTP_CMD) { FtpCmd *c = (FtpCmd*) m->A(); c->Callback->OnCmdComplete(c); DeleteObj(c); } return LWindow::OnEvent(m); } }; struct FtpThreadPriv : public LMutex { bool Loop; LArray Conn; LArray Cmds; FtpRedir *Redir; FtpThreadPriv() : LMutex("FtpThreadPriv") { Loop = true; Redir = new FtpRedir; } ~FtpThreadPriv() { DeleteObj(Redir); } FtpConn *GetConn(char *Uri, LList *Watch = 0) { // Look for existing connection for (int i=0; iMatch(Uri)) { Conn[i]->SetLog(Watch); return Conn[i]; } } // Create new connection FtpConn *n = new FtpConn(Uri); if (n) { if (n->Open(Watch)) { Conn.Add(n); } else DeleteObj(n); return n; } return 0; } void FreeConn(FtpConn *c) { Conn.Delete(c); DeleteObj(c); } }; FtpThread::FtpThread() : LThread("FtpThread") { d = new FtpThreadPriv; Run(); } FtpThread::~FtpThread() { d->Loop = false; while (!IsExited()) { LSleep(1); } DeleteObj(d); } void FtpThread::Post(FtpCmd *Cmd) { LMutex::Auto Lock(d, _FL); d->Cmds.Add(Cmd); } int FtpThread::Main() { while (d->Loop) { FtpCmd *c = 0; if (d->LockWithTimeout(50, _FL)) { if (d->Cmds.Length()) { c = d->Cmds[0]; d->Cmds.DeleteAt(0, true); } d->Unlock(); } if (c) { switch (c->Cmd) { case FtpList: { if (c->Uri) { FtpConn *Conn = d->GetConn(c->Uri, c->Watch); if (Conn) { if (Conn->Base->sPath) { if (!Conn->Ftp.SetDir(Conn->Base->sPath)) { c->Error("Couldn't set path."); } } c->Status = Conn->Ftp.ListDir(c->Dir); if (!c->Status) c->Error("Failed to list folder."); } else c->Error("Failed to connect."); } break; } case FtpRead: { if (c->Uri) { FtpConn *Conn = d->GetConn(c->Uri, c->Watch); if (Conn) { LUri u(c->Uri); if (u.sPath) { char p[256]; strcpy_s(p, sizeof(p), u.sPath); char *d = strrchr(p, '/'); if (d) *d = 0; if (!Conn->Ftp.SetDir(p)) { c->Error("Couldn't set path."); break; } } char r[256], *d = strrchr(c->Uri, '/'); LMakePath(r, sizeof(r), LGetSystemPath(LSP_TEMP), d + 1); if (LFileExists(r)) { FileDev->Delete(r, false); } IFtpEntry e; e.Size = -1; e.Name = d + 1; c->Status = Conn->Ftp.DownloadFile(r, &e); if (c->Status) { c->File = NewStr(r); } else { c->Error("Download failed."); } } else c->Error("Failed to connect."); } break; } case FtpWrite: { if (c->Uri) { FtpConn *Conn = d->GetConn(c->Uri, c->Watch); if (Conn) { LUri u(c->Uri); if (u.sPath) { char p[256]; strcpy_s(p, sizeof(p), u.sPath); char *d = strrchr(p, '/'); if (d) *d = 0; if (!Conn->Ftp.SetDir(p)) { c->Error("Couldn't set path."); break; } } if (LFileExists(c->File)) { char *d = strrchr(c->File, DIR_CHAR); c->Status = Conn->Ftp.UploadFile(c->File, d + 1); if (!c->Status) { c->Error("Upload failed."); } } else c->Error("Source file doesn't exist"); } else c->Error("Failed to connect."); } break; } default: { LAssert(!"Not implemented."); break; } } if (c->Callback) { d->Redir->PostEvent(M_FTP_CMD, (LMessage::Param)c); } else DeleteObj(c); } else LSleep(1); } return 0; } FtpThread *GetFtpThread() { if (!Ftp) Ftp = new FtpThread; return Ftp; } void ShutdownFtpThread() { DeleteObj(Ftp); } diff --git a/Ide/src/IdeProject.cpp b/Ide/src/IdeProject.cpp --- a/Ide/src/IdeProject.cpp +++ b/Ide/src/IdeProject.cpp @@ -1,4107 +1,4112 @@ #if defined(WIN32) #include #else #include #endif #include #include "lgi/common/Lgi.h" #include "lgi/common/DragAndDrop.h" #include "lgi/common/Token.h" #include "lgi/common/Combo.h" #include "lgi/common/Net.h" #include "lgi/common/ListItemCheckBox.h" #include "lgi/common/ClipBoard.h" #include "lgi/common/DropFiles.h" #include "lgi/common/SubProcess.h" #include "lgi/common/Css.h" #include "lgi/common/TableLayout.h" #include "lgi/common/TextLabel.h" #include "lgi/common/Button.h" #include "lgi/common/RegKey.h" #include "lgi/common/FileSelect.h" #include "lgi/common/Menu.h" #include "LgiIde.h" #include "resdefs.h" #include "FtpThread.h" #include "ProjectNode.h" #include "WebFldDlg.h" extern const char *Untitled; const char SourcePatterns[] = "*.c;*.h;*.cpp;*.cc;*.java;*.d;*.php;*.html;*.css;*.js"; const char *AddFilesProgress::DefaultExt = "c,cpp,cc,cxx,h,hpp,hxx,html,css,json,js,jsx,txt,png,jpg,jpeg,rc,xml,mk,paths,makefile,py,java,php"; const char *VsBinaries[] = {"devenv.com", "WDExpress.exe"}; #define USE_OPEN_PROGRESS 1 #define STOP_BUILD_TIMEOUT 2000 #ifdef WINDOWS #define LGI_STATIC_LIBRARY_EXT "lib" #else #define LGI_STATIC_LIBRARY_EXT "a" #endif const char *PlatformNames[] = { "Windows", "Linux", "Mac", "Haiku", 0 }; int PlatformCtrlId[] = { IDC_WIN32, IDC_LINUX, IDC_MAC, IDC_HAIKU, 0 }; const char *PlatformDynamicLibraryExt(IdePlatform Platform) { if (Platform == PlatformWin) return "dll"; if (Platform == PlatformMac) return "dylib"; return "so"; } const char *PlatformSharedLibraryExt(IdePlatform Platform) { if (Platform == PlatformWin) return "lib"; return "a"; } const char *PlatformExecutableExt(IdePlatform Platform) { if (Platform == PlatformWin) return ".exe"; return ""; } char *ToUnixPath(char *s) { if (s) { char *c; while ((c = strchr(s, '\\'))) *c = '/'; } return s; } const char *CastEmpty(char *s) { return s ? s : ""; } bool FindInPath(LString &Exe) { LString::Array Path = LString(getenv("PATH")).Split(LGI_PATH_SEPARATOR); for (unsigned i=0; i SubProc; LString::Array BuildConfigs; LString::Array PostBuild; int AppHnd; enum CompilerType { DefaultCompiler, VisualStudio, MingW, Gcc, CrossCompiler, PythonScript, IAR, Nmake, Cygwin, Xcode, } Compiler; enum ArchType { DefaultArch, ArchX32, ArchX64, ArchArm6, ArchArm7, } Arch; public: BuildThread(IdeProject *proj, char *makefile, bool clean, BuildConfig config, bool all, int wordsize); ~BuildThread(); ssize_t Write(const void *Buffer, ssize_t Size, int Flags = 0) override; LString FindExe(); LAutoString WinToMingWPath(const char *path); int Main() override; }; class IdeProjectPrivate { public: AppWnd *App; IdeProject *Project; bool Dirty, UserFileDirty; LString FileName; IdeProject *ParentProject; IdeProjectSettings Settings; LAutoPtr Thread; LHashTbl, ProjectNode*> Nodes; int NextNodeId; // Threads LAutoPtr CreateMakefile; // User info file LString UserFile; LHashTbl,int> UserNodeFlags; IdeProjectPrivate(AppWnd *a, IdeProject *project) : Project(project), Settings(project) { App = a; Dirty = false; UserFileDirty = false; ParentProject = 0; NextNodeId = 1; } void CollectAllFiles(LTreeNode *Base, LArray &Files, bool SubProjects, int Platform); }; LString ToPlatformPath(const char *s, IdePlatform platform) { LString p = s; if (platform == PlatformWin) return p.Replace("/", "\\"); else return p.Replace("\\", "/"); } class MakefileThread : public LThread, public LCancel { IdeProjectPrivate *d; IdeProject *Proj; IdePlatform Platform; LStream *Log; bool BuildAfterwards; bool HasError; public: static int Instances; MakefileThread(IdeProjectPrivate *priv, IdePlatform platform, bool Build) : LThread("MakefileThread") { Instances++; d = priv; Proj = d->Project; Platform = platform; BuildAfterwards = Build; HasError = false; Log = d->App->GetBuildLog(); Run(); } ~MakefileThread() { Cancel(); while (!IsExited()) LSleep(1); Instances--; } void OnError(const char *Fmt, ...) { va_list Arg; va_start(Arg, Fmt); LStreamPrintf(Log, 0, Fmt, Arg); va_end(Arg); HasError = true; } int Main() { const char *PlatformName = PlatformNames[Platform]; const char *PlatformLibraryExt = NULL; const char *PlatformStaticLibExt = NULL; const char *PlatformExeExt = ""; const char *CompilerFlags = "-fPIC -fno-inline -fpermissive -Wno-format-truncation"; - LString LinkerFlags; const char *TargetType = d->Settings.GetStr(ProjTargetType, NULL, Platform); const char *CompilerName = d->Settings.GetStr(ProjCompiler); + LString LinkerFlags; LString CCompilerBinary = "gcc"; LString CppCompilerBinary = "g++"; LStream *Log = d->App->GetBuildLog(); bool IsExecutableTarget = TargetType && !stricmp(TargetType, "Executable"); bool IsDynamicLibrary = TargetType && !stricmp(TargetType, "DynamicLibrary"); LAssert(Log); if (!Log) return false; Log->Print("CreateMakefile for '%s'...\n", PlatformName); if (Platform == PlatformWin) { LinkerFlags = ",--enable-auto-import"; } else { if (IsDynamicLibrary) { LinkerFlags = ",-soname,$(TargetFile)"; } LinkerFlags += ",-export-dynamic,-R."; } auto Base = Proj->GetBasePath(); auto MakeFile = Proj->GetMakefile(Platform); LString MakeFilePath; Proj->CheckExists(MakeFile); if (!MakeFile) { MakeFilePath = Base.Get(); LFile::Path p(MakeFilePath, "makefile"); MakeFile = p.GetFull(); } else if (LIsRelativePath(MakeFile)) { LFile::Path p(Base); p += MakeFile; MakeFile = p.GetFull(); p--; MakeFilePath = p.GetFull(); } else { LFile::Path p(MakeFile); p--; MakeFilePath = p.GetFull(); } // LGI_LIBRARY_EXT switch (Platform) { case PlatformWin: PlatformLibraryExt = "dll"; PlatformStaticLibExt = "lib"; PlatformExeExt = ".exe"; break; case PlatformLinux: case PlatformHaiku: PlatformLibraryExt = "so"; PlatformStaticLibExt = "a"; break; case PlatformMac: PlatformLibraryExt = "dylib"; PlatformStaticLibExt = "a"; break; default: LAssert(0); break; } if (CompilerName) { if (!stricmp(CompilerName, "cross")) { LString CBin = d->Settings.GetStr(ProjCCrossCompiler, NULL, Platform); if (CBin && !LFileExists(CBin)) FindInPath(CBin); if (CBin && LFileExists(CBin)) CCompilerBinary = CBin; else Log->Print("%s:%i - Error: C cross compiler '%s' not found.\n", _FL, CBin.Get()); LString CppBin = d->Settings.GetStr(ProjCppCrossCompiler, NULL, Platform); if (CppBin && !LFileExists(CppBin)) FindInPath(CppBin); if (CppBin && LFileExists(CppBin)) CppCompilerBinary = CppBin; else Log->Print("%s:%i - Error: C++ cross compiler '%s' not found.\n", _FL, CppBin.Get()); } } LFile m; if (!m.Open(MakeFile, O_WRITE)) { Log->Print("Error: Failed to open '%s' for writing.\n", MakeFile.Get()); return false; } m.SetSize(0); m.Print("#!/usr/bin/make\n" "#\n" "# This makefile generated by LgiIde\n" "# http://www.memecode.com/lgi.php\n" "#\n" "\n" ".SILENT :\n" "\n" "CC = %s\n" "CPP = %s\n", CCompilerBinary.Get(), CppCompilerBinary.Get()); // Collect all files that require building LArray Files; d->CollectAllFiles ( Proj, Files, false, 1 << Platform ); if (IsExecutableTarget) { LString Exe = Proj->GetExecutable(Platform); if (Exe) { if (LIsRelativePath(Exe)) m.Print("Target = %s\n", ToPlatformPath(Exe, Platform).Get()); else { auto RelExe = LMakeRelativePath(Base, Exe); if (Base && RelExe) { m.Print("Target = %s\n", ToPlatformPath(RelExe, Platform).Get()); } else { Log->Print("%s:%i - Error: Missing path (%s, %s).\n", _FL, Base.Get(), RelExe.Get()); return false; } } } else { Log->Print("%s:%i - Error: No executable name specified (%s, %s).\n", _FL, TargetType, d->FileName.Get()); return false; } } else { LString Target = Proj->GetTargetName(Platform); if (Target) m.Print("Target = %s\n", ToPlatformPath(Target, Platform).Get()); else { Log->Print("%s:%i - Error: No target name specified.\n", _FL); return false; } } // Output the build mode, flags and some paths auto BuildMode = d->App->GetBuildMode(); auto BuildModeName = toString(BuildMode); m.Print("ifndef Build\n" " Build = %s\n" "endif\n", BuildModeName); m.Print("MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))\n"); LString sDefines[BuildMax]; LString sLibs[BuildMax]; LString sIncludes[BuildMax]; const char *ExtraLinkFlags = NULL; const char *ExeFlags = NULL; if (Platform == PlatformWin) { ExtraLinkFlags = ""; ExeFlags = " -mwindows"; m.Print("BuildDir = $(Build)\n" "\n" "Flags = %s\n", CompilerFlags); const char *DefDefs = "-DWIN32 -D_REENTRANT"; sDefines[BuildDebug] = DefDefs; sDefines[BuildRelease] = DefDefs; } else { LString PlatformCap = PlatformName; ExtraLinkFlags = ""; ExeFlags = ""; m.Print("BuildDir = $(Build)\n" "\n" "Flags = %s\n", CompilerFlags); sDefines[0].Printf("-D%s -D_REENTRANT", PlatformCap.Upper().Get()); #ifdef LINUX sDefines[BuildDebug] += " -D_FILE_OFFSET_BITS=64"; // >:-( sDefines[BuildDebug] += " -DPOSIX"; #endif sDefines[BuildRelease] = sDefines[BuildDebug]; } List Deps; Proj->GetChildProjects(Deps); for (int Cfg = BuildDebug; Cfg < BuildMax; Cfg++) { // Set the config auto cfgName = toString((BuildConfig)Cfg); d->Settings.SetCurrentConfig(cfgName); // Get the defines setup auto PDefs = d->Settings.GetStr(ProjDefines, NULL, Platform); if (ValidStr(PDefs)) { LToken Defs(PDefs, " ;,\r\n"); for (int i=0; iSettings.GetStr(ProjLibraryPaths, NULL, Platform); if (ValidStr(PLibPaths)) { LString::Array LibPaths = PLibPaths.Split("\n"); for (auto i: LibPaths) { LString s, in = i.Strip(); if (!in.Length()) continue; if (strchr("`-", in(0))) { s.Printf(" \\\n\t\t%s", in.Get()); } else { LString Rel; if (!LIsRelativePath(in)) Rel = LMakeRelativePath(Base, in); LString Final = Rel ? Rel.Get() : in.Get(); if (!Proj->CheckExists(Final)) OnError("%s:%i - Library path '%s' doesn't exist (from %s).\n", _FL, Final.Get(), Proj->GetFileName()); s.Printf(" \\\n\t\t-L%s", ToUnixPath(Final)); } sLibs[Cfg] += s; } } const char *PLibs = d->Settings.GetStr(ProjLibraries, NULL, Platform); if (ValidStr(PLibs)) { LToken Libs(PLibs, "\r\n"); for (int i=0; iCheckExists(l); s.Printf(" \\\n\t\t-l%s", ToUnixPath(l)); } sLibs[Cfg] += s; } } for (auto dep: Deps) { LString Target = dep->GetTargetName(Platform); if (Target) { char t[MAX_PATH_LEN]; strcpy_s(t, sizeof(t), Target); if (!strnicmp(t, "lib", 3)) memmove(t, t + 3, strlen(t + 3) + 1); char *dot = strrchr(t, '.'); if (dot) *dot = 0; LString s, sTarget = t; Proj->CheckExists(sTarget); s.Printf(" \\\n\t\t-l%s$(Tag)", ToUnixPath(sTarget)); sLibs[Cfg] += s; auto DepBase = dep->GetBasePath(); if (DepBase) { LString DepPath = DepBase.Get(); auto Rel = LMakeRelativePath(Base, DepPath); LString Final = Rel ? Rel.Get() : DepPath.Get(); Proj->CheckExists(Final); s.Printf(" \\\n\t\t-L%s/$(BuildDir)", ToUnixPath(Final.RStrip("/\\"))); sLibs[Cfg] += s; } } } // Includes // Do include paths LHashTbl,bool> Inc; auto ProjIncludes = d->Settings.GetStr(ProjIncludePaths, NULL, Platform); if (ValidStr(ProjIncludes)) { // Add settings include paths. LToken Paths(ProjIncludes, "\r\n"); for (int i=0; iCheckExists(pn)) OnError("%s:%i - Include path '%s' doesn't exist.\n", _FL, pn.Get()); else if (!Inc.Find(pn)) Inc.Add(pn, true); } } const char *SysIncludes = d->Settings.GetStr(ProjSystemIncludes, NULL, Platform); if (ValidStr(SysIncludes)) { // Add settings include paths. LToken Paths(SysIncludes, "\r\n"); for (int i=0; iCheckExists(pn)) OnError("%s:%i - System include path '%s' doesn't exist (from %s).\n", _FL, pn.Get(), Proj->GetFileName()); else if (!Inc.Find(pn)) Inc.Add(pn, true); } } LString::Array Incs; for (auto i: Inc) Incs.New() = i.key; Incs.Sort(); for (auto i: Incs) { LString s; if (*i == '`') { // Pass though shell cmd s.Printf(" \\\n\t\t%s", i.Get()); } else { LFile::Path p; if (LIsRelativePath(i)) { p = Base.Get(); p += i; } else p = i; auto rel = LMakeRelativePath(Base, p.GetFull()); s.Printf(" \\\n\t\t-I%s", ToUnixPath(rel ? rel : i)); } sIncludes[Cfg] += s; } } // Output the defs section for Debug and Release // Debug specific m.Print("\n" "ifeq ($(Build),Debug)\n" " Flags += -MMD -MP -g -std=c++14\n" " Tag = d\n" " Defs = -D_DEBUG %s\n" " Libs = %s\n" " Inc = %s\n", CastEmpty(sDefines [BuildDebug].Get()), CastEmpty(sLibs [BuildDebug].Get()), CastEmpty(sIncludes[BuildDebug].Get())); // Release specific m.Print("else\n" " Flags += -MMD -MP -s -Os -std=c++14\n" " Defs = %s\n" " Libs = %s\n" " Inc = %s\n" "endif\n" "\n", CastEmpty(sDefines [BuildRelease].Get()), CastEmpty(sLibs [BuildRelease].Get()), CastEmpty(sIncludes[BuildRelease].Get())); if (Files.Length()) { LArray VPath; // Proj->BuildIncludePaths(VPath, false, false, Platform); auto AddVPath = [&VPath](LString p) { for (auto s: VPath) if (p == s) return; VPath.Add(p); }; // Do source code list... m.Print("# Dependencies\n" "Source =\t"); LString::Array SourceFiles; for (auto &n: Files) { if (n->GetType() == NodeSrc) { auto f = n->GetFileName(); auto path = ToPlatformPath(f, Platform); LFile::Path p; if (LIsRelativePath(path)) { p = Base.Get(); p += path; } else { p = path; } auto rel = LMakeRelativePath(Base, p.GetFull()); if (rel && rel.Find("./") == 0) rel = rel(2,-1); SourceFiles.Add(rel ? rel : path); if (true) { // Also add path of file to VPath. p--; AddVPath(p.GetFull()); } } } SourceFiles.Sort(); int c = 0; for (auto &src: SourceFiles) { if (c++) m.Print(" \\\n\t\t\t"); m.Print("%s", src.Get()); } m.Print("\n" "\n" "SourceC := $(filter %%.c,$(Source))\n" "ObjectsC := $(SourceC:.c=.o)\n" "SourceCpp := $(filter %%.cpp,$(Source))\n" "ObjectsCpp := $(SourceCpp:.cpp=.o)\n" "Objects := $(notdir $(ObjectsC) $(ObjectsCpp))\n" "Objects := $(addprefix $(BuildDir)/,$(Objects))\n" "Deps := $(patsubst %%.o,%%.d,$(Objects))\n" "\n" "$(BuildDir)/%%.o: %%.c\n" " mkdir -p $(@D)\n" " echo $(notdir $<) [$(Build)]\n" " $(CC) $(Inc) $(Flags) $(Defs) -c $< -o $@\n" "\n" "$(BuildDir)/%%.o: %%.cpp\n" " mkdir -p $(@D)\n" " echo $(notdir $<) [$(Build)]\n" " $(CPP) $(Inc) $(Flags) $(Defs) -c $< -o $@\n" "\n"); // Write out the target stuff m.Print("# Target\n"); LHashTbl,bool> DepFiles; if (TargetType) { if (IsExecutableTarget) { m.Print("# Executable target\n" "$(Target) :"); LStringPipe Rules; IdeProject *Dep; uint64 Last = LCurrentTime(); int Count = 0; auto It = Deps.begin(); for (Dep=*It; Dep && !IsCancelled(); Dep=*(++It), Count++) { // Get dependency to create it's own makefile... Dep->CreateMakefile(Platform, false); // Build a rule to make the dependency if any of the source changes... auto DepBase = Dep->GetBasePath(); auto TargetFile = Dep->GetTargetFile(Platform); if (DepBase && Base && TargetFile) { LString Rel = LMakeRelativePath(Base, DepBase); ToNativePath(Rel); // Add tag to target name auto Parts = TargetFile.SplitDelimit("."); if (Parts.Length() == 2) TargetFile.Printf("lib%s$(Tag).%s", Parts[0].Get(), Parts[1].Get()); LFile::Path Buf(Rel); Buf += "$(BuildDir)"; Buf += TargetFile; m.Print(" %s", Buf.GetFull().Get()); LArray AllDeps; Dep->GetAllDependencies(AllDeps, Platform); LAssert(AllDeps.Length() > 0); AllDeps.Sort(StrSort); Rules.Print("%s : ", Buf.GetFull().Get()); for (int i=0; iGetMakefile(Platform); - // RenameMakefileForPlatform(Mk, Platform); if (Mk) { - char *DepMakefile = strrchr(Mk, DIR_CHAR); - if (DepMakefile) + LString MakefileRel = LMakeRelativePath(DepBase, Mk); + if (MakefileRel) + { + ToNativePath(MakefileRel); + Rules.Print(" -f %s", MakefileRel.Get()); + } + else if (auto DepMakefile = strrchr(Mk, DIR_CHAR)) + { Rules.Print(" -f %s", DepMakefile + 1); + } } else { Mk = Dep->GetMakefile(Platform); OnError("%s:%i - No makefile for '%s'\n", _FL, Dep->GetFullPath().Get()); } Rules.Print("\n\n"); } uint64 Now = LCurrentTime(); if (Now - Last > 1000) { Last = Now; Log->Print("Building deps %i%%...\n", (int) (((int64)Count+1)*100/Deps.Length())); } } m.Print(" $(Objects)\n" " mkdir -p $(BuildDir)\n" " @echo Linking $(Target) [$(Build)]...\n" " $(CPP)%s%s %s%s -o \\\n" " $(Target) $(Objects) $(Libs)\n", ExtraLinkFlags, ExeFlags, ValidStr(LinkerFlags) ? "-Wl" : "", LinkerFlags.Get()); if (Platform == PlatformHaiku) { // Is there an application icon configured? const char *AppIcon = d->Settings.GetStr(ProjApplicationIcon, NULL, Platform); if (AppIcon) { m.Print(" addattr -f %s -t \"'VICN'\" \"BEOS:ICON\" $(Target)\n", AppIcon); } } LString PostBuildCmds = d->Settings.GetStr(ProjPostBuildCommands, NULL, Platform); if (ValidStr(PostBuildCmds)) { LString::Array a = PostBuildCmds.Split("\n"); for (unsigned i=0; iGetMakefile(Platform); if (mk) { LAutoString dep_base = d->GetBasePath(); d->CheckExists(dep_base); auto rel_dir = LMakeRelativePath(Base, dep_base); d->CheckExists(rel_dir); char *mk_leaf = strrchr(mk, DIR_CHAR); m.Print(" +make -C \"%s\" -f \"%s\" clean\n", ToUnixPath(rel_dir ? rel_dir.Get() : dep_base.Get()), ToUnixPath(mk_leaf ? mk_leaf + 1 : mk.Get())); } } m.Print("\n"); } // Shared library else if (!stricmp(TargetType, "DynamicLibrary")) { m.Print("TargetFile = lib$(Target)$(Tag).%s\n" "$(TargetFile) : $(Objects)\n" " mkdir -p $(BuildDir)\n" " @echo Linking $(TargetFile) [$(Build)]...\n" " $(CPP)$s -shared \\\n" " %s%s \\\n" " -o $(BuildDir)/$(TargetFile) \\\n" " $(Objects) \\\n" " $(Libs)\n", PlatformLibraryExt, ValidStr(ExtraLinkFlags) ? "-Wl" : "", ExtraLinkFlags, LinkerFlags.Get()); LString PostBuildCmds = d->Settings.GetStr(ProjPostBuildCommands, NULL, Platform); if (ValidStr(PostBuildCmds)) { LString::Array a = PostBuildCmds.Split("\n"); for (unsigned i=0; iSettings.GetStr(ProjPostBuildCommands, NULL, Platform); if (ValidStr(PostBuildCmds)) { LString::Array a = PostBuildCmds.Split("\n"); for (unsigned i=0; iCheckExists(p); if (p && !strchr(p, '`')) { if (!LIsRelativePath(p)) { auto a = LMakeRelativePath(Base, p); m.Print(" \\\n\t%s", ToPlatformPath(a ? a.Get() : p.Get(), Platform).Get()); } else { m.Print(" \\\n\t%s", ToPlatformPath(p, Platform).Get()); } } } m.Print("\n"); const char *OtherMakefileRules = d->Settings.GetStr(ProjMakefileRules, NULL, Platform); if (ValidStr(OtherMakefileRules)) { m.Print("\n%s\n", OtherMakefileRules); } } } else { m.Print("# No files require building.\n"); } Log->Print("...Done: '%s'\n", MakeFile.Get()); if (BuildAfterwards) { if (!Proj->GetApp()->PostEvent(M_START_BUILD)) printf("%s:%i - PostEvent(M_START_BUILD) failed.\n", _FL); } return HasError; } void OnAfterMain() { Proj->GetApp()->PostEvent(M_MAKEFILES_CREATED, (LMessage::Param)Proj); } }; ///////////////////////////////////////////////////////////////////////////////////// NodeSource::~NodeSource() { if (nView) { nView->nSrc = 0; } } NodeView::~NodeView() { if (nSrc) { nSrc->nView = 0; } } ////////////////////////////////////////////////////////////////////////////////// int NodeSort(LTreeItem *a, LTreeItem *b, NativeInt d) { ProjectNode *A = dynamic_cast(a); ProjectNode *B = dynamic_cast(b); if (A && B) { if ( (A->GetType() == NodeDir) ^ (B->GetType() == NodeDir) ) { return A->GetType() == NodeDir ? -1 : 1; } else { return Stricmp(a->GetText(0), b->GetText(0)); } } return 0; } //////////////////////////////////////////////////////////////////////////////////////////////////// bool ReadVsProjFile(LString File, LString &Ver, LString::Array &Configs) { const char *Ext = LGetExtension(File); if (!Ext || _stricmp(Ext, "vcxproj")) return false; LFile f; if (!f.Open(File, O_READ)) return false; LXmlTree Io; LXmlTag r; if (Io.Read(&r, &f) && r.IsTag("Project")) { Ver = r.GetAttr("ToolsVersion"); LXmlTag *ItemGroup = r.GetChildTag("ItemGroup"); if (ItemGroup) for (auto c: ItemGroup->Children) { if (c->IsTag("ProjectConfiguration")) { char *s = c->GetAttr("Include"); if (s) Configs.New() = s; } } } else return false; return true; } //////////////////////////////////////////////////////////////////////////////////////////////////// BuildThread::BuildThread(IdeProject *proj, char *makefile, bool clean, BuildConfig config, bool all, int wordsize) : LThread("BuildThread") { Proj = proj; Makefile = makefile; Clean = clean; Config = config; All = all; WordSize = wordsize; Arch = DefaultArch; Compiler = DefaultCompiler; AppHnd = Proj->GetApp()->AddDispatch(); LString Cmds = proj->d->Settings.GetStr(ProjPostBuildCommands, NULL); if (ValidStr(Cmds)) PostBuild = Cmds.SplitDelimit("\r\n"); auto Ext = LGetExtension(Makefile); if (Ext && !_stricmp(Ext, "py")) Compiler = PythonScript; else if (Ext && !_stricmp(Ext, "sln")) Compiler = VisualStudio; else if (Ext && !Stricmp(Ext, "xcodeproj")) Compiler = Xcode; else { auto Comp = Proj->GetSettings()->GetStr(ProjCompiler); if (Comp) { // Use the specified compiler... if (!stricmp(Comp, "VisualStudio")) Compiler = VisualStudio; else if (!stricmp(Comp, "MingW")) Compiler = MingW; else if (!stricmp(Comp, "gcc")) Compiler = Gcc; else if (!stricmp(Comp, "cross")) Compiler = CrossCompiler; else if (!stricmp(Comp, "IAR")) Compiler = IAR; else if (!stricmp(Comp, "Cygwin")) Compiler = Cygwin; else LAssert(!"Unknown compiler."); } } if (Compiler == DefaultCompiler) { // Use default compiler for platform... #ifdef WIN32 Compiler = VisualStudio; #else Compiler = Gcc; #endif } Run(); } BuildThread::~BuildThread() { if (SubProc) { bool b = SubProc->Interrupt(); LgiTrace("%s:%i - Sub process interrupt = %i.\n", _FL, b); } else LgiTrace("%s:%i - No sub process to interrupt.\n", _FL); uint64 Start = LCurrentTime(); bool Killed = false; while (!IsExited()) { LSleep(10); if (LCurrentTime() - Start > STOP_BUILD_TIMEOUT && SubProc) { if (Killed) { // Thread is stuck as well... ok kill that too!!! Argh - kill all the things!!!! Terminate(); LgiTrace("%s:%i - Thread killed.\n", _FL); Proj->GetApp()->PostEvent(M_BUILD_DONE); break; } else { // Kill the sub-process... bool b = SubProc->Kill(); Killed = true; LgiTrace("%s:%i - Sub process killed.\n", _FL, b); Start = LCurrentTime(); } } } } ssize_t BuildThread::Write(const void *Buffer, ssize_t Size, int Flags) { if (Proj->GetApp()) { Proj->GetApp()->PostEvent(M_APPEND_TEXT, (LMessage::Param)NewStr((char*)Buffer, Size), AppWnd::BuildTab); } return Size; } #pragma comment(lib, "version.lib") struct ProjInfo { LString Guid, Name, File; LHashTbl,ssize_t> Configs; }; LString BuildThread::FindExe() { LString::Array p = LGetPath(); if (Compiler == PythonScript) { #if defined(WINDOWS) uint32_t BestVer = 0; #else LString BestVer; #endif static LString Best; if (!Best) { const char *binName[] = {"python3", "python"}; for (int i=0; idwProductVersionMS > BestVer) { BestVer = v->dwProductVersionMS; Best = Path; } } } else if (!Best) { Best = Path; } free(Buf); #else LSubProcess p(Path, "--version"); LStringPipe o; if (p.Start()) p.Communicate(&o); auto Out = o.NewLStr(); auto Ver = Out.SplitDelimit().Last(); printf("Ver=%s\n", Ver.Get()); if (!BestVer || Stricmp(Ver.Get(), BestVer.Get()) > 0) { Best = Path; BestVer = Ver; } break; #endif } } } } return Best; } else if (Compiler == VisualStudio) { // Find the version we need: double fVer = 0.0; ProjInfo *First = NULL; LHashTbl, ProjInfo*> Projects; const char *Ext = LGetExtension(Makefile); if (Ext && !_stricmp(Ext, "sln")) { LFile f; if (f.Open(Makefile, O_READ)) { LString ProjKey = "Project("; LString StartSection = "GlobalSection("; LString EndSection = "EndGlobalSection"; LString Section; ssize_t Pos; LString::Array Ln = f.Read().SplitDelimit("\r\n"); for (size_t i = 0; i < Ln.Length(); i++) { LString s = Ln[i].Strip(); if ((Pos = s.Find(ProjKey)) >= 0) { LString::Array p = s.SplitDelimit("(),="); if (p.Length() > 5) { ProjInfo *i = new ProjInfo; i->Name = p[3].Strip(" \t\""); i->File = p[4].Strip(" \t\'\""); i->Guid = p[5].Strip(" \t\""); if (LIsRelativePath(i->File)) { char f[MAX_PATH_LEN]; LMakePath(f, sizeof(f), Makefile, ".."); LMakePath(f, sizeof(f), f, i->File); if (LFileExists(f)) i->File = f; /* else LAssert(0); */ } if (!First) First = i; Projects.Add(i->Guid, i); } } else if (s.Find(StartSection) >= 0) { auto p = s.SplitDelimit("() \t"); Section = p[1]; } else if (s.Find(EndSection) >= 0) { Section.Empty(); } else if (Section == "ProjectConfigurationPlatforms") { auto p = s.SplitDelimit(". \t"); auto i = Projects.Find(p[0]); if (i) { if (!i->Configs.Find(p[1])) { auto Idx = i->Configs.Length() + 1; i->Configs.Add(p[1], Idx); } } } else if (Section == "SolutionConfigurationPlatforms") { auto p = s.SplitDelimit(); auto config = p[0]; for (auto &it: Projects) { auto proj = it.value; if (!proj->Configs.Find(config)) proj->Configs.Add(config, proj->Configs.Length()+1); } } } } } else if (Ext && !_stricmp(Ext, "vcxproj")) { // ProjFile = Makefile; } else { if (Arch == DefaultArch) { if (sizeof(size_t) == 4) Arch = ArchX32; else Arch = ArchX64; } #ifdef _MSC_VER // Nmake file.. LString NmakePath; switch (_MSC_VER) { #ifdef _MSC_VER_VS2013 case _MSC_VER_VS2013: { if (Arch == ArchX32) NmakePath = "c:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\nmake.exe"; else NmakePath = "c:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\nmake.exe"; break; } #endif #ifdef _MSC_VER_VS2015 case _MSC_VER_VS2015: { if (Arch == ArchX32) NmakePath = "c:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\nmake.exe"; else NmakePath = "c:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\nmake.exe"; break; } #endif default: { LAssert(!"Impl me."); break; } } if (LFileExists(NmakePath)) { Compiler = Nmake; return NmakePath; } #endif } /* if (ProjFile && LFileExists(ProjFile)) { LString sVer; if (ReadVsProjFile(ProjFile, sVer, BuildConfigs)) { fVer = sVer.Float(); } } */ if (First) { for (auto i: First->Configs) { BuildConfigs[i.value - 1] = i.key; LFile f(First->File, O_READ); LXmlTree t; LXmlTag r; if (t.Read(&r, &f)) { if (r.IsTag("Project")) { auto ToolsVersion = r.GetAttr("ToolsVersion"); if (ToolsVersion) { fVer = atof(ToolsVersion); } } } } } if (fVer > 0.0) { for (int i=0; i LatestVer) { LatestVer = p[2].Float(); Latest = n; } } } if (Latest && LMakePath(p, sizeof(p), p, Latest) && LMakePath(p, sizeof(p), p, "common\\bin\\IarBuild.exe")) { if (LFileExists(p)) return p; } } else if (Compiler == Xcode) { return "/usr/bin/xcodebuild"; } else if (Compiler == Cygwin) { #ifdef WINDOWS LRegKey k(false, "HKEY_CURRENT_USER\\Software\\Cygwin\\Installations"); List n; k.GetValueNames(n); LString s; for (auto i:n) { s = k.GetStr(i); if (s.Find("\\??\\") == 0) s = s(4,-1); if (LDirExists(s)) { CygwinPath = s; break; } } n.DeleteArrays(); LFile::Path p(s, "bin\\make.exe"); if (p.Exists()) return p.GetFull(); #endif } else { if (Compiler == MingW) { // Have a look in the default spot first... const char *Def = "C:\\MinGW\\msys\\1.0\\bin\\make.exe"; if (LFileExists(Def)) { return Def; } } for (int i=0; iGetBasePath(); LString InitDir = InitFolder.Get(); LVariant Jobs; if (!Proj->GetApp()->GetOptions()->GetValue(OPT_Jobs, Jobs) || Jobs.CastInt32() < 1) Jobs = 2; LString TmpArgs, Include, Lib, LibPath, Path; if (Compiler == VisualStudio) { // TmpArgs.Printf("\"%s\" /make \"All - Win32 Debug\"", Makefile.Get()); LString BuildConf = "All - Win32 Debug"; if (BuildConfigs.Length()) { auto Key = toString(Config); for (size_t i=0; i= 0) { if (!BuildConf || (c.Find("x64") >= 0 && BuildConf.Find("x64") < 0)) BuildConf = c; } } } TmpArgs.Printf("\"%s\" %s \"%s\"", Makefile.Get(), Clean ? "/Clean" : "/Build", BuildConf.Get()); } else if (Compiler == Nmake) { const char *DefInc[] = { "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\INCLUDE", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\ATLMFC\\INCLUDE", "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\shared", "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\um", "C:\\Program Files (x86)\\Windows Kits\\8.1\\include\\winrt" }; LString f; #define ADD_PATHS(out, in) \ for (unsigned i=0; iGetChildTag("name") : NULL; if (c) Conf = c->GetContent(); } } TmpArgs.Printf("\"%s\" %s %s -log warnings", Makefile.Get(), Clean ? "-clean" : "-make", Conf.Get()); } else if (Compiler == Xcode) { LString::Array Configs; Configs.SetFixedLength(false); LString a; a.Printf("-list -project \"%s\"", Makefile.Get()); LSubProcess Ls(Exe, a); if (Ls.Start()) { LStringPipe o; Ls.Communicate(&o); auto key = "Build Configurations:"; auto lines = o.NewLStr().SplitDelimit("\n"); int inKey = -1; for (auto l: lines) { int ws = 0; for (int i=0; i=0) inKey = ws; else if (inKey>=0) { if (ws>inKey) { Configs.New() = l.Strip(); } else { inKey = -1; } } // printf("%s\n", l.Get()); } } auto Config = Configs.Length() > 0 ? Configs[0] : LString("Debug"); TmpArgs.Printf("-project \"%s\" -configuration %s", Makefile.Get(), Config.Get()); } else { if (Compiler == Cygwin) { LFile::Path p(CygwinPath, "bin"); Path = p.GetFull(); } if (Compiler == MingW) { LString a; char *Dir = strrchr(MakePath, DIR_CHAR); #if 1 TmpArgs.Printf("/C \"%s\"", Exe.Get()); /* As of MSYS v1.0.18 the support for multiple jobs causes make to hang: http://sourceforge.net/p/mingw/bugs/1950/ http://mingw-users.1079350.n2.nabble.com/MSYS-make-freezes-td7579038.html Apparently it'll be "fixed" in v1.0.19. We'll see. >:-( if (Jobs.CastInt32() > 1) a.Print(" -j %i", Jobs.CastInt32()); */ a.Printf(" -f \"%s\"", Dir ? Dir + 1 : MakePath.Get()); TmpArgs += a; #else TmpArgs.Printf("/C set"); #endif Exe = "C:\\Windows\\System32\\cmd.exe"; } else { if (Jobs.CastInt32()) TmpArgs.Printf("-j %i -f \"%s\"", Jobs.CastInt32(), MakePath.Get()); else TmpArgs.Printf("-f \"%s\"", MakePath.Get()); } if (Clean) { if (All) TmpArgs += " cleanall"; else TmpArgs += " clean"; } if (Config == BuildRelease) TmpArgs += " Build=Release"; } PostThreadEvent(AppHnd, M_SELECT_TAB, AppWnd::BuildTab); LString Msg; Msg.Printf("Making: %s\n", MakePath.Get()); // Msg.Printf("InitDir: %s\n", InitDir.Get()); Proj->GetApp()->PostEvent(M_APPEND_TEXT, (LMessage::Param)NewStr(Msg), AppWnd::BuildTab); LgiTrace("%s %s\n", Exe.Get(), TmpArgs.Get()); if (SubProc.Reset(new LSubProcess(Exe, TmpArgs))) { SubProc->SetNewGroup(false); SubProc->SetInitFolder(InitDir); if (Include) SubProc->SetEnvironment("INCLUDE", Include); if (Lib) SubProc->SetEnvironment("LIB", Lib); if (LibPath) SubProc->SetEnvironment("LIBPATHS", LibPath); if (Path) { LString Cur = getenv("PATH"); LString New = Cur + LGI_PATH_SEPARATOR + Path; SubProc->SetEnvironment("PATH", New); } // SubProc->SetEnvironment("DLL", "1"); if (Compiler == MingW) SubProc->SetEnvironment("PATH", "c:\\MingW\\bin;C:\\MinGW\\msys\\1.0\\bin;%PATH%"); if ((Status = SubProc->Start(true, false))) { // Read all the output char Buf[256]; ssize_t rd; while ( (rd = SubProc->Read(Buf, sizeof(Buf))) > 0 ) { Write(Buf, rd); } uint32_t ex = SubProc->Wait(); Print("Make exited with %i (0x%x)\n", ex, ex); if (Compiler == IAR && ex == 0 && PostBuild.Length()) { for (auto Cmd : PostBuild) { auto p = Cmd.Split(" ", 1); if (p[0].Equals("cd")) { if (p.Length() > 1) FileDev->SetCurrentFolder(p[1]); else LAssert(!"No folder for cd?"); } else { LSubProcess PostCmd(p[0], p.Length() > 1 ? p[1] : LString()); if (PostCmd.Start(true, false)) { char Buf[256]; ssize_t rd; while ( (rd = PostCmd.Read(Buf, sizeof(Buf))) > 0 ) { Write(Buf, rd); } } } } } } else { // Create a nice error message. LString ErrStr = LErrorCodeToString(SubProc->GetErrorCode()); if (ErrStr) { char *e = ErrStr.Get() + ErrStr.Length(); while (e > ErrStr && strchr(" \t\r\n.", e[-1])) *(--e) = 0; } sprintf_s(ErrBuf, sizeof(ErrBuf), "Running make failed with %i (%s)\n", SubProc->GetErrorCode(), ErrStr.Get()); Err = ErrBuf; } } } else { Err = "Couldn't find program to build makefile."; LgiTrace("%s,%i - %s.\n", _FL, Err); } AppWnd *w = Proj->GetApp(); if (w) { w->PostEvent(M_BUILD_DONE); if (Err) Proj->GetApp()->PostEvent(M_BUILD_ERR, 0, (LMessage::Param)NewStr(Err)); } else LAssert(0); return 0; } ////////////////////////////////////////////////////////////////////////////////// IdeProject::IdeProject(AppWnd *App) : IdeCommon(NULL) { Project = this; d = new IdeProjectPrivate(App, this); Tag = NewStr("Project"); } IdeProject::~IdeProject() { d->App->OnProjectDestroy(this); LXmlTag::Empty(true); DeleteObj(d); } bool IdeProject::OnNode(const char *Path, ProjectNode *Node, bool Add) { if (!Path || !Node) { LAssert(0); return false; } char Full[MAX_PATH_LEN]; if (LIsRelativePath(Path)) { LAutoString Base = GetBasePath(); if (LMakePath(Full, sizeof(Full), Base, Path)) { Path = Full; } } bool Status = false; if (Add) Status = d->Nodes.Add(Path, Node); else Status = d->Nodes.Delete(Path); LString p = Path; if (Status && CheckExists(p)) d->App->OnNode(p, Node, Add ? FindSymbolSystem::FileAdd : FindSymbolSystem::FileRemove); return Status; } void IdeProject::ShowFileProperties(const char *File) { ProjectNode *Node = NULL; // char *fp = FindFullPath(File, &Node); if (Node) { Node->OnProperties(); } } const char *IdeProject::GetFileComment() { return d->Settings.GetStr(ProjCommentFile); } const char *IdeProject::GetFunctionComment() { return d->Settings.GetStr(ProjCommentFunction); } IdeProject *IdeProject::GetParentProject() { return d->ParentProject; } void IdeProject::SetParentProject(IdeProject *p) { d->ParentProject = p; } bool IdeProject::GetChildProjects(List &c) { CollectAllSubProjects(c); return c.Length() > 0; } bool IdeProject::RelativePath(LString &Out, const char *In, bool Debug) { if (!In) return false; auto Base = GetBasePath(); if (!Base) return false; CheckExists(Base); if (Debug) LgiTrace("XmlBase='%s'\n In='%s'\n", Base.Get(), In); LToken b(Base, DIR_STR); LToken i(In, DIR_STR); char out[MAX_PATH_LEN] = ""; int outCh = 0; if (Debug) LgiTrace("Len %i-%i\n", b.Length(), i.Length()); auto ILen = i.Length() + (LDirExists(In) ? 0 : 1); auto Max = MIN(b.Length(), ILen); int Common = 0; for (; Common < Max; Common++) { #ifdef WIN32 #define StrCompare stricmp #else #define StrCompare strcmp #endif if (Debug) LgiTrace("Cmd '%s'-'%s'\n", b[Common], i[Common]); if (StrCompare(b[Common], i[Common]) != 0) { break; } } if (Debug) LgiTrace("Common=%i\n", Common); if (Common > 0) { if (Common < b.Length()) { out[outCh = 0] = 0; auto Back = b.Length() - Common; if (Debug) LgiTrace("Back=%i\n", (int)Back); for (int n=0; nSettings.GetStr(ProjExe); LString Exe; if (!PExe) { // Use the default exe name? Exe = GetExecutable(GetCurrentPlatform()); if (Exe) { printf("Exe='%s'\n", Exe.Get()); PExe = Exe; } } if (!PExe) return false; if (LIsRelativePath(PExe)) { auto Base = GetBasePath(); if (Base) LMakePath(Path, Len, Base, PExe); else return false; } else { strcpy_s(Path, Len, PExe); } return true; } LString IdeProject::GetMakefile(IdePlatform Platform) { const char *PMakefile = d->Settings.GetStr(ProjMakefile, NULL, Platform); if (!PMakefile) return LString(); LString Path; if (LIsRelativePath(PMakefile)) { auto Base = GetBasePath(); if (Base) { char p[MAX_PATH_LEN]; LMakePath(p, sizeof(p), Base, PMakefile); Path = p; } } else { Path = PMakefile; } return Path; } void IdeProject::Clean(bool All, BuildConfig Config) { if (!d->Thread && d->Settings.GetStr(ProjMakefile)) { auto m = GetMakefile(PlatformCurrent); if (m) { CheckExists(m); d->Thread.Reset(new BuildThread(this, m, true, Config, All, sizeof(ssize_t)*8)); } } } char *QuoteStr(char *s) { LStringPipe p(256); while (s && *s) { if (*s == ' ') { p.Push("\\ ", 2); } else p.Push(s, 1); s++; } return p.NewStr(); } class ExecuteThread : public LThread, public LStream, public LCancel { IdeProject *Proj; LString Exe, Args, Path; int Len; ExeAction Act; int AppHnd; public: ExecuteThread(IdeProject *proj, const char *exe, const char *args, char *path, ExeAction act) : LThread("ExecuteThread") { Len = 32 << 10; Proj = proj; Act = act; Exe = exe; Args = args; Path = path; DeleteOnExit = true; AppHnd = proj->GetApp()->AddDispatch(); Run(); } ~ExecuteThread() { Cancel(); while (!IsExited()) LSleep(1); } int Main() override { PostThreadEvent(AppHnd, M_SELECT_TAB, AppWnd::OutputTab); PostThreadEvent(AppHnd, M_APPEND_TEXT, 0, AppWnd::OutputTab); if (Exe) { if (Act == ExeDebug) { LSubProcess sub("kdbg", Exe); if (Path) sub.SetInitFolder(Path); if (sub.Start()) sub.Communicate(this, NULL, this); } else if (Act == ExeValgrind) { #ifdef LINUX LString ExePath = Proj->GetExecutable(GetCurrentPlatform()); if (ExePath) { char Path[MAX_PATH_LEN]; char *ExeLeaf = LGetLeaf(Exe); strcpy_s(Path, sizeof(Path), ExeLeaf ? ExeLeaf : Exe.Get()); LTrimDir(Path); const char *Term = NULL; const char *WorkDir = NULL; const char *Execute = NULL; switch (LGetWindowManager()) { case WM_Kde: Term = "konsole"; WorkDir = "--workdir "; Execute = "-e"; break; case WM_Gnome: Term = "gnome-terminal"; WorkDir = "--working-directory="; Execute = "-x"; break; } if (Term && WorkDir && Execute) { char *e = QuoteStr(ExePath); char *p = QuoteStr(Path); const char *a = Proj->GetExeArgs() ? Proj->GetExeArgs() : ""; char Args[512]; sprintf(Args, "%s%s " "--noclose " "%s valgrind --tool=memcheck --num-callers=20 %s %s", WorkDir, p, Execute, e, a); LExecute(Term, Args); } } #endif } else { LSubProcess sub(Exe, Args); if (Path) sub.SetInitFolder(Path); if (sub.Start()) sub.Communicate(this, NULL, this); } } return 0; } ssize_t Write(const void *Buffer, ssize_t Size, int Flags = 0) override { if (Len <= 0) return 0; PostThreadEvent(AppHnd, M_APPEND_TEXT, (LMessage::Param)NewStr((char*)Buffer, Size), AppWnd::OutputTab); Len -= Size; return Size; } }; LDebugContext *IdeProject::Execute(ExeAction Act, LString *ErrMsg) { auto Base = GetBasePath(); if (!Base) { if (ErrMsg) *ErrMsg = "No base path for project."; return NULL; } char e[MAX_PATH_LEN]; if (!GetExePath(e, sizeof(e))) { if (ErrMsg) *ErrMsg = "GetExePath failed."; return NULL; } if (!LFileExists(e)) { if (ErrMsg) ErrMsg->Printf("Executable '%s' doesn't exist.\n", e); return NULL; } const char *Args = d->Settings.GetStr(ProjArgs); const char *Env = d->Settings.GetStr(ProjEnv); LString InitDir = d->Settings.GetStr(ProjInitDir); int RunAsAdmin = d->Settings.GetInt(ProjDebugAdmin); #ifndef HAIKU if (Act == ExeDebug) { if (InitDir && LIsRelativePath(InitDir)) { LFile::Path p(Base); p += InitDir; InitDir = p.GetFull(); } return new LDebugContext(d->App, this, e, Args, RunAsAdmin != 0, Env, InitDir); } #endif new ExecuteThread( this, e, Args, Base, #if defined(HAIKU) || defined(WINDOWS) ExeRun // No gdb or valgrind #else Act #endif ); return NULL; } bool IdeProject::IsMakefileAScript() { auto m = GetMakefile(PlatformCurrent); if (m) { auto Ext = LGetExtension(m); if (!Stricmp(Ext, "py")) { // Not a makefile but a build script... can't update. return true; } } return false; } bool IdeProject::IsMakefileUpToDate() { if (IsMakefileAScript()) return true; // We can't know if it's up to date... List Proj; GetChildProjects(Proj); Proj.Insert(this); for (auto p: Proj) { // Is the project file modified after the makefile? auto Proj = p->GetFullPath(); uint64 ProjModTime = 0, MakeModTime = 0; LDirectory dir; if (dir.First(Proj)) { ProjModTime = dir.GetLastWriteTime(); dir.Close(); } auto m = p->GetMakefile(PlatformCurrent); if (!m) { d->App->GetBuildLog()->Print("Error: no makefile? (%s:%i)\n", _FL); break; } auto Ext = LGetExtension(m); if (!Stricmp(Ext, "py")) { // Not a makefile but a build script... can't update. return true; } if (dir.First(m)) { MakeModTime = dir.GetLastWriteTime(); dir.Close(); } // printf("Proj=%s - Timestamps " LGI_PrintfInt64 " - " LGI_PrintfInt64 "\n", Proj.Get(), ProjModTime, MakeModTime); if (ProjModTime != 0 && MakeModTime != 0 && ProjModTime > MakeModTime) { // Need to rebuild the makefile... return false; } } return true; } bool IdeProject::FindDuplicateSymbols() { LStream *Log = d->App->GetBuildLog(); Log->Print("FindDuplicateSymbols starting...\n"); List Proj; CollectAllSubProjects(Proj); Proj.Insert(this); int Lines = 0; LHashTbl,int64> Map(200000); int Found = 0; for (auto p: Proj) { LString s = p->GetExecutable(GetCurrentPlatform()); if (s) { LString Args; Args.Printf("--print-size --defined-only -C %s", s.Get()); LSubProcess Nm("nm", Args); if (Nm.Start(true, false)) { char Buf[256]; LStringPipe q; for (ssize_t Rd = 0; (Rd = Nm.Read(Buf, sizeof(Buf))); ) q.Write(Buf, Rd); LString::Array a = q.NewLStr().SplitDelimit("\r\n"); LHashTbl,bool> Local(200000); for (auto &Ln: a) { LString::Array p = Ln.SplitDelimit(" \t", 3); if (!Local.Find(p.Last())) { Local.Add(p.Last(), true); // const char *Sz = p[1]; int64 Ours = p[1].Int(16); int64 Theirs = Map.Find(p.Last()); if (Theirs >= 0) { if (Ours != Theirs) { if (Found++ < 100) Log->Print(" %s (" LPrintfInt64 " -> " LPrintfInt64 ")\n", p.Last().Get(), Ours, Theirs); } } else if (Ours >= 0) { Map.Add(p.Last(), Ours); } else { printf("Bad line: %s\n", Ln.Get()); } } Lines++; } } } else printf("%s:%i - GetExecutable failed.\n", _FL); } /* char *Sym; for (int Count = Map.First(&Sym); Count; Count = Map.Next(&Sym)) { if (Count > 1) Log->Print(" %i: %s\n", Count, Sym); } */ Log->Print("FindDuplicateSymbols finished (%i lines)\n", Lines); return false; } bool IdeProject::FixMissingFiles() { FixMissingFilesDlg(this); return true; } void IdeProject::Build(bool All, BuildConfig Config) { if (d->Thread) { d->App->GetBuildLog()->Print("Error: Already building (%s:%i)\n", _FL); return; } auto m = GetMakefile(PlatformCurrent); CheckExists(m); if (!m) { d->App->GetBuildLog()->Print("Error: no makefile? (%s:%i)\n", _FL); return; } if (GetApp()) GetApp()->PostEvent(M_APPEND_TEXT, 0, 0); SetClean([this, m, All, Config](bool ok) { if (!ok) return; if (!IsMakefileUpToDate()) CreateMakefile(GetCurrentPlatform(), true); else // Start the build thread... d->Thread.Reset ( new BuildThread ( this, m, false, Config, All, sizeof(size_t)*8 ) ); }); } void IdeProject::StopBuild() { d->Thread.Reset(); } bool IdeProject::Serialize(bool Write) { return true; } AppWnd *IdeProject::GetApp() { return d->App; } const char *IdeProject::GetIncludePaths() { return d->Settings.GetStr(ProjIncludePaths); } const char *IdeProject::GetPreDefinedValues() { return d->Settings.GetStr(ProjDefines); } const char *IdeProject::GetExeArgs() { return d->Settings.GetStr(ProjArgs); } LString IdeProject::GetExecutable(IdePlatform Platform) { LString Bin = d->Settings.GetStr(ProjExe, NULL, Platform); auto TargetType = d->Settings.GetStr(ProjTargetType, NULL, Platform); auto Base = GetBasePath(); if (Bin) { if (LIsRelativePath(Bin) && Base) { char p[MAX_PATH_LEN]; if (LMakePath(p, sizeof(p), Base, Bin)) Bin = p; } return Bin; } // Create binary name from target: auto Target = GetTargetName(Platform); if (Target) { bool IsLibrary = Stristr(TargetType, "library"); int BuildMode = d->App->GetBuildMode(); const char *Name = BuildMode ? "Release" : "Debug"; const char *Postfix = BuildMode ? "" : "d"; switch (Platform) { case PlatformWin: { if (IsLibrary) Bin.Printf("%s%s.dll", Target.Get(), Postfix); else Bin = Target; break; } case PlatformMac: { if (IsLibrary) Bin.Printf("lib%s%s.dylib", Target.Get(), Postfix); else Bin = Target; break; } case PlatformLinux: case PlatformHaiku: { if (IsLibrary) Bin.Printf("lib%s%s.so", Target.Get(), Postfix); else Bin = Target; break; } default: { LAssert(0); printf("%s:%i - Unknown platform.\n", _FL); return LString(); } } // Find the actual file... if (!Base) { printf("%s:%i - GetBasePath failed.\n", _FL); return LString(); } char Path[MAX_PATH_LEN]; LMakePath(Path, sizeof(Path), Base, Name); LMakePath(Path, sizeof(Path), Path, Bin); if (LFileExists(Path)) Bin = Path; else printf("%s:%i - '%s' doesn't exist.\n", _FL, Path); return Bin; } return LString(); } const char *IdeProject::GetFileName() { return d->FileName; } int IdeProject::GetPlatforms() { return PLATFORM_ALL; } LAutoString IdeProject::GetFullPath() { LAutoString Status; if (!d->FileName) { // LAssert(!"No path."); return Status; } LArray sections; IdeProject *proj = this; while ( proj && proj->GetFileName() && LIsRelativePath(proj->GetFileName())) { sections.AddAt(0, proj->GetFileName()); proj = proj->GetParentProject(); } if (!proj) { // LAssert(!"All projects have a relative path?"); return Status; // No absolute path in the parent projects? } char p[MAX_PATH_LEN]; strcpy_s(p, sizeof(p), proj->GetFileName()); // Copy the base path if (sections.Length() > 0) LTrimDir(p); // Trim off the filename for (int i=0; iFileName.Empty(); d->UserFile.Empty(); d->App->GetTree()->Insert(this); ProjectNode *f = new ProjectNode(this); if (f) { f->SetName("Source"); f->SetType(NodeDir); InsertTag(f); } f = new ProjectNode(this); if (f) { f->SetName("Headers"); f->SetType(NodeDir); InsertTag(f); } d->Settings.Set(ProjEditorTabSize, 4); d->Settings.Set(ProjEditorIndentSize, 4); d->Settings.Set(ProjEditorUseHardTabs, true); d->Dirty = true; Expanded(true); } ProjectStatus IdeProject::OpenFile(const char *FileName) { auto Log = d->App->GetBuildLog(); LProfile Prof("IdeProject::OpenFile"); Prof.HideResultsIfBelow(1000); Empty(); Prof.Add("Init"); d->UserNodeFlags.Empty(); if (LIsRelativePath(FileName)) { char p[MAX_PATH_LEN]; getcwd(p, sizeof(p)); LMakePath(p, sizeof(p), p, FileName); d->FileName = p; } else { d->FileName = FileName; } d->UserFile = d->FileName + "." + LCurrentUserName(); if (!d->FileName) { Log->Print("%s:%i - No filename.\n", _FL); return OpenError; } Prof.Add("FileOpen"); LFile f; LString FullPath = d->FileName.Get(); if (!CheckExists(FullPath) || !f.Open(FullPath, O_READWRITE)) { Log->Print("%s:%i - Error: Can't open '%s'.\n", _FL, FullPath.Get()); return OpenError; } Prof.Add("Xml"); LXmlTree x; LXmlTag r; if (!x.Read(&r, &f)) { Log->Print("%s:%i - Error: Can't read XML: %s\n", _FL, x.GetErrorMsg()); return OpenError; } Prof.Add("Progress Setup"); #if DEBUG_OPEN_PROGRESS int64 Nodes = r.CountTags(); LProgressDlg Prog(d->App, 1000); Prog.SetDescription("Loading project..."); Prog.SetLimits(0, Nodes); Prog.SetYieldTime(1000); Prog.SetAlwaysOnTop(true); #endif Prof.Add("UserFile"); if (LFileExists(d->UserFile)) { LFile Uf; if (Uf.Open(d->UserFile, O_READ)) { LString::Array Ln = Uf.Read().SplitDelimit("\n"); for (unsigned i=0; iUserNodeFlags.Add((int)p[0].Int(), (int)p[1].Int(16)); } } } if (!r.IsTag("Project")) { Log->Print("%s:%i - No 'Project' tag.\n", _FL); return OpenError; } Prof.Add("OnOpen"); bool Ok = OnOpen( #if DEBUG_OPEN_PROGRESS &Prog, #else NULL, #endif &r); #if DEBUG_OPEN_PROGRESS if (Prog.IsCancelled()) return OpenCancel; else #endif if (!Ok) return OpenError; Prof.Add("Insert"); d->App->GetTree()->Insert(this); Expanded(true); Prof.Add("Serialize"); d->Settings.Serialize(&r, false /* read */); return OpenOk; } bool IdeProject::SaveFile() { auto Full = GetFullPath(); if (ValidStr(Full) && d->Dirty) { LFile f; if (f.Open(Full, O_WRITE)) { f.SetSize(0); LXmlTree x; d->Settings.Serialize(this, true /* write */); if (x.Write(this, &f)) d->Dirty = false; else LgiTrace("%s:%i - Failed to write XML.\n", _FL); } else LgiTrace("%s:%i - Couldn't open '%s' for writing.\n", _FL, Full.Get()); } if (d->UserFileDirty) { LFile f; LAssert(d->UserFile.Get()); if (f.Open(d->UserFile, O_WRITE)) { f.SetSize(0); // Save user file details.. // int Id; // for (int Flags = d->UserNodeFlags.First(&Id); Flags >= 0; Flags = d->UserNodeFlags.Next(&Id)) for (auto i : d->UserNodeFlags) { f.Print("%i,%x\n", i.key, i.value); } d->UserFileDirty = false; } } printf("\tIdeProject::SaveFile %i %i\n", d->Dirty, d->UserFileDirty); return !d->Dirty && !d->UserFileDirty; } void IdeProject::SetDirty() { d->Dirty = true; d->App->OnProjectChange(); } void IdeProject::SetUserFileDirty() { d->UserFileDirty = true; } bool IdeProject::GetExpanded(int Id) { int f = d->UserNodeFlags.Find(Id); return f >= 0 ? f : false; } void IdeProject::SetExpanded(int Id, bool Exp) { if (d->UserNodeFlags.Find(Id) != (int)Exp) { d->UserNodeFlags.Add(Id, Exp); SetUserFileDirty(); } } int IdeProject::AllocateId() { return d->NextNodeId++; } template bool CheckExists(LAutoString Base, T &p, Fn Setter, bool Debug) { LFile::Path Full; bool WasRel = LIsRelativePath(p); if (WasRel) { Full = Base.Get(); Full += p.Get(); } else Full = p.Get(); bool Ret = Full.Exists(); if (!Ret) { // Is the case wrong? for (int i=1; i%s\n", i, Leaf.Get(), dir.GetName()); Leaf = dir.GetName(); Matched = true; break; } } if (!Matched) break; } } if ((Ret = Full.Exists())) { LString Old = p.Get(); if (WasRel) { auto r = LMakeRelativePath(Base, Full); Setter(p, r); } else { Setter(p, Full.GetFull()); } if (Debug) printf("%s -> %s\n", Old.Get(), p.Get()); } } if (Debug) printf("CheckExists '%s' = %i\n", Full.GetFull().Get(), Ret); return Ret; } bool IdeProject::CheckExists(LString &p, bool Debug) { return ::CheckExists(GetBasePath(), p, [](LString &o, const char *i) { o = i; }, Debug); } bool IdeProject::CheckExists(LAutoString &p, bool Debug) { return ::CheckExists(GetBasePath(), p, [](LAutoString &o, const char *i) { o.Reset(NewStr(i)); }, Debug); } bool IdeProject::GetClean() { for (auto i: *this) { ProjectNode *p = dynamic_cast(i); if (p && !p->GetClean()) return false; } return !d->Dirty && !d->UserFileDirty; } void IdeProject::SetClean(std::function OnDone) { auto CleanNodes = [this, OnDone]() { // printf("IdeProject.SetClean.CleanNodes\n"); for (auto i: *this) { ProjectNode *p = dynamic_cast(i); if (!p) break; p->SetClean(); } if (OnDone) OnDone(true); }; // printf("IdeProject.SetClean dirty=%i,%i validfile=%i\n", d->Dirty, d->UserFileDirty, ValidStr(d->FileName)); if (d->Dirty || d->UserFileDirty) { if (ValidStr(d->FileName)) SaveFile(); else { auto s = new LFileSelect; s->Parent(Tree); s->Name("Project.xml"); s->Save([this, OnDone, CleanNodes](auto s, auto ok) { // printf("IdeProject.SetClean.FileSelect ok=%i\n", ok); if (ok) { d->FileName = s->Name(); d->UserFile = d->FileName + "." + LCurrentUserName(); d->App->OnFile(d->FileName, true); Update(); CleanNodes(); } else { if (OnDone) OnDone(false); } delete s; }); return; } } CleanNodes(); } const char *IdeProject::GetText(int Col) { if (d->FileName) { char *s = strrchr(d->FileName, DIR_CHAR); return s ? s + 1 : d->FileName.Get(); } return Untitled; } int IdeProject::GetImage(int Flags) { return 0; } void IdeProject::Empty() { LXmlTag *t; while (Children.Length() > 0 && (t = Children[0])) { ProjectNode *n = dynamic_cast(t); if (n) { n->Remove(); } DeleteObj(t); } } LXmlTag *IdeProject::Create(char *Tag) { if (!stricmp(Tag, TagSettings)) return NULL; return new ProjectNode(this); } void IdeProject::OnMouseClick(LMouse &m) { if (m.IsContextMenu()) { LSubMenu Sub; Sub.AppendItem("New Folder", IDM_NEW_FOLDER); Sub.AppendItem("New Web Folder", IDM_WEB_FOLDER); Sub.AppendSeparator(); Sub.AppendItem("Build", IDM_BUILD); Sub.AppendItem("Clean Project", IDM_CLEAN_PROJECT); Sub.AppendItem("Clean All", IDM_CLEAN_ALL); Sub.AppendItem("Rebuild Project", IDM_REBUILD_PROJECT); Sub.AppendItem("Rebuild All", IDM_REBUILD_ALL); Sub.AppendSeparator(); Sub.AppendItem("Sort Children", IDM_SORT_CHILDREN); Sub.AppendSeparator(); Sub.AppendItem("Settings", IDM_SETTINGS, true); Sub.AppendItem("Insert Dependency", IDM_INSERT_DEP); m.ToScreen(); auto c = _ScrollPos(); m.x -= c.x; m.y -= c.y; switch (Sub.Float(Tree, m.x, m.y)) { case IDM_NEW_FOLDER: { auto Name = new LInput(Tree, "", "Name:", AppName); Name->DoModal([this, Name](auto d, auto code) { if (code) GetSubFolder(this, Name->GetStr(), true); delete d; }); break; } case IDM_WEB_FOLDER: { WebFldDlg *Dlg = new WebFldDlg(Tree, 0, 0, 0); Dlg->DoModal([Dlg, this](auto d, auto code) { if (Dlg->Ftp && Dlg->Www) { IdeCommon *f = GetSubFolder(this, Dlg->Name, true); if (f) { f->SetAttr(OPT_Ftp, Dlg->Ftp); f->SetAttr(OPT_Www, Dlg->Www); } } delete Dlg; }); break; } case IDM_BUILD: { StopBuild(); Build(true, d->App->GetBuildMode()); break; } case IDM_CLEAN_PROJECT: { Clean(false, d->App->GetBuildMode()); break; } case IDM_CLEAN_ALL: { Clean(true, d->App->GetBuildMode()); break; } case IDM_REBUILD_PROJECT: { StopBuild(); Clean(false, d->App->GetBuildMode()); Build(false, d->App->GetBuildMode()); break; } case IDM_REBUILD_ALL: { StopBuild(); Clean(true, d->App->GetBuildMode()); Build(true, d->App->GetBuildMode()); break; } case IDM_SORT_CHILDREN: { SortChildren(); Project->SetDirty(); break; } case IDM_SETTINGS: { d->Settings.Edit(Tree, [this]() { SetDirty(); }); break; } case IDM_INSERT_DEP: { LFileSelect *s = new LFileSelect; s->Parent(Tree); s->Type("Project", "*.xml"); s->Open([this](auto s, bool ok) { if (ok) { ProjectNode *New = new ProjectNode(this); if (New) { New->SetFileName(s->Name()); New->SetType(NodeDependancy); InsertTag(New); SetDirty(); } } delete s; }); break; } } } } char *IdeProject::FindFullPath(const char *File, ProjectNode **Node) { char *Full = 0; for (auto i:*this) { ProjectNode *c = dynamic_cast(i); if (!c) break; ProjectNode *n = c->FindFile(File, &Full); if (n) { if (Node) *Node = n; break; } } return Full; } bool IdeProject::HasNode(ProjectNode *Node) { for (auto i:*this) { ProjectNode *c = dynamic_cast(i); if (!c) break; if (c->HasNode(Node)) return true; } return false; } bool IdeProject::GetAllNodes(LArray &Nodes) { for (auto i:*this) { ProjectNode *c = dynamic_cast(i); if (!c) break; c->AddNodes(Nodes); } return true; } bool IdeProject::InProject(bool FuzzyMatch, const char *Path, bool Open, IdeDoc **Doc) { if (!Path) return false; // Search complete path first... ProjectNode *n = d->Nodes.Find(Path); if (!n && FuzzyMatch) { // No match, do partial matching. const char *Leaf = LGetLeaf(Path); auto PathLen = strlen(Path); auto LeafLen = strlen(Leaf); uint32_t MatchingScore = 0; // Traverse all nodes and try and find the best fit. // const char *p; // for (ProjectNode *Cur = d->Nodes.First(&p); Cur; Cur = d->Nodes.Next(&p)) for (auto Cur : d->Nodes) { int CurPlatform = Cur.value->GetPlatforms(); uint32_t Score = 0; if (stristr(Cur.key, Path)) { Score += PathLen; } else if (stristr(Cur.key, Leaf)) { Score += LeafLen; } const char *pLeaf = LGetLeaf(Cur.key); if (pLeaf && !stricmp(pLeaf, Leaf)) { Score |= 0x40000000; } if (Score && (CurPlatform & PLATFORM_CURRENT) != 0) { Score |= 0x80000000; } if (Score > MatchingScore) { MatchingScore = Score; n = Cur.value; } } } if (n && Doc) { *Doc = n->Open(); } return n != 0; } char *GetQuotedStr(char *Str) { char *s = strchr(Str, '\"'); if (s) { s++; char *e = strchr(s, '\"'); if (e) { return NewStr(s, e - s); } } return 0; } void IdeProject::ImportDsp(const char *File) { if (File && LFileExists(File)) { char Base[256]; strcpy(Base, File); LTrimDir(Base); char *Dsp = LReadTextFile(File); if (Dsp) { LToken Lines(Dsp, "\r\n"); IdeCommon *Current = this; bool IsSource = false; for (int i=0; iGetSubFolder(this, Folder, true); if (Sub) { Current = Sub; } DeleteArray(Folder); } } else if (strnicmp(L, "# End Group", 11) == 0) { IdeCommon *Parent = dynamic_cast(Current->GetParent()); if (Parent) { Current = Parent; } } else if (strnicmp(L, "# Begin Source", 14) == 0) { IsSource = true; } else if (strnicmp(L, "# End Source", 12) == 0) { IsSource = false; } else if (Current && IsSource && strncmp(L, "SOURCE=", 7) == 0) { ProjectNode *New = new ProjectNode(this); if (New) { char *Src = 0; if (strchr(L, '\"')) { Src = GetQuotedStr(L); } else { Src = NewStr(L + 7); } if (Src) { // Make absolute path char Abs[256]; LMakePath(Abs, sizeof(Abs), Base, ToUnixPath(Src)); // Make relitive path New->SetFileName(Src); DeleteArray(Src); } Current->InsertTag(New); SetDirty(); } } } DeleteArray(Dsp); } } } IdeProjectSettings *IdeProject::GetSettings() { return &d->Settings; } bool IdeProject::BuildIncludePaths(LArray &Paths, bool Recurse, bool IncludeSystem, IdePlatform Platform) { List Projects; if (Recurse) GetChildProjects(Projects); Projects.Insert(this, 0); LHashTbl, bool> Map; for (auto p: Projects) { LString ProjInclude = d->Settings.GetStr(ProjIncludePaths, NULL, Platform); LAutoString Base = p->GetBasePath(); const char *Delim = ",;\r\n"; LString::Array In, Out; LString::Array a = ProjInclude.SplitDelimit(Delim); In = a; if (IncludeSystem) { LString SysInclude = d->Settings.GetStr(ProjSystemIncludes, NULL, Platform); a = SysInclude.SplitDelimit(Delim); In.SetFixedLength(false); In.Add(a); } for (unsigned i=0; i 1 ? a[1].Get() : NULL); LStringPipe Buf; if (Proc.Start()) { Proc.Communicate(&Buf); LString result = Buf.NewLStr(); a = result.Split(" \t\r\n"); for (int i=0; i Nodes; if (p->GetAllNodes(Nodes)) { auto Base = p->GetFullPath(); if (Base) { LTrimDir(Base); for (auto &n: Nodes) { if (n->GetType() == NodeHeader && // Only look at headers. (n->GetPlatforms() & (1 << Platform)) != 0) // Exclude files not on this platform. { auto f = n->GetFileName(); char p[MAX_PATH_LEN]; if (f && LMakePath(p, sizeof(p), Base, f)) { char *l = strrchr(p, DIR_CHAR); if (l) *l = 0; if (!Map.Find(p)) { Map.Add(p, true); } } } } } } } // char *p; // for (bool b = Map.First(&p); b; b = Map.Next(&p)) for (auto p : Map) Paths.Add(p.key); return true; } void IdeProjectPrivate::CollectAllFiles(LTreeNode *Base, LArray &Files, bool SubProjects, int Platform) { for (auto i:*Base) { IdeProject *Proj = dynamic_cast(i); if (Proj) { if (Proj->GetParentProject() && !SubProjects) { continue; } } else { ProjectNode *p = dynamic_cast(i); if (p) { if (p->GetType() == NodeSrc || p->GetType() == NodeHeader) { if (p->GetPlatforms() & Platform) { Files.Add(p); } } } } CollectAllFiles(i, Files, SubProjects, Platform); } } LString IdeProject::GetTargetName(IdePlatform Platform) { LString Status; const char *t = d->Settings.GetStr(ProjTargetName, NULL, Platform); if (ValidStr(t)) { // Take target name from the settings Status = t; } else { char *s = strrchr(d->FileName, DIR_CHAR); if (s) { // Generate the target executable name char Target[MAX_PATH_LEN]; strcpy_s(Target, sizeof(Target), s + 1); s = strrchr(Target, '.'); if (s) *s = 0; strlwr(Target); s = Target; for (char *i = Target; *i; i++) { if (*i != '.' && *i != ' ') { *s++ = *i; } } *s = 0; Status = Target; } } return Status; } LString IdeProject::GetTargetFile(IdePlatform Platform) { LString Target = GetTargetName(PlatformCurrent); if (!Target) { LAssert(!"No target?"); return LString(); } const char *TargetType = d->Settings.GetStr(ProjTargetType); if (!TargetType) { LAssert(!"Needs a target type."); return LString(); } if (!stricmp(TargetType, "Executable")) { return Target; } else if (!stricmp(TargetType, "DynamicLibrary")) { char t[MAX_PATH_LEN]; auto DefExt = PlatformDynamicLibraryExt(Platform); strcpy_s(t, sizeof(t), Target); auto tCh = strlen(t); char *ext = LGetExtension(t); if (!ext) snprintf(t+tCh, sizeof(t)-tCh, ".%s", DefExt); else if (stricmp(ext, DefExt)) strcpy(ext, DefExt); return t; } else if (!stricmp(TargetType, "StaticLibrary")) { LString Ret; Ret.Printf("%s.%s", Target.Get(), PlatformSharedLibraryExt(Platform)); return Ret; } return LString(); } struct ProjDependency { bool Scanned; LAutoString File; ProjDependency(const char *f) { Scanned = false; File.Reset(NewStr(f)); } }; bool IdeProject::GetAllDependencies(LArray &Files, IdePlatform Platform) { if (!GetTree()->Lock(_FL)) return false; LHashTbl, ProjDependency*> Deps; auto Base = GetBasePath(); // Build list of all the source files... LArray Src; CollectAllSource(Src, Platform); // Get all include paths LArray IncPaths; BuildIncludePaths(IncPaths, false, false, Platform); // Add all source to dependencies for (int i=0; i Unscanned; do { // Find all the unscanned dependencies Unscanned.Length(0); for (auto d : Deps) { if (!d.value->Scanned) Unscanned.Add(d.value); } for (int i=0; iScanned = true; char *Src = d->File; char Full[MAX_PATH_LEN]; if (LIsRelativePath(d->File)) { LMakePath(Full, sizeof(Full), Base, d->File); Src = Full; } LArray SrcDeps; if (GetDependencies(Src, IncPaths, SrcDeps, Platform)) { for (auto File: SrcDeps) { // Add include to dependencies... if (LIsRelativePath(File)) { LMakePath(Full, sizeof(Full), Base, File); File = Full; } if (!Deps.Find(File)) { Deps.Add(File, new ProjDependency(File)); } } SrcDeps.DeleteArrays(); } } } while (Unscanned.Length() > 0); for (auto d : Deps) { Files.Add(d.value->File.Release()); } Deps.DeleteObjects(); GetTree()->Unlock(); return true; } bool IdeProject::GetDependencies(const char *InSourceFile, LArray &IncPaths, LArray &Files, IdePlatform Platform) { LString SourceFile = InSourceFile; if (!CheckExists(SourceFile)) { LgiTrace("%s:%i - can't read '%s'\n", _FL, SourceFile.Get()); return false; } LAutoString c8(LReadTextFile(SourceFile)); if (!c8) return false; LArray Headers; if (!BuildHeaderList(c8, Headers, IncPaths, false)) return false; for (int n=0; nCreateMakefile) { if (d->CreateMakefile->IsExited()) d->CreateMakefile.Reset(); else { d->App->GetBuildLog()->Print("%s:%i - Makefile thread still running.\n", _FL); return false; } } if (Platform == PlatformCurrent) Platform = GetCurrentPlatform(); return d->CreateMakefile.Reset(new MakefileThread(d, Platform, BuildAfterwards)); } void IdeProject::OnMakefileCreated() { if (d->CreateMakefile) { d->CreateMakefile.Reset(); if (MakefileThread::Instances == 0) GetApp()->PostEvent(M_LAST_MAKEFILE_CREATED); } } //////////////////////////////////////////////////////////////////////////////////////////// IdeTree::IdeTree() : LTree(IDC_PROJECT_TREE, 0, 0, 100, 100) { Hit = 0; MultiSelect(true); } void IdeTree::OnCreate() { SetWindow(this); } void IdeTree::OnDragExit() { SelectDropTarget(0); } int IdeTree::WillAccept(LDragFormats &Formats, LPoint p, int KeyState) { static bool First = true; Formats.SupportsFileDrops(); Formats.Supports(NODE_DROP_FORMAT); First = false; if (Formats.Length() == 0) { LgiTrace("%s:%i - No valid drop formats.\n", _FL); return DROPEFFECT_NONE; } Hit = ItemAtPoint(p.x, p.y); if (!Hit) { SelectDropTarget(NULL); return DROPEFFECT_NONE; } if (Formats.HasFormat(LGI_FileDropFormat)) { SelectDropTarget(Hit); return DROPEFFECT_LINK; } IdeCommon *Src = dynamic_cast(Selection()); IdeCommon *Dst = dynamic_cast(Hit); if (Src && Dst) { // Check this folder is not a child of the src for (IdeCommon *n=Dst; n; n=dynamic_cast(n->GetParent())) { if (n == Src) return DROPEFFECT_NONE; } } // Valid target SelectDropTarget(Hit); return DROPEFFECT_MOVE; } int IdeTree::OnDrop(LArray &Data, LPoint p, int KeyState) { int Ret = DROPEFFECT_NONE; SelectDropTarget(NULL); if (!(Hit = ItemAtPoint(p.x, p.y))) return Ret; for (unsigned n=0; nType == GV_BINARY && Data->Value.Binary.Length == sizeof(ProjectNode*)) { ProjectNode *Src = ((ProjectNode**)Data->Value.Binary.Data)[0]; if (Src) { ProjectNode *Folder = dynamic_cast(Hit); while (Folder && Folder->GetType() != NodeDir) Folder = dynamic_cast(Folder->GetParent()); IdeCommon *Dst = dynamic_cast(Folder?Folder:Hit); if (Dst) { // Check this folder is not a child of the src for (IdeCommon *n=Dst; n; n=dynamic_cast(n->GetParent())) { if (n == Src) return DROPEFFECT_NONE; } // Detach LTreeItem *i = dynamic_cast(Src); i->Detach(); if (Src->LXmlTag::Parent) { LAssert(Src->LXmlTag::Parent->Children.HasItem(Src)); Src->LXmlTag::Parent->Children.Delete(Src); } // Attach Src->LXmlTag::Parent = Dst; Dst->Children.SetFixedLength(false); Dst->Children.Add(Src); Dst->Children.SetFixedLength(true); Dst->Insert(Src); // Dirty Src->GetProject()->SetDirty(); } Ret = DROPEFFECT_MOVE; } } } else if (dd.IsFileDrop()) { ProjectNode *Folder = dynamic_cast(Hit); while (Folder && Folder->GetType() > NodeDir) Folder = dynamic_cast(Folder->GetParent()); IdeCommon *Dst = dynamic_cast(Folder?Folder:Hit); if (Dst) { AddFilesProgress Prog(this); LDropFiles Df(dd); for (int i=0; iAddFiles(&Prog, Df[i])) Ret = DROPEFFECT_LINK; } } } else LgiTrace("%s:%i - Unknown drop format: %s.\n", _FL, dd.Format.Get()); } return Ret; } ///////////////////////////////////////////////////////////////////////////////////////////////// AddFilesProgress::AddFilesProgress(LViewI *par) { v = 0; Cancel = false; Msg = NULL; SetParent(par); Ts = LCurrentTime(); LRect r(0, 0, 140, 100); SetPos(r); MoveSameScreen(par); Name("Importing files..."); LString::Array a = LString(DefaultExt).SplitDelimit(","); for (unsigned i=0; iGetCell(0, 0); c->Add(new LTextLabel(-1, 0, 0, -1, -1, "Loaded:")); c = t->GetCell(1, 0); c->Add(Msg = new LTextLabel(-1, 0, 0, -1, -1, "...")); c = t->GetCell(0, 1, true, 2); c->TextAlign(LCss::Len(LCss::AlignRight)); c->Add(new LButton(IDCANCEL, 0, 0, -1, -1, "Cancel")); } int64 AddFilesProgress::Value() { return v; } void AddFilesProgress::Value(int64 val) { v = val; uint64 Now = LCurrentTime(); if (Visible()) { if (Now - Ts > 200) { if (Msg) { Msg->Value(v); Msg->SendNotify(LNotifyTableLayoutRefresh); } Ts = Now; } } else if (Now - Ts > 1000) { DoModeless(); SetAlwaysOnTop(true); } } int AddFilesProgress::OnNotify(LViewI *c, LNotification n) { if (c->GetId() == IDCANCEL) Cancel = true; return 0; } diff --git a/Ide/src/WebFldDlg.cpp b/Ide/src/WebFldDlg.cpp --- a/Ide/src/WebFldDlg.cpp +++ b/Ide/src/WebFldDlg.cpp @@ -1,60 +1,62 @@ #include "lgi/common/Lgi.h" #include "lgi/common/Net.h" +#include "lgi/common/Uri.h" + #include "WebFldDlg.h" #include "resdefs.h" ////////////////////////////////////////////////////////////////////////////////// WebFldDlg::WebFldDlg(LViewI *p, char *name, char *ftp, char *www) { Name = 0; Www = 0; SetParent(p); LoadFromResource(IDD_WEB_FOLDER); if (ftp) { LUri u(ftp); SetCtrlName(IDC_HOST, u.sHost); SetCtrlName(IDC_USERNAME, u.sUser); SetCtrlName(IDC_PASSWORD, u.sPass); SetCtrlName(IDC_PATH, u.sPath); } SetCtrlName(IDC_NAME, name); SetCtrlName(IDC_WWW, www); MoveToCenter(); } WebFldDlg::~WebFldDlg() { DeleteArray(Name); DeleteArray(Www); } int WebFldDlg::OnNotify(LViewI *v, LNotification n) { switch (v->GetId()) { case IDOK: { LUri u; u.sHost = GetCtrlName(IDC_HOST); u.sUser = GetCtrlName(IDC_USERNAME); u.sPass = GetCtrlName(IDC_PASSWORD); u.sPath = GetCtrlName(IDC_PATH); u.sProtocol = "ftp"; Ftp = u.ToString(); Www = NewStr(GetCtrlName(IDC_WWW)); Name = NewStr(GetCtrlName(IDC_NAME)); EndModal(1); break; } case IDCANCEL: { EndModal(0); break; } } return 0; } diff --git a/Ide/win/LgiIde.vcxproj b/Ide/win/LgiIde.vcxproj --- a/Ide/win/LgiIde.vcxproj +++ b/Ide/win/LgiIde.vcxproj @@ -1,279 +1,282 @@  Debug Win32 Debug x64 Release Win32 Release x64 LgiIde {967AF7EF-7C17-4FCC-997E-BED17F886F07} LgiIde_vc8 Win32Proj 10.0 Application v142 Unicode true Application v142 Unicode true Application v142 Unicode Application v142 Unicode <_ProjectFileVersion>12.0.30501.0 $(Platform)$(Configuration)14\ $(Platform)$(Configuration)14\ true $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\CodeLib\libpng-1.6.26 $(Platform)$(Configuration)14\ $(Platform)$(Configuration)14\ true $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\CodeLib\libpng-1.6.26 $(Platform)$(Configuration)14\ $(Platform)$(Configuration)14\ false $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\CodeLib\libpng-1.6.26 $(Platform)$(Configuration)14\ $(Platform)$(Configuration)14\ false $(VC_IncludePath);$(WindowsSDK_IncludePath);..\..\..\..\..\CodeLib\libpng-1.6.26 Disabled ..\..\include;..\..\include\lgi\win;..\..\..\..\..\CodeLib\zlib;..\..\..\..\..\CodeLib\libpng;..\..\..\..\..\CodeLib\libpng\win32;..\..\..\..\..\CodeLib\zlib\win32;..\resources;C:\Program Files (x86)\OpenSSL-Win32\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;WINDOWS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level2 ProgramDatabase imm32.lib;Mincore.lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) ..\lib;%(AdditionalLibraryDirectories) true Windows false MachineX86 Disabled ..\..\include;..\..\include\lgi\win;..\..\..\..\..\CodeLib\zlib;..\..\..\..\..\CodeLib\libpng;..\..\..\..\..\CodeLib\libpng\win32;..\..\..\..\..\CodeLib\zlib\win32;..\resources;C:\Program Files\OpenSSL-Win64\include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;WINDOWS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL Level2 ProgramDatabase imm32.lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) ..\lib;%(AdditionalLibraryDirectories) true Windows false ..\..\src\win\General\Lgi.manifest ..\..\include;..\..\include\lgi\win;..\..\..\..\..\CodeLib\zlib;..\..\..\..\..\CodeLib\libpng;..\..\..\..\..\CodeLib\libpng\win32;..\..\..\..\..\CodeLib\zlib\win32;.\Resources;C:\Program Files (x86)\OpenSSL-Win32\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;WINDOWS;%(PreprocessorDefinitions) MultiThreadedDLL Level2 ProgramDatabase imm32.lib;Mincore.lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) ..\lib;%(AdditionalLibraryDirectories) true Windows true true false MachineX86 ..\..\include;..\..\include\lgi\win;..\..\..\..\..\CodeLib\zlib;..\..\..\..\..\CodeLib\libpng;..\..\..\..\..\CodeLib\libpng\win32;..\..\..\..\..\CodeLib\zlib\win32;..\resources;C:\Program Files\OpenSSL-Win64\include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;WINDOWS;%(PreprocessorDefinitions) MultiThreadedDLL Level2 ProgramDatabase imm32.lib;%(AdditionalDependencies) $(OutDir)$(TargetFileName) ..\lib;%(AdditionalLibraryDirectories) true Windows true true false ..\..\src\win\General\Lgi.manifest {95df9ca4-6d37-4a85-a648-80c2712e0da1} false true false true + + + \ No newline at end of file diff --git a/Ide/win/LgiIde.vcxproj.filters b/Ide/win/LgiIde.vcxproj.filters --- a/Ide/win/LgiIde.vcxproj.filters +++ b/Ide/win/LgiIde.vcxproj.filters @@ -1,253 +1,261 @@  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {6b83273a-b199-4420-ae65-9663c7c7e75b} {e809cc3d-4694-4e36-b2d4-60e9f9450e56} {b327086f-7d0e-4840-ac95-7dc18a89fe19} {3cefce7e-26bb-4e9e-8711-c7fa5c51373d} {63c6319b-3755-4b59-95f2-1e7b5b2c1a75} {f1667c53-311d-44b9-aafb-6db5c2bb7ea7} {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav {0823126b-5e9f-417c-b233-7025ea646dad} {2be01d30-b91b-466c-8aaf-bb656db55afb} {404b5cc0-5e53-4ae3-945c-274b0fc3f889} {29793244-2c02-4203-b755-49237ba42e24} {a789d0ae-552d-4e98-902b-7ffb0d018bbc} {5aca11fa-b1cb-4707-bb7f-22f85d399ab9} {abcd6327-e6b7-4c09-8f78-c42a306904fe} + + {a785385b-f482-4978-8bff-26a6863d03bd} + Source Files\Debugger Lgi Source Files\Search Source Files\Search Source Files\Utils Source Files\Utils Source Files\Docs Source Files\Docs Source Files\Projects Source Files Source Files\Search\Cpp Parser Source Files\Projects Source Files\Search\Python Parser Resource Files Resource Files Source Files\Scripting Source Files\Scripting Source Files\Search\Simple Cpp Parser Source Files\Utils Source Files\Process Source Files\Dialogs Source Files\Dialogs Source Files\Debugger Lgi Source Files\Debugger Source Files\Debugger Source Files\Docs Source Files\Docs Source Files\Search Source Files\Search Source Files\Utils Source Files\Utils Source Files\Utils Lgi Source Files Source Files\Docs Source Files\Projects Source Files\Projects Source Files\Search\Javascript Source Files\Scripting Source Files Lgi Lgi Lgi Source Files\Utils Source Files\Utils Source Files\Projects Lgi Source Files\Search\Cpp Parser Lgi Source Files\Projects Source Files\Search\Python Parser Source Files\Scripting Source Files\Scripting Source Files\Scripting Source Files\Search\Simple Cpp Parser Source Files\Utils Source Files\Utils Source Files\Dialogs Source Files\Dialogs Resource Files Source Files + + + Build + + \ No newline at end of file diff --git a/Ide/win/Makefile.windows b/Ide/win/Makefile.windows --- a/Ide/win/Makefile.windows +++ b/Ide/win/Makefile.windows @@ -1,410 +1,411 @@ #!/usr/bin/make # # This makefile generated by LgiIde # http://www.memecode.com/lgi.php # .SILENT : CC = gcc CPP = g++ Target = .\LgiIde.exe ifndef Build Build = Debug endif +MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BuildDir = $(Build) -Flags = -fPIC -w -fno-inline -fpermissive +Flags = -fPIC -fno-inline -fpermissive -Wno-format-truncation ifeq ($(Build),Debug) - Flags += -g -std=c++14 + Flags += -MMD -MP -g -std=c++14 Tag = d Defs = -D_DEBUG -DWIN32 -D_REENTRANT Libs = \ - -L../x64Debug19 \ -limm32 \ -llgi$(Tag) \ -L../$(BuildDir) Inc = \ -I./src \ -I./resources \ -I../include/lgi/win \ -I../include else - Flags += -s -Os -std=c++14 + Flags += -MMD -MP -s -Os -std=c++14 Defs = -DWIN32 -D_REENTRANT Libs = \ - -L../x64Release19 \ -limm32 \ -llgi$(Tag) \ -L../$(BuildDir) Inc = \ -I./src \ -I./resources \ -I../include/lgi/win \ -I../include endif # Dependencies Source = .\src\WebFldDlg.cpp \ .\src\SysCharSupport.cpp \ .\src\SpaceTabConv.cpp \ .\src\SimpleCppParser.cpp \ .\src\PythonParser.cpp \ .\src\ProjectNode.cpp \ .\src\NewProjectFromTemplate.cpp \ .\src\MissingFiles.cpp \ .\src\MemDumpViewer.cpp \ .\src\LgiUtils.cpp \ .\src\LgiIde.cpp \ - .\src\levenshtein.c \ .\src\JavascriptParser.cpp \ .\src\IdeProjectSettings.cpp \ .\src\IdeProject.cpp \ + .\src\IdeFindInFiles.cpp \ .\src\IdeDoc.cpp \ .\src\IdeCommon.cpp \ .\src\History.cpp \ .\src\FtpThread.cpp \ .\src\FindSymbol.cpp \ - .\src\FindInFiles.cpp \ .\src\DocEditStyling.cpp \ .\src\DocEdit.cpp \ .\src\Debugger.cpp \ .\src\DebugContext.cpp \ .\src\AddFtpFile.cpp \ ..\src\common\Text\TextConvert.cpp \ ..\src\common\Text\HtmlParser.cpp \ ..\src\common\Text\HtmlCommon.cpp \ ..\src\common\Text\Html.cpp \ ..\src\common\Text\Homoglyphs\HomoglyphsTable.cpp \ ..\src\common\Text\Homoglyphs\Homoglyphs.cpp \ ..\src\common\Text\DocView.cpp \ ..\src\common\Net\OpenSSLSocket.cpp \ ..\src\common\Net\Http.cpp \ ..\src\common\Net\Ftp.cpp \ ..\src\common\Lgi\Mdi.cpp \ ..\src\common\Lgi\LgiMain.cpp \ ..\src\common\Lgi\About.cpp \ ..\src\common\Gdc2\Filters\Png.cpp \ ..\src\common\Coding\ParseCpp.cpp \ ..\src\common\Coding\LexCpp.cpp -SourceLst := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(Source))) -Objects := $(addprefix $(BuildDir)/,$(SourceLst)) -Deps := $(patsubst %.o,%.d,$(Objects)) +SourceC := $(filter %.c,$(Source)) +ObjectsC := $(SourceC:.c=.o) +SourceCpp := $(filter %.cpp,$(Source)) +ObjectsCpp := $(SourceCpp:.cpp=.o) +Objects := $(notdir $(ObjectsC) $(ObjectsCpp)) +Objects := $(addprefix $(BuildDir)/,$(Objects)) +Deps := $(patsubst %.o,%.d,$(Objects)) + +$(BuildDir)/%.o: %.c + mkdir -p $(@D) + echo $(notdir $<) [$(Build)] + $(CC) $(Inc) $(Flags) $(Defs) -c $< -o $@ + +$(BuildDir)/%.o: %.cpp + mkdir -p $(@D) + echo $(notdir $<) [$(Build)] + $(CPP) $(Inc) $(Flags) $(Defs) -c $< -o $@ # Target # Executable target -$(Target) : ..\..\$(BuildDir)\liblgi$(Tag).dll $(Objects) +$(Target) : ..\$(BuildDir)\liblgi$(Tag).dll $(Objects) mkdir -p $(BuildDir) @echo Linking $(Target) [$(Build)]... $(CPP) -mwindows -Wl,--enable-auto-import -o \ $(Target) $(Objects) $(Libs) @echo Done. -..\..\$(BuildDir)\liblgi$(Tag).dll : ..\..\include\lgi\common\App.h \ - ..\..\include\lgi\common\Array.h \ - ..\..\include\lgi\common\AutoPtr.h \ - ..\..\include\lgi\common\Base64.h \ - ..\..\include\lgi\common\Bitmap.h \ - ..\..\include\lgi\common\Box.h \ - ..\..\include\lgi\common\Button.h \ - ..\..\include\lgi\common\CairoSurface.h \ - ..\..\include\lgi\common\Cancel.h \ - ..\..\include\lgi\common\Capabilities.h \ - ..\..\include\lgi\common\Charset.h \ - ..\..\include\lgi\common\CheckBox.h \ - ..\..\include\lgi\common\ClipBoard.h \ - ..\..\include\lgi\common\Colour.h \ - ..\..\include\lgi\common\ColourSpace.h \ - ..\..\include\lgi\common\Com.h \ - ..\..\include\lgi\common\Combo.h \ - ..\..\include\lgi\common\Containers.h \ - ..\..\include\lgi\common\Core.h \ - ..\..\include\lgi\common\Css.h \ - ..\..\include\lgi\common\CssTools.h \ - ..\..\include\lgi\common\CurrentTime.h \ - ..\..\include\lgi\common\DataDlg.h \ - ..\..\include\lgi\common\DateTime.h \ - ..\..\include\lgi\common\Dialog.h \ - ..\..\include\lgi\common\DisplayString.h \ - ..\..\include\lgi\common\DocView.h \ - ..\..\include\lgi\common\Dom.h \ - ..\..\include\lgi\common\DomFields.h \ - ..\..\include\lgi\common\DragAndDrop.h \ - ..\..\include\lgi\common\DropFiles.h \ - ..\..\include\lgi\common\Edit.h \ - ..\..\include\lgi\common\Error.h \ - ..\..\include\lgi\common\EventTargetThread.h \ - ..\..\include\lgi\common\File.h \ - ..\..\include\lgi\common\FileSelect.h \ - ..\..\include\lgi\common\Filter.h \ - ..\..\include\lgi\common\FindReplaceDlg.h \ - ..\..\include\lgi\common\Font.h \ - ..\..\include\lgi\common\FontCache.h \ - ..\..\include\lgi\common\FontSelect.h \ - ..\..\include\lgi\common\Gdc2.h \ - ..\..\include\lgi\common\GdcTools.h \ - ..\..\include\lgi\common\GdiLeak.h \ - ..\..\include\lgi\common\HashTable.h \ - ..\..\include\lgi\common\ImageList.h \ - ..\..\include\lgi\common\Input.h \ - ..\..\include\lgi\common\ItemContainer.h \ - ..\..\include\lgi\common\Json.h \ - ..\..\include\lgi\common\Layout.h \ - ..\..\include\lgi\common\Lgi.h \ - ..\..\include\lgi\common\LgiClasses.h \ - ..\..\include\lgi\common\LgiCommon.h \ - ..\..\include\lgi\common\LgiDefs.h \ - ..\..\include\lgi\common\LgiInc.h \ - ..\..\include\lgi\common\LgiInterfaces.h \ - ..\..\include\lgi\common\LgiMsgs.h \ - ..\..\include\lgi\common\LgiNetInc.h \ - ..\..\include\lgi\common\LgiRes.h \ - ..\..\include\lgi\common\LgiString.h \ - ..\..\include\lgi\common\LgiUiBase.h \ - ..\..\include\lgi\common\Library.h \ - ..\..\include\lgi\common\LibraryUtils.h \ - ..\..\include\lgi\common\List.h \ - ..\..\include\lgi\common\ListItemCheckBox.h \ - ..\..\include\lgi\common\ListItemRadioBtn.h \ - ..\..\include\lgi\common\LMallocArray.h \ - ..\..\include\lgi\common\Matrix.h \ - ..\..\include\lgi\common\Mem.h \ - ..\..\include\lgi\common\Menu.h \ - ..\..\include\lgi\common\Message.h \ - ..\..\include\lgi\common\Mime.h \ - ..\..\include\lgi\common\Mru.h \ - ..\..\include\lgi\common\Mutex.h \ - ..\..\include\lgi\common\Net.h \ - ..\..\include\lgi\common\NetTools.h \ - ..\..\include\lgi\common\Notifications.h \ - ..\..\include\lgi\common\OptionsFile.h \ - ..\..\include\lgi\common\Palette.h \ - ..\..\include\lgi\common\Panel.h \ - ..\..\include\lgi\common\Password.h \ - ..\..\include\lgi\common\Path.h \ - ..\..\include\lgi\common\PixelRops.h \ - ..\..\include\lgi\common\Point.h \ - ..\..\include\lgi\common\Popup.h \ - ..\..\include\lgi\common\PopupList.h \ - ..\..\include\lgi\common\PopupNotification.h \ - ..\..\include\lgi\common\Printer.h \ - ..\..\include\lgi\common\process.h \ - ..\..\include\lgi\common\Profile.h \ - ..\..\include\lgi\common\Progress.h \ - ..\..\include\lgi\common\ProgressDlg.h \ - ..\..\include\lgi\common\ProgressView.h \ - ..\..\include\lgi\common\Properties.h \ - ..\..\include\lgi\common\RadioGroup.h \ - ..\..\include\lgi\common\Range.h \ - ..\..\include\lgi\common\Rect.h \ - ..\..\include\lgi\common\RectF.h \ - ..\..\include\lgi\common\RefCount.h \ - ..\..\include\lgi\common\RegKey.h \ - ..\..\include\lgi\common\Res.h \ - ..\..\include\lgi\common\Rops.h \ - ..\..\include\lgi\common\ScrollBar.h \ - ..\..\include\lgi\common\SkinEngine.h \ - ..\..\include\lgi\common\Slider.h \ - ..\..\include\lgi\common\SpellCheck.h \ - ..\..\include\lgi\common\Splitter.h \ - ..\..\include\lgi\common\StatusBar.h \ - ..\..\include\lgi\common\Stream.h \ - ..\..\include\lgi\common\StringClass.h \ - ..\..\include\lgi\common\StringLayout.h \ - ..\..\include\lgi\common\StructuredIo.h \ - ..\..\include\lgi\common\StructuredLog.h \ - ..\..\include\lgi\common\SubProcess.h \ - ..\..\include\lgi\common\TableLayout.h \ - ..\..\include\lgi\common\TabView.h \ - ..\..\include\lgi\common\TextFile.h \ - ..\..\include\lgi\common\TextLabel.h \ - ..\..\include\lgi\common\TextLog.h \ - ..\..\include\lgi\common\TextView3.h \ - ..\..\include\lgi\common\Thread.h \ - ..\..\include\lgi\common\ThreadEvent.h \ - ..\..\include\lgi\common\Token.h \ - ..\..\include\lgi\common\ToolBar.h \ - ..\..\include\lgi\common\ToolTip.h \ - ..\..\include\lgi\common\TrayIcon.h \ - ..\..\include\lgi\common\Tree.h \ - ..\..\include\lgi\common\Undo.h \ - ..\..\include\lgi\common\Unicode.h \ - ..\..\include\lgi\common\UnicodeString.h \ - ..\..\include\lgi\common\UnrolledList.h \ - ..\..\include\lgi\common\Variant.h \ - ..\..\include\lgi\common\View.h \ - ..\..\include\lgi\common\Widgets.h \ - ..\..\include\lgi\common\Window.h \ - ..\..\include\lgi\common\XmlTree.h \ - ..\..\include\lgi\linux\Gtk\LgiWidget.h \ - ..\..\include\lgi\linux\Gtk\LgiWinManGlue.h \ - ..\..\include\lgi\mac\cocoa\LCocoaView.h \ - ..\..\include\lgi\mac\cocoa\LgiMac.h \ - ..\..\include\lgi\mac\cocoa\LgiOs.h \ - ..\..\include\lgi\mac\cocoa\LgiOsClasses.h \ - ..\..\include\lgi\mac\cocoa\LgiOsDefs.h \ - ..\..\include\lgi\mac\cocoa\ObjCWrapper.h \ - ..\..\include\lgi\mac\cocoa\SymLookup.h \ - ..\..\include\lgi\win\LgiOsClasses.h \ - ..\..\include\lgi\win\LgiOsDefs.h \ - ..\..\include\lgi\win\StackWalker.h \ - ..\..\include\lgi\win\SymLookup.h \ - ..\..\private\common\FontPriv.h \ - ..\..\private\common\ViewPriv.h \ - ..\..\private\linux\AppPriv.h \ - ..\..\private\win\AppPriv.h \ - ..\..\src\common\Gdc2\15Bit.cpp \ - ..\..\src\common\Gdc2\16Bit.cpp \ - ..\..\src\common\Gdc2\24Bit.cpp \ - ..\..\src\common\Gdc2\32Bit.cpp \ - ..\..\src\common\Gdc2\8Bit.cpp \ - ..\..\src\common\Gdc2\Alpha.cpp \ - ..\..\src\common\Gdc2\Colour.cpp \ - ..\..\src\common\Gdc2\Filters\Filter.cpp \ - ..\..\src\common\Gdc2\Font\Charset.cpp \ - ..\..\src\common\Gdc2\Font\DisplayString.cpp \ - ..\..\src\common\Gdc2\Font\Font.cpp \ - ..\..\src\common\Gdc2\Font\FontSystem.cpp \ - ..\..\src\common\Gdc2\Font\FontType.cpp \ - ..\..\src\common\Gdc2\Font\StringLayout.cpp \ - ..\..\src\common\Gdc2\Font\TypeFace.cpp \ - ..\..\src\common\Gdc2\GdcCommon.cpp \ - ..\..\src\common\Gdc2\Path\Path.cpp \ - ..\..\src\common\Gdc2\Rect.cpp \ - ..\..\src\common\Gdc2\RopsCases.cpp \ - ..\..\src\common\Gdc2\Surface.cpp \ - ..\..\src\common\Gdc2\Tools\ColourReduce.cpp \ - ..\..\src\common\Gdc2\Tools\GdcTools.cpp \ - ..\..\src\common\General\Containers.cpp \ - ..\..\src\common\General\DateTime.cpp \ - ..\..\src\common\General\ExeCheck.cpp \ - ..\..\src\common\General\FileCommon.cpp \ - ..\..\src\common\General\Password.cpp \ - ..\..\src\common\General\Properties.cpp \ - ..\..\src\common\General\qsort.cpp \ - ..\..\src\common\Hash\md5\md5.c \ - ..\..\src\common\Hash\md5\md5.h \ - ..\..\src\common\Hash\sha1\sha1.c \ - ..\..\src\common\Hash\sha1\sha1.h \ - ..\..\src\common\Lgi\Alert.cpp \ - ..\..\src\common\Lgi\AppCommon.cpp \ - ..\..\src\common\Lgi\Css.cpp \ - ..\..\src\common\Lgi\CssTools.cpp \ - ..\..\src\common\Lgi\DataDlg.cpp \ - ..\..\src\common\Lgi\DragAndDropCommon.cpp \ - ..\..\src\common\Lgi\FindReplace.cpp \ - ..\..\src\common\Lgi\FontSelect.cpp \ - ..\..\src\common\Lgi\GuiUtils.cpp \ - ..\..\src\common\Lgi\Input.cpp \ - ..\..\src\common\Lgi\LgiCommon.cpp \ - ..\..\src\common\Lgi\Library.cpp \ - ..\..\src\common\Lgi\LMsg.cpp \ - ..\..\src\common\Lgi\MemStream.cpp \ - ..\..\src\common\Lgi\MenuCommon.cpp \ - ..\..\src\common\Lgi\Mru.cpp \ - ..\..\src\common\Lgi\Mutex.cpp \ - ..\..\src\common\Lgi\Object.cpp \ - ..\..\src\common\Lgi\OptionsFile.cpp \ - ..\..\src\common\Lgi\Rand.cpp \ - ..\..\src\common\Lgi\Stream.cpp \ - ..\..\src\common\Lgi\SubProcess.cpp \ - ..\..\src\common\Lgi\ThreadCommon.cpp \ - ..\..\src\common\Lgi\ThreadEvent.cpp \ - ..\..\src\common\Lgi\ToolTip.cpp \ - ..\..\src\common\Lgi\TrayIcon.cpp \ - ..\..\src\common\Lgi\Variant.cpp \ - ..\..\src\common\Lgi\ViewCommon.cpp \ - ..\..\src\common\Lgi\WindowCommon.cpp \ - ..\..\src\common\Net\Base64.cpp \ - ..\..\src\common\Net\MDStringToDigest.cpp \ - ..\..\src\common\Net\Net.cpp \ - ..\..\src\common\Net\NetTools.cpp \ - ..\..\src\common\Net\Uri.cpp \ - ..\..\src\common\Resource\LgiRes.cpp \ - ..\..\src\common\Resource\Res.cpp \ - ..\..\src\common\Skins\Gel\Gel.cpp \ - ..\..\src\common\Text\String.cpp \ - ..\..\src\common\Text\Token.cpp \ - ..\..\src\common\Text\Unicode.cpp \ - ..\..\src\common\Text\Utf8.cpp \ - ..\..\src\common\Text\XmlTree.cpp \ - ..\..\src\common\Widgets\Bitmap.cpp \ - ..\..\src\common\Widgets\Box.cpp \ - ..\..\src\common\Widgets\Button.cpp \ - ..\..\src\common\Widgets\CheckBox.cpp \ - ..\..\src\common\Widgets\Combo.cpp \ - ..\..\src\common\Widgets\ItemContainer.cpp \ - ..\..\src\common\Widgets\List.cpp \ - ..\..\src\common\Widgets\Panel.cpp \ - ..\..\src\common\Widgets\Popup.cpp \ - ..\..\src\common\Widgets\Progress.cpp \ - ..\..\src\common\Widgets\ProgressDlg.cpp \ - ..\..\src\common\Widgets\RadioGroup.cpp \ - ..\..\src\common\Widgets\Slider.cpp \ - ..\..\src\common\Widgets\Splitter.cpp \ - ..\..\src\common\Widgets\StatusBar.cpp \ - ..\..\src\common\Widgets\TableLayout.cpp \ - ..\..\src\common\Widgets\TabView.cpp \ - ..\..\src\common\Widgets\TextLabel.cpp \ - ..\..\src\common\Widgets\ToolBar.cpp \ - ..\..\src\common\Widgets\Tree.cpp \ - ..\..\src\win\Gdc2\Gdc2.cpp \ - ..\..\src\win\Gdc2\GdiLeak.cpp \ - ..\..\src\win\Gdc2\MemDC.cpp \ - ..\..\src\win\Gdc2\PrintDC.cpp \ - ..\..\src\win\Gdc2\ScreenDC.cpp \ - ..\..\src\win\General\File.cpp \ - ..\..\src\win\General\Mem.cpp \ - ..\..\src\win\General\ShowFileProp_Win.cpp \ - ..\..\src\win\INet\MibAccess.cpp \ - ..\..\src\win\Lgi\App.cpp \ - ..\..\src\win\Lgi\ClipBoard.cpp \ - ..\..\src\win\Lgi\DragAndDrop.cpp \ - ..\..\src\win\Lgi\FileSelect.cpp \ - ..\..\src\win\Lgi\General.cpp \ - ..\..\src\win\Lgi\Layout.cpp \ - ..\..\src\win\Lgi\LgiException.cpp \ - ..\..\src\win\Lgi\Menu.cpp \ - ..\..\src\win\Lgi\Printer.cpp \ - ..\..\src\win\Lgi\ScrollBar.cpp \ - ..\..\src\win\Lgi\Thread.cpp \ - ..\..\src\win\Lgi\View.cpp \ - ..\..\src\win\Lgi\Window.cpp \ - ..\..\src\win\Widgets\Dialog_Win.cpp \ - ..\..\src\win\Widgets\Edit_Win.cpp +..\$(BuildDir)\liblgi$(Tag).dll : ..\include\lgi\common\App.h \ + ..\include\lgi\common\Array.h \ + ..\include\lgi\common\AutoPtr.h \ + ..\include\lgi\common\Base64.h \ + ..\include\lgi\common\Bitmap.h \ + ..\include\lgi\common\Box.h \ + ..\include\lgi\common\Button.h \ + ..\include\lgi\common\CairoSurface.h \ + ..\include\lgi\common\Cancel.h \ + ..\include\lgi\common\Capabilities.h \ + ..\include\lgi\common\Charset.h \ + ..\include\lgi\common\CheckBox.h \ + ..\include\lgi\common\ClipBoard.h \ + ..\include\lgi\common\Colour.h \ + ..\include\lgi\common\ColourSpace.h \ + ..\include\lgi\common\Com.h \ + ..\include\lgi\common\Combo.h \ + ..\include\lgi\common\Containers.h \ + ..\include\lgi\common\Core.h \ + ..\include\lgi\common\Css.h \ + ..\include\lgi\common\CssTools.h \ + ..\include\lgi\common\CurrentTime.h \ + ..\include\lgi\common\DataDlg.h \ + ..\include\lgi\common\DateTime.h \ + ..\include\lgi\common\Dialog.h \ + ..\include\lgi\common\DisplayString.h \ + ..\include\lgi\common\DocView.h \ + ..\include\lgi\common\Dom.h \ + ..\include\lgi\common\DomFields.h \ + ..\include\lgi\common\DragAndDrop.h \ + ..\include\lgi\common\DropFiles.h \ + ..\include\lgi\common\Edit.h \ + ..\include\lgi\common\Emoji.h \ + ..\include\lgi\common\Error.h \ + ..\include\lgi\common\EventTargetThread.h \ + ..\include\lgi\common\File.h \ + ..\include\lgi\common\FileSelect.h \ + ..\include\lgi\common\Filter.h \ + ..\include\lgi\common\FindReplaceDlg.h \ + ..\include\lgi\common\Font.h \ + ..\include\lgi\common\FontCache.h \ + ..\include\lgi\common\FontSelect.h \ + ..\include\lgi\common\Gdc2.h \ + ..\include\lgi\common\GdcTools.h \ + ..\include\lgi\common\GdiLeak.h \ + ..\include\lgi\common\HashTable.h \ + ..\include\lgi\common\ImageList.h \ + ..\include\lgi\common\Input.h \ + ..\include\lgi\common\ItemContainer.h \ + ..\include\lgi\common\Json.h \ + ..\include\lgi\common\Layout.h \ + ..\include\lgi\common\Lgi.h \ + ..\include\lgi\common\LgiClasses.h \ + ..\include\lgi\common\LgiCommon.h \ + ..\include\lgi\common\LgiDefs.h \ + ..\include\lgi\common\LgiInc.h \ + ..\include\lgi\common\LgiInterfaces.h \ + ..\include\lgi\common\LgiMsgs.h \ + ..\include\lgi\common\LgiRes.h \ + ..\include\lgi\common\LgiString.h \ + ..\include\lgi\common\LgiUiBase.h \ + ..\include\lgi\common\Library.h \ + ..\include\lgi\common\LibraryUtils.h \ + ..\include\lgi\common\List.h \ + ..\include\lgi\common\ListItemCheckBox.h \ + ..\include\lgi\common\ListItemRadioBtn.h \ + ..\include\lgi\common\LMallocArray.h \ + ..\include\lgi\common\Matrix.h \ + ..\include\lgi\common\Mem.h \ + ..\include\lgi\common\Menu.h \ + ..\include\lgi\common\Message.h \ + ..\include\lgi\common\Mime.h \ + ..\include\lgi\common\Mru.h \ + ..\include\lgi\common\Mutex.h \ + ..\include\lgi\common\Net.h \ + ..\include\lgi\common\Notifications.h \ + ..\include\lgi\common\OptionsFile.h \ + ..\include\lgi\common\Palette.h \ + ..\include\lgi\common\Panel.h \ + ..\include\lgi\common\Password.h \ + ..\include\lgi\common\Path.h \ + ..\include\lgi\common\PixelRops.h \ + ..\include\lgi\common\Point.h \ + ..\include\lgi\common\Popup.h \ + ..\include\lgi\common\PopupList.h \ + ..\include\lgi\common\PopupNotification.h \ + ..\include\lgi\common\Printer.h \ + ..\include\lgi\common\process.h \ + ..\include\lgi\common\Profile.h \ + ..\include\lgi\common\Progress.h \ + ..\include\lgi\common\ProgressDlg.h \ + ..\include\lgi\common\ProgressView.h \ + ..\include\lgi\common\Properties.h \ + ..\include\lgi\common\RadioGroup.h \ + ..\include\lgi\common\Range.h \ + ..\include\lgi\common\Rect.h \ + ..\include\lgi\common\RectF.h \ + ..\include\lgi\common\RefCount.h \ + ..\include\lgi\common\RegKey.h \ + ..\include\lgi\common\Res.h \ + ..\include\lgi\common\Rops.h \ + ..\include\lgi\common\ScrollBar.h \ + ..\include\lgi\common\SkinEngine.h \ + ..\include\lgi\common\Slider.h \ + ..\include\lgi\common\SpellCheck.h \ + ..\include\lgi\common\Splitter.h \ + ..\include\lgi\common\StatusBar.h \ + ..\include\lgi\common\Stream.h \ + ..\include\lgi\common\StringClass.h \ + ..\include\lgi\common\StringLayout.h \ + ..\include\lgi\common\StructuredIo.h \ + ..\include\lgi\common\StructuredLog.h \ + ..\include\lgi\common\SubProcess.h \ + ..\include\lgi\common\TableLayout.h \ + ..\include\lgi\common\TabView.h \ + ..\include\lgi\common\TextFile.h \ + ..\include\lgi\common\TextLabel.h \ + ..\include\lgi\common\TextLog.h \ + ..\include\lgi\common\TextView3.h \ + ..\include\lgi\common\Thread.h \ + ..\include\lgi\common\ThreadEvent.h \ + ..\include\lgi\common\Token.h \ + ..\include\lgi\common\ToolBar.h \ + ..\include\lgi\common\ToolTip.h \ + ..\include\lgi\common\TrayIcon.h \ + ..\include\lgi\common\Tree.h \ + ..\include\lgi\common\Undo.h \ + ..\include\lgi\common\Unicode.h \ + ..\include\lgi\common\UnicodeString.h \ + ..\include\lgi\common\UnrolledList.h \ + ..\include\lgi\common\Uri.h \ + ..\include\lgi\common\Variant.h \ + ..\include\lgi\common\View.h \ + ..\include\lgi\common\Widgets.h \ + ..\include\lgi\common\Window.h \ + ..\include\lgi\common\XmlTree.h \ + ..\include\lgi\linux\Gtk\LgiWidget.h \ + ..\include\lgi\linux\Gtk\LgiWinManGlue.h \ + ..\include\lgi\mac\cocoa\LCocoaView.h \ + ..\include\lgi\mac\cocoa\LgiMac.h \ + ..\include\lgi\mac\cocoa\LgiOs.h \ + ..\include\lgi\mac\cocoa\LgiOsClasses.h \ + ..\include\lgi\mac\cocoa\LgiOsDefs.h \ + ..\include\lgi\mac\cocoa\ObjCWrapper.h \ + ..\include\lgi\mac\cocoa\SymLookup.h \ + ..\include\lgi\win\LgiOsClasses.h \ + ..\include\lgi\win\LgiOsDefs.h \ + ..\include\lgi\win\StackWalker.h \ + ..\include\lgi\win\SymLookup.h \ + ..\private\common\FontPriv.h \ + ..\private\common\ViewPriv.h \ + ..\private\linux\AppPriv.h \ + ..\private\win\AppPriv.h \ + ..\src\common\Gdc2\15Bit.cpp \ + ..\src\common\Gdc2\16Bit.cpp \ + ..\src\common\Gdc2\24Bit.cpp \ + ..\src\common\Gdc2\32Bit.cpp \ + ..\src\common\Gdc2\8Bit.cpp \ + ..\src\common\Gdc2\Alpha.cpp \ + ..\src\common\Gdc2\Colour.cpp \ + ..\src\common\Gdc2\Filters\Filter.cpp \ + ..\src\common\Gdc2\Font\Charset.cpp \ + ..\src\common\Gdc2\Font\DisplayString.cpp \ + ..\src\common\Gdc2\Font\Font.cpp \ + ..\src\common\Gdc2\Font\FontSystem.cpp \ + ..\src\common\Gdc2\Font\FontType.cpp \ + ..\src\common\Gdc2\Font\StringLayout.cpp \ + ..\src\common\Gdc2\Font\TypeFace.cpp \ + ..\src\common\Gdc2\GdcCommon.cpp \ + ..\src\common\Gdc2\Path\Path.cpp \ + ..\src\common\Gdc2\Rect.cpp \ + ..\src\common\Gdc2\RopsCases.cpp \ + ..\src\common\Gdc2\Surface.cpp \ + ..\src\common\Gdc2\Tools\ColourReduce.cpp \ + ..\src\common\Gdc2\Tools\GdcTools.cpp \ + ..\src\common\General\Containers.cpp \ + ..\src\common\General\DateTime.cpp \ + ..\src\common\General\ExeCheck.cpp \ + ..\src\common\General\FileCommon.cpp \ + ..\src\common\General\Password.cpp \ + ..\src\common\General\Properties.cpp \ + ..\src\common\General\qsort.cpp \ + ..\src\common\Hash\md5\md5.c \ + ..\src\common\Hash\md5\md5.h \ + ..\src\common\Hash\sha1\sha1.c \ + ..\src\common\Hash\sha1\sha1.h \ + ..\src\common\Lgi\Alert.cpp \ + ..\src\common\Lgi\AppCommon.cpp \ + ..\src\common\Lgi\Css.cpp \ + ..\src\common\Lgi\CssTools.cpp \ + ..\src\common\Lgi\DataDlg.cpp \ + ..\src\common\Lgi\DragAndDropCommon.cpp \ + ..\src\common\Lgi\FindReplace.cpp \ + ..\src\common\Lgi\FontSelect.cpp \ + ..\src\common\Lgi\GuiUtils.cpp \ + ..\src\common\Lgi\Input.cpp \ + ..\src\common\Lgi\LgiCommon.cpp \ + ..\src\common\Lgi\Library.cpp \ + ..\src\common\Lgi\LMsg.cpp \ + ..\src\common\Lgi\MemStream.cpp \ + ..\src\common\Lgi\MenuCommon.cpp \ + ..\src\common\Lgi\Mru.cpp \ + ..\src\common\Lgi\Mutex.cpp \ + ..\src\common\Lgi\Object.cpp \ + ..\src\common\Lgi\OptionsFile.cpp \ + ..\src\common\Lgi\Rand.cpp \ + ..\src\common\Lgi\Stream.cpp \ + ..\src\common\Lgi\SubProcess.cpp \ + ..\src\common\Lgi\ThreadCommon.cpp \ + ..\src\common\Lgi\ThreadEvent.cpp \ + ..\src\common\Lgi\ToolTip.cpp \ + ..\src\common\Lgi\TrayIcon.cpp \ + ..\src\common\Lgi\Variant.cpp \ + ..\src\common\Lgi\ViewCommon.cpp \ + ..\src\common\Lgi\WindowCommon.cpp \ + ..\src\common\Net\Base64.cpp \ + ..\src\common\Net\MDStringToDigest.cpp \ + ..\src\common\Net\Net.cpp \ + ..\src\common\Net\Uri.cpp \ + ..\src\common\Resource\LgiRes.cpp \ + ..\src\common\Resource\Res.cpp \ + ..\src\common\Skins\Gel\Gel.cpp \ + ..\src\common\Text\String.cpp \ + ..\src\common\Text\Token.cpp \ + ..\src\common\Text\Unicode.cpp \ + ..\src\common\Text\Utf8.cpp \ + ..\src\common\Text\XmlTree.cpp \ + ..\src\common\Widgets\Bitmap.cpp \ + ..\src\common\Widgets\Box.cpp \ + ..\src\common\Widgets\Button.cpp \ + ..\src\common\Widgets\CheckBox.cpp \ + ..\src\common\Widgets\Combo.cpp \ + ..\src\common\Widgets\ItemContainer.cpp \ + ..\src\common\Widgets\List.cpp \ + ..\src\common\Widgets\Panel.cpp \ + ..\src\common\Widgets\Popup.cpp \ + ..\src\common\Widgets\Progress.cpp \ + ..\src\common\Widgets\ProgressDlg.cpp \ + ..\src\common\Widgets\RadioGroup.cpp \ + ..\src\common\Widgets\Slider.cpp \ + ..\src\common\Widgets\Splitter.cpp \ + ..\src\common\Widgets\StatusBar.cpp \ + ..\src\common\Widgets\TableLayout.cpp \ + ..\src\common\Widgets\TabView.cpp \ + ..\src\common\Widgets\TextLabel.cpp \ + ..\src\common\Widgets\ToolBar.cpp \ + ..\src\common\Widgets\Tree.cpp \ + ..\src\win\Gdc2\Gdc2.cpp \ + ..\src\win\Gdc2\GdiLeak.cpp \ + ..\src\win\Gdc2\MemDC.cpp \ + ..\src\win\Gdc2\PrintDC.cpp \ + ..\src\win\Gdc2\ScreenDC.cpp \ + ..\src\win\General\File.cpp \ + ..\src\win\General\Mem.cpp \ + ..\src\win\General\ShowFileProp_Win.cpp \ + ..\src\win\INet\MibAccess.cpp \ + ..\src\win\Lgi\App.cpp \ + ..\src\win\Lgi\ClipBoard.cpp \ + ..\src\win\Lgi\DragAndDrop.cpp \ + ..\src\win\Lgi\FileSelect.cpp \ + ..\src\win\Lgi\General.cpp \ + ..\src\win\Lgi\Layout.cpp \ + ..\src\win\Lgi\LgiException.cpp \ + ..\src\win\Lgi\Menu.cpp \ + ..\src\win\Lgi\Printer.cpp \ + ..\src\win\Lgi\ScrollBar.cpp \ + ..\src\win\Lgi\Thread.cpp \ + ..\src\win\Lgi\View.cpp \ + ..\src\win\Lgi\Window.cpp \ + ..\src\win\Widgets\Dialog_Win.cpp \ + ..\src\win\Widgets\Edit_Win.cpp export Build=$(Build); \ - $(MAKE) -C ..\..\ -f Makefile.windows - -.SECONDEXPANSION: -$(Objects): $(BuildDir)/%.o: $$(wildcard %.c*) - mkdir -p $(@D) - @echo $( - - - + linux/Makefile.linux - Makefile.windows + win\Makefile.windows Makefile.macosx gcc 0 - - - - - + ./include ./private/common ./include ./private/common ./include/lgi/linux ./include/lgi/linux/Gtk ./private/linux ./include/lgi/linux ./include/lgi/linux/Gtk ./private/linux ./include/lgi/win ./private/win ./include/lgi/win ./private/win ./include/lgi/haiku ./private/haiku ./include/lgi/haiku ./private/haiku /usr/include/libappindicator3-0.1 `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gstreamer-1.0` /usr/include/libappindicator3-0.1 `pkg-config --cflags gtk+-3.0` `pkg-config --cflags gstreamer-1.0` magic appindicator3 crypt -static-libgcc `pkg-config --libs gtk+-3.0` magic appindicator3 crypt -static-libgcc `pkg-config --libs gtk+-3.0` -static-libgcc gnu network be -static-libgcc gnu network be - lgi-gtk3 lgi-gtk3 DynamicLibrary LGI_LIBRARY LGI_LIBRARY POSIX _GNU_SOURCE POSIX _GNU_SOURCE - - - - - - + - - - - + - - - - - - + - - - - - - - - - - - - + + diff --git a/win/Makefile.windows b/win/Makefile.windows --- a/win/Makefile.windows +++ b/win/Makefile.windows @@ -1,203 +1,214 @@ #!/usr/bin/make # # This makefile generated by LgiIde # http://www.memecode.com/lgi.php # .SILENT : CC = gcc CPP = g++ Target = lgi ifndef Build Build = Debug endif +MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) BuildDir = $(Build) -Flags = -fPIC -w -fno-inline -fpermissive +Flags = -fPIC -fno-inline -fpermissive -Wno-format-truncation ifeq ($(Build),Debug) - Flags += -g -std=c++14 + Flags += -MMD -MP -g -std=c++14 Tag = d Defs = -D_DEBUG -DWIN32 -D_REENTRANT -DLGI_LIBRARY Libs = Inc = \ -I./private/win \ -I./private/common \ -I./include/lgi/win \ -I./include else - Flags += -s -Os -std=c++14 + Flags += -MMD -MP -s -Os -std=c++14 Defs = -DWIN32 -D_REENTRANT -DLGI_LIBRARY Libs = Inc = \ -I./private/win \ -I./private/common \ -I./include/lgi/win \ -I./include endif # Dependencies Source = .\src\win\Widgets\Edit_Win.cpp \ .\src\win\Widgets\Dialog_Win.cpp \ .\src\win\Lgi\Window.cpp \ .\src\win\Lgi\View.cpp \ .\src\win\Lgi\Thread.cpp \ .\src\win\Lgi\ScrollBar.cpp \ .\src\win\Lgi\Printer.cpp \ .\src\win\Lgi\Menu.cpp \ .\src\win\Lgi\LgiException.cpp \ .\src\win\Lgi\Layout.cpp \ .\src\win\Lgi\General.cpp \ .\src\win\Lgi\FileSelect.cpp \ .\src\win\Lgi\DragAndDrop.cpp \ .\src\win\Lgi\ClipBoard.cpp \ .\src\win\Lgi\App.cpp \ .\src\win\INet\MibAccess.cpp \ .\src\win\General\ShowFileProp_Win.cpp \ .\src\win\General\Mem.cpp \ .\src\win\General\File.cpp \ .\src\win\Gdc2\ScreenDC.cpp \ .\src\win\Gdc2\PrintDC.cpp \ .\src\win\Gdc2\MemDC.cpp \ .\src\win\Gdc2\GdiLeak.cpp \ .\src\win\Gdc2\Gdc2.cpp \ .\src\common\Widgets\Tree.cpp \ .\src\common\Widgets\ToolBar.cpp \ .\src\common\Widgets\TextLabel.cpp \ .\src\common\Widgets\TabView.cpp \ .\src\common\Widgets\TableLayout.cpp \ .\src\common\Widgets\StatusBar.cpp \ .\src\common\Widgets\Splitter.cpp \ .\src\common\Widgets\Slider.cpp \ .\src\common\Widgets\RadioGroup.cpp \ .\src\common\Widgets\ProgressDlg.cpp \ .\src\common\Widgets\Progress.cpp \ .\src\common\Widgets\Popup.cpp \ .\src\common\Widgets\Panel.cpp \ .\src\common\Widgets\List.cpp \ .\src\common\Widgets\ItemContainer.cpp \ .\src\common\Widgets\Combo.cpp \ .\src\common\Widgets\CheckBox.cpp \ .\src\common\Widgets\Button.cpp \ .\src\common\Widgets\Box.cpp \ .\src\common\Widgets\Bitmap.cpp \ .\src\common\Text\XmlTree.cpp \ .\src\common\Text\Utf8.cpp \ .\src\common\Text\Unicode.cpp \ .\src\common\Text\Token.cpp \ .\src\common\Text\String.cpp \ .\src\common\Skins\Gel\Gel.cpp \ .\src\common\Resource\Res.cpp \ .\src\common\Resource\LgiRes.cpp \ .\src\common\Net\Uri.cpp \ - .\src\common\Net\NetTools.cpp \ .\src\common\Net\Net.cpp \ .\src\common\Net\MDStringToDigest.cpp \ .\src\common\Net\Base64.cpp \ .\src\common\Lgi\WindowCommon.cpp \ .\src\common\Lgi\ViewCommon.cpp \ .\src\common\Lgi\Variant.cpp \ .\src\common\Lgi\TrayIcon.cpp \ .\src\common\Lgi\ToolTip.cpp \ .\src\common\Lgi\ThreadEvent.cpp \ .\src\common\Lgi\ThreadCommon.cpp \ .\src\common\Lgi\SubProcess.cpp \ .\src\common\Lgi\Stream.cpp \ .\src\common\Lgi\Rand.cpp \ .\src\common\Lgi\OptionsFile.cpp \ .\src\common\Lgi\Object.cpp \ .\src\common\Lgi\Mutex.cpp \ .\src\common\Lgi\Mru.cpp \ .\src\common\Lgi\MenuCommon.cpp \ .\src\common\Lgi\MemStream.cpp \ .\src\common\Lgi\LMsg.cpp \ .\src\common\Lgi\Library.cpp \ .\src\common\Lgi\LgiCommon.cpp \ .\src\common\Lgi\Input.cpp \ .\src\common\Lgi\GuiUtils.cpp \ .\src\common\Lgi\FontSelect.cpp \ .\src\common\Lgi\FindReplace.cpp \ .\src\common\Lgi\DragAndDropCommon.cpp \ .\src\common\Lgi\DataDlg.cpp \ .\src\common\Lgi\CssTools.cpp \ .\src\common\Lgi\Css.cpp \ .\src\common\Lgi\AppCommon.cpp \ .\src\common\Lgi\Alert.cpp \ .\src\common\Hash\sha1\sha1.c \ .\src\common\Hash\md5\md5.c \ .\src\common\General\qsort.cpp \ .\src\common\General\Properties.cpp \ .\src\common\General\Password.cpp \ .\src\common\General\FileCommon.cpp \ .\src\common\General\ExeCheck.cpp \ .\src\common\General\DateTime.cpp \ .\src\common\General\Containers.cpp \ .\src\common\Gdc2\Tools\GdcTools.cpp \ .\src\common\Gdc2\Tools\ColourReduce.cpp \ .\src\common\Gdc2\Surface.cpp \ .\src\common\Gdc2\Rect.cpp \ .\src\common\Gdc2\Path\Path.cpp \ .\src\common\Gdc2\GdcCommon.cpp \ .\src\common\Gdc2\Font\TypeFace.cpp \ .\src\common\Gdc2\Font\StringLayout.cpp \ .\src\common\Gdc2\Font\FontType.cpp \ .\src\common\Gdc2\Font\FontSystem.cpp \ .\src\common\Gdc2\Font\Font.cpp \ .\src\common\Gdc2\Font\DisplayString.cpp \ .\src\common\Gdc2\Font\Charset.cpp \ .\src\common\Gdc2\Filters\Filter.cpp \ .\src\common\Gdc2\Colour.cpp \ .\src\common\Gdc2\Alpha.cpp \ .\src\common\Gdc2\8Bit.cpp \ .\src\common\Gdc2\32Bit.cpp \ .\src\common\Gdc2\24Bit.cpp \ .\src\common\Gdc2\16Bit.cpp \ .\src\common\Gdc2\15Bit.cpp -SourceLst := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(Source))) -Objects := $(addprefix $(BuildDir)/,$(SourceLst)) -Deps := $(patsubst %.o,%.d,$(Objects)) +SourceC := $(filter %.c,$(Source)) +ObjectsC := $(SourceC:.c=.o) +SourceCpp := $(filter %.cpp,$(Source)) +ObjectsCpp := $(SourceCpp:.cpp=.o) +Objects := $(notdir $(ObjectsC) $(ObjectsCpp)) +Objects := $(addprefix $(BuildDir)/,$(Objects)) +Deps := $(patsubst %.o,%.d,$(Objects)) + +$(BuildDir)/%.o: %.c + mkdir -p $(@D) + echo $(notdir $<) [$(Build)] + $(CC) $(Inc) $(Flags) $(Defs) -c $< -o $@ + +$(BuildDir)/%.o: %.cpp + mkdir -p $(@D) + echo $(notdir $<) [$(Build)] + $(CPP) $(Inc) $(Flags) $(Defs) -c $< -o $@ # Target TargetFile = lib$(Target)$(Tag).dll $(TargetFile) : $(Objects) mkdir -p $(BuildDir) @echo Linking $(TargetFile) [$(Build)]... $(CPP)$s -shared \ \ -o $(BuildDir)/$(TargetFile) \ $(Objects) \ $(Libs) @echo Done. -.SECONDEXPANSION: -$(Objects): $(BuildDir)/%.o: $$(wildcard %.c*) - mkdir -p $(@D) - @echo $(