Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

219 lignes
6.7 KiB

  1. #
  2. # Makefile for utl Unit test
  3. #
  4. # Copyright (C) 2019-2020 Christos Choutouridis <christos@choutouridis.net>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Lesser General Public License as
  8. # published by the Free Software Foundation, either version 3
  9. # of the License, or (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. #
  19. # ult notes:
  20. # ==============
  21. # This makefile provides support for unix-like local builds and
  22. # docker based builds for gcc and clang.
  23. # ** msvc is not currently supported.
  24. #
  25. # Use cases:
  26. # 1) build localy using **local rules** in terminal.
  27. # example:
  28. # make -j4 MK_ARG="-std=c++14 -fconcepts" build-gcc
  29. #
  30. # 2) build localy using **docker based rules** via terminal or script
  31. # in order to compile for all compilers/versions/dialects.
  32. # example in bash:
  33. # #!/bin/bash
  34. # for im in gcc:8 gcc:9 gcc:10; do
  35. # for dial in -std=c++14 -std=c++17; do
  36. # make IMAGE="$im" MK_ARG="$dial" dock-gcc
  37. # done
  38. # done
  39. #
  40. # 3) build inside a docker instance using **local rules** in order to
  41. # build and test using a CD/CI system.
  42. # example in a yml file:
  43. # image: gcc:8
  44. # build:
  45. # stage: build
  46. # - make MK_ARG="-std=c++14" build-gcc
  47. # - make MK_ARG="-std=c++14 -fconcepts" build-gcc
  48. # - make MK_ARG="-std=c++17" build-gcc
  49. # - make MK_ARG="-std=c++17 -fconcepts" build-gcc
  50. # - make MK_ARG="-std=c++2a" build-gcc
  51. # ... etc
  52. # test:
  53. # stage: test
  54. # - bin/utlTest
  55. # ... etc
  56. # ============== Project settings ==============
  57. # Project's name
  58. PROJECT := utl
  59. # Excecutable's name
  60. TARGET := utlTest
  61. # Source directories list(space seperated).
  62. # Relative path, under current directory only
  63. SRC_DIR_LIST := tests gtest
  64. # Include directories list(space seperated).
  65. # Relative path
  66. INC_DIR_LIST := ../include gtest
  67. # Exclude files list(space seperated). Filenames only.
  68. # EXC_FILE_LIST := bad.cpp old.cpp
  69. # Build directories
  70. BUILD_DIR := bin
  71. OBJ_DIR := $(BUILD_DIR)/obj
  72. DEP_DIR := $(BUILD_DIR)/.dep
  73. # ============== Compiler settings ==============
  74. CLANGXX := clang++
  75. GCCXX := g++
  76. CSIZE := size
  77. # Compiler flags for debug and release
  78. DEB_CFLAGS := -DDEBUG -g3 -Wall -Wextra
  79. REL_CFLAGS := -Wall -Wextra -O2
  80. # Pre-defines
  81. # PRE_DEFS := MYCAB=1729 SUPER_MODE
  82. # ============== Linker settings ==============
  83. # Linker flags
  84. LDFLAGS := -pthread
  85. # Map output file
  86. MAP_FILE := output.map
  87. MAP_FLAG := -Xlinker -Map=$(BUILD_DIR)/$(MAP_FILE)
  88. # ============== Docker settings ==============
  89. # We need:
  90. # 1) Bind the entire project directory(the dir that icludes all the code) as volume.
  91. # 2) In docker instance change to working directory(where the makefile is).
  92. # For utl we use the directories `${PWD%/*}` and `test`.
  93. # We double-$$ for double evaluating.
  94. DOCKER_VOL_DIR := "$${PWD%/*}"
  95. DOCKER_WRK_DIR := test
  96. DOCKER_RUN := docker run --rm -v $(DOCKER_VOL_DIR):/usr/src/$(PROJECT) -w /usr/src/$(PROJECT)/$(DOCKER_WRK_DIR)
  97. # ============== Default settings ==============
  98. # compiler and compiler flags. By default docker is not used.
  99. CFLAGS := $(DEB_CFLAGS)
  100. CXX := $(GCCXX)
  101. DOCKER :=
  102. #
  103. # =========== Main body and Patterns ===========
  104. #
  105. ifeq ($(OS), Windows_NT)
  106. TARGET := $(TARGET).exe
  107. endif
  108. INC := $(foreach dir,$(INC_DIR_LIST),-I$(dir))
  109. DEF := $(foreach def,$(PRE_DEFS),-D$(def))
  110. EXC := $(foreach fil,$(EXC_FILE_LIST), \
  111. $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/$(fil))) \
  112. )
  113. # source files, object and dependencies list
  114. # recursive search into current and source directories
  115. SRC := $(wildcard *.cpp)
  116. SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/*.cpp))
  117. SRC += $(foreach dir,$(SRC_DIR_LIST),$(wildcard $(dir)/**/*.cpp))
  118. #SRC := $(abspath $(filter-out $(EXC),$(SRC)))
  119. SRC := $(filter-out $(EXC),$(SRC))
  120. OBJ := $(foreach file,$(SRC:%.cpp=%.o),$(OBJ_DIR)/$(file))
  121. DEP := $(foreach file,$(SRC:%.cpp=%.d),$(DEP_DIR)/$(file))
  122. # Make Dependencies pattern.
  123. # This little trick enables recompilation only when dependencies change
  124. # and it does so for changes both in source AND header files ;)
  125. #
  126. # It is based on Tom Tromey's method.
  127. #
  128. # Invoke cpp to create makefile rules with dependencies for each source file
  129. $(DEP_DIR)/%.d: %.cpp
  130. @mkdir -p $(@D)
  131. @$(DOCKER) $(CXX) -E $(CFLAGS) $(INC) $(DEF) -MM -MT $(OBJ_DIR)/$(<:.cpp=.o) -MF $@ $<
  132. # objects depent on .cpp AND dependency files, which have an empty recipe
  133. $(OBJ_DIR)/%.o: %.cpp $(DEP_DIR)/%.d
  134. @mkdir -p $(@D)
  135. $(DOCKER) $(CXX) -c $(CFLAGS) $(INC) $(DEF) -o $@ $<
  136. # empty recipe for dependency files. This prevents make errors
  137. $(DEP):
  138. # now include all dependencies
  139. # After all they are makefile dependency rules ;)
  140. include $(wildcard $(DEP))
  141. # main target rule
  142. $(BUILD_DIR)/$(TARGET): $(OBJ)
  143. @mkdir -p $(@D)
  144. @echo Linking to target: $(TARGET)
  145. @echo $(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) '$$(OBJ)'
  146. @$(DOCKER) $(CXX) $(LDFLAGS) $(MAP_FLAG) -o $(@D)/$(TARGET) $(OBJ)
  147. @echo
  148. @echo Print size information
  149. @$(CSIZE) $(@D)/$(TARGET)
  150. @echo Done
  151. .PHONY: clean
  152. clean:
  153. @echo Cleaning build directories
  154. @rm -rf $(OBJ_DIR)
  155. @rm -rf $(DEP_DIR)
  156. @rm -rf $(BUILD_DIR)
  157. #
  158. # ================ Local build rules =================
  159. # examples:
  160. # make MK_ARG="-std=c++14 -fconcepts" build-gcc
  161. # make MK_ARG="-std=c++17" build-clang
  162. #
  163. .PHONY: build-gcc
  164. build-gcc: CFLAGS += $(MK_ARG)
  165. build-gcc: $(BUILD_DIR)/$(TARGET)
  166. .PHONY: build-clang
  167. build-clang: CXX := $(CLANGXX)
  168. build-clang: CFLAGS += $(MK_ARG)
  169. build-clang: $(BUILD_DIR)/$(TARGET)
  170. .PHONY: debug
  171. debug: $(BUILD_DIR)/$(TARGET)
  172. .PHONY: release
  173. release: CFLAGS := $(REL_FLAGS)
  174. release: clean $(BUILD_DIR)/$(TARGET)
  175. .PHONY: all
  176. all: clean release
  177. #
  178. # ================ Docker based rules ================
  179. # examples:
  180. # make IMAGE="gcc:8.3" MK_ARG="-std=c++14 -fconcepts" dock-gcc
  181. # make IMAGE="a-clang-image" MK_ARG="-std=c++17" dock-clang
  182. #
  183. .PHONY: dock-gcc
  184. dock-gcc: DOCKER := $(DOCKER_RUN) $(IMAGE)
  185. dock-gcc: CFLAGS += $(MK_ARG)
  186. dock-gcc: $(BUILD_DIR)/$(TARGET)
  187. .PHONY: dock-clang
  188. dock-clang: CXX := $(CLANGXX)
  189. dock-clang: DOCKER := $(DOCKER_RUN) $(IMAGE)
  190. dock-clang: CFLAGS += $(MK_ARG)
  191. dock-clang: $(BUILD_DIR)/$(TARGET)