diff --git a/Ide/LgiIdeProj.xml b/Ide/LgiIdeProj.xml --- a/Ide/LgiIdeProj.xml +++ b/Ide/LgiIdeProj.xml @@ -1,269 +1,284 @@ - - - - - + + + + + + - + - .\buildHaiku.py + .\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 -/local/include + ..\include\lgi\win -/local/include + ../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 + - ..\Debug - ..\Release + ..\x64Debug19 + ..\x64Release19 + Executable lgiide lgiide LgiIde.exe LgiIde.exe lgiide lgiide - - C:\Data\CodeLib\Gtk\include\gtk-2.0\gtk -C:\Data\CodeLib\Gtk\include\gtk-2.0\gdk - C:\Data\CodeLib\Gtk\include\gtk-2.0\gtk -C:\Data\CodeLib\Gtk\include\gtk-2.0\gdk - + `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 - + + + + + - + + + + - + + + + diff --git a/Ide/src/IdeProject.cpp b/Ide/src/IdeProject.cpp --- a/Ide/src/IdeProject.cpp +++ b/Ide/src/IdeProject.cpp @@ -1,4108 +1,4126 @@ #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 = ""; LString LinkerFlags; const char *TargetType = d->Settings.GetStr(ProjTargetType, NULL, Platform); const char *CompilerName = d->Settings.GetStr(ProjCompiler); 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."; } - char Buf[256]; + auto Base = Proj->GetBasePath(); auto MakeFile = Proj->GetMakefile(Platform); + LString MakeFilePath; Proj->CheckExists(MakeFile); if (!MakeFile) - MakeFile = "../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 ); - auto Base = Proj->GetBasePath(); 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); 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 = -fPIC -w -fno-inline -fpermissive\n"); 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 = -fPIC -w -fno-inline -fpermissive\n" // -fexceptions ); 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); } } #if 0 /* Currently this code is adding extra paths that are covered by the official 'IncludePaths' in addition to relative paths in the actual #include parameter. e.g. #include "lgi/common/SomeHeader.h" Hence disabling it for the time being. */ // Add paths of headers for (int i=0; iGetFileName()) { char *e = LGetExtension(n->GetFileName()); if (e && stricmp(e, "h") == 0) { LString Fn = n->GetFileName(); for (char *Dir = Fn; *Dir; Dir++) { if (*Dir == '/' || *Dir == '\\') { *Dir = DIR_CHAR; } } char Path[MAX_PATH_LEN]; strcpy_s(Path, sizeof(Path), Fn); LTrimDir(Path); LString Rel; if (!Proj->RelativePath(Rel, Path)) Rel = Path; if (stricmp(Rel, ".") != 0) { LAutoString RelN = ToNativePath(Rel); if (!Proj->CheckExists(RelN)) OnError("Header include path '%s' doesn't exist.\n", RelN.Get()); else if (!Inc.Find(RelN)) Inc.Add(RelN, true); } } } } #endif LString::Array Incs; for (auto i: Inc) Incs.New() = i.key; Incs.Sort(); for (auto i: Incs) { LString s; if (*i == '`') s.Printf(" \\\n\t\t%s", i.Get()); else s.Printf(" \\\n\t\t-I%s", ToUnixPath(i)); sIncludes[Cfg] += s; } } // Output the defs section for Debug and Release // Debug specific m.Print("\n" "ifeq ($(Build),Debug)\n" " Flags += -g -std=c++14\n" " Tag = d\n" " Defs = -D_DEBUG %s\n" " Libs = %s\n" " Inc = %s\n", CastEmpty(sDefines[0].Get()), CastEmpty(sLibs[0].Get()), CastEmpty(sIncludes[0].Get())); // Release specific m.Print("else\n" " Flags += -s -Os -std=c++14\n" " Defs = %s\n" " Libs = %s\n" " Inc = %s\n" "endif\n" "\n", CastEmpty(sDefines[1].Get()), CastEmpty(sLibs[1].Get()), CastEmpty(sIncludes[1].Get())); if (Files.Length()) { LArray IncPaths; if (Proj->BuildIncludePaths(IncPaths, false, false, Platform)) { // 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); if (path.Find("./") == 0) path = path(2,-1); SourceFiles.Add(path); } } 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" "SourceLst := $(patsubst %%.c,%%.o,$(patsubst %%.cpp,%%.o,$(Source)))\n" "Objects := $(addprefix $(BuildDir)/,$(SourceLst))\n" "Deps := $(patsubst %%.o,%%.d,$(Objects))\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 Base = Proj->GetBasePath(); + auto Base = MakeFilePath; auto TargetFile = Dep->GetTargetFile(Platform); if (DepBase && Base && TargetFile) { - LString Rel; - if (!Proj->RelativePath(Rel, DepBase)) - Rel = DepBase; - ToUnixPath(Rel); + 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()); - sprintf(Buf, "%s/$(BuildDir)/%s", Rel.Get(), TargetFile.Get()); - m.Print(" %s", Buf); + 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); + Rules.Print("%s : ", Buf.GetFull().Get()); for (int i=0; iRelativePath(DepRel, AllDeps[i]) ? DepRel.Get() : AllDeps[i]; - ToUnixPath(f); + LString DepRel = LMakeRelativePath(Base, AllDeps[i]); + auto f = DepRel ? DepRel.Get() : AllDeps[i]; + ToNativePath(f); Rules.Print("%s", f); // Add these dependencies to this makefiles dep list if (!DepFiles.Find(f)) DepFiles.Add(f, true); } AllDeps.DeleteArrays(); Rules.Print("\n\texport Build=$(Build); \\\n" "\t$(MAKE) -C %s", Rel.Get()); auto Mk = Dep->GetMakefile(Platform); // RenameMakefileForPlatform(Mk, Platform); if (Mk) { char *DepMakefile = strrchr(Mk, DIR_CHAR); if (DepMakefile) 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 my_base = Proj->GetBasePath(); LAutoString dep_base = d->GetBasePath(); d->CheckExists(dep_base); auto rel_dir = LMakeRelativePath(my_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("\t%s \\\n", ToPlatformPath(a ? a.Get() : p.Get(), Platform).Get()); } else { m.Print("\t%s \\\n", ToPlatformPath(p, Platform).Get()); } } } m.Print("\t$(BuildDir)\n\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; iGetApp()->GetOptions()->GetValue(OPT_Jobs, Jobs) || Jobs.CastInt32() < 1) Jobs = 2; auto Pos = InitDir.RFind(DIR_STR); if (Pos) InitDir.Length(Pos); 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()); 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] = ""; 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[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); char *Term = 0; char *WorkDir = 0; char *Execute = 0; 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); char *a = Proj->GetExeArgs() ? Proj->GetExeArgs() : (char*)""; 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([&](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([&](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, [&]() { SetDirty(); }); break; } case IDM_INSERT_DEP: { LFileSelect *s = new LFileSelect; s->Parent(Tree); s->Type("Project", "*.xml"); s->Open([&](auto s, bool ok) { if (!ok) return; 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); char *ext = LGetExtension(t); if (!ext) sprintf(t + strlen(t), ".%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; LAutoString 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 (ProjDependency *d = Deps.First(); d; d = Deps.Next()) 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 (int n=0; n 0); // for (ProjDependency *d = Deps.First(); d; d = Deps.Next()) 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/win/Makefile.windows b/Ide/win/Makefile.windows --- a/Ide/win/Makefile.windows +++ b/Ide/win/Makefile.windows @@ -1,2126 +1,410 @@ #!/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 BuildDir = $(Build) Flags = -fPIC -w -fno-inline -fpermissive ifeq ($(Build),Debug) - Flags += -g -std=c++11 + Flags += -g -std=c++14 Tag = d - Defs = -D_DEBUG -DWIN32 -D_REENTRANT -DWINDOWS -DWINNATIVE + Defs = -D_DEBUG -DWIN32 -D_REENTRANT Libs = \ - -L../Debug \ + -L../x64Debug19 \ -limm32 \ -llgi$(Tag) \ - -L//MALLEN-UBUNTU/Code/Lgi/trunk/$(BuildDir) + -L../$(BuildDir) Inc = \ - -I../include/common \ - -I../include/win32 \ - -I./Code \ - -I./Resources \ - -I/local/include \ - -IC:/Data/CodeLib/Gtk/include/gtk-2.0/gdk \ - -IC:/Data/CodeLib/Gtk/include/gtk-2.0/gtk + -I./src \ + -I./resources \ + -I../include/lgi/win \ + -I../include else - Flags += -s -Os -std=c++11 - Defs = -DWIN32 -D_REENTRANT -DWINDOWS -DWINNATIVE + Flags += -s -Os -std=c++14 + Defs = -DWIN32 -D_REENTRANT Libs = \ - -L../Release \ + -L../x64Release19 \ -limm32 \ -llgi$(Tag) \ - -L//MALLEN-UBUNTU/Code/Lgi/trunk/$(BuildDir) + -L../$(BuildDir) Inc = \ - -I../include/common \ - -I../include/win32 \ - -I./Code \ - -I./Resources \ - -I/local/include \ - -IC:/Data/CodeLib/Gtk/include/gtk-2.0/gdk \ - -IC:/Data/CodeLib/Gtk/include/gtk-2.0/gtk + -I./src \ + -I./resources \ + -I../include/lgi/win \ + -I../include endif # Dependencies -Depends = GDebugContext.o \ - GDebugger.o \ - GSubProcess.o \ - AddFtpFile.o \ - WebFldDlg.o \ - DocEdit.o \ - DocEditStyling.o \ - IdeDoc.o \ - FtpThread.o \ - IFtp.o \ - IdeProject.o \ - IdeProjectSettings.o \ - levenshtein.o \ - MissingFiles.o \ - ProjectNode.o \ - FindInFiles.o \ - FindSymbol.o \ - GHistory.o \ - SimpleCppParser.o \ - GLexCpp.o \ - GParseCpp.o \ - SysCharSupport.o \ - IdeCommon.o \ - LgiIde.o \ - LgiUtils.o \ - MemDumpViewer.o \ - SpaceTabConv.o \ - GDocView.o \ - GMdi.o \ - IHttp.o \ - LgiMain.o \ - OpenSSLSocket.o \ - Png.o +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\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)) # Target # Executable target -$(Target) : ../$(BuildDir)/liblgi$(Tag).dll outputfolder $(Depends) +$(Target) : ..\..\$(BuildDir)\liblgi$(Tag).dll $(Objects) + mkdir -p $(BuildDir) @echo Linking $(Target) [$(Build)]... $(CPP) -mwindows -Wl,--enable-auto-import -o \ - $(Target) $(addprefix $(BuildDir)/,$(Depends)) $(Libs) + $(Target) $(Objects) $(Libs) @echo Done. -../$(BuildDir)/liblgi$(Tag).dll : ../include/common/Base64.h \ - ../include/common/Core.h \ - ../include/common/GArray.h \ - ../include/common/GAutoPtr.h \ - ../include/common/GBitmap.h \ - ../include/common/GBox.h \ - ../include/common/GButton.h \ - ../include/common/GCapabilities.h \ - ../include/common/GCheckBox.h \ - ../include/common/GClipBoard.h \ - ../include/common/GColour.h \ - ../include/common/GColourSpace.h \ - ../include/common/GCom.h \ - ../include/common/GCombo.h \ - ../include/common/GContainers.h \ - ../include/common/GCss.h \ - ../include/common/GCssTools.h \ - ../include/common/GDataDlg.h \ - ../include/common/Gdc2.h \ - ../include/common/GdcTools.h \ - ../include/common/GdiLeak.h \ - ../include/common/GDisplayString.h \ - ../include/common/GDocView.h \ - ../include/common/GDom.h \ - ../include/common/GDragAndDrop.h \ - ../include/common/GDropFiles.h \ - ../include/common/GEdit.h \ - ../include/common/GEventTargetThread.h \ - ../include/common/GFile.h \ - ../include/common/GFileSelect.h \ - ../include/common/GFilter.h \ - ../include/common/GFindReplaceDlg.h \ - ../include/common/GFont.h \ - ../include/common/GFontCache.h \ - ../include/common/GFontSelect.h \ - ../include/common/GHashTable.h \ - ../include/common/GImageList.h \ - ../include/common/GInput.h \ - ../include/common/GItemContainer.h \ - ../include/common/GLibrary.h \ - ../include/common/GLibraryUtils.h \ - ../include/common/GMatrix.h \ - ../include/common/GMem.h \ - ../include/common/GMenu.h \ - ../include/common/GMenuImpl.h \ - ../include/common/GMessage.h \ - ../include/common/GMime.h \ - ../include/common/GMru.h \ - ../include/common/GNotifications.h \ - ../include/common/GOptionsFile.h \ - ../include/common/GPalette.h \ - ../include/common/GPanel.h \ - ../include/common/GPassword.h \ - ../include/common/GPath.h \ - ../include/common/GPixelRops.h \ - ../include/common/GPoint.h \ - ../include/common/GPopup.h \ - ../include/common/GPopupList.h \ - ../include/common/GPrinter.h \ - ../include/common/GProcess.h \ - ../include/common/GProgress.h \ - ../include/common/GProgressDlg.h \ - ../include/common/GProperties.h \ - ../include/common/GRadioGroup.h \ - ../include/common/GRange.h \ - ../include/common/GRect.h \ - ../include/common/GRefCount.h \ - ../include/common/GRegKey.h \ - ../include/common/GRops.h \ - ../include/common/GScrollBar.h \ - ../include/common/GSkinEngine.h \ - ../include/common/GSlider.h \ - ../include/common/GStream.h \ - ../include/common/GString.h \ - ../include/common/GStringClass.h \ - ../include/common/GTableLayout.h \ - ../include/common/GTabView.h \ - ../include/common/GTextFile.h \ - ../include/common/GTextLabel.h \ - ../include/common/GTextView3.h \ - ../include/common/GToken.h \ - ../include/common/GToolBar.h \ - ../include/common/GTree.h \ - ../include/common/GUndo.h \ - ../include/common/GUnicode.h \ - ../include/common/GUtf8.h \ - ../include/common/GVariant.h \ - ../include/common/GViewPriv.h \ - ../include/common/GXmlTree.h \ - ../include/common/INet.h \ - ../include/common/INetTools.h \ - ../include/common/LCancel.h \ - ../include/common/LDateTime.h \ - ../include/common/LDomFields.h \ - ../include/common/Lgi.h \ - ../include/common/LgiClass.h \ - ../include/common/LgiClasses.h \ - ../include/common/LgiCommon.h \ - ../include/common/LgiDefs.h \ - ../include/common/LgiInc.h \ - ../include/common/LgiInterfaces.h \ - ../include/common/LgiMsgs.h \ - ../include/common/LgiNetInc.h \ - ../include/common/LgiRes.h \ - ../include/common/LgiSpellCheck.h \ - ../include/common/LgiWidgets.h \ - ../include/common/LHashTable.h \ - ../include/common/LList.h \ - ../include/common/LListItemCheckBox.h \ - ../include/common/LListItemRadioBtn.h \ - ../include/common/LMutex.h \ - ../include/common/LStringLayout.h \ - ../include/common/LThread.h \ - ../include/common/LThreadEvent.h \ - ../include/common/Progress.h \ - ../include/common/Res.h \ - ../include/linux/GSymLookup.h \ - ../include/linux/Gtk/LgiWidget.h \ - ../include/linux/Gtk/LgiWinManGlue.h \ - ../include/win32/GSymLookup.h \ - ../include/win32/LgiOsClasses.h \ - ../include/win32/LgiOsDefs.h \ - ../include/win32/StackWalker.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/Filters/GFilter.cpp \ - ../src/common/Gdc2/Font/GDisplayString.cpp \ - ../src/common/Gdc2/Font/GFont.cpp \ - ../src/common/Gdc2/Font/GFont_W.cpp \ - ../src/common/Gdc2/Font/GFontCodePages.cpp \ - ../src/common/Gdc2/Font/GFontSystem.cpp \ - ../src/common/Gdc2/Font/LStringLayout.cpp \ - ../src/common/Gdc2/GColour.cpp \ - ../src/common/Gdc2/GdcCommon.cpp \ - ../src/common/Gdc2/GRect.cpp \ - ../src/common/Gdc2/GRopsCases.cpp \ - ../src/common/Gdc2/GSurface.cpp \ - ../src/common/Gdc2/Path/GPath.cpp \ - ../src/common/Gdc2/Tools/GColourReduce.cpp \ - ../src/common/Gdc2/Tools/GdcTools.cpp \ - ../src/common/General/GContainers.cpp \ - ../src/common/General/GExeCheck.cpp \ - ../src/common/General/GFileCommon.cpp \ - ../src/common/General/GPassword.cpp \ - ../src/common/General/GProperties.cpp \ - ../src/common/General/LDateTime.cpp \ - ../src/common/General/qsort.cpp \ - ../src/common/Hash/md5/md5.c \ - ../src/common/INet/Base64.cpp \ - ../src/common/INet/GUri.cpp \ - ../src/common/INet/INet.cpp \ - ../src/common/INet/INetTools.cpp \ - ../src/common/INet/MDStringToDigest.cpp \ - ../src/common/Lgi/GAlert.cpp \ - ../src/common/Lgi/GCss.cpp \ - ../src/common/Lgi/GCssTools.cpp \ - ../src/common/Lgi/GDataDlg.cpp \ - ../src/common/Lgi/GFindReplace.cpp \ - ../src/common/Lgi/GFontSelect.cpp \ - ../src/common/Lgi/GGuiUtils.cpp \ - ../src/common/Lgi/GInput.cpp \ - ../src/common/Lgi/GLibrary.cpp \ - ../src/common/Lgi/GMemStream.cpp \ - ../src/common/Lgi/GMenuCommon.cpp \ - ../src/common/Lgi/GMru.cpp \ - ../src/common/Lgi/GObject.cpp \ - ../src/common/Lgi/GOptionsFile.cpp \ - ../src/common/Lgi/GProcess.cpp \ - ../src/common/Lgi/GStream.cpp \ - ../src/common/Lgi/GToolTip.cpp \ - ../src/common/Lgi/GTrayIcon.cpp \ - ../src/common/Lgi/GVariant.cpp \ - ../src/common/Lgi/GViewCommon.cpp \ - ../src/common/Lgi/GWindowCommon.cpp \ - ../src/common/Lgi/Lgi.cpp \ - ../src/common/Lgi/LgiMsg.cpp \ - ../src/common/Lgi/LgiRand.cpp \ - ../src/common/Lgi/LMutex.cpp \ - ../src/common/Lgi/LThreadCommon.cpp \ - ../src/common/Lgi/LThreadEvent.cpp \ - ../src/common/Resource/LgiRes.cpp \ - ../src/common/Resource/Res.cpp \ - ../src/common/Skins/Gel/Gel.cpp \ - ../src/common/Text/GString.cpp \ - ../src/common/Text/GToken.cpp \ - ../src/common/Text/GUnicode.cpp \ - ../src/common/Text/GUtf8.cpp \ - ../src/common/Text/GXmlTree.cpp \ - ../src/common/Widgets/GBitmap.cpp \ - ../src/common/Widgets/GBox.cpp \ - ../src/common/Widgets/GButton.cpp \ - ../src/common/Widgets/GCheckBox.cpp \ - ../src/common/Widgets/GCombo.cpp \ - ../src/common/Widgets/GItemContainer.cpp \ - ../src/common/Widgets/GPanel.cpp \ - ../src/common/Widgets/GPopup.cpp \ - ../src/common/Widgets/GProgressDlg.cpp \ - ../src/common/Widgets/GRadioGroup.cpp \ - ../src/common/Widgets/GSplitter.cpp \ - ../src/common/Widgets/GStatusBar.cpp \ - ../src/common/Widgets/GTableLayout.cpp \ - ../src/common/Widgets/GTabView.cpp \ - ../src/common/Widgets/GTextLabel.cpp \ - ../src/common/Widgets/GToolBar.cpp \ - ../src/common/Widgets/GTree.cpp \ - ../src/common/Widgets/LList.cpp \ - ../src/win32/Gdc2/Gdc2.cpp \ - ../src/win32/Gdc2/GdiLeak.cpp \ - ../src/win32/Gdc2/GMemDC.cpp \ - ../src/win32/Gdc2/GPrintDC.cpp \ - ../src/win32/Gdc2/GScreenDC.cpp \ - ../src/win32/General/GFile.cpp \ - ../src/win32/General/GMem.cpp \ - ../src/win32/General/ShowFileProp_Win.cpp \ - ../src/win32/INet/MibAccess.cpp \ - ../src/win32/Lgi/GApp.cpp \ - ../src/win32/Lgi/GClipBoard.cpp \ - ../src/win32/Lgi/GDragAndDrop.cpp \ - ../src/win32/Lgi/GFileSelect.cpp \ - ../src/win32/Lgi/GGeneral.cpp \ - ../src/win32/Lgi/GLayout.cpp \ - ../src/win32/Lgi/GMenu.cpp \ - ../src/win32/Lgi/GPrinter.cpp \ - ../src/win32/Lgi/GScrollBar.cpp \ - ../src/win32/Lgi/GView.cpp \ - ../src/win32/Lgi/GWindow.cpp \ - ../src/win32/Lgi/LgiException.cpp \ - ../src/win32/Lgi/LThread.cpp \ - ../src/win32/Widgets/GDialog.cpp \ - ../src/win32/Widgets/GEdit_Win.cpp \ - ../src/win32/Widgets/GProgress.cpp \ - ../src/win32/Widgets/GSlider.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\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 export Build=$(Build); \ - $(MAKE) -C .. -f Makefile.windows + $(MAKE) -C ..\..\ -f Makefile.windows -# Create the output folder -outputfolder : - -mkdir -p $(BuildDir) 2> /dev/null +.SECONDEXPANSION: +$(Objects): $(BuildDir)/%.o: $$(wildcard %.c*) + mkdir -p $(@D) + @echo $( Makefile.linux - Makefile.win64 + 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/Makefile.windows b/Makefile.windows --- a/Makefile.windows +++ b/Makefile.windows @@ -1,1599 +1,203 @@ #!/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 BuildDir = $(Build) Flags = -fPIC -w -fno-inline -fpermissive ifeq ($(Build),Debug) - Flags += -g -std=c++11 + Flags += -g -std=c++14 Tag = d - Defs = -D_DEBUG -DWIN32 -D_REENTRANT -DLGI_LIBRARY -DHAS_FILE_CMD=1 -DWINNATIVE -DWINDOWS - Libs = \ - -lws2_32 \ - -lComCtl32 \ - -luxtheme \ - -lgdi32 \ - -lcomdlg32 \ - -lole32 \ - -luuid + Defs = -D_DEBUG -DWIN32 -D_REENTRANT -DLGI_LIBRARY + Libs = Inc = \ - -I./include/common \ - -I./include/linux/Gtk \ - -I./include/win32 \ - -I./src/common/Hash/md5 \ - -I./src/common/Hash/sha1 \ - -I/local/include \ - -Iinclude/common \ - -Iinclude/win32 + -I./private/win \ + -I./private/common \ + -I./include/lgi/win \ + -I./include else - Flags += -s -Os -std=c++11 - Defs = -DWIN32 -D_REENTRANT -DLGI_LIBRARY -DHAS_FILE_CMD=1 -DWINNATIVE -DWINDOWS - Libs = \ - -lws2_32 \ - -lComCtl32 \ - -luxtheme \ - -lgdi32 \ - -lcomdlg32 \ - -lole32 \ - -luuid + Flags += -s -Os -std=c++14 + Defs = -DWIN32 -D_REENTRANT -DLGI_LIBRARY + Libs = Inc = \ - -I./include/common \ - -I./include/linux/Gtk \ - -I./include/win32 \ - -I./src/common/Hash/md5 \ - -I./src/common/Hash/sha1 \ - -I/local/include \ - -Iinclude/common \ - -Iinclude/win32 + -I./private/win \ + -I./private/common \ + -I./include/lgi/win \ + -I./include endif # Dependencies -Depends = LDateTime.o \ - GDragAndDrop.o \ - GFile.o \ - ShowFileProp_Win.o \ - GExeCheck.o \ - GFileCommon.o \ - GApp.o \ - GGeneral.o \ - GPrinter.o \ - GView.o \ - GWindow.o \ - LgiException.o \ - GViewCommon.o \ - GWindowCommon.o \ - GLibrary.o \ - GProperties.o \ - GMem.o \ - qsort.o \ - GContainers.o \ - GMenu.o \ - GMenuCommon.o \ - GProcess.o \ - LgiRes.o \ - Res.o \ - Gel.o \ - GPath.o \ - GMemStream.o \ - GStream.o \ - LThread.o \ - LMutex.o \ - LThreadCommon.o \ - LThreadEvent.o \ - GVariant.o \ - GGuiUtils.o \ - GObject.o \ - GToolTip.o \ - GTrayIcon.o \ - LgiCommon.o \ - LgiMsg.o \ - GFileSelect.o \ - GAlert.o \ - GFindReplace.o \ - GFontSelect.o \ - GInput.o \ - Gdc2.o \ - GColour.o \ - GColourReduce.o \ - GdcCommon.o \ - GdcTools.o \ - GDisplayString.o \ - GFont.o \ - GFont_W.o \ - GFontCodePages.o \ - GFontSystem.o \ - LStringLayout.o \ - 15Bit.o \ - 16Bit.o \ - 24Bit.o \ - 32Bit.o \ - 8Bit.o \ - Alpha.o \ - GFilter.o \ - GRect.o \ - GScreenDC.o \ - GPrintDC.o \ - GMemDC.o \ - GSurface.o \ - GdiLeak.o \ - GClipBoard.o \ - GDataDlg.o \ - GPassword.o \ - md5.o \ - sha1.o \ - GMru.o \ - Base64.o \ - GOptionsFile.o \ - LgiRand.o \ - GString.o \ - GToken.o \ - GUnicode.o \ - GUtf8.o \ - GXmlTree.o \ - GBitmap.o \ - GButton.o \ - GCheckBox.o \ - GCombo.o \ - GItemContainer.o \ - GPanel.o \ - GPopup.o \ - GProgressDlg.o \ - GRadioGroup.o \ - GStatusBar.o \ - GTabView.o \ - GTextLabel.o \ - GToolBar.o \ - GTree.o \ - LList.o \ - GCss.o \ - GCssTools.o \ - GEdit_Win.o \ - GDialog.o \ - GSlider.o \ - GLayout.o \ - GProgress.o \ - GScrollBar.o \ - GBox.o \ - GSplitter.o \ - GTableLayout.o \ - GUri.o \ - INet.o \ - INetTools.o \ - MDStringToDigest.o \ - MibAccess.o +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)) # Target TargetFile = lib$(Target)$(Tag).dll -$(TargetFile) : outputfolder $(Depends) +$(TargetFile) : $(Objects) + mkdir -p $(BuildDir) @echo Linking $(TargetFile) [$(Build)]... $(CPP)$s -shared \ \ -o $(BuildDir)/$(TargetFile) \ - $(addprefix $(BuildDir)/,$(Depends)) \ + $(Objects) \ $(Libs) @echo Done. -# Create the output folder -outputfolder : - -mkdir -p $(BuildDir) 2> /dev/null +.SECONDEXPANSION: +$(Objects): $(BuildDir)/%.o: $$(wildcard %.c*) + mkdir -p $(@D) + @echo $(