Last active
August 2, 2018 21:14
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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 *); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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