fwknop: init script improvements
[feed/packages.git] / lang / golang / golang-package.mk
1 #
2 # Copyright (C) 2018 Jeffery To
3 #
4 # This is free software, licensed under the GNU General Public License v2.
5 # See /LICENSE for more information.
6 #
7
8 ifeq ($(origin GO_INCLUDE_DIR),undefined)
9 GO_INCLUDE_DIR:=$(dir $(lastword $(MAKEFILE_LIST)))
10 endif
11
12 include $(GO_INCLUDE_DIR)/golang-values.mk
13
14
15 # Variables (all optional, except GO_PKG) to be set in package
16 # Makefiles:
17 #
18 # GO_PKG (required) - name of Go package
19 #
20 # Go name of the package.
21 #
22 # e.g. GO_PKG:=golang.org/x/text
23 #
24 #
25 # GO_PKG_INSTALL_EXTRA - list of regular expressions, default empty
26 #
27 # Additional files/directories to install. By default, only these
28 # files are installed:
29 #
30 # * Files with one of these extensions:
31 # .go, .c, .cc, .cpp, .h, .hh, .hpp, .proto, .s
32 #
33 # * Files in any 'testdata' directory
34 #
35 # * go.mod and go.sum, in any directory
36 #
37 # e.g. GO_PKG_INSTALL_EXTRA:=example.toml marshal_test.toml
38 #
39 #
40 # GO_PKG_INSTALL_ALL - boolean (0 or 1), default false
41 #
42 # If true, install all files regardless of extension or directory.
43 #
44 # e.g. GO_PKG_INSTALL_ALL:=1
45 #
46 #
47 # GO_PKG_SOURCE_ONLY - boolean (0 or 1), default false
48 #
49 # If true, 'go install' will not be called. If the package does not
50 # (or should not) build any binaries, then specifying this option will
51 # save build time.
52 #
53 # e.g. GO_PKG_SOURCE_ONLY:=1
54 #
55 #
56 # GO_PKG_BUILD_PKG - list of build targets, default GO_PKG/...
57 #
58 # Build targets for compiling this Go package, i.e. arguments passed
59 # to 'go install'
60 #
61 # e.g. GO_PKG_BUILD_PKG:=github.com/debian/ratt/cmd/...
62 #
63 #
64 # GO_PKG_EXCLUDES - list of regular expressions, default empty
65 #
66 # Patterns to exclude from the build targets expanded from
67 # GO_PKG_BUILD_PKG.
68 #
69 # e.g. GO_PKG_EXCLUDES:=examples/
70 #
71 #
72 # GO_PKG_GO_GENERATE - boolean (0 or 1), default false
73 #
74 # If true, 'go generate' will be called on all build targets (as
75 # determined by GO_PKG_BUILD_PKG and GO_PKG_EXCLUDES). This is usually
76 # not necessary.
77 #
78 # e.g. GO_PKG_GO_GENERATE:=1
79 #
80 #
81 # GO_PKG_GCFLAGS - list of arguments, default empty
82 #
83 # Additional go tool compile arguments to use when building targets.
84 #
85 # e.g. GO_PKG_GCFLAGS:=-N -l
86 #
87 #
88 # GO_PKG_LDFLAGS - list of arguments, default empty
89 #
90 # Additional go tool link arguments to use when building targets.
91 #
92 # e.g. GO_PKG_LDFLAGS:=-s -w
93 #
94 #
95 # GO_PKG_LDFLAGS_X - list of string variable definitions, default empty
96 #
97 # Each definition will be passed as the parameter to the -X go tool
98 # link argument, i.e. -ldflags "-X importpath.name=value"
99 #
100 # e.g. GO_PKG_LDFLAGS_X:=main.Version=$(PKG_VERSION) main.BuildStamp=$(SOURCE_DATE_EPOCH)
101
102 # Credit for this package build process (GoPackage/Build/Configure and
103 # GoPackage/Build/Compile) belong to Debian's dh-golang completely.
104 # https://salsa.debian.org/go-team/packages/dh-golang
105
106
107 # for building packages, not user code
108 GO_PKG_PATH:=/usr/share/gocode
109
110 GO_PKG_BUILD_PKG?=$(strip $(GO_PKG))/...
111
112 GO_PKG_WORK_DIR_NAME:=.go_work
113 GO_PKG_WORK_DIR:=$(PKG_BUILD_DIR)/$(GO_PKG_WORK_DIR_NAME)
114
115 GO_PKG_BUILD_DIR:=$(GO_PKG_WORK_DIR)/build
116 GO_PKG_CACHE_DIR:=$(GO_PKG_WORK_DIR)/cache
117
118 GO_PKG_BUILD_BIN_DIR:=$(GO_PKG_BUILD_DIR)/bin$(if $(GO_HOST_TARGET_DIFFERENT),/$(GO_OS_ARCH))
119
120 GO_PKG_BUILD_DEPENDS_SRC:=$(STAGING_DIR)$(GO_PKG_PATH)/src
121
122 ifdef CONFIG_PKG_ASLR_PIE_ALL
123 ifeq ($(strip $(PKG_ASLR_PIE)),1)
124 ifeq ($(GO_TARGET_PIE_SUPPORTED),1)
125 GO_PKG_ENABLE_PIE:=1
126 else
127 $(warning PIE buildmode is not supported for $(GO_OS)/$(GO_ARCH))
128 endif
129 endif
130 endif
131
132 ifdef CONFIG_PKG_ASLR_PIE_REGULAR
133 ifeq ($(strip $(PKG_ASLR_PIE_REGULAR)),1)
134 ifeq ($(GO_TARGET_PIE_SUPPORTED),1)
135 GO_PKG_ENABLE_PIE:=1
136 else
137 $(warning PIE buildmode is not supported for $(GO_OS)/$(GO_ARCH))
138 endif
139 endif
140 endif
141
142 # sstrip causes corrupted section header size
143 ifneq ($(CONFIG_USE_SSTRIP),)
144 ifneq ($(CONFIG_DEBUG),)
145 GO_PKG_STRIP_ARGS:=--strip-unneeded --remove-section=.comment --remove-section=.note
146 else
147 GO_PKG_STRIP_ARGS:=--strip-all
148 endif
149 STRIP:=$(TARGET_CROSS)strip $(GO_PKG_STRIP_ARGS)
150 RSTRIP= \
151 export CROSS="$(TARGET_CROSS)" \
152 $(if $(PKG_BUILD_ID),KEEP_BUILD_ID=1) \
153 $(if $(CONFIG_KERNEL_KALLSYMS),NO_RENAME=1) \
154 $(if $(CONFIG_KERNEL_PROFILING),KEEP_SYMBOLS=1); \
155 NM="$(TARGET_CROSS)nm" \
156 STRIP="$(STRIP)" \
157 STRIP_KMOD="$(SCRIPT_DIR)/strip-kmod.sh" \
158 PATCHELF="$(STAGING_DIR_HOST)/bin/patchelf" \
159 $(SCRIPT_DIR)/rstrip.sh
160 endif
161
162 define GoPackage/GoSubMenu
163 SUBMENU:=Go
164 SECTION:=lang
165 CATEGORY:=Languages
166 endef
167
168 define GoPackage/Environment/Target
169 GOOS=$(GO_OS) \
170 GOARCH=$(GO_ARCH) \
171 GO386=$(GO_386) \
172 GOARM=$(GO_ARM) \
173 GOMIPS=$(GO_MIPS) \
174 GOMIPS64=$(GO_MIPS64) \
175 CGO_ENABLED=1 \
176 CC=$(TARGET_CC) \
177 CXX=$(TARGET_CXX) \
178 CGO_CFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CFLAGS))" \
179 CGO_CPPFLAGS="$(TARGET_CPPFLAGS)" \
180 CGO_CXXFLAGS="$(filter-out $(GO_CFLAGS_TO_REMOVE),$(TARGET_CXXFLAGS))" \
181 CGO_LDFLAGS="$(TARGET_LDFLAGS)"
182 endef
183
184 define GoPackage/Environment/Build
185 GOPATH=$(GO_PKG_BUILD_DIR) \
186 GOCACHE=$(GO_PKG_CACHE_DIR) \
187 GOENV=off
188 endef
189
190 define GoPackage/Environment/Default
191 $(call GoPackage/Environment/Target) \
192 $(call GoPackage/Environment/Build)
193 endef
194
195 GoPackage/Environment=$(call GoPackage/Environment/Default)
196
197 # false if directory does not exist
198 GoPackage/is_dir_not_empty=$$$$($(FIND) $(1) -maxdepth 0 -type d \! -empty 2>/dev/null)
199
200 GoPackage/has_binaries=$(call GoPackage/is_dir_not_empty,$(GO_PKG_BUILD_BIN_DIR))
201
202 define GoPackage/Build/Configure
203 ( \
204 cd $(PKG_BUILD_DIR) ; \
205 mkdir -p $(GO_PKG_BUILD_DIR)/bin $(GO_PKG_BUILD_DIR)/src $(GO_PKG_CACHE_DIR) ; \
206 \
207 files=$$$$($(FIND) ./ \
208 -type d -a \( -path './.git' -o -path './$(GO_PKG_WORK_DIR_NAME)' \) -prune -o \
209 \! -type d -print | \
210 sed 's|^\./||') ; \
211 \
212 if [ "$(strip $(GO_PKG_INSTALL_ALL))" != 1 ]; then \
213 code=$$$$(echo "$$$$files" | grep '\.\(c\|cc\|cpp\|go\|h\|hh\|hpp\|proto\|s\)$$$$') ; \
214 testdata=$$$$(echo "$$$$files" | grep '\(^\|/\)testdata/') ; \
215 gomod=$$$$(echo "$$$$files" | grep '\(^\|/\)go\.\(mod\|sum\)$$$$') ; \
216 \
217 for pattern in $(GO_PKG_INSTALL_EXTRA); do \
218 extra=$$$$(echo "$$$$extra"; echo "$$$$files" | grep "$$$$pattern") ; \
219 done ; \
220 \
221 files=$$$$(echo "$$$$code"; echo "$$$$testdata"; echo "$$$$gomod"; echo "$$$$extra") ; \
222 files=$$$$(echo "$$$$files" | grep -v '^[[:space:]]*$$$$' | sort -u) ; \
223 fi ; \
224 \
225 IFS=$$$$'\n' ; \
226 \
227 echo "Copying files from $(PKG_BUILD_DIR) into $(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG))" ; \
228 for file in $$$$files; do \
229 echo $$$$file ; \
230 dest=$(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG))/$$$$file ; \
231 mkdir -p $$$$(dirname $$$$dest) ; \
232 $(CP) $$$$file $$$$dest ; \
233 done ; \
234 echo ; \
235 \
236 link_contents() { \
237 local src=$$$$1 ; \
238 local dest=$$$$2 ; \
239 local dirs dir base ; \
240 \
241 if [ -n "$$$$($(FIND) $$$$src -mindepth 1 -maxdepth 1 -name '*.go' \! -type d)" ]; then \
242 echo "$$$$src is already a Go library" ; \
243 return 1 ; \
244 fi ; \
245 \
246 dirs=$$$$($(FIND) $$$$src -mindepth 1 -maxdepth 1 -type d) ; \
247 for dir in $$$$dirs; do \
248 base=$$$$(basename $$$$dir) ; \
249 if [ -d $$$$dest/$$$$base ]; then \
250 case $$$$dir in \
251 *$(GO_PKG_PATH)/src/$(strip $(GO_PKG))) \
252 echo "$(strip $(GO_PKG)) is already installed. Please check for circular dependencies." ;; \
253 *) \
254 link_contents $$$$src/$$$$base $$$$dest/$$$$base ;; \
255 esac ; \
256 else \
257 echo "...$$$${src#$(GO_PKG_BUILD_DEPENDS_SRC)}/$$$$base" ; \
258 $(LN) $$$$src/$$$$base $$$$dest/$$$$base ; \
259 fi ; \
260 done ; \
261 } ; \
262 \
263 if [ "$(strip $(GO_PKG_SOURCE_ONLY))" != 1 ]; then \
264 if [ -d $(GO_PKG_BUILD_DEPENDS_SRC) ]; then \
265 echo "Symlinking directories from $(GO_PKG_BUILD_DEPENDS_SRC) into $(GO_PKG_BUILD_DIR)/src" ; \
266 link_contents $(GO_PKG_BUILD_DEPENDS_SRC) $(GO_PKG_BUILD_DIR)/src ; \
267 else \
268 echo "$(GO_PKG_BUILD_DEPENDS_SRC) does not exist, skipping symlinks" ; \
269 fi ; \
270 else \
271 echo "Not building binaries, skipping symlinks" ; \
272 fi ; \
273 echo ; \
274 )
275 endef
276
277 # $(1) additional arguments for go command line (optional)
278 define GoPackage/Build/Compile
279 ( \
280 cd $(GO_PKG_BUILD_DIR) ; \
281 export $(call GoPackage/Environment) ; \
282 \
283 echo "Finding targets" ; \
284 targets=$$$$(go list $(GO_PKG_BUILD_PKG)) ; \
285 for pattern in $(GO_PKG_EXCLUDES); do \
286 targets=$$$$(echo "$$$$targets" | grep -v "$$$$pattern") ; \
287 done ; \
288 echo ; \
289 \
290 if [ "$(strip $(GO_PKG_GO_GENERATE))" = 1 ]; then \
291 echo "Calling go generate" ; \
292 go generate -v $(1) $$$$targets ; \
293 echo ; \
294 fi ; \
295 \
296 if [ "$(strip $(GO_PKG_SOURCE_ONLY))" != 1 ]; then \
297 echo "Building targets" ; \
298 case $(GO_ARCH) in \
299 arm) installsuffix="v$(GO_ARM)" ;; \
300 mips|mipsle) installsuffix="$(GO_MIPS)" ;; \
301 mips64|mips64le) installsuffix="$(GO_MIPS64)" ;; \
302 esac ; \
303 ldflags="-linkmode external -extldflags '$(TARGET_LDFLAGS:-z%=-Wl,-z,%)'" ; \
304 pkg_gcflags="$(strip $(GO_PKG_GCFLAGS))" ; \
305 pkg_ldflags="$(strip $(GO_PKG_LDFLAGS))" ; \
306 for def in $(GO_PKG_LDFLAGS_X); do \
307 pkg_ldflags="$$$$pkg_ldflags -X $$$$def" ; \
308 done ; \
309 go install \
310 $(if $(GO_PKG_ENABLE_PIE),-buildmode pie) \
311 $$$${installsuffix:+-installsuffix $$$$installsuffix} \
312 -trimpath \
313 -ldflags "all=$$$$ldflags" \
314 -v \
315 $$$${pkg_gcflags:+-gcflags "$$$$pkg_gcflags"} \
316 $$$${pkg_ldflags:+-ldflags "$$$$pkg_ldflags $$$$ldflags"} \
317 $(1) \
318 $$$$targets ; \
319 retval=$$$$? ; \
320 echo ; \
321 \
322 if [ "$$$$retval" -eq 0 ] && [ -z "$(call GoPackage/has_binaries)" ]; then \
323 echo "No binaries were generated, consider adding GO_PKG_SOURCE_ONLY:=1 to Makefile" ; \
324 echo ; \
325 fi ; \
326 \
327 echo "Cleaning module download cache (golang/go#27455)" ; \
328 go clean -modcache ; \
329 echo ; \
330 fi ; \
331 exit $$$$retval ; \
332 )
333 endef
334
335 define GoPackage/Build/InstallDev
336 $(call GoPackage/Package/Install/Src,$(1))
337 endef
338
339 define GoPackage/Package/Install/Bin
340 if [ -n "$(call GoPackage/has_binaries)" ]; then \
341 $(INSTALL_DIR) $(1)/usr/bin ; \
342 $(INSTALL_BIN) $(GO_PKG_BUILD_BIN_DIR)/* $(1)/usr/bin/ ; \
343 fi
344 endef
345
346 define GoPackage/Package/Install/Src
347 dir=$$$$(dirname $(GO_PKG)) ; \
348 $(INSTALL_DIR) $(1)$(GO_PKG_PATH)/src/$$$$dir ; \
349 $(CP) $(GO_PKG_BUILD_DIR)/src/$(strip $(GO_PKG)) $(1)$(GO_PKG_PATH)/src/$$$$dir/
350 endef
351
352 define GoPackage/Package/Install
353 $(call GoPackage/Package/Install/Bin,$(1))
354 $(call GoPackage/Package/Install/Src,$(1))
355 endef
356
357
358 ifneq ($(strip $(GO_PKG)),)
359 Build/Configure=$(call GoPackage/Build/Configure)
360 Build/Compile=$(call GoPackage/Build/Compile)
361 Build/InstallDev=$(call GoPackage/Build/InstallDev,$(1))
362 endif
363
364 define GoPackage
365 ifndef Package/$(1)/install
366 Package/$(1)/install=$$(call GoPackage/Package/Install,$$(1))
367 endif
368 endef
369
370 define GoBinPackage
371 ifndef Package/$(1)/install
372 Package/$(1)/install=$$(call GoPackage/Package/Install/Bin,$$(1))
373 endif
374 endef
375
376 define GoSrcPackage
377 ifndef Package/$(1)/install
378 Package/$(1)/install=$$(call GoPackage/Package/Install/Src,$$(1))
379 endif
380 endef