Skip to content

Instantly share code, notes, and snippets.

@gvanem
Last active August 2, 2018 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gvanem/e8d2db10aa6899c752e5df032fd66785 to your computer and use it in GitHub Desktop.
Save gvanem/e8d2db10aa6899c752e5df032fd66785 to your computer and use it in GitHub Desktop.
A GNU-makefile for GNU-make. Targets MinGW, MSVC and clang-cl. Needs trace.c too (see below). Get the sources at git://git.sv.gnu.org/make.git. Apply the below '*.diff' files to check for mem-leaks
--- a/src/main.c 2018-08-02 05:02:30
+++ b/main.c 2018-08-02 18:19:25
@@ -827,6 +827,8 @@
#endif /* NO_OUTPUT_SYNC */
+#ifndef MAKE_MAINTAINER_MODE
+
/*
* HANDLE runtime exceptions by avoiding a requestor on the GUI. Capture
* exception and print it to stderr instead.
@@ -901,6 +903,7 @@
return (255); /* not reached */
#endif
}
+#endif /* MAKE_MAINTAINER_MODE */
/*
* On WIN32 systems we don't have the luxury of a /bin directory that
@@ -1070,7 +1073,17 @@
const char *unix_path = NULL;
const char *windows32_path = NULL;
+ crtdbug_init();
+
+#ifndef MAKE_MAINTAINER_MODE
+ /*
+ * If '-DMAKE_MAINTAINER_MODE' is *not* set, all 'abort()' calls are
+ * disabled via 'define NDEBUG' (makeint.h). Hence in 'MAKE_MAINTAINER_MODE'
+ * an 'abort()' would trigger very little useful 'handle_runtime_exceptions()'
+ * function. Just let 'abort()' give a better trace-back.
+ */
SetUnhandledExceptionFilter (handle_runtime_exceptions);
+#endif
/* start off assuming we have no shell */
unixy_shell = 0;
@@ -3499,5 +3512,9 @@
}
}
+#ifdef WINDOWS32
+ crtdbug_exit();
+#endif
+
exit (status);
}
#
# GNU Make to generate GNU Make (gnumake.exe) using
# either MinGW gcc, MinGW64-TDM gcc, clang-CL or MSVC cl.
#
# By G. Vanem <gvanem@yahoo.no> 2013.
#
VERSION := $(shell grep AC_INIT ../configure.ac | cut -d']' -f2 | sed -e 's/,\[//g')
DATE := $(shell date +%d-%B-%Y)
DEST_BIN = $(realpath $(MINGW32)/bin)
DEST_MAN1 = $(realpath $(MINGW32)/share/man/man1)
DEST_PDF = $(realpath $(MINGW32)/share/doc)
THIS_FILE = $(firstword $(MAKEFILE_LIST))
#
# Some Gnulib files are required to build:
# $(GNULIB_ROOT)/lib/getloadavg.c
# $(GNULIB_ROOT)/lib/intprops.h
#
# See below.
#
GNULIB_ROOT ?= ../../Gnulib
#
# Comment out this in order NOT to rebuild when $(THIS_FILE) changes.
#
MDEPEND = $(THIS_FILE)
#
# If your $(CC) can target 64-bits Windows, set "USE_WIN64=1" on cmd-line.
# In case of TDM-gcc, it is assumed it's on PATH.
# Same for 64-bit version of MSVC.
#
USE_WIN64 ?= 0
VPATH = ../lib w32 w32/subproc w32/compat
ifeq ($(USER),gv)
space :=
COMMENT = $(space) by <gvanem@yahoo.no>
endif
define Usage
Say "make -f $(THIS_FILE) [CC=xx] <USE_WIN64=1> [all | clean | vclean | depend | check | install]"
Specify CC=gcc - use MinGW
Specify CC=cl - use MSVC
Specify CC=clang-cl - use clang-cl
endef
#
# Choose your weapons:
# libintl.h and intl.lib (or libintl.a) must be in %INCLUDE and %LIB paths.
#
CRT_DEBUG = 0
ALL_WARNINGS = 0
ENABLE_NLS = 0
HAVE_GUILE = 0
HAVE_CYGWIN_SHELL = 1
USE_WINKIT = 0
#
# The import-lib created by the link-step of gnumake.exe.
# Used by .DLLs loaded within Makefiles by the "load" keyword.
#
ifeq ($(CC),gcc)
IMPLIB = ./libgnumake-1.dll.a
EXT_LIBS = -luser32 -ladvapi32
CFLAGS = -Wall -O2 -g
LDFLAGS = $($(CRT_DEBUG:0=-s):1)
LDFLAGS += -Wl,--subsystem,console
O = o
OBJ_DIR = MinGW_obj
HOST = MinGW
ifeq ($(USE_WIN64),1)
CFLAGS += -m64
LDFLAGS += -m64
RCFLAGS = --target=pe-x86-64
else
CFLAGS += -m32
LDFLAGS += -m32
RCFLAGS = --target=pe-i386
endif
ifeq ($(ALL_WARNINGS),0)
CFLAGS += -Wno-unused-label \
-Wno-unused-value \
-Wno-unused-variable \
-Wno-parentheses \
-Wno-format
endif
else ifeq ($(CC),cl)
CFLAGS = -W2 -Fp./gnumake.pch
OBJ_DIR = MSVC_obj
HOST = MSVC
else ifeq ($(CC),clang-cl)
CFLAGS = -Wall
#
# In case %CL is set, undefine it since clang-cl may not like what's in it.
#
export CL=
ifeq ($(ALL_WARNINGS),0)
#
# Warning control, lots of them
#
CFLAGS += -Wno-undef \
-Wno-unknown-warning-option \
-Wno-reserved-id-macro \
-Wno-language-extension-token \
-Wno-float-equal \
-Wno-bad-function-cast \
-Wno-cast-align \
-Wno-cast-qual \
-Wno-dangling-else \
-Wno-sign-conversion \
-Wno-sign-compare \
-Wno-missing-prototypes \
-Wno-missing-noreturn \
-Wno-deprecated-declarations \
-Wno-unused-parameter \
-Wno-unused-variable \
-Wno-unused-label \
-Wno-unused-macros \
-Wno-format \
-Wno-format-non-iso \
-Wno-format-security \
-Wno-format-pedantic \
-Wno-format-nonliteral \
-Wno-unreachable-code-return \
-Wno-unreachable-code-break \
-Wno-conversion \
-Wno-switch-enum \
-Wno-strict-prototypes \
-Wno-covered-switch-default \
-Wno-conditional-uninitialized \
-Wno-missing-variable-declarations \
-Wno-nonportable-system-include-path \
-Wno-incompatible-pointer-types-discards-qualifiers
endif
OBJ_DIR = CLANG_obj
HOST = clang-cl
else ifneq ($(firstword $(MAKECMDGOALS)),test_dll)
$(error $(Usage))
endif
#
# Stuff common to 'cl' and 'clang-cl'.
#
ifneq ($(CC),gcc)
USE_WIN64 = 0
IMPLIB = ./libgnumake-1.lib
EXT_LIBS = user32.lib advapi32.lib
CFLAGS += -nologo -GF -DWIN32 -D_CRT_NONSTDC_NO_WARNINGS
ifeq ($(CRT_DEBUG),1)
CFLAGS += -MTd -Od -GS -EHsc -RTCs -RTCu -RTCc -D_DEBUG=1 -DDEBUG=1
CFLAGS += -FI./config.h -DMAKE_MAINTAINER_MODE=1
RCFLAGS = -D_DEBUG
else
CFLAGS += -MT -Ot # -Gr
RCFLAGS = -D_RELEASE
endif
ifeq ($(USE_WINKIT),1)
CFLAGS += -DNO_OUTPUT_SYNC
endif
LDFLAGS = -nologo -debug -map -incremental:no -verbose
#
# Enable gnumake.exe to be used on Win-XP SP3 (5.1) in case
# it was built under Win-Vista+
#
LDFLAGS += -subsystem:console,5.01
O = obj
endif
ifeq ($(USE_WIN64),1)
RCFLAGS += -DBITS=64
else
RCFLAGS += -DBITS=32
endif
ifeq ($(HAVE_CYGWIN_SHELL),1)
CFLAGS += -DHAVE_CYGWIN_SHELL -DHAVE_MKS_SHELL
endif
ifeq ($(HAVE_GUILE),1)
CFLAGS += -DHAVE_GUILE
endif
ifeq ($(ENABLE_NLS),1)
CFLAGS += -DENABLE_NLS=1
ifeq ($(CC),gcc)
EXT_LIBS += libintl.a
else
EXT_LIBS += intl.lib
endif
else
CFLAGS += -DENABLE_NLS=0
endif
CFLAGS += -DHAVE_CONFIG_H -I. -I../lib -I./w32/include
SOURCES = ar.c \
arscan.c \
commands.c \
default.c \
dir.c \
expand.c \
file.c \
function.c \
getopt.c \
getopt1.c \
guile.c \
hash.c \
implicit.c \
job.c \
load.c \
loadapi.c \
main.c \
misc.c \
output.c \
read.c \
remake.c \
remote-stub.c \
rule.c \
signame.c \
strcache.c \
variable.c \
version.c \
vpath.c
SOURCES += ../lib/fnmatch.c \
../lib/getloadavg.c \
../lib/glob.c \
w32/compat/posixfcn.c \
w32/pathstuff.c \
w32/w32os.c \
w32/subproc/sub_proc.c \
w32/subproc/w32err.c
#
# Add dirent.c for MSVC or clang-cl
#
ifneq ($(CC),gcc)
SOURCES += w32/compat/dirent.c
endif
OBJ_FILES = $(addprefix $(OBJ_DIR)/, \
w32misc.$(O) $(notdir $(SOURCES:.c=.$(O))))
OBJ_FILES += $(OBJ_DIR)/win-misc.$(O)
GENERATED = config.h \
dmalloc.h \
$(addprefix ../lib/, \
fnmatch.h \
glob.h \
getloadavg.c \
intprops.h)
#################################################################
all: message $(OBJ_DIR) $(GENERATED) gnumake.exe mk_test.dll
@echo 'Welcome to gnumake.exe and mk_test.dll.'
@echo 'Now you can do "set GNUMAKEFLAGS=--debug & gnumake.exe -f $(THIS_FILE) test_dll".'
message:
@echo 'Building GNU Make ver. $(VERSION) ($(HOST)).'
install: gnumake.exe ../doc/make.1 ../doc/make.pdf
cp --update gnumake.exe $(DEST_BIN)/make.exe
cp --update ../doc/make.1 $(DEST_MAN1)
cp --update ../doc/make.pdf $(DEST_PDF)
../doc/make.1 ../doc/make.pdf:
$(MAKE) -f Makefile.Windows -C ../doc all
.PHONY: check check_vars check_variant
check: check_vars check_variant
check_vars:
@echo '$$(CFLAGS): $(CFLAGS)'
@echo '$$(LDFLAGS): $(LDFLAGS)'
@echo '$$(OBJ_DIR): $(OBJ_DIR)'
@echo '$$(MAKE): $(MAKE)'
@echo '$$(SHELL): $(SHELL)'
@echo '$$(THIS_FILE): $(THIS_FILE)'
@echo '$$(MAKEFLAGS): $(MAKEFLAGS)'
@echo '$$(MAKECMDGOALS): $(MAKECMDGOALS)'
@echo '$$(DEST_BIN): $(DEST_BIN)'
@echo '$$(DEST_MAN1): $(DEST_MAN1)'
@echo '$$(.VARIABLES): $(.VARIABLES)'
IS_GNU = $(firstword $(shell $(MAKE) --version))
check_variant:
@echo '$$(IS_GNU): $(IS_GNU)'
ifneq ($(IS_GNU),GNU)
$(error 'Not using GNU make')
endif
config.h: $(MDEPEND) $(OBJ_DIR) ../configure.ac
$(call Generate,$@,$(CONFIG_H))
dmalloc.h: $(MDEPEND) $(OBJ_DIR)
$(call Generate,$@,$(DMALLOC_H))
../lib/glob.h:
cp --update ../lib/glob.in.h $@
../lib/fnmatch.h:
cp --update ../lib/fnmatch.in.h $@
#
# Simply copy these from Gnulib
#
../lib/getloadavg.c:
cp --update $(GNULIB_ROOT)/lib/getloadavg.c $@
../lib/intprops.h:
cp --update $(GNULIB_ROOT)/lib/intprops.h $@
$(OBJ_DIR):
- mkdir $@
$(IMPLIB): gnumake.exe
ifeq ($(CC),gcc)
gnumake.exe: $(OBJ_FILES) $(OBJ_DIR)/gnumake.res
gcc $(LDFLAGS) -o $@ $^ -Wl,--out-implib=$(IMPLIB) $(EXT_LIBS)
@echo
else
gnumake.exe: $(OBJ_FILES) $(OBJ_DIR)/gnumake.res
link $(LDFLAGS) -out:$@ $^ -implib:$(IMPLIB) $(EXT_LIBS) > link.tmp
cat link.tmp >> gnumake.map
rm -f link.tmp $(IMPLIB:.lib=.exp)
@echo
endif
#
# "load" is a new feature in this 'gnumake.exe' (version 3.99+).
# Since Windows doesn't allow overwriting the .exe file of the
# current process (gnumake.exe), we MUST use an older make
# (e.g. mingw32-make) to link this newer 'gnumake.exe'.
#
ifeq ($(findstring load,$(.FEATURES)),load)
-load mk_test.dll
VAR1 = $(hello_world "Hello world. Loaded modules: '$(.LOADED)'. FEATURES: '$(.FEATURES)'. Make version: '$(MAKE_VERSION)'")
VAR2 = $(hello_world Hello, 2nd arg, 3rd arg)
test_dll:
@echo '1) Function "$$(hello_world)": $(VAR1)'
@echo '2) Function "$$(hello_world)": $(VAR2)'
@echo '3) Loaded modules: "$(.LOADED)".'
@echo '4) Features: "$(.FEATURES)".'
#
# Test the new TTY internal variables.
#
test_tty:
@echo '$$(MAKE_TERMOUT): $(MAKE_TERMOUT)'
@echo '$$(MAKE_TERMERR): $(MAKE_TERMERR)'
endif
define Generate
$(info Generating $(1))
$(file > $(1), /*)
$(file >> $(1), * $(1): Generated from $(realpath $(THIS_FILE)) at $(DATE).)
$(file >> $(1), * DO NOT EDIT.)
$(file >> $(1), */)
$(file >> $(1),$(2))
endef
mk_test.dll: $(IMPLIB) $(MDEPEND) $(OBJ_DIR)/win-misc.$(O)
$(call Generate,mk_test.c,$(MK_TEST_C))
ifeq ($(CC),gcc)
$(CC) $(CFLAGS) $(LDFLAGS) -shared mk_test.c $(OBJ_DIR)/win-misc.$(O) -o $@ $(IMPLIB)
else
$(CC) -c $(CFLAGS) -Fo./mk_test.$(O) mk_test.c
link $(LDFLAGS) -dll -out:$@ mk_test.$(O) $(OBJ_DIR)/win-misc.$(O) $(IMPLIB) > link.tmp
cat link.tmp >> mk_test.map
rm -f link.tmp mk_test.exp mk_test.lib
endif
$(OBJ_DIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
@echo
$(OBJ_DIR)/%.obj: %.c
$(CC) -c $(CFLAGS) -Fo./$@ $<
@echo
$(OBJ_DIR)/w32misc.o: w32/subproc/misc.c $(GENERATED)
$(CC) -c $(CFLAGS) -o $@ $<
@echo
$(OBJ_DIR)/w32misc.obj: w32/subproc/misc.c $(GENERATED)
$(CC) -c $(CFLAGS) -Fo./$@ $<
@echo
MSVC_obj/gnumake.res: $(MDEPEND) ../configure.ac gnumake.ico
$(call Generate,$(OBJ_DIR)/gnumake.rc,$(GNUMAKE_RC))
rc -nologo -D_MSC_VER $(RCFLAGS) -Fo $@ $(OBJ_DIR)/gnumake.rc
CLANG_obj/gnumake.res: $(MDEPEND) ../configure.ac gnumake.ico
$(call Generate,$(OBJ_DIR)/gnumake.rc,$(GNUMAKE_RC))
rc -nologo -D__clang__ $(RCFLAGS) -Fo $@ $(OBJ_DIR)/gnumake.rc
MinGW_obj/gnumake.res: $(MDEPEND) ../configure.ac gnumake.ico
$(call Generate,$(OBJ_DIR)/gnumake.rc,$(GNUMAKE_RC))
windres -v -I. -O COFF $(RCFLAGS) -o $@ $(OBJ_DIR)/gnumake.rc
clean:
rm -f MinGW_obj/* MSVC_obj/* CLANG_obj/* mk_test.* \
$(GENERATED) $(IMPLIB) gnumake.map gnumake.pdb gnumake.pch \
vc1*.pdb
vclean realclean: clean
- rm -f gnumake.exe .depend.MinGW .depend.MSVC .depend.clang-cl
- rmdir $(OBJ_DIR)
#
# Generate config.h here instead of using the
# 'config.h.W32.template' stuff.
#
define CONFIG_H
#ifndef _CONFIG_H
#define _CONFIG_H
#include <stdio.h>
#include <sys/types.h>
#include <windows.h>
#define WINDOWS32
#define _WINDOWS
#define VERSION "$(VERSION)"
#define MAKE_HOST "Windows32 ($(HOST))"
#if !defined(HAVE_CYGWIN_SHELL)
#define BATCH_MODE_ONLY_SHELL
#endif
#define _FILE_OFFSET_BITS 64
#define C_GETLOADAVG 1
#define FILE_TIMESTAMP_HI_RES 0
#define HAVE_CASE_INSENSITIVE_FS 1
//#define HAVE_ALLOCA_H 0
#define HAVE_ALLOCA 1
#define HAVE_ATEXIT 1
#define HAVE_DECL_BSD_SIGNAL 0
#define HAVE_DECL_SYS_SIGLIST 0
#define HAVE_DECL__SYS_SIGLIST 0
#define HAVE_DECL___SYS_SIGLIST 0
#define HAVE_DOS_PATHS 1
#define HAVE_DUP2 1
#define HAVE_DIRECT_H 1
#define HAVE_DIRENT_H 1 /* ./w32/include/dirent.h */
#define HAVE_FCNTL_H 1
#define HAVE_FDOPEN 1
#define HAVE_FILENO 1
#define HAVE_GETCWD 1
#define HAVE_ISATTY 1
#define HAVE_LIMITS_H 1
#define HAVE_LOCALE_H 1
#define HAVE_MEMORY_H 1
#define HAVE_MKTEMP 1
#define HAVE_SETVBUF 1
#define HAVE_STDINT_H 1
#define HAVE_STRCMPI 1
#define HAVE_STRCOLL 1
#define HAVE_STRDUP 1
#define HAVE_STRERROR 1
#define HAVE_STRICMP 1
#define HAVE_STRING_H 1
#define HAVE_STRNICMP 1
#define HAVE_SYS_STAT_H 1
#define HAVE_SYS_TIMEB_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_TTYNAME 1
#define HAVE_INTTYPES_H 1
extern char * ttyname (int fd);
#define MAKE_JOBSERVER 1
#define MAKE_LOAD 1
#define PACKAGE "make"
#define LOCALEDIR "."
#define PATH_SEPARATOR_CHAR ';'
#define RETSIGTYPE void
#define SCCS_GET "echo no sccs get"
#define STDC_HEADERS 1
#define gid_t int
#define uid_t int
#if defined(__MINGW32__)
#define HAVE_UNISTD_H 1
#define HAVE_GETTIMEOFDAY 1
#define HAVE_STRCASECMP 1
#define HAVE_STRNCASECMP 1
#define HAVE_SYS_PARAM_H 1
#define HAVE_SYS_TIME_H 1
#define TIME_WITH_SYS_TIME 1
#elif defined(_MSC_VER) /* Implies 'clang-cl' too */
#define pid_t INT_PTR
#define ssize_t int
#define HAVE_STRCASECMP 0
#define HAVE_STRNCASECMP 0
#define TIME_WITH_SYS_TIME 0
#define HAVE_SYS_TIME_H 0
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS /* function or variable may be unsafe */
#endif
#ifndef _CRT_NONSTDC_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS /* functions w/o a leading underscore */
#endif
#if defined(__clang__)
/*
* Use more gcc-like '-Wno-xx' warning supressors for 'clang-cl'.
* See above.
*/
#else
#pragma warning (disable:4100) /* unreferenced formal parameter */
#pragma warning (disable:4102) /* unreferenced label */
#pragma warning (disable:4127) /* conditional expression is constant */
#pragma warning (disable:4131) /* uses old-style declarator */
#pragma warning (disable:4702) /* unreachable code */
#endif
#endif
/* In win-misc.c
*/
extern void gmk_trace (const char *fmt, ...);
extern void gmk_set_colour (unsigned short col);
extern void crtdbug_init (void);
extern void crtdbug_exit (void);
#if defined(_MSC_VER) && defined(_DEBUG)
#include <malloc.h>
/* Avoid MSVC-9 <malloc.h>/<crtdbg.h> name-clash
*/
#undef _malloca
#define _CRTDBG_MAP_ALLOC
/* Just fake it. Ref. "makeint.h" and the generated "dmalloc.h"
*/
#define HAVE_DMALLOC_H
#include <crtdbg.h>
#endif
#endif /* _CONFIG_H */
endef
define DMALLOC_H
/*
* Fake <dmalloc.h> for MSVC/clang-cl.
* Refer "config.h" and '_CRTDBG_MAP_ALLOC' instead.
*/
endef
define MK_TEST_C
/*
* A simple test for loadable .DLLs in GnuMake.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gnumake.h"
#include "makeint.h" /* This includes "config.h" */
int handling_fatal_signal = 0;
#define EXPORT __declspec(dllexport)
EXPORT int plugin_is_GPL_compatible;
/* Simply echo back the given strings.
*/
static char *hello_world (const char *func_name, unsigned int argc, char **argv)
{
unsigned i, len = 1;
char *buf;
for (i = 0; i < argc; i++)
len += strlen (argv[i]);
buf = gmk_alloc (len);
*buf = '\0';
for (i = 0; i < argc; i++)
{
gmk_trace ("argv[%d]: \"%s\"\n", i, argv[i]);
strcat (buf, argv[i]);
}
return (buf);
}
/* An '$$(info )' with colour support
* Sets green on default background.
*/
static char *_info2 (const char *func_name, unsigned int argc, char **argv)
{
gmk_set_colour (FOREGROUND_INTENSITY | 2);
puts (*argv);
gmk_set_colour (0);
return (NULL);
}
/*
* Sets bright yellow on default background.
*/
static char *_info3 (const char *func_name, unsigned int argc, char **argv)
{
gmk_set_colour (FOREGROUND_INTENSITY | 6);
puts (*argv);
gmk_set_colour (0);
return (NULL);
}
static char *_set_colour (const char *func_name, unsigned int argc, char **argv)
{
const char *arg;
int i;
for (i = 0; i < argc; i++)
gmk_trace ("argv[%d]: \"%s\"\n", i, argv[i]);
if (argc != 1)
return ("");
arg = argv[0];
while (*arg == ' ' || *arg == '\t')
arg++;
gmk_trace ("arg: \"%s\"\n", arg);
if (!strcmp(arg, "green"))
gmk_set_colour (FOREGROUND_INTENSITY | 2);
else if (!strcmp(arg, "white"))
gmk_set_colour (FOREGROUND_INTENSITY | 7);
else if (!strcmp(arg, "yellow"))
gmk_set_colour (FOREGROUND_INTENSITY | 6);
else if (!strcmp(arg, "0") || !strcmp(arg, "off") || !strcmp(arg, "default"))
gmk_set_colour (0);
fflush (stdout);
return ("");
}
EXPORT int mk_test_gmk_setup (const gmk_floc *flocp)
{
gmk_trace ("\"%s()\" called from %s (%lu)\n",
__FUNCTION__, flocp->filenm, flocp->lineno);
gmk_add_function ("hello_world", hello_world, 0, 255, GMK_FUNC_DEFAULT);
gmk_add_function ("set_colour", _set_colour, 1, 1, GMK_FUNC_NOEXPAND);
gmk_add_function ("set_color", _set_colour, 1, 1, GMK_FUNC_NOEXPAND);
gmk_add_function ("info2", _info2, 1, 1, GMK_FUNC_DEFAULT);
gmk_add_function ("info3", _info3, 1, 1, GMK_FUNC_DEFAULT);
#if 0
printf ("batch_mode_shell = %d; forcing it to 1\n", batch_mode_shell);
batch_mode_shell = 1;
#endif
/* "If the return value is -1, then GNU make will not attempt to rebuild the
* object file".
*/
return (-1);
}
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
gmk_trace ("dwReason == DLL_PROCESS_ATTACH.\n");
break;
case DLL_PROCESS_DETACH:
gmk_trace ("dwReason == DLL_PROCESS_DETACH.\n");
break;
case DLL_THREAD_ATTACH:
gmk_trace ("DLL_THREAD_ATTACH. hinstDLL: 0x%lX, thr-id: %lu.\n",
hinstDLL, GetCurrentThreadId());
break;
case DLL_THREAD_DETACH:
gmk_trace ("DLL_THREAD_DETACH. hinstDLL: 0x%lX, thr-id: %lu.\n",
hinstDLL, GetCurrentThreadId());
break;
}
(void) lpvReserved;
return (TRUE);
}
endef
comma := ,
define GNUMAKE_RC
#include <winver.h>
#include "config.h"
#define RC_VERSION $(subst .,$(comma),$(VERSION)),0
/* Ripped from:
* http://en.wikipedia.org/wiki/File:Heckert_GNU_white.svg
* and converted to ICO-format and scaled to 30% using IrfanView.
*/
APPICON ICON "gnumake.ico"
VS_VERSION_INFO VERSIONINFO
FILEVERSION RC_VERSION
PRODUCTVERSION RC_VERSION
FILEFLAGSMASK 0x3fL
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0x0L
#define RC_DBG_REL ""
#if defined(BITS)
#if (BITS == 64)
#define RC_BITS_STR ", 64-bit"
#else
#define RC_BITS_STR ", 32-bit"
#endif
#else
#define RC_BITS_STR ""
#endif
#if defined(_DEBUG)
FILEFLAGS 1
#if defined(_MSC_VER) || defined(__clang__)
#undef RC_DBG_REL
#define RC_DBG_REL ", debug"
#endif
#else
FILEFLAGS 0
#if defined(_MSC_VER) || defined(__clang__)
#undef RC_DBG_REL
#define RC_DBG_REL ", release"
#endif
#endif
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "GNU, http://www.gnu.org/software/make/"
VALUE "FileDescription", "GNU Make ($(HOST)" RC_DBG_REL RC_BITS_STR ")"
VALUE "FileVersion", "$(VERSION)"
VALUE "InternalName", "GNU Make."
VALUE "LegalCopyright", "GNU GENERAL PUBLIC LICENSE: http://www.gnu.org/licenses/gpl.html"
VALUE "Comments", "Built on $(DATE)$(COMMENT)."
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
endef
#
# arg $(1): object-suffix.
# arg $(2): dependency file.
#
define make_deps
@echo 'Generating dependencies...'
@echo '# Generated dependencies at $(DATE). DO NOT EDIT' > $(1)
gcc -MM $(filter -D% -I%, $(CFLAGS)) $(SOURCES) | \
sed -e 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/\1$(strip $(1)): /' >> $(1)
@echo '' >> $(1)
@echo 'mk_test.c: win-misc.c gnumake.h' >> $(1)
@echo 'mk_test.$$(O): mk_test.c' >> $(1)
endef
depend: $(GENERATED)
$(call make_deps, .depend.$(HOST))
-include .depend.$(HOST)
--- a/makeint.h 2018-08-02 05:02:30
+++ b/makeint.h 2018-08-02 20:23:04
@@ -514,11 +514,22 @@
void pfatal_with_name (const char *) __attribute__ ((noreturn));
void perror_with_name (const char *, const char *);
#define xstrlen(_s) ((_s)==NULL ? 0 : strlen (_s))
-void *xmalloc (size_t);
-void *xcalloc (size_t);
-void *xrealloc (void *, size_t);
-char *xstrdup (const char *);
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+ #define xmalloc(sz) malloc (sz)
+ #define xcalloc(sz) calloc (sz, 1)
+ #define xrealloc(ptr,sz) realloc (ptr, sz)
+ #define xstrdup(str) strdup (str)
+
+#else
+ void *xmalloc (size_t);
+ void *xcalloc (size_t);
+ void *xrealloc (void *, size_t);
+ char *xstrdup (const char *);
+#endif
+
char *xstrndup (const char *, size_t);
+
char *find_next_token (const char **, size_t *);
/*
* A simple trace-function used in mk_test.dll etc.
* Effective only if "GNUMAKEFLAGS=-debug" is set.
*
* Maybe the 'gmk_x()' functions should be exported from 'gnumake.exe'?
* (present in libgnumake-1.lib').
*
* Also some dmalloc-like mem-leak detection code in below
*/
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include <windows.h>
#include "makeint.h"
static CONSOLE_SCREEN_BUFFER_INFO console_info;
static HANDLE stdout_hnd;
static CRITICAL_SECTION crit;
/* With gcc: p: 0022F2B0
* q: 0022F2A0 (diff=16)
*
* With MSVC (-MTd): p: 0012ED90
* q: 0012ED60 (diff=48)
* With MSVC (-MT): ...
*
*/
static void ugly_alloca_diff_test (void)
{
#if 0
const char *p = alloca (1);
const char *q = alloca (1);
printf (" p: %p\n"
" q: %p (diff=%d)\n", p, q, p-q);
#endif
}
void gmk_set_colour (unsigned short col)
{
fflush (stdout);
if (col == 0)
SetConsoleTextAttribute (stdout_hnd, console_info.wAttributes);
else SetConsoleTextAttribute (stdout_hnd, (console_info.wAttributes & ~7) | col);
}
void gmk_trace (const char *fmt, ...)
{
static int init = 0;
static int debug = 0;
if (!init)
{
const char *env = getenv ("GNUMAKEFLAGS");
if (env && strstr(env,"--debug"))
debug = 1;
#ifdef MAKE_MAINTAINER_MODE
debug = 1;
#endif
stdout_hnd = GetStdHandle (STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo (stdout_hnd, &console_info);
InitializeCriticalSection (&crit);
if (debug)
ugly_alloca_diff_test();
}
init = 1;
if (debug && fmt)
{
va_list args;
EnterCriticalSection (&crit);
va_start (args, fmt);
gmk_set_colour (FOREGROUND_INTENSITY | 2); /* bright green */
fputs (" **: ", stdout);
vfprintf (stdout, fmt, args);
gmk_set_colour (0);
LeaveCriticalSection (&crit);
va_end (args);
}
}
#if defined(_MSC_VER) && defined(_DEBUG)
/**
* Only one global mem-state.
*/
static _CrtMemState last_state;
/**
* In `_DEBUG`-mode, remember the `last_state` as the CRT-memory
* start-up state.
*
* \note
* Enable this for MSVC and clang-cl only.
*/
void crtdbug_init (void)
{
_HFILE file = _CRTDBG_FILE_STDERR;
int mode = _CRTDBG_MODE_FILE;
int flags = _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_DELAY_FREE_MEM_DF;
_CrtSetReportFile (_CRT_ASSERT, file);
_CrtSetReportMode (_CRT_ASSERT, mode);
_CrtSetReportFile (_CRT_ERROR, file);
_CrtSetReportMode (_CRT_ERROR, mode);
_CrtSetReportFile (_CRT_WARN, file);
_CrtSetReportMode (_CRT_WARN, mode);
_CrtSetDbgFlag (flags | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG));
_CrtMemCheckpoint (&last_state);
}
/**
* In `_DEBUG`-mode, compare the `last_state` set in `crtdbug_init()` to
* check if there is a significant difference in the mem-state.
*
* This function should be called as late as possible.
*/
void crtdbug_exit (void)
{
_CrtMemState new_state, diff_state;
if (handling_fatal_signal)
return;
_CrtMemCheckpoint (&new_state);
/* No significant difference in the mem-state. So just get out.
*/
if (!_CrtMemDifference(&diff_state, &last_state, &new_state))
{
gmk_trace ("No CRT memory leaks detected since crtdbug_init() was called.\n");
return;
}
_CrtCheckMemory();
//_CrtMemDumpAllObjectsSince (&last_state);
_CrtDumpMemoryLeaks();
gmk_trace ("CRT memory leaks detected.\n");
}
#if !defined(HAVE_DMALLOC_H)
#error "Add '-DHAVE_DMALLOC_H' for '_MSC_VER' and '_DEBUG'."
#endif
#else
/*
* NO-OPs
*/
void crtdbug_init (void)
{
}
void crtdbug_exit (void)
{
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment