Makefile
Posted on July 1, 2014
Tags: c
1 Makefile
Makefile build rule looks like stuff.o: stuff.c stuff.h
which tells us we can only build [left-hand side]stuff.o
, only if we find [right-hand side] files stuff.c stuff.h
- Example build rule
stuff.o: stuff.c stuff.h
$@
means whatever is on the left-hand side of build rule,stuff.o
$^
means whatever is on the right-hand side of build rule,stuff.c stuff.h
$<
means first thing on right-hand side of build rule,stuff.c
# CC is our chosen compiler gcc / g++ / llvmcc
CC=gcc
#`-I somedirectory` flag adds directories to be searched for include files
INCDIRS=-I.
#`-O0` flag is OPTIMIZATION flag, we use `-O0` for minimal optimization, `-O3` for max optimization
OPT=-O0
#CFLAGS just brings it(the flags defined above) all together
CFLAGS=-Wall -Wextra -g $(INCDIRS) $(OPT)
#CFILES are your input c files
CFILES=x.c y.c
#OBJECTS are your output object file after using gcc or g++ on your CFILES
OBJECTS=x.o y.o
#B
BINARY=bin
all: $(BINARY)
$(BINARY): $(OBJECTS)
$(CC) -o $@ $^
# %.o is a wildcard for .o object files , same for %.c
# building any object .o file depends on it's respective .c file
# `$@` means whatever is on the left-hand side of the build rule colon which is %.o in this case
# `$^` means whatever is on the right-hand side of the build rule colon which is %.c in this case
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $^
clean:
rm -rf $(BINARY) $(OBJECTS)
2 Lean Makefile
filepaths
* $(addsuffix .c,foo bar)
returns foo.c bar.c
* $(addprefix $(OUT)/testcpp/,$(CPP_SRCS:.cpp=.o))
returns path appended object, home/testcpp/myfuns.o
*$(CPP_SRCS:.cpp=.o)
replaces extension .cpp with .o
CPP_SRCS is myfuncs.cpp meaning this replaces myfuncs.cpp to myfuncs.o
# tells us $(CXX) means g++ compiler
CXX ?= c++
# -O3 is a g++ flag for code optimization
CPPFLAGS = -O3
# first make the lean.mk makefile
include lean.mk
CPP_SRCS = myfuns.cpp
CPP_OBJS = $(addprefix $(OUT)/testcpp/,$(CPP_SRCS:.cpp=.o))
all: run_test run_interp
$(OUT)/testcpp/%.o: %.cpp
@mkdir -p "$(@D)"
$(CXX) -std=c++14 -c -o $@ $< $(CPPFLAGS) `leanc --print-cflags`
#g++ -std=c++14 -c -o something/testcpp/myfuns.o myfunc.cpp -O3 `leanc --print-cflags`
# $< refers to %.cpp
# $@ refers to $(OUT)/testcpp/%.o
# to avoid conflicts between the system C++ stdlib needed by the above object file and the internal one used in the Lean runtime,
# we need to dynamically link the Lean runtime.
ifeq ($(OS),Windows_NT)
# make S.so find testcpp.so
export PATH := $(BIN_OUT):$(PATH)
else
# find libleanshared.so
TEST_SHARED_LINK_FLAGS := -Wl,-rpath,`lean --print-prefix`/lib/lean
endif
$(BIN_OUT)/testcpp.so: $(CPP_OBJS) | $(BIN_OUT)
$(CXX) -shared -o $@ $^ `leanc -shared --print-ldflags`
# g++ -shared -o $(BIN_OUT)/testcpp.so $(CPP_OBJS) `leanc -shared --print-ldflags`
$(BIN_OUT)/test: $(LIB_OUT)/libMain.a $(CPP_OBJS) | $(BIN_OUT)
$(CXX) -o $@ $^ `leanc -shared --print-ldflags` -lleanshared $(TEST_SHARED_LINK_FLAGS)
run_test: $(BIN_OUT)/test
$^
# also test interpreter; see doc/dev/ffi.md
$(BIN_OUT)/S.so: $(C_OUT)/Main/S.c $(BIN_OUT)/testcpp.so
leanc -shared -o $@ $^
run_interp: $(BIN_OUT)/S.so
lean --load-dynlib=$^ --run Main.lean
out: a.req b.req c.req
cat a.req b.req c.req > out
%.req: %.in
cp $< $@
echo Bleh >> $@
$<
refers to %.in which first prereq means all .in dependencies are processed$@
refers to %.req which means output all the output are .req
result is shown below
cp a.in a.req
echo Bleh >> a.req
cp b.in b.req
echo Bleh >> b.req
cp c.in c.req
echo Bleh >> c.req
cat a.req b.req c.req > out