Skip to content

Instantly share code, notes, and snippets.

@ecnerwala
Last active Jun 26, 2022
Embed
What would you like to do?
Competitive Programming Makefile
# +--------------------+
# | |
# | GENERAL CONFIG |
# | |
# +--------------------+
PROBLEM_NAME := problem_name
DEBUG := true
LANG := cpp
ifeq ($(LANG),cpp)
TARGET := $(PROBLEM_NAME)
EXECUTE := ./$(TARGET)
CLEAN_TARGETS := $(TARGET)
else ifeq ($(LANG),python)
TARGET := $(PROBLEM_NAME).py
EXECUTE := python3 ./$(TARGET)
CLEAN_TARGETS :=
else
$(error "Unknown language; please set TARGET, EXECUTE, and CLEAN_TARGETS manually")
endif
CXX := g++
CXXFLAGS := -std=c++17 -O2 -Wall -Wextra -pedantic -Wshadow -Wformat=2 -Wfloat-equal -Wconversion -Wlogical-op -Wshift-overflow=2 -Wduplicated-cond -Wcast-qual -Wcast-align -Wno-unused-result -Wno-sign-conversion
DEBUG_CXXFLAGS := -fsanitize=address -fsanitize=undefined -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize-recover=all -fstack-protector-all -D_FORTIFY_SOURCE=2
DEBUG_CXXFLAGS += -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
PRECOMPILE_HEADERS := bits/stdc++.h
#PRECOMPILE_HEADERS := bits/extc++.h
# +-------------------+
# | |
# | GENERAL RULES |
# | |
# +-------------------+
all: $(TARGET)
.PHONY: all
clean:
-rm -rf $(CLEAN_TARGETS)
.PHONY: clean
veryclean:
-rm -rf $(CLEAN_TARGETS) *.res
.PHONY: veryclean
rebuild: clean all
.PHONY: rebuild
# +---------------------+
# | |
# | C++ COMPILATION |
# | |
# +---------------------+
ifeq ($(DEBUG),true)
CXXFLAGS += $(DEBUG_CXXFLAGS)
endif
PCH := .precompiled_headers
CLEAN_TARGETS += $(PCH)
$(PCH)/%.gch:
rm -f $@
mkdir -p $(dir $@)
$(LINK.cpp) -x c++-header "$$(echo '#include<$*>' | $(LINK.cpp) -H -E -x c++ - 2>&1 >/dev/null | head -1 | cut -d ' ' -f2)" -o $@
.PRECIOUS: $(PCH)/%.gch
%: %.cpp # Cancel the builtin rule
%: %.cpp $(patsubst %,$(PCH)/%.gch,$(PRECOMPILE_HEADERS))
$(LINK.cpp) -isystem $(PCH) $< $(LOADLIBES) $(LDLIBS) -o $@
.PRECIOUS: %
# +-----------------------+
# | |
# | RUNNING / TESTING |
# | |
# +-----------------------+
export TIME=\n real\t%es\n user\t%Us\n sys\t%Ss\n mem\t%MKB
run: $(TARGET)
\time $(EXECUTE)
ifeq ($(DEBUG),true)
@echo "Built with DEBUG flags enabled, code may be slower than normal"
endif
.PHONY: run
%.res: $(TARGET) %.in
\time $(EXECUTE) < $*.in > $*.res
ifeq ($(DEBUG),true)
@echo "Built with DEBUG flags enabled, code may be slower than normal"
endif
.PRECIOUS: %.res
%.out: % # Cancel the builtin rule
__test_%: %.res %.out
diff $*.res $*.out
.PHONY: __test_%
CASES := $(sort $(basename $(wildcard *.in)))
TESTS := $(sort $(basename $(wildcard *.out)))
runs: $(patsubst %,%.res,$(CASES))
.PHONY: run
solve: runs
.PHONY: solve
test: $(patsubst %,__test_%,$(TESTS))
.PHONY: test
@JiahaoYao
Copy link

JiahaoYao commented Aug 30, 2020

Hi Andrew, thank you so much. Can we also have the setup? I think that will automatically change the problem_name https://gist.github.com/ecnerwala/a3c6332ac626bc448165#file-makefile-L10, right?

@ecnerwala
Copy link
Author

ecnerwala commented Aug 30, 2020

@JiahaoYao
Copy link

JiahaoYao commented Aug 30, 2020

Thanks! Appreciate it!

@Akash671
Copy link

Akash671 commented Dec 29, 2020

Hi !, I am Akash Kumar....
How I will use this on my pc...
Can you explain step by step...

@vtjeng
Copy link

vtjeng commented Jan 26, 2021

For future readers: if you're trying to integrate this Makefile with make_prob.sh, linked above by @ecnerwala, you'll have to modify line 7 to read

PROBLEM_NAME := ${PROBLEM_NAME}

@GaurangTandon
Copy link

GaurangTandon commented May 10, 2021

Hi, I recently noticed that my codeforces directory was of 10GB, and that most of my contest subdirectories are ~100MB or more, because each of them has a .precompiled_headers directory. My guess is that this directory has been created as a result of compiling all my codes with this Makefile.

I am not very good at Makefiles, hence I wish to ask, what is the best way to fix this problem? Ideally, I would want to reuse a single ~/codeforces/.precompiled_headers directory in all my contest subdirectories (~/codeforces/1515/A/A.cpp file, for example).

@ecnerwala
Copy link
Author

ecnerwala commented May 10, 2021

Feel free to try to modify the makefile to use a shared header folder; it'll be a little tricky because make isn't designed for global systemwide stuff.

Personally, I just delete the precompiled header folder after contests (when compile time doesn't matter much anymore). I have a little script to automate that, you can do that too.

@backermanbd
Copy link

backermanbd commented Jan 5, 2022

@ecnerwala Can you share the automation script too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment