Sign in Sign up
kretrod/lodestone-cpp Public
Branches
main
80 lines (64 loc) · 3.1 KB Raw
# Lodestone client — cross-compiled from Linux to a Windows DLL with mingw.
#
# The C++ runtime is linked statically on purpose. A DLL that depends on
# libstdc++-6.dll cannot be injected into a game that has never heard of mingw:
# LoadLibrary fails with "a dependency is missing". Linking with g++ (rather
# than gcc) is what makes -static-libstdc++ actually take effect.

CXX      := x86_64-w64-mingw32-g++
CC       := x86_64-w64-mingw32-gcc
STRIP    := x86_64-w64-mingw32-strip

IMGUI    := third_party/imgui
MINHOOK  := third_party/minhook
BUILD    := build
TARGET   := $(BUILD)/lodestone_client.dll
INJECT   := $(BUILD)/lodestone-inject.exe

# jni.h includes "jni_md.h" and the JDK keeps its own under include/<os>. We
# point at src/jni_md instead and never add include/linux, so the Windows
# definitions win — otherwise jint would be a Linux `int` in a Windows DLL.
JAVA_INC ?= /opt/java/current/include

INCLUDES := -Isrc -Isrc/jni_md -I$(JAVA_INC) \
            -I$(IMGUI) -I$(IMGUI)/backends -I$(MINHOOK)/include
DEFINES  := -DWIN32_LEAN_AND_MEAN -DNOMINMAX -DUNICODE -D_UNICODE

# -MMD -MP emits a .d beside each .o listing the headers it included. Nearly
# all of this client lives in headers, so without them `make` sees only the two
# .cpp files and quietly does nothing after a header edit — leaving a stale DLL
# that looks freshly built.
CXXFLAGS := -std=c++20 -O2 -Wall -Wextra -Wno-unused-parameter -fno-rtti -MMD -MP \
            $(INCLUDES) $(DEFINES)
CFLAGS   := -O2 -Wall -MMD -MP $(INCLUDES) $(DEFINES)

# No winpthread: everything that needs a thread uses CreateThread, which keeps
# the static link to just libstdc++ and libgcc.
LDFLAGS  := -shared -static-libgcc -static-libstdc++ \
            -Wl,--exclude-all-symbols \
            -lopengl32 -lgdi32 -luser32 -lkernel32

CXX_SRC  := src/main.cpp src/overlay.cpp \
            $(IMGUI)/imgui.cpp $(IMGUI)/imgui_draw.cpp \
            $(IMGUI)/imgui_tables.cpp $(IMGUI)/imgui_widgets.cpp \
            $(IMGUI)/backends/imgui_impl_opengl3.cpp

C_SRC    := $(MINHOOK)/src/hook.c $(MINHOOK)/src/buffer.c \
            $(MINHOOK)/src/trampoline.c $(MINHOOK)/src/hde/hde64.c

CXX_OBJ  := $(patsubst %,$(BUILD)/%.o,$(CXX_SRC))
C_OBJ    := $(patsubst %,$(BUILD)/%.o,$(C_SRC))

.PHONY: all clean deps
all: $(TARGET) $(INJECT)

# The loader is a plain console executable: no ImGui, no MinHook, just the
# process walk and the remote LoadLibraryW.
$(INJECT): $(BUILD)/inject/main.cpp.o
	@mkdir -p $(dir $@)
	$(CXX) $^ -o $@ -static-libgcc -static-libstdc++ -lpsapi -luser32 -lkernel32

$(TARGET): $(CXX_OBJ) $(C_OBJ)
	@mkdir -p $(dir $@)
	$(CXX) $^ -o $@ $(LDFLAGS)
	@echo "--- dependencies (libstdc++-6.dll here means the static link failed) ---"
	@x86_64-w64-mingw32-objdump -p $@ | grep "DLL Name" | sort -u

$(BUILD)/%.cpp.o: %.cpp
	@mkdir -p $(dir $@)
	$(CXX) $(CXXFLAGS) -c $< -o $@

$(BUILD)/%.c.o: %.c
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -rf $(BUILD)

# Pulled in last, and with a leading '-' so a first build (no .d files yet) is
# not an error.
-include $(CXX_OBJ:.o=.d) $(C_OBJ:.o=.d) $(BUILD)/inject/main.cpp.d