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 $(