blob: 84c507d9ede66633988360826ce0a3aaffc92ee2 [file] [log] [blame]
Joey Armstrong7d51e8a2023-12-09 11:58:42 -05001# -*- makefile -*-
2# -----------------------------------------------------------------------
3# Copyright 2017-2024 Open Networking Foundation (ONF) and the ONF Contributors
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16# -----------------------------------------------------------------------
17# SPDX-FileCopyrightText: 2017-2024 Open Networking Foundation (ONF) and the ONF Contributors
18# SPDX-License-Identifier: Apache-2.0
19## -----------------------------------------------------------------------
20## Intent:
21## - This makefile defines logic for interacting with library makefiles.
22## - Derived path construction assigned to make variables.
23## - Avoid duplicate makefile inclusion.
24## - Logic is non-destructive, at most two variables are defined.
25## -----------------------------------------------------------------------
26## Note:
27## o make function $(foreach) is often used purely for side effects.
28## It will artifically create context allowing declaration of named
29## local variables to improve readability.
30## Todo:
31## o GNU Make v4.4 introduced $(let var[, ..var],list,action)
32## -----------------------------------------------------------------------
33## Usage:
34## include path-to-makefiles/makefiles/include.mk
35## prefix := project-mk
36## $(call gen-mk-paths,{prefix})
37## $(call gen-mk-include,{prefix})
38## $(info makefiles directory ($prefix) is $(project-mk-dir))
39## -----------------------------------------------------------------------
40## {prefix}-dir makefiles/ directory containing include.mk (absolute path)
41## {prefix}-top sandbox root: path to parent makefile directory that
42## included {prefix}-dir/makefiles/include.mk
43## -----------------------------------------------------------------------
44
45ifndef space
46 null :=#
47 space := $(null) $(null)
48endif
49
50$(if $(DEBUG),$(eval DEBUG-onf-mk-paths := 1)) # Enabled by global debug flag
51$(if $(-onf-mk-paths),$(warning ENTER))
52
53## -----------------------------------------------------------------------
54## Intent: Helper function used to trim trailing directory slash from a path
55## -----------------------------------------------------------------------
56dir-wo-slash = $(strip \
57 $(foreach path,$(dir $(1)),\
58 $(patsubst %/,%,$(path))\
59 ))
60
61## -----------------------------------------------------------------------
62## Intent: Include a makefile at most once
63## -----------------------------------------------------------------------
64## Usage:
65## $(call include-once,path/to/makefile)
66## Debug-mode:
67## % make DEBUG-onf-mk-paths=1#
68## -----------------------------------------------------------------------
69## Given:
70## scalar - path to a makefile (relative or absolute)
71## Return:
72## none
73## -----------------------------------------------------------------------
74## Pre:
75## none
76## Post:
77## Define a unique make variable to indicate a makefile has been loaded.
78## include-once-^-^path/to/makefile := true
79## -----------------------------------------------------------------------
80include-once =\
81 $(if $(DEBUG-onf-mk-paths),\
82 $(info ** include-once (makefile=$(1))))\
83\
84 $(foreach makefile,$(1),\
85 $(foreach seen,include-once^-^$(makefile),\
86 $(if $($(seen)),$(null),\
87\
88 $(if $(DEBUG-onf-mk-paths),\
89 $(info ** $$(eval include $(makefile)))\
90 $(info ** $$(eval $(seen) := true))\
91 )\
92\
93 $(eval include $(makefile))\
94 $(eval $(seen) := true)\
95 )))
96
97## -----------------------------------------------------------------------
98## Intent: Given a string prefix conditionally define make variables
99## that reference derived path to a sandbox root directory.
100##
101## A sandbox root directory is defined as the directory containing
102## a top level [mM]akefile that includes library makefiles.
103## -----------------------------------------------------------------------
104## Given:
105## scalar A string prefix derived paths will be assigned to.
106##
107## Return:
108## none
109## -----------------------------------------------------------------------
110## Pre:
111## None
112##
113## Post: Variable defined containing derived paths:
114## {prefix}-top Parent directory (makefiles/ removed).
115## -----------------------------------------------------------------------
116## Usage:
117## prefix := my-mk
118## $(call gen-mk-paths--var-top,$(prefix))
119## $(info sandbox root is $(my-mk-top))
120## -----------------------------------------------------------------------
121## Note: skip
122## 1) skip current makefile: library-makefiles.mk
123## 2) skip library makefile: include.mk
124## 3) skip library includes: makefiles/%
125## [TODO: verify] $(filter-out makefiles/%) may cover everything
126## -----------------------------------------------------------------------
127gen-mk-paths--var-top =\
128 $(if $(DEBUG-onf-mk-paths),\
129 $(info ** gen-mk-paths--var-top (prefix=$(1))))\
130\
131 $(foreach prefix,$(1),\
132 $(foreach skip,$(lastword $(MAKEFILE_LIST)),\
133 $(eval skip += makefiles/)\
134 $(eval skip += %/include.mk)\
135 $(foreach parent,$(lastword \
136 $(filter-out $(skip),$(MAKEFILE_LIST))),\
137 $(foreach abs-parent,$(abspath $(parent)),\
138 $(if $(DEBUG-onf-mk-paths),\
139 $(info ** $$(eval $(prefix)-top := $(call dir-wo-slash,$(abs-parent)))))\
140 $(eval $(prefix)-top := $(call dir-wo-slash,$(abs-parent)))\
141 ))))
142
143## -----------------------------------------------------------------------
144## Intent: Given a string prefix conditionally define make variables
145## that reference derived path to a library makefile directory.
146##
147## A library makefile directory is defined by existence of a
148## filesystem path that contains makefiles/include.mk.
149## -----------------------------------------------------------------------
150## Given:
151## scalar A string prefix derived paths will be assigned to.
152##
153## Return:
154## none
155## -----------------------------------------------------------------------
156## Pre:
157## None
158##
159## Post: Variables defined containing derived paths:
160## {prefix}-abs Absolute path to include.mk (current makefile).
161## {prefix}-dir makefiles/ directory containing include.mk
162## {prefix}-top Parent directory (makefiles/ removed).
163## -----------------------------------------------------------------------
164## Usage:
165## prefix := my-mk
166## $(call gen-mk-paths--var-dir,$(prefix))
167## $(info library makefile path is $(my-mk-dir))
168## -----------------------------------------------------------------------
169gen-mk-paths--var-dir =\
170 $(if $(DEBUG-onf-mk-paths),\
171 $(info ** gen-mk-paths--var-dir (prefix=$(1))))\
172\
173$(foreach prefix,$(1),\
174\
175 $(foreach loaded,$(prefix)-dir,\
176 $(if $($(loaded)),$(null),\
177\
178 $(foreach makefile,$(lastword $(filter %/include.mk,$(MAKEFILE_LIST))),\
179 $(foreach abs-mk,$(abspath $(makefile)),\
180 $(foreach path,$(firstword $(subst /makefiles/,$(space),$(abs-mk))),\
181\
182 $(if $(DEBUG-onf-mk-paths),\
183 $(info ** $$(eval $(prefix)-dir := [$(path)/makefiles])))\
184 $(eval $(prefix)-dir := $(path)/makefiles)\
185 ))\
186 )))\
187)
188
189## -----------------------------------------------------------------------
190## Intent: Derive paths to library makefile directory and parent makefile
191## that is including the library
192## -----------------------------------------------------------------------
193## Usage:
194## prefix := my-mk
195## $(call gen-mk-paths,$(prefix))
196## $(info sandbox root is $(my-mk-top))
197## $(info library makefile path is $(my-mk-dir))
198## -----------------------------------------------------------------------
199gen-mk-paths =\
200 $(if $(DEBUG-onf-mk-paths),\
201 $(info ** gen-mk-paths (prefix=$(1))))\
202\
203 $(foreach prefix,$(1),\
204 $(call gen-mk-paths--var-dir,$(prefix),$(1))\
205 $(call gen-mk-paths--var-top,$(prefix),$(1))\
206)
207
208## -----------------------------------------------------------------------
209## Intent: Derive paths then include top level library makefile
210## -----------------------------------------------------------------------
211## Usage:
212## prefix := my-mk
213## $(call gen-mk-include,$(prefix))
214## $(info makefile loaded: $(my-mk-dir)/include.mk)
215## $(info sandbox root is $(my-mk-top))
216## $(info library makefile path is $(my-mk-dir))
217## -----------------------------------------------------------------------
218gen-mk-include =\
219\
220 $(if $(DEBUG-onf-mk-paths),\
221 $(info ** gen-mk-include (prefix=$(1))))\
222\
223 $(foreach prefix,$(strip $(1)),\
224 $(call gen-mk-paths,$(prefix))\
225 $(call include-once,$($(prefix)-dir)/include.mk)\
226 )
227
228$(if $(-onf-mk-paths),$(warning LEAVE))
229
230# [EOF]