# Pipe leak Makefile v1.2 [191114] # Variables ===================================== # Compiler options CC=cc CXX=g++ LINKER=$(CC) DEFINES= FLAGS=-Wall -Wextra -Wpedantic $(DEFINES) CFLAGS=$(FLAGS) -std=c11 CXXFLAGS=$(FLAGS) -std=c++11 LIBS= # Configure flags according to the target debug: FLAGS += -g release: FLAGS += -O3 -DNDEBUG # Directories BIN_DIR=bin BUILD_DIR=build DOC_DIR=doc LIB_DIR=lib SRC_DIR=src SRC_CLI_NAME=cli SRC_LIB_NAME=pipeleak SRC_TST_NAME=tester SRC_CLI_DIR=$(SRC_DIR)/$(SRC_CLI_NAME) SRC_LIB_DIR=$(SRC_DIR)/$(SRC_LIB_NAME) SRC_TST_DIR=$(SRC_DIR)/$(SRC_TST_NAME) TEST_DIR=tests TEST_OUT_DIR=$(BUILD_DIR)/$(TEST_DIR) BUILD_CLI_DIR=$(BUILD_DIR)/$(SRC_CLI_NAME) BUILD_LIB_DIR=$(BUILD_DIR)/$(SRC_LIB_NAME) BUILD_TST_DIR=$(BUILD_DIR)/$(SRC_TST_NAME) INST_DIR=$(HOME)/bin # Project variables APP_NAME=pipeleak CLI_PATH=$(BIN_DIR)/$(APP_NAME) LIB_NAME=lib$(APP_NAME).so LIB_PATH=$(LIB_DIR)/$(LIB_NAME) LIB_LINK=$(BIN_DIR)/$(LIB_NAME) TST_PATH=$(BIN_DIR)/$(SRC_TST_NAME) # Files and test cases HEADERS_CLI=$(shell find $(SRC_CLI_DIR) -type f -name '*.h') HEADERS_LIB=$(shell find $(SRC_LIB_DIR) -type f -name '*.h') HEADERS_TST=$(shell find $(SRC_TST_DIR) -type f -name '*.h') SOURCES_CLI=$(shell find $(SRC_CLI_DIR) -type f -name '*.c' -o -name '*.cpp') SOURCES_LIB=$(shell find $(SRC_LIB_DIR) -type f -name '*.c' -o -name '*.cpp') SOURCES_TST=$(shell find $(SRC_TST_DIR) -type f -name '*.c' -o -name '*.cpp') OBJECTS_CLI=$(SOURCES_CLI:$(SRC_CLI_DIR)/%.c=$(BUILD_CLI_DIR)/%.o) OBJECTS_LIB=$(SOURCES_LIB:$(SRC_LIB_DIR)/%.c=$(BUILD_LIB_DIR)/%.o) OBJECTS_TST=$(SOURCES_TST:$(SRC_TST_DIR)/%.c=$(BUILD_TST_DIR)/%.o) # Test cases input are arguments, not stdin TEST_IN=$(wildcard $(TEST_DIR)/level0*) TEST_OUT=$(TEST_IN:$(TEST_DIR)/level%=$(TEST_OUT_DIR)/level%) # Building ====================================== # Default rule is debug target debug: $(LIB_PATH) $(CLI_PATH) $(TST_PATH) release: $(CLI_PATH) $(TST_PATH) # All targets all: debug doc test .SECONDEXPANSION: #Making .so relative to executable path (for easy installation in $HOME/bin): # See commit f9e98baa552f411fd6508c28144a63401e7a0d36 for adjusting both .so and executable # https://aimlesslygoingforward.com/blog/2014/01/19/bundling-shared-libraries-on-linux/ # https://unix.stackexchange.com/questions/137492/load-shared-objects-relative-to-executable-path # https://stackoverflow.com/questions/51839902/using-a-shared-library-in-another-shared-library # Linker call #!Outdated: $(CXX) $(CFLAGS) -o $@ $^ $(LIBS) $(CLI_PATH): $(OBJECTS_CLI) $(LIB_PATH) | $(LIB_LINK) $(LINKER) $(CFLAGS) -o $@ $(OBJECTS_CLI) -L$(LIB_DIR) -l$(APP_NAME) -Wl,-rpath,'$$ORIGIN' $(LIBS) ifeq ($(shell uname -s),Darwin) install_name_tool -add_rpath @executable_path/. $(CLI_PATH) install_name_tool -change $(LIB_PATH) @rpath/$(LIB_NAME) $(CLI_PATH) endif $(LIB_PATH): $(OBJECTS_LIB) | $$(@D)/. $(LINKER) -shared $(CFLAGS) -o $@ $^ $(TST_PATH): $(OBJECTS_TST) $(LIB_PATH) | $$(@D)/. $(LINKER) $(CFLAGS) -o $@ $^ $(LIBS) # Link to the library $(LIB_LINK): $(LIB_PATH) | $$(@D)/. cd $(BIN_DIR) && ln -s ../$(LIB_PATH) # Compile C source into .o object file $(BUILD_LIB_DIR)/%.o: $(SRC_LIB_DIR)/%.c $(HEADERS_LIB) | $$(@D)/. $(CC) -c $(CFLAGS) -fPIC $< -o $@ $(BUILD_CLI_DIR)/%.o: $(SRC_CLI_DIR)/%.c $(HEADERS_CLI) | $$(@D)/. $(CC) -c $(CFLAGS) -I $(SRC_LIB_DIR) $< -o $@ $(BUILD_TST_DIR)/%.o: $(SRC_TST_DIR)/%.c $(HEADERS_TST) | $$(@D)/. $(CC) -c $(CFLAGS) -I $(SRC_LIB_DIR) $< -o $@ # Compile C++ source into .o object file #!Outdated rule $(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS) | $$(@D)/. $(CXX) -c $(CXXFLAGS) $< -o $@ # Documentation .PHONY: doc | $(DOC_DIR)/. doc: doxygen Doxyfile # Testing ======================================= # Testing .PHONY: test test: debug $(TEST_OUT) @rm -rf $(TEST_OUT) .PHONY: $(TEST_OUT_DIR)/level% $(TEST_OUT_DIR)/level%: $(TEST_DIR)/level% | $$(@D)/$$(@F)/. $(CLI_PATH) convert -ib $