diff --git a/include/lgi/common/LgiDefs.h b/include/lgi/common/LgiDefs.h
--- a/include/lgi/common/LgiDefs.h
+++ b/include/lgi/common/LgiDefs.h
@@ -1,589 +1,590 @@
/**
\file
\author Matthew Allen
\date 24/9/1999
\brief Defines and types
Copyright (C) 1999-2004, Matthew Allen
*/
#ifndef _LGIDEFS_H_
#define _LGIDEFS_H_
#ifdef HAIKU
#include
#endif
#include "LgiInc.h"
#if defined(WIN32) && defined(__GNUC__)
#define PLATFORM_MINGW
#endif
#include
// Unsafe typedefs, for backward compatibility
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
// Length safe typedesf, use these in new code
#ifdef _MSC_VER
/// 64-bit signed int type (size safe, guaranteed to be 64 bits)
typedef signed __int64 int64;
/// 64-bit unsigned int type (size safe, guaranteed to be 64 bits)
typedef unsigned __int64 uint64;
#ifndef _WCHAR_T_DEFINED
#include
#endif
#pragma warning(error:4263)
#ifdef _WIN64
typedef signed __int64 ssize_t;
#else
typedef signed int ssize_t;
#endif
#elif defined(LINUX)
/// 64-bit signed int type (size safe, guaranteed to be 64 bits)
typedef int64_t int64;
/// 64-bit unsigned int type (size safe, guaranteed to be 64 bits)
typedef uint64_t uint64;
#elif !defined(HAIKU)
/// 64-bit signed int type (size safe, guaranteed to be 64 bits)
typedef signed long long int64;
/// 64-bit unsigned int type (size safe, guaranteed to be 64 bits)
typedef unsigned long long uint64;
#endif
#ifndef __cplusplus
#include
#if defined(_MSC_VER) && _MSC_VER<1800
typedef unsigned char bool;
#define true 1
#define false 0
#else
#include
#endif
#endif
/// \brief Wide unicode char
///
/// This is 16 bits on Win32 and Mac, but 32 bits on unix platforms. There are a number
/// of wide character string function available for manipulating wide char strings.
///
/// Firstly to convert to and from utf-8 there is:
///
/// - Utf8ToWide()
///
- WideToUtf8()
///
///
/// Wide versions of standard library functions are available:
///
/// - StrchrW()
///
- StrrchrW()
///
- StrnchrW()
///
- StrstrW()
///
- StristrW()
///
- StrnstrW()
///
- StrnistrW()
///
- StrcmpW()
///
- StricmpW()
///
- StrncmpW()
///
- StrnicmpW()
///
- StrcpyW()
///
- StrncpyW()
///
- StrlenW()
///
- StrcatW()
///
- HtoiW()
///
- NewStrW()
///
- TrimStrW()
///
- ValidStrW()
///
- MatchStrW()
///
#include
typedef wchar_t char16;
#if !WINNATIVE
#ifdef UNICODE
typedef char16 TCHAR;
#ifndef _T
#define _T(arg) L##arg
#endif
#else
typedef char TCHAR;
#ifndef _T
#define _T(arg) arg
#endif
#endif
#endif
#if defined(_MSC_VER)
#if _MSC_VER >= 1400
#ifdef _WIN64
typedef __int64 NativeInt;
typedef unsigned __int64 UNativeInt;
#else
typedef _W64 int NativeInt;
typedef _W64 unsigned int UNativeInt;
#endif
#else
typedef int NativeInt;
typedef unsigned int UNativeInt;
#endif
#else
#if __LP64__
typedef int64 NativeInt;
typedef uint64 UNativeInt;
#else
typedef int NativeInt;
typedef unsigned int UNativeInt;
#endif
#endif
/// Generic pointer to any base type. Used when addressing continuous data of
/// different types.
typedef union
{
int8_t *s8;
uint8_t *u8;
int16_t *s16;
uint16_t *u16;
int32_t *s32;
uint32_t *u32;
int64 *s64;
uint64 *u64;
NativeInt *ni;
UNativeInt *uni;
char *c;
char16 *w;
float *f;
double *d;
#ifdef __cplusplus
bool *b;
#else
unsigned char *b;
#endif
void **vp;
int i;
} LPointer;
// Basic macros
#define limit(i,l,u) (((i)<(l)) ? (l) : (((i)>(u)) ? (u) : (i)))
// #define makelong(a, b) ((a)<<16 | (b&0xFFFF))
// #define loword(a) (a&0xFFFF)
// #define hiword(a) (a>>16)
#undef ABS
#ifdef __cplusplus
template
inline T ABS(T v)
{
if (v < 0) return -v;
return v;
}
#else
#define ABS(v) ((v) < 0 ? -(v) : (v))
#endif
/// Returns true if 'c' is an ascii character
#define IsAlpha(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
/// Returns true if 'c' is a digit (number)
#define IsDigit(c) ((c) >= '0' && (c) <= '9')
/// Returns true if 'c' is a hexadecimal digit
#define IsHexDigit(c) ( \
((c) >= '0' && (c) <= '9') || \
((c) >= 'a' && (c) <= 'f') || \
((c) >= 'A' && (c) <= 'F') \
)
// Byte swapping
#define LgiSwap16(a) ( (((a) & 0xff00) >> 8) | \
(((a) & 0x00ff) << 8) )
#define LgiSwap32(a) ( (((a) & 0xff000000) >> 24) | \
(((a) & 0x00ff0000) >> 8) | \
(((a) & 0x0000ff00) << 8) | \
(((a) & 0x000000ff) << 24) )
#ifdef __GNUC__
#define LgiSwap64(a) ( (((a) & 0xff00000000000000LLU) >> 56) | \
(((a) & 0x00ff000000000000LLU) >> 40) | \
(((a) & 0x0000ff0000000000LLU) >> 24) | \
(((a) & 0x000000ff00000000LLU) >> 8) | \
(((a) & 0x00000000ff000000LLU) << 8) | \
(((a) & 0x0000000000ff0000LLU) << 24) | \
(((a) & 0x000000000000ff00LLU) << 40) | \
(((a) & 0x00000000000000ffLLU) << 56) )
#else
#define LgiSwap64(a) ( (((a) & 0xff00000000000000) >> 56) | \
(((a) & 0x00ff000000000000) >> 40) | \
(((a) & 0x0000ff0000000000) >> 24) | \
(((a) & 0x000000ff00000000) >> 8) | \
(((a) & 0x00000000ff000000) << 8) | \
(((a) & 0x0000000000ff0000) << 24) | \
(((a) & 0x000000000000ff00) << 40) | \
(((a) & 0x00000000000000ff) << 56) )
#endif
#ifdef __cplusplus
// Define a way of creating a 4 character code string literal as an int.
constexpr uint32_t Lgi4CC( char const p[5] )
{
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
#endif
// Asserts
+#ifndef LAssert
LgiFunc void _lgi_assert(bool b, const char *test, const char *file, int line);
#ifdef _DEBUG
#define LAssert(b) _lgi_assert(b, #b, __FILE__, __LINE__)
#else
#define LAssert(b) ((void)0)
#endif
-
+#endif
// Good ol NULLy
#ifndef NULL
#define NULL 0
#endif
// Slashes and quotes
#define IsSlash(c) (((c)=='/')||((c)=='\\'))
#define IsQuote(c) (((c)=='\"')||((c)=='\''))
// Some objectish ones
#define ZeroObj(obj) memset(&obj, 0, sizeof(obj))
#ifndef CountOf
#define CountOf(array) (sizeof(array)/sizeof(array[0]))
#endif
#ifdef __cplusplus
template
void LSwap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}
#endif
#ifndef MEMORY_DEBUG
#define DeleteObj(obj) if (obj) { delete obj; obj = 0; }
#define DeleteArray(obj) if (obj) { delete [] obj; obj = 0; }
#endif
// Flags
#define SetFlag(i, f) (i) |= (f)
#define ClearFlag(i, f) (i) &= ~(f)
#define TestFlag(i, f) (((i) & (f)) != 0)
// Defines
/// Enum of all the operating systems we might be running on.
enum LgiOs
{
/// \brief Unknown OS
/// \sa LGetOs
LGI_OS_UNKNOWN = 0,
/// \brief Windows 95, 98[se] or ME. (Not supported)
/// \sa LGetOs
LGI_OS_WIN9X,
/// \brief Windows 10+ 32bit. (Not supported)
/// \sa LGetOs
LGI_OS_WIN32,
/// \brief Windows 10+ 64bit. (Supported)
/// \sa LGetOs
LGI_OS_WIN64,
/// \brief BeOS/Haiku. (Somewhat supported)
/// \sa LGetOs
LGI_OS_HAIKU,
/// \brief Linux. (Kernels v2.4 and up supported)
/// \sa LGetOs
LGI_OS_LINUX,
/// \brief Mac OS X 10.15 or later. (Supported)
/// \sa LGetOs
LGI_OS_MAC_OS_X,
/// One higher than the maximum OS define
LGI_OS_MAX,
};
// Edge types
enum LEdge
{
EdgeNone,
EdgeXpSunken,
EdgeXpRaised,
EdgeXpChisel,
EdgeXpFlat,
EdgeWin7FocusSunken,
EdgeWin7Sunken,
};
#define DefaultSunkenEdge EdgeWin7Sunken
#define DefaultRaisedEdge EdgeXpRaised
// Cursors
enum LCursor
{
/// Blank/invisible cursor
LCUR_Blank,
/// Normal arrow
LCUR_Normal,
/// Upwards arrow
LCUR_UpArrow,
/// Downwards arrow
LCUR_DownArrow,
/// Left arrow
LCUR_LeftArrow,
/// Right arrow
LCUR_RightArrow,
/// Crosshair
LCUR_Cross,
/// Hourglass/watch
LCUR_Wait,
/// Ibeam/text entry
LCUR_Ibeam,
/// Vertical resize (|)
LCUR_SizeVer,
/// Horizontal resize (-)
LCUR_SizeHor,
/// Diagonal resize (/)
LCUR_SizeBDiag,
/// Diagonal resize (\)
LCUR_SizeFDiag,
/// All directions resize
LCUR_SizeAll,
/// Vertical splitting
LCUR_SplitV,
/// Horziontal splitting
LCUR_SplitH,
/// A pointing hand
LCUR_PointingHand,
/// A slashed circle
LCUR_Forbidden,
/// Copy Drop
LCUR_DropCopy,
/// Copy Move
LCUR_DropMove,
};
// General Event Flags
#define LGI_EF_LCTRL (1 << 0)
#define LGI_EF_RCTRL (1 << 1)
#define LGI_EF_CTRL (LGI_EF_LCTRL | LGI_EF_RCTRL)
#define LGI_EF_LALT (1 << 2)
#define LGI_EF_RALT (1 << 3)
#define LGI_EF_ALT (LGI_EF_LALT | LGI_EF_RALT)
#define LGI_EF_LSHIFT (1 << 4)
#define LGI_EF_RSHIFT (1 << 5)
#define LGI_EF_SHIFT (LGI_EF_LSHIFT | LGI_EF_RSHIFT)
#define LGI_EF_DOWN (1 << 6)
#define LGI_EF_DOUBLE (1 << 7)
#define LGI_EF_CAPS_LOCK (1 << 8)
#define LGI_EF_IS_CHAR (1 << 9)
#define LGI_EF_IS_NOT_CHAR (1 << 10)
#define LGI_EF_SYSTEM (1 << 11) // Windows key/Apple key etc
// Mouse Event Flags
#define LGI_EF_LEFT (1 << 16)
#define LGI_EF_MIDDLE (1 << 17)
#define LGI_EF_RIGHT (1 << 18)
#define LGI_EF_MOVE (1 << 19)
#define LGI_EF_XBTN1 (1 << 20)
#define LGI_EF_XBTN2 (1 << 21)
// Emit compiler warnings
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __LOC__ __FILE__ "(" __STR1__(__LINE__) ") : Warning: "
// To use just do #pragma message(__LOC__"My warning message")
// Simple definition of breakable unicode characters
#define LGI_BreakableChar(c) ( \
(c) == '\n' || \
(c) == ' ' || \
(c) == '\t' || \
( (c) >= 0x3040 && (c) <= 0x30FF ) || \
( (c) >= 0x3300 && (c) <= 0x9FAF ) \
)
// Os metrics
enum LSystemMetric
{
/// Get the standard window horizontal border size
/// \sa LApp::GetMetric()
LGI_MET_DECOR_X = 1,
/// Get the standard window vertical border size including caption bar.
/// \sa LApp::GetMetric()
LGI_MET_DECOR_Y,
/// Get the standard window caption bar height only.
/// \sa LApp::GetMetric()
LGI_MET_DECOR_CAPTION,
/// Get the height of a single line menu bar
/// \sa LApp::GetMetric()
LGI_MET_MENU,
/// This is non-zero if the system is theme aware
LGI_MET_THEME_AWARE,
/// Size of a window's shadow
LGI_MET_WINDOW_SHADOW,
};
/// \brief Types of system paths available for querying
/// \sa LgiGetSystemPath
enum LSystemPath
{
LSP_ROOT,
/// The location of the operating system folder
/// [Win32] = e.g. C:\Windows
/// [Mac] = /System
/// [Linux] /boot
LSP_OS,
/// The system library folder
/// [Win32] = e.g. C:\Windows\System32
/// [Mac] = /Library
/// [Linux] = /usr/lib
LSP_OS_LIB,
/// A folder for storing temporary files. These files are usually
/// deleted automatically later by the system.
/// [Win32] = ~\Local Settings\Temp
/// [Mac] = ~/Library/Caches/TemporaryItems
/// [Linux] = /tmp
LSP_TEMP,
/// System wide application data
/// [Win32] = ~\..\All Users\Application Data
/// [Mac] = /System/Library
/// [Linux] = /usr
LSP_COMMON_APP_DATA,
/// User specific application data
/// [Win32] = ~\Application Data
/// [Mac] = ~/Library
/// [Linux] = /usr
/// [Haiku] = ~/config (???)
LSP_USER_APP_DATA,
/// Machine + user specific application data (probably should not use)
/// [Win32] = ~\Local Settings\Application Data
/// [Mac] = ~/Library
/// [Linux] = /usr/local
LSP_LOCAL_APP_DATA,
/// Desktop dir
/// i.e. ~/Desktop
LSP_DESKTOP,
/// Home dir
/// i.e. ~
LSP_HOME,
/// Application install folder:
/// [Win] c:\Program Files
/// [Mac] /Applications
/// [Linux] /usr/bin
LSP_USER_APPS,
/// The running application's path.
/// [Mac] This doesn't include the "Contents/MacOS" part of the path inside the bundle.
LSP_EXE,
/// The system trash folder.
LSP_TRASH,
/// The app's install folder.
/// [Win32] = $ExePath (sans '\Release' or '\Debug')
/// [Mac/Linux] = $ExePath
/// Where $ExePath is the folder the application is running from
LSP_APP_INSTALL,
/// The app's root folder (Where config and data should be stored)
/// LOptionsFile uses LSP_APP_ROOT as the default location.
/// [Win32] = ~\Application Data\Roaming\$AppName
/// [Mac] = ~/Library/$AppName
/// [Linux] = ~/.$AppName
/// Where $AppName = LApp::GetName.
/// If the given folder doesn't exist it will be created.
LSP_APP_ROOT,
/// This is the user's documents folder
/// [Win32] ~\My Documents
/// [Mac] ~\Documents
LSP_USER_DOCUMENTS,
/// This is the user's music folder
/// [Win32] ~\My Music
/// [Mac] ~\Music
LSP_USER_MUSIC,
/// This is the user's video folder
/// [Win32] ~\My Videos
/// [Mac] ~\Movies
LSP_USER_VIDEO,
/// This is the user's download folder
/// ~\Downloads
LSP_USER_DOWNLOADS,
/// This is the user's links folder
/// [Win32] = ~\Links
/// [Mac] = ???
/// [Linux] = ???
LSP_USER_LINKS,
/// User's pictures/photos folder
LSP_USER_PICTURES,
/// [Win32] = C:\Users\%HOME%\Pictures
/// [Mac] = ???
/// [Linux] = ~\Pictures
LSP_MOUNT_POINT,
};
#ifdef _DEBUG
#define DeclDebugArgs , const char *_file, int _line
#define PassDebugArgs , __FILE__, __LINE__
#else
#define DeclDebugArgs
#define PassDebugArgs
#endif
#define _FL __FILE__, __LINE__
#define CALL_MEMBER_FN(obj, memFn) ((obj).*(memFn))
#include "lgi/common/AutoPtr.h"
#endif
diff --git a/src/linux/CrashHandler/CrashHandler.cpp b/src/linux/CrashHandler/CrashHandler.cpp
--- a/src/linux/CrashHandler/CrashHandler.cpp
+++ b/src/linux/CrashHandler/CrashHandler.cpp
@@ -1,425 +1,425 @@
#include
#include
#include
#include
#include
#include
#include
#define LAssert assert
#include "lgi/common/LgiDefs.h"
#include "lgi/common/Array.h"
#include "lgi/common/StringClass.h"
#define _FL __FILE__, __LINE__
enum HandleType
{
hRead,
hWrite,
hMax,
};
int in[hMax]; // app -> child pipe
int out[hMax]; // child -> app pipe
bool loop = true;
void LSleep(uint32_t i)
{
struct timespec request = {}, remain = {};
request.tv_sec = i / 1000;
request.tv_nsec = (i % 1000) * 1000000;
while (nanosleep(&request, &remain) == -1)
request = remain;
}
template
T *strnchr(T *str, char ch, size_t len)
{
if (!str)
return NULL;
T *end = str + len;
while (str < end)
{
if (*str == ch)
return str;
str++;
}
return NULL;
}
enum AppState
{
sInit,
sFrameSwitch,
sLocals,
sArgs,
sList,
sGetThreads,
sThreadSwitch,
sThreadBt,
} state = sInit;
LString::Array *output = NULL;
int curThread = 1, threads = -1;
FILE *crashLog = NULL;
void Log(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
char buf[1024];
auto ch = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
if (ch > 0)
{
printf("%.*s", (int)ch, buf);
if (crashLog)
fwrite(buf, ch, 1, crashLog);
}
}
void OpenCrashLog()
{
if (crashLog)
return;
time_t now;
time(&now);
auto cur = localtime(&now);
char file[256] = "crash.log";
if (cur)
snprintf(file, sizeof(file),
- "crash-%i%02.2i%02.2i-%02.2i%02.2i%02.2i.log",
+ "crash-%i%2.2i%2.2i-%2.2i%2.2i%2.2i.log",
cur->tm_year + 1900,
cur->tm_mon + 1,
cur->tm_mday,
cur->tm_hour,
cur->tm_min,
cur->tm_sec);
crashLog = fopen(file, "w");
}
void DumpOutput(const char *Label)
{
Log("%s:\n", Label);
for (auto ln: *output)
{
if (ln.Find("(gdb)") < 0)
Log(" %s\n", ln.Get());
}
Log("\n");
output->Length(0);
}
/*
Basic state flow:
sInit
sGetThreads # display all the threads
for each thread:
sThreadBt # back trace the thread
sThreadSwitch # display back trace and check for crashed frame
if has crash frame:
sFrameSwitch # get to the right frame...
sLocals # display the locals
sArgs # display any function args
sList # list the source code around the crash point
*/
void AtPrompt()
{
auto GotoNextThread = [&]()
{
if (curThread <= threads)
{
// Check out the next thread...
char cmd[256];
auto cmdSz = snprintf(cmd, sizeof(cmd), "thread %i\n", curThread);
int wr = write(in[hWrite], cmd, cmdSz);
state = sThreadBt;
}
else loop = false;
};
switch (state)
{
case sInit:
{
/*
First thing is to look through all the threads and find the one that crashed...
No point dumping locals and args from the thread that didn't crash.
*/
auto cmd = "info threads\n";
int wr = write(in[hWrite], cmd, strlen(cmd));
state = sGetThreads;
output = new LString::Array;
OpenCrashLog();
break;
}
case sFrameSwitch:
{
DumpOutput("Frame");
// Then start dumping out the locals and args...
auto cmd = "info locals\n";
auto wr = write(in[hWrite], cmd, strlen(cmd));
state = sLocals;
break;
}
case sLocals:
{
DumpOutput("Locals");
auto cmd = "info args\n";
int wr = write(in[hWrite], cmd, strlen(cmd));
state = sArgs;
break;
}
case sArgs:
{
DumpOutput("Args");
auto cmd = "list\n";
int wr = write(in[hWrite], cmd, strlen(cmd));
state = sList;
break;
}
case sList:
{
DumpOutput("List");
// If there are more threads... go back trace them
GotoNextThread();
break;
}
case sGetThreads:
{
LString last;
for (int i=output->Length()-1; i>=0; i--)
{
last = (*output)[i].Strip();
if (isdigit(last(0)))
{
threads = (int)last.Int();
break;
}
}
DumpOutput("Threads");
output->Length(0);
if (threads > 0)
{
GotoNextThread();
}
else
{
Log("%s:%i - Error: failed to get thread count.\n", _FL);
loop = false;
}
break;
}
case sThreadSwitch:
{
bool hasCrash = false;
int crashFrame = -1;
if (output->Length() > 0)
{
char label[64];
snprintf(label, sizeof(label), "Thread %i", curThread++);
// Scan through the output and look for some crash indication
int curFrame = -1;
for (unsigned i=0; iLength(); i++)
{
auto ln = (*output)[i];
auto s = ln.Strip();
if (s.Length() && s(0) == '#')
curFrame = s.SplitDelimit()[0].Strip("#").Int();
if (ln.Find("LgiCrashHandler") >= 0 ||
ln.Find("signal handler called") >= 0)
{
hasCrash = true;
crashFrame = curFrame + 1;
}
}
DumpOutput(label);
}
char cmd[256];
if (hasCrash && crashFrame >= 0)
{
// Switch to the crashing frame here...
auto cmdSz = snprintf(cmd, sizeof(cmd), "frame %i\n", crashFrame);
int wr = write(in[hWrite], cmd, cmdSz);
state = sFrameSwitch;
}
else
{
// Check out the next thread...
GotoNextThread();
}
break;
}
case sThreadBt:
{
auto cmd = "bt\n";
int wr = write(in[hWrite], cmd, strlen(cmd));
state = sThreadSwitch;
output->Length(0);
break;
}
}
}
void OnLine(char *str)
{
// printf("line='%s'\n", str);
if (output)
output->Add(str);
if (!strcasecmp(str, "(gdb) "))
AtPrompt();
}
int main(int argCount, char **arg)
{
int pid = -1;
for (int i=1; i 0)
{
memmove(buf, nl, remaining);
used = remaining;
// printf("rem=%i used=%i\n", (int)remaining, (int)used);
}
else
{
used = 0;
// printf("break used=%i\n", (int)used);
break;
}
}
if (used > 0)
{
buf[used] = 0;
OnLine(buf);
used = 0;
}
// printf("\n");
}
if (crashLog)
fclose(crashLog);
return 0;
}
diff --git a/src/linux/CrashHandler/CrashHandlerMakefile.linux b/src/linux/CrashHandler/CrashHandlerMakefile.linux
--- a/src/linux/CrashHandler/CrashHandlerMakefile.linux
+++ b/src/linux/CrashHandler/CrashHandlerMakefile.linux
@@ -1,80 +1,85 @@
#!/usr/bin/make
#
# This makefile generated by LgiIde
# http://www.memecode.com/lgi.php
#
.SILENT :
CC = gcc
CPP = g++
Target = ./crash-handler
ifndef Build
Build = Debug
endif
+MakeDir := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
BuildDir = $(Build)
-Flags = -fPIC -w -fno-inline -fpermissive
+CFlags = -MMD -MP -g -fPIC -fno-inline
+CppFlags = $(CFlags) -fpermissive -std=c++14
ifeq ($(Build),Debug)
- Flags += -g -std=c++14
+ CFlags += -g
+ CppFlags += -g
Tag = d
Defs = -D_DEBUG -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX
Libs =
Inc = \
`pkg-config --cflags gtk+-3.0` \
-I../../../include/lgi/linux/Gtk \
-I../../../include
else
- Flags += -s -Os -std=c++14
+ CFlags += -s -Os
+ CppFlags += -s -Os
Defs = -DLINUX -D_REENTRANT -D_FILE_OFFSET_BITS=64 -DPOSIX
Libs =
Inc = \
`pkg-config --cflags gtk+-3.0` \
-I../../../include/lgi/linux/Gtk \
-I../../../include
endif
# Dependencies
Source = CrashHandler.cpp
-SourceLst := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(Source)))
+SourceC := $(filter %.c,$(Source))
+ObjectsC := $(SourceC:.c=.o)
+SourceCpp := $(filter %.cpp,$(Source))
+ObjectsCpp := $(SourceCpp:.cpp=.o)
+Objects := $(notdir $(ObjectsC) $(ObjectsCpp))
+Objects := $(addprefix $(BuildDir)/,$(Objects))
+Deps := $(patsubst %.o,%.d,$(Objects))
-Objects := $(addprefix $(BuildDir)/,$(SourceLst))
+$(BuildDir)/%.o: %.c
+ mkdir -p $(@D)
+ echo $(notdir $<) [$(Build)]
+ $(CC) $(Inc) $(CFlags) $(Defs) -c $< -o $@
+
+$(BuildDir)/%.o: %.cpp
+ mkdir -p $(@D)
+ echo $(notdir $<) [$(Build)]
+ $(CPP) $(Inc) $(CppFlags) $(Defs) -c $< -o $@
# Target
# Executable target
$(Target) : $(Objects)
mkdir -p $(BuildDir)
@echo Linking $(Target) [$(Build)]...
$(CPP) -Wl,-export-dynamic,-R. -o \
$(Target) $(Objects) $(Libs)
@echo Done.
-.SECONDEXPANSION:
-$(Objects): $(BuildDir)/%.o: $$(wildcard %.c*)
- mkdir -p $(@D)
- @echo $(