Created
October 16, 2025 05:28
-
-
Save gvanem/d03dc7e49d87cf4290a9dbb811ee34c7 to your computer and use it in GitHub Desktop.
Makefile for NGrep
This file contains hidden or 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
| # | |
| # ngrep Makefile for Windows; MSVC + clang-cl | |
| # | |
| # Ref: https://github.com/jpr5/ngrep.git | |
| # | |
| THIS_FILE := Makefile.Windows | |
| TODAY := $(shell date +%d-%B-%Y) | |
| PYTHON := py -3 | |
| MAKEFLAGS += --warn-undefined-variables | |
| VCPKG_ROOT := $(realpath $(VCPKG_ROOT)) | |
| PCRE2_ROOT ?= $(VCPKG_ROOT)/installed/$(CPU)-windows-static | |
| PCAP_ROOT ?= f:/MinGW32/src/inet/libpcap | |
| NPCAP_ROOT ?= f:/MinGW32/src/inet/libpcap/NPcap | |
| LIBNET_ROOT ?= f:/MinGW32/src/inet/libnet | |
| INSTALL_ROOT := $(realpath $(VSINSTALLDIR)) | |
| MANPAGE_ROOT ?= f:/MinGW32/share/man | |
| USE_ASTYLE ?= 1 | |
| USE_PCRE2 ?= 1 | |
| USE_STATIC_PCAP ?= 0 | |
| USE_TCPKILL ?= 0 | |
| USE_TRACE ?= 0 | |
| USE_WSOCK_TRACE ?= 1 | |
| # | |
| # From 'ngrep.h': | |
| # | |
| VER_MAJOR = 1 | |
| VER_MINOR = 48 | |
| VER_MICRO = 0 | |
| VERSION = $(VER_MAJOR).$(VER_MINOR).$(VER_MICRO) | |
| define Usage | |
| Usage: "make -f $(THIS_FILE) CC=[cl | clang-cl] [all | clean | vclean | realclean | install]" | |
| Specify CC=cl - use MSVC | |
| Specify CC=clang-cl - use clang-cl | |
| endef | |
| # | |
| # Undefine these: | |
| # | |
| export CL= | |
| export C_INCLUDE_PATH= | |
| OBJ_DIR = objects | |
| CFLAGS = -nologo -MD -W3 -Zi \ | |
| -GS- -Gy -GF -Ob2 \ | |
| -Ox -Oy -Ot \ | |
| -I. \ | |
| -I./winXX/support \ | |
| -I./regex-0.12 \ | |
| -I./$(OBJ_DIR) \ | |
| -I$(PCAP_ROOT) \ | |
| -Fd./$(OBJ_DIR)/vc14x.pdb | |
| LDFLAGS = -nologo -verbose -incremental:no -debug -nodefaultlib:uuid.lib | |
| RCFLAGS = -nologo | |
| ifeq ($(CC),cl) | |
| RCFLAGS += -D_MSC_VER | |
| else ifeq ($(CC),clang-cl) | |
| RCFLAGS += -D__clang__ | |
| CFLAGS += -fms-compatibility \ | |
| -ferror-limit=5 | |
| else | |
| $(error $(Usage)) | |
| endif | |
| ifeq ($(USE_WSOCK_TRACE),1) | |
| WS2_32_LIB = wsock_trace-$(CPU).lib | |
| LDFLAGS += -nodefaultlib:ws2_32.lib | |
| else | |
| WS2_32_LIB = ws2_32.lib | |
| endif | |
| # | |
| # External libraries needed: | |
| # | |
| EX_LIBS = | |
| OS_LIBS = $(WS2_32_LIB) | |
| # | |
| # Make 'regex.c' shut-up about 'alloca()'. | |
| # | |
| CFLAGS += -FImalloc.h | |
| # | |
| # Do not use 'winXX/support/config.h' | |
| # | |
| CFLAGS += -Dwin32_CONFIG_H | |
| # | |
| # But this instead: | |
| # | |
| CFLAGS += -FI./$(OBJ_DIR)/config.h | |
| ifeq ($(USE_STATIC_PCAP),1) | |
| EX_LIBS += $(PCAP_ROOT)/lib/wpcap2_static-$(CPU).lib | |
| OS_LIBS += advapi32.lib iphlpapi.lib ntdll.lib shell32.lib version.lib winmm.lib | |
| else | |
| CFLAGS += -DPCAP_DLL | |
| EX_LIBS += $(PCAP_ROOT)/lib/wpcap-$(CPU).lib | |
| endif | |
| ifeq ($(USE_PCRE2),1) | |
| CFLAGS += -DUSE_PCRE2=1 -I$(PCRE2_ROOT)/include | |
| LDFLAGS += -nodefaultlib:libcmt.lib | |
| EX_LIBS += $(PCRE2_ROOT)/lib/pcre2-8.lib | |
| else | |
| CFLAGS += -DUSE_PCRE2=0 | |
| endif | |
| vpath %.c regex-0.12 \ | |
| winXX/support | |
| SOURCES = ngrep.c \ | |
| regex-0.12/regex.c \ | |
| winXX/support/getopt.c | |
| ifeq ($(USE_TCPKILL),1) | |
| CFLAGS += -DUSE_TCPKILL=1 \ | |
| -I$(LIBNET_ROOT)/include \ | |
| -I$(NPCAP_ROOT)/Common | |
| SOURCES += tcpkill.c | |
| EX_LIBS += $(LIBNET_ROOT)/lib/libnet_imp-$(CPU).lib | |
| endif | |
| ifeq ($(USE_TRACE),1) | |
| CFLAGS += -DUSE_TRACE | |
| SOURCES += trace.c | |
| endif | |
| OBJECTS = $(addprefix $(OBJ_DIR)/, \ | |
| $(notdir $(SOURCES:.c=.obj))) | |
| GENERATED = $(addprefix $(OBJ_DIR)/, \ | |
| config.h \ | |
| err.h \ | |
| unistd.h) | |
| all: $(GENERATED) bin/ngrep.exe epilogue | |
| epilogue: | |
| $(call green_msg, Welcome to ngrep/Win32 $(BRIGHT_WHITE)(VERSION=$(VERSION), CC=$(CC))) | |
| $(OBJ_DIR) bin: | |
| mkdir $@ | |
| bin/ngrep.exe: $(OBJECTS) $(EX_LIBS) $(OBJ_DIR)/ngrep.res | bin | |
| $(call link_EXE, $@, $^ $(OS_LIBS)) | |
| $(OBJ_DIR)/%.obj: %.c | $(GENERATED) | |
| $(call C_compile, $@, $<) | |
| $(OBJ_DIR)/%.res: $(OBJ_DIR)/%.rc | |
| rc $(RCFLAGS) -fo./$@ $< | |
| @echo | |
| $(OBJ_DIR)/config.h: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, //) | |
| $(file >> $@, $(NGREP_CONFIG_H)) | |
| $(OBJ_DIR)/err.h: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, //) | |
| $(file >> $@, $(ERR_H)) | |
| $(OBJ_DIR)/unistd.h: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, //) | |
| $(file >> $@, // Fake <unistd.h> for Windows) | |
| $(OBJ_DIR)/ngrep.rc: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, //) | |
| $(file >> $@, $(NGREP_RC)) | |
| %.i: %.c FORCE | $(GENERATED) $(OBJ_DIR)/cpp-filter.py | |
| $(call C_preprocess, $@, $<) | |
| FORCE: | |
| $(OBJ_DIR)/cpp-filter.py: $(THIS_FILE) | $(OBJ_DIR) | |
| $(call generate, $@, #) | |
| $(file >> $@,if 1:) | |
| $(file >> $@,$(CPP_FILTER_PY)) | |
| clean: | |
| rm -fr $(OBJ_DIR) | |
| rm -f link.tmp | |
| vclean realclean: clean | |
| rm -fr bin | |
| install: all | |
| cp --update bin/ngrep.exe bin/ngrep.pdb $(INSTALL_ROOT)/bin | |
| cp --update ngrep.8 $(MANPAGE_ROOT)/man8 | |
| # | |
| # GNU-make macros | |
| # | |
| BRIGHT_GREEN = \e[1;32m | |
| BRIGHT_WHITE = \e[1;37m | |
| colour_msg = @echo -e "$(1)\e[0m" | |
| green_msg = $(call colour_msg,$(BRIGHT_GREEN)$(strip $(1))) | |
| define C_compile | |
| $(CC) -c $(CFLAGS) -Fo./$(strip $(1) $(2)) | |
| @echo | |
| endef | |
| pp_filter = $(PYTHON) $(OBJ_DIR)/cpp-filter.py | |
| ifeq ($(USE_ASTYLE),1) | |
| pp_comment = The preprocessed and Astyled output of '$(strip $(1))' | |
| pp_filter += | astyle | |
| else | |
| pp_comment = The raw preprocessed output of '$(strip $(1))' | |
| endif | |
| define C_preprocess | |
| $(file > $(1),/* $(call pp_comment, $(2)):) | |
| $(file >> $(1), * $(CC) -E) | |
| $(foreach f, $(CFLAGS), $(file >> $(1), * $(f))) | |
| $(file >> $(1), *) | |
| $(file >> $(1), *---------------------------------------------------------) | |
| $(file >> $(1), */) | |
| $(CC) -E $(CFLAGS) $(2) | $(pp_filter) >> $(1) | |
| endef | |
| define generate | |
| $(call green_msg, Generating $(BRIGHT_WHITE)$(strip $(1))) | |
| $(file > $(1), $(2)) | |
| $(file > $(1), $(2) This file was generated by $(THIS_FILE) at $(TODAY).) | |
| $(file > $(1), $(2) DO NOT EDIT. YOUR CHANGED WILL BE LOST.) | |
| $(file > $(1), $(2)) | |
| endef | |
| define link_EXE | |
| $(file > $(OBJ_DIR)/check-for-unused-libs.py,if 1:) | |
| $(file >> $(OBJ_DIR)/check-for-unused-libs.py,$(CHECK_FOR_UNUSED_LIBS_PY)) | |
| $(call green_msg, Linking $(BRIGHT_WHITE)$(strip $(1))) | |
| link -out:$(strip $(1)) $(LDFLAGS) $(2) > link.tmp | |
| @cat link.tmp >> $(1:.exe=.map) | |
| @rm -f $(1:.exe=.lib) $(1:.exe=.exp) | |
| @$(PYTHON) $(OBJ_DIR)/check-for-unused-libs.py link.tmp | |
| endef | |
| define NGREP_CONFIG_H | |
| #pragma once | |
| #define _CRT_SECURE_NO_WARNINGS | |
| #define _CRT_NONSTDC_NO_WARNINGS | |
| #define _CRT_SECURE_NO_DEPRECATE | |
| /* | |
| * Warning control: | |
| */ | |
| #if defined(__clang__) | |
| #pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
| #pragma clang diagnostic ignored "-Wincompatible-pointer-types" | |
| #pragma clang diagnostic ignored "-Wnon-literal-null-conversion" | |
| #pragma clang diagnostic ignored "-Wunused-variable" | |
| #pragma clang diagnostic ignored "-Wunused-but-set-variable" | |
| #pragma clang diagnostic ignored "-Wdangling-else" | |
| #pragma clang diagnostic ignored "-Wvisibility" | |
| #pragma clang diagnostic ignored "-Wpointer-to-int-cast" | |
| #pragma clang diagnostic ignored "-Wint-to-pointer-cast" | |
| #pragma clang diagnostic ignored "-Wdeprecated-non-prototype" | |
| #elif defined(_MSC_VER) | |
| #pragma warning (disable: 4018 4047 4244 4267 4311 4312 4996) | |
| #endif | |
| /* | |
| * Just a test. | |
| */ | |
| #define USE_VLAN_HACK 1 | |
| /* | |
| * For 'regex-0.12/regex.c': | |
| */ | |
| #define HAVE_STRING_H 1 | |
| #define STDC_HEADERS 1 | |
| /* | |
| * For Winsock and 'inet_ntop()' | |
| */ | |
| #define _WIN32_WINNT 0x0601 | |
| #define USE_IPv6 1 | |
| #ifdef USE_TCPKILL | |
| /* | |
| * Ignore '$$(NPCAP_ROOT)/Common/npcap-bpf.h' | |
| */ | |
| #define NPCAP_BPF_H | |
| #endif | |
| /* Instead of patching 'ngrep.c' with '#ifdef DLT_RAW' etc. | |
| * just do this. A value '0' or '1' isn't important. | |
| * Only '0' or '>0' is. | |
| * | |
| * BUT, how the heck can we get a 'DLT_LINUX_SLL' from 'pcap_datalink()' | |
| * on Win32 anyway? AFAICS, the 3 first of these 'HAVE_x' should always | |
| * be set to '0'. | |
| */ | |
| #define HAVE_DLT_RAW (0+DLT_RAW) | |
| #define HAVE_DLT_LOOP (0+DLT_LOOP) | |
| #define HAVE_DLT_LINUX_SLL (0+DLT_LINUX_SLL) | |
| #define HAVE_DLT_IEEE802_11 (0+DLT_IEEE802_11) | |
| #define HAVE_DLT_IEEE802_11_RADIO (0+DLT_IEEE802_11_RADIO) | |
| #define USE_PCAP_RESTART 0 | |
| #define PCAP_RESTART_FUNC abort /* just in case some fubar is going on */ | |
| #if defined(USE_TRACE) | |
| /* | |
| * Trace printer controlled by env-var "set NGREP_TRACE=level": | |
| * Ref. 'trace.c' | |
| */ | |
| #define TRACE(level, fmt, ...) \ | |
| do { \ | |
| if (trace_level() >= level) \ | |
| trace_printf (__FILE__, __LINE__, fmt, ## __VA_ARGS__); \ | |
| } while (0) | |
| int trace_level (void); | |
| void trace_printf (const char *file, unsigned line, const char *fmt, ...); | |
| #else | |
| #define TRACE(level, fmt, ...) (void) 0 | |
| #endif | |
| endef | |
| define ERR_H | |
| #pragma once | |
| extern void err (int eval, const char *fmt, ...); | |
| endef | |
| ifeq ($(USER),gv) | |
| RC_COMMENT = "Built on $(TODAY) by <[email protected]>" | |
| else | |
| RC_COMMENT = "" | |
| endif | |
| define NGREP_RC | |
| #include <winver.h> | |
| #if defined(__clang__) | |
| #define RC_COMPILER "clang-cl" | |
| #elif defined(_MSC_VER) | |
| #define RC_COMPILER "MSVC" | |
| #else | |
| #error "Unsupported compiler" | |
| #endif | |
| #define RC_VERSION $(VER_MAJOR),$(VER_MINOR),$(VER_MICRO),0 | |
| LANGUAGE 0x09,0x01 | |
| VS_VERSION_INFO VERSIONINFO | |
| FILEVERSION RC_VERSION | |
| PRODUCTVERSION RC_VERSION | |
| FILEFLAGSMASK 0x3fL | |
| FILEOS VOS__WINDOWS32 | |
| FILETYPE VFT_APP | |
| FILESUBTYPE 0x0L | |
| FILEFLAGS 0 | |
| BEGIN | |
| BLOCK "StringFileInfo" | |
| BEGIN | |
| BLOCK "040904b0" | |
| BEGIN | |
| VALUE "CompanyName", "https://github.com/jpr5/ngrep" | |
| VALUE "FileDescription", "ngrep.exe (" RC_COMPILER ", $(CPU))" | |
| VALUE "FileVersion", "$(VERSION)" | |
| VALUE "InternalName", "ngrep.exe" | |
| VALUE "ProductName", "ngrep.exe; Copyright (c) 2025 Jordan Ritter" | |
| VALUE "ProductVersion", "$(VERSION)" | |
| VALUE "LegalCopyright", "GNU GENERAL PUBLIC LICENSE v2 or commercial licence" | |
| VALUE "Comments", $(RC_COMMENT) | |
| END | |
| END | |
| BLOCK "VarFileInfo" | |
| BEGIN | |
| VALUE "Translation", 0x409, 1200 | |
| END | |
| END | |
| endef | |
| define CPP_FILTER_PY | |
| import sys, os | |
| empty_lines = 0 | |
| while True: | |
| line = sys.stdin.readline() | |
| if not line: | |
| break | |
| line = line.rstrip() | |
| if line == "": | |
| empty_lines += 1 | |
| continue | |
| # | |
| # MSVC or clang-cl 'line' directive | |
| # | |
| l = line.lstrip() | |
| if l.startswith("#line") or l.startswith("# "): | |
| line = line.replace (r"\\", "/") | |
| print (line) | |
| # | |
| # Print a newline after a functions or structs | |
| # | |
| if l == "}" or l == "};": | |
| print ("") | |
| print ("Removed %d empty lines." % empty_lines, file=sys.stderr) | |
| endef | |
| define CHECK_FOR_UNUSED_LIBS_PY | |
| import os, sys, colorama | |
| map_file = sys.argv[1] | |
| ignore_libs = [ "oldnames.lib" ] | |
| colorama.init() | |
| class State(): | |
| IDLE = 0 | |
| UNUSED = 1 | |
| class Color(): | |
| RESET = colorama.Style.RESET_ALL | |
| RED = colorama.Fore.RED + colorama.Style.BRIGHT | |
| WHITE = colorama.Fore.WHITE + colorama.Style.BRIGHT | |
| def cprint (color, s): | |
| print ("%s%s%s" % (color, s, Color.RESET)) | |
| def report (unused): | |
| num = len(unused) | |
| plural = [ "library", "libraries" ] | |
| if num > 0: | |
| cprint (Color.RED, "%d unused %s in %s:" % (num, plural[num > 1], map_file)) | |
| for u in unused: | |
| print (" " + u) | |
| cprint (Color.WHITE, "Done.\n") | |
| def process (state): | |
| unused_libs = [] | |
| f = open (map_file, "rt") | |
| lines = f.readlines() | |
| f.close() | |
| for l in lines: | |
| l = l.strip() | |
| if l == "Unused libraries:": | |
| state = State.UNUSED | |
| continue | |
| if state == State.UNUSED: | |
| if l == "": | |
| break | |
| if os.path.basename(l).lower() not in ignore_libs: | |
| unused_libs.append (l) | |
| return unused_libs | |
| report (process(State.IDLE)) | |
| endef | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment