# # PDS excercise 1 Makefile # # Copyright (C) 2019-2020 Christos Choutouridis # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . # # ============== Project settings ============== # Project's name PROJECT := exercise_1 # Excecutable's name TARGET := triangCounting # Source directories list(space seperated). Makefile-relative path, UNDER current directory. SRC_DIR_LIST := src # Include directories list(space seperated). Makefile-relative path. INC_DIR_LIST := src inc # Exclude files list(space seperated). Filenames only. # EXC_FILE_LIST := bad.cpp old.cpp # Build directories BUILD_DIR := bin OBJ_DIR := $(BUILD_DIR)/obj DEP_DIR := $(BUILD_DIR)/.dep # ========== Compiler settings ========== # Compiler flags for debug and release DEB_CFLAGS := -DDEBUG -g3 -Wall -Wextra -std=c++14 REL_CFLAGS := -Wall -Wextra -O3 -std=c++14 # Pre-defines # PRE_DEFS := MYCAB=1729 SUPER_MODE PRE_DEFS := # ============== Linker settings ============== # Linker flags (example: -pthread -lm) LDFLAGS := -pthread # Map output file MAP_FILE := output.map MAP_FLAG := -Xlinker -Map=$(BUILD_DIR)/$(MAP_FILE) # ============== Docker settings ============== # We need: # - Bind the entire project directory(the dir that icludes all the code) as volume. # - In docker instance, change to working directory(where the makefile is). DOCKER_VOL_DIR := $${PWD} DOCKER_WRK_DIR := DOCKER_RUN := docker run --rm DOCKER_FLAGS := -v $(DOCKER_VOL_DIR):/usr/src/$(PROJECT) -w /usr/src/$(PROJECT)/$(DOCKER_WRK_DIR) # docker invoke mechanism (edit with care) # note: # Here, `DOCKER` variable is empty. Rules can assign `DOCKER := DOCKER_CMD` when docker # functionality is needed. DOCKER_CMD = $(DOCKER_RUN) $(DOCKER_FLAGS) $(IMAGE) DOCKER := # ============== Tool selection ============== # compiler and compiler flags. CSIZE := size CFLAGS := $(DEB_CFLAGS) CXX := g++ # # =========== Main body and Patterns =========== # #ifeq ($(OS), Windows_NT) # TARGET := $(TARGET).exe #endif INC := $(foreach dir,$(INC_DIR_LIST),-I$(dir)) DEF := $(foreach def,$(PRE_DEFS),-D$(def)) EXC := $(foreach fil,$(EXC_FILE_LIST), \ $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/$(fil))) \ ) # source files. object and dependencies list # recursive search into current and source directories SRC := $(wildcard *.cpp) SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/*.cpp)) SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/**/*.cpp)) SRC := $(filter-out $(EXC),$(SRC)) #SRC := $(abspath $(SRC)) OBJ := $(foreach file,$(SRC:%.cpp=%.o),$(OBJ_DIR)/$(file)) DEP := $(foreach file,$(SRC:%.cpp=%.d),$(DEP_DIR)/$(file)) # Make Dependencies pattern. # This little trick enables recompilation only when dependencies change # and it does so for changes both in source AND header files ;) # # It is based on Tom Tromey's method. # # Invoke cpp to create makefile rules with dependencies for each source file $(DEP_DIR)/%.d: %.cpp @mkdir -p $(@D) $(DOCKER) $(CXX) -E $(CFLAGS) $(INC) $(DEF) -MM -MT $(OBJ_DIR)/$(<:.cpp=.o) -MF $@ $< # objects depent on .cpp AND dependency files, which have an empty recipe $(OBJ_DIR)/%.o: %.cpp $(DEP_DIR)/%.d @mkdir -p $(@D) $(DOCKER) $(CXX) -c $(CFLAGS) $(INC) $(DEF) -o $@ $< # empty recipe for dependency files. This prevents make errors $(DEP): # now include all dependencies # After all they are makefile dependency rules ;) include $(wildcard $(DEP)) # main target rule $(BUILD_DIR)/$(TARGET): $(OBJ) @mkdir -p $(@D) @echo Linking to target: $(TARGET) @echo $(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) '$$(OBJ)' @$(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) $(OBJ) @echo @echo Print size information @$(CSIZE) $(@D)/$(TARGET) @echo Done .PHONY: clean clean: @echo Cleaning build directories @rm -rf $(OBJ_DIR) @rm -rf $(DEP_DIR) @rm -rf $(BUILD_DIR) # # ================ Local build rules ================= # examples: # make debug debug: CFLAGS := $(DEB_CFLAGS) debug: $(BUILD_DIR)/$(TARGET) release: CFLAGS := $(REL_CFLAGS) release: $(BUILD_DIR)/$(TARGET) all: release hpc-results/post: $(CXX) $(CFLAGS) -o $@ hpc-results/main.cpp hpc-clean: rm hpc-results/post local_v3: CFLAGS := $(DEB_CFLAGS) -DCODE_VERSION=3 local_v3: TARGET := local_v3 local_v3: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) local_v4: CFLAGS := $(DEB_CFLAGS) -DCODE_VERSION=4 local_v4: TARGET := local_v4 local_v4: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) elearn: CFLAGS := $(DEB_CFLAGS) -DELEARNING elearn: TARGET := elearn elearn: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) local_v4_opt: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 -pg local_v4_opt: LDFLAGS += -pg local_v4_opt: TARGET := local_v4_opt local_v4_opt: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v3: DOCKER := $(DOCKER_CMD) v3: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=3 v3: TARGET := tcount_v3 v3: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v3_cilk: DOCKER := $(DOCKER_CMD) v3_cilk: CXX := /usr/local/OpenCilk-9.0.1-Linux/bin/clang++ v3_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=3 -DCILK v3_cilk: LDFLAGS += -fcilkplus v3_cilk: TARGET := tcount_cilkv3 v3_cilk: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v3_omp: DOCKER := $(DOCKER_CMD) v3_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=3 -DOMP v3_omp: LDFLAGS += -fopenmp v3_omp: TARGET := tcount_ompv3 v3_omp: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v4: DOCKER := $(DOCKER_CMD) v4: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 v4: TARGET := tcount_v4 v4: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v4_cilk: DOCKER := $(DOCKER_CMD) v4_cilk: CXX := /usr/local/OpenCilk-9.0.1-Linux/bin/clang++ v4_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=V4 -DCILK v4_cilk: LDFLAGS += -fcilkplus v4_cilk: TARGET := tcount_cilkv4 v4_cilk: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v4_omp: DOCKER := $(DOCKER_CMD) v4_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=4 -DOMP v4_omp: LDFLAGS += -fopenmp v4_omp: TARGET := tcount_ompv4 v4_omp: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) v4_pthreads: DOCKER := $(DOCKER_CMD) v4_pthreads: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 -DTHREADS v4_pthreads: TARGET := tcount_pthv4 v4_pthreads: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) # # ========= Inside CSAL Image build rules =========== # # 1) first jump into image (make sure you are in the directory where Makefile is): # > docker run -it -v ${PWD}:/usr/src/exercise_1 -w /usr/src/exercise_1/ hpcimage # 2) Clean binaries first **important** # > make clean # 3) for v4 cilk for example: # > make csal_v4_cilk # 4) run executables from `bin/`. Examples: # > ./bin/tcount_ompv3 -i mtx/NACA0015.mtx --timing -r 3 -o /dev/null # > ./bin/tcount_pthv4 -i mtx/com_Youtube.mtx --timing --dynamic --print_count csal_v3: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=3 csal_v3: TARGET := tcount_v3 csal_v3: $(BUILD_DIR)/$(TARGET) csal_v3_cilk: CXX := /usr/local/OpenCilk-9.0.1-Linux/bin/clang++ csal_v3_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=3 -DCILK csal_v3_cilk: LDFLAGS += -fcilkplus csal_v3_cilk: TARGET := tcount_cilkv3 csal_v3_cilk: $(BUILD_DIR)/$(TARGET) csal_v3_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=3 -DOMP csal_v3_omp: LDFLAGS += -fopenmp csal_v3_omp: TARGET := tcount_ompv3 csal_v3_omp: $(BUILD_DIR)/$(TARGET) csal_v4: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 csal_v4: TARGET := tcount_v4 csal_v4: $(BUILD_DIR)/$(TARGET) csal_v4_cilk: CXX := /usr/local/OpenCilk-9.0.1-Linux/bin/clang++ csal_v4_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=V4 -DCILK csal_v4_cilk: LDFLAGS += -fcilkplus csal_v4_cilk: TARGET := tcount_cilkv4 csal_v4_cilk: $(BUILD_DIR)/$(TARGET) csal_v4_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=4 -DOMP csal_v4_omp: LDFLAGS += -fopenmp csal_v4_omp: TARGET := tcount_ompv4 csal_v4_omp: $(BUILD_DIR)/$(TARGET) csal_v4_pthreads: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 -DTHREADS csal_v4_pthreads: TARGET := tcount_pthv4 csal_v4_pthreads: $(BUILD_DIR)/$(TARGET) # # ================ hpc build rules ================= # hpc_v3_ser: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=3 hpc_v3_ser: TARGET := hpc_v3 hpc_v3_ser: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v3_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=3 -DOMP hpc_v3_omp: LDFLAGS += -fopenmp hpc_v3_omp: TARGET := hpc_ompv3 hpc_v3_omp: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v3_cilk: CXX := clang++ hpc_v3_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=3 -DCILK hpc_v3_cilk: LDFLAGS += -fcilkplus hpc_v3_cilk: TARGET := hpc_cilkv3 hpc_v3_cilk: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v4_ser: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 hpc_v4_ser: TARGET := hpc_v4 hpc_v4_ser: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v4_omp: CFLAGS := $(REL_CFLAGS) -fopenmp -DCODE_VERSION=4 -DOMP hpc_v4_omp: LDFLAGS += -fopenmp hpc_v4_omp: TARGET := hpc_ompv4 hpc_v4_omp: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v4_cilk: CXX := clang++ hpc_v4_cilk: CFLAGS := $(REL_CFLAGS) -fcilkplus -DCODE_VERSION=4 -DCILK hpc_v4_cilk: LDFLAGS += -fcilkplus hpc_v4_cilk: TARGET := hpc_cilkv4 hpc_v4_cilk: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET) hpc_v4_pth: CFLAGS := $(REL_CFLAGS) -DCODE_VERSION=4 -DTHREADS hpc_v4_pth: TARGET := hpc_pthv4 hpc_v4_pth: $(BUILD_DIR)/$(TARGET) cp $(BUILD_DIR)/$(TARGET) out/$(TARGET)