aboutsummaryrefslogtreecommitdiffstats
path: root/Makefile
blob: cf5d1851d1523f4f335571bb0dc663f5139cf1a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
# Copyright (c) 2021 Cisco and/or its affiliates.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

export WS_ROOT=$(CURDIR)
export BR=$(WS_ROOT)/build-root
CCACHE_DIR?=$(BR)/.ccache
SHELL:=$(shell which bash)
GDB?=gdb
PLATFORM?=vpp
SAMPLE_PLUGIN?=no
STARTUP_DIR?=$(PWD)
MACHINE=$(shell uname -m)
SUDO?=sudo -E
DPDK_CONFIG?=no-pci

ifeq ($(strip $(SHELL)),)
$(error "bash not found, VPP requires bash to build")
endif

,:=,
define disable_plugins
$(if $(1), \
  "plugins {" \
  $(patsubst %,"plugin %_plugin.so { disable }",$(subst $(,), ,$(1))) \
  " }" \
  ,)
endef

MINIMAL_STARTUP_CONF="							\
unix { 									\
	interactive 							\
	cli-listen /run/vpp/cli.sock					\
	gid $(shell id -g)						\
	$(if $(wildcard startup.vpp),"exec startup.vpp",)		\
}									\
$(if $(DPDK_CONFIG), "dpdk { $(DPDK_CONFIG) }",)			\
$(if $(EXTRA_VPP_CONFIG), "$(EXTRA_VPP_CONFIG)",)			\
$(call disable_plugins,$(DISABLED_PLUGINS))				\
"

GDB_ARGS= -ex "handle SIGUSR1 noprint nostop"

#
# OS Detection
#
# We allow Darwin (MacOS) for docs generation; VPP build will still fail.
ifneq ($(shell uname),Darwin)
OS_ID        = $(shell grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
OS_VERSION_ID= $(shell grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g')
endif

ifeq ($(filter ubuntu debian linuxmint,$(OS_ID)),$(OS_ID))
PKG=deb
else ifeq ($(filter rhel centos fedora opensuse-leap rocky almalinux,$(OS_ID)),$(OS_ID))
PKG=rpm
endif

# +libganglia1-dev if building the gmond plugin

DEB_DEPENDS  = curl build-essential autoconf automake ccache
DEB_DEPENDS += debhelper dkms git libtool libapr1-dev dh-python
DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config
DEB_DEPENDS += gcovr lcov chrpath autoconf libnuma-dev
DEB_DEPENDS += python3-all python3-setuptools check
DEB_DEPENDS += libffi-dev python3-ply libunwind-dev
DEB_DEPENDS += cmake ninja-build python3-jsonschema python3-yaml
DEB_DEPENDS += python3-venv  # ensurepip
DEB_DEPENDS += python3-dev python3-pip
DEB_DEPENDS += libnl-3-dev libnl-route-3-dev libmnl-dev
# DEB_DEPENDS += enchant  # for docs
DEB_DEPENDS += python3-virtualenv
DEB_DEPENDS += libssl-dev
DEB_DEPENDS += libelf-dev libpcap-dev # for libxdp (af_xdp)
DEB_DEPENDS += iperf3 # for 'make test TEST=vcl'
DEB_DEPENDS += nasm
DEB_DEPENDS += iperf ethtool  # for 'make test TEST=vm_vpp_interfaces'
DEB_DEPENDS += libpcap-dev
DEB_DEPENDS += tshark
DEB_DEPENDS += jq # for extracting test summary from .json report (hs-test)

LIBFFI=libffi6 # works on all but 20.04 and debian-testing

ifeq ($(OS_VERSION_ID),22.04)
	DEB_DEPENDS += python3-virtualenv
	DEB_DEPENDS += libssl-dev
	DEB_DEPENDS += clang clang-format-11
	LIBFFI=libffi7
	DEB_DEPENDS += enchant-2  # for docs
else ifeq ($(OS_VERSION_ID),20.04)
	DEB_DEPENDS += python3-virtualenv
	DEB_DEPENDS += libssl-dev
	DEB_DEPENDS += clang clang-format-11
	LIBFFI=libffi7
	DEB_DEPENDS += enchant-2  # for docs
else ifeq ($(OS_VERSION_ID),20.10)
	DEB_DEPENDS += clang clang-format-11
	LIBFFI=libffi8ubuntu1
else ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-10)
	DEB_DEPENDS += virtualenv
else ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-11)
	DEB_DEPENDS += virtualenv
	DEB_DEPENDS += clang clang-format-11
	LIBFFI=libffi7
else ifeq ($(OS_ID)-$(OS_VERSION_ID),debian-12)
	DEB_DEPENDS += virtualenv
	DEB_DEPENDS += clang-14 clang-format-14
	# for extras/scripts/checkstyle.sh
	export CLANG_FORMAT_VER=14
	LIBFFI=libffi8
else
	DEB_DEPENDS += clang-11 clang-format-11
	LIBFFI=libffi7
	DEB_DEPENDS += enchant-2  # for docs
endif

DEB_DEPENDS += $(LIBFFI)

RPM_DEPENDS  = glibc-static
RPM_DEPENDS += apr-devel
RPM_DEPENDS += numactl-devel
RPM_DEPENDS += check check-devel
RPM_DEPENDS += selinux-policy selinux-policy-devel
RPM_DEPENDS += ninja-build
RPM_DEPENDS += ccache
RPM_DEPENDS += xmlto
RPM_DEPENDS += elfutils-libelf-devel libpcap-devel
RPM_DEPENDS += libnl3-devel libmnl-devel
RPM_DEPENDS += nasm

ifeq ($(OS_ID),fedora)
	RPM_DEPENDS += dnf-utils
	RPM_DEPENDS += subunit subunit-devel
	RPM_DEPENDS += compat-openssl10-devel
	RPM_DEPENDS += python3-devel  # needed for python3 -m pip install psutil
	RPM_DEPENDS += python3-ply  # for vppapigen
	RPM_DEPENDS += python3-virtualenv python3-jsonschema
	RPM_DEPENDS += cmake
	RPM_DEPENDS_GROUPS = 'C Development Tools and Libraries'
else ifeq ($(OS_ID),rocky)
	RPM_DEPENDS += yum-utils
	RPM_DEPENDS += subunit subunit-devel
	RPM_DEPENDS += openssl-devel
	RPM_DEPENDS += python3-devel  # needed for python3 -m pip install psutil
	RPM_DEPENDS += python3-ply  # for vppapigen
	RPM_DEPENDS += python3-virtualenv python3-jsonschema
	RPM_DEPENDS += infiniband-diags llvm clang cmake
	RPM_DEPENDS_GROUPS = 'Development Tools'
else ifeq ($(OS_ID),almalinux)
	RPM_DEPENDS += yum-utils
	RPM_DEPENDS += subunit subunit-devel
	RPM_DEPENDS += openssl-devel
	RPM_DEPENDS += python3-devel  # needed for python3 -m pip install psutil
	RPM_DEPENDS += python3-ply  # for vppapigen
	RPM_DEPENDS += python3-virtualenv python3-jsonschema
	RPM_DEPENDS += infiniband-diags llvm clang cmake
	RPM_DEPENDS_GROUPS = 'Development Tools'
else ifeq ($(OS_ID)-$(OS_VERSION_ID),centos-8)
	RPM_DEPENDS += yum-utils
	RPM_DEPENDS += compat-openssl10 openssl-devel
	RPM_DEPENDS += python2-devel python36-devel python3-ply
	RPM_DEPENDS += python3-virtualenv python3-jsonschema
	RPM_DEPENDS += libarchive cmake
	RPM_DEPENDS += infiniband-diags libibumad
	RPM_DEPENDS += libpcap-devel llvm-toolset
	RPM_DEPENDS_GROUPS = 'Development Tools'
else
	RPM_DEPENDS += yum-utils
	RPM_DEPENDS += openssl-devel
	RPM_DEPENDS += python36-ply  # for vppapigen
	RPM_DEPENDS += python3-devel python3-pip
	RPM_DEPENDS += python-virtualenv python36-jsonschema
	RPM_DEPENDS += devtoolset-9 devtoolset-9-libasan-devel
	RPM_DEPENDS += cmake3
	RPM_DEPENDS_GROUPS = 'Development Tools'
endif

# +ganglia-devel if building the ganglia plugin

RPM_DEPENDS += chrpath libffi-devel rpm-build

RPM_DEPENDS_DEBUG  = glibc-debuginfo e2fsprogs-debuginfo
RPM_DEPENDS_DEBUG += krb5-debuginfo openssl-debuginfo
RPM_DEPENDS_DEBUG += zlib-debuginfo nss-softokn-debuginfo
RPM_DEPENDS_DEBUG += yum-plugin-auto-update-debug-info

RPM_SUSE_BUILDTOOLS_DEPS = autoconf automake ccache check-devel chrpath
RPM_SUSE_BUILDTOOLS_DEPS += clang cmake indent libtool make ninja python3-ply

RPM_SUSE_DEVEL_DEPS = glibc-devel-static libnuma-devel libelf-devel
RPM_SUSE_DEVEL_DEPS += libopenssl-devel lsb-release
RPM_SUSE_DEVEL_DEPS += libpcap-devel llvm-devel
RPM_SUSE_DEVEL_DEPS += curl libstdc++-devel bison gcc-c++ zlib-devel

RPM_SUSE_PYTHON_DEPS = python3-devel python3-pip python3-rpm-macros

RPM_SUSE_PLATFORM_DEPS = shadow rpm-build

ifeq ($(OS_ID),opensuse-leap)
	RPM_SUSE_DEVEL_DEPS += xmlto openssl-devel asciidoc git nasm
	RPM_SUSE_PYTHON_DEPS += python3 python3-ply python3-virtualenv
	RPM_SUSE_PLATFORM_DEPS += distribution-release
endif

RPM_SUSE_DEPENDS += $(RPM_SUSE_BUILDTOOLS_DEPS) $(RPM_SUSE_DEVEL_DEPS) $(RPM_SUSE_PYTHON_DEPS) $(RPM_SUSE_PLATFORM_DEPS)

ifneq ($(wildcard $(STARTUP_DIR)/startup.conf),)
        STARTUP_CONF ?= $(STARTUP_DIR)/startup.conf
endif

ifeq ($(findstring y,$(UNATTENDED)),y)
DEBIAN_FRONTEND=noninteractive
CONFIRM=-y
FORCE=--allow-downgrades --allow-remove-essential --allow-change-held-packages
endif

TARGETS = vpp

ifneq ($(SAMPLE_PLUGIN),no)
TARGETS += sample-plugin
endif

define banner
	@echo "========================================================================"
	@echo " $(1)"
	@echo "========================================================================"
	@echo " "
endef

.PHONY: help
help:
	@echo "Make Targets:"
	@echo " install-dep[s]       - install software dependencies"
	@echo " wipe                 - wipe all products of debug build "
	@echo " wipe-release         - wipe all products of release build "
	@echo " build                - build debug binaries"
	@echo " build-release        - build release binaries"
	@echo " build-coverity       - build coverity artifacts"
	@echo " build-vpp-gcov 		 - build gcov vpp only"
	@echo " rebuild              - wipe and build debug binaries"
	@echo " rebuild-release      - wipe and build release binaries"
	@echo " run                  - run debug binary"
	@echo " run-release          - run release binary"
	@echo " debug                - run debug binary with debugger"
	@echo " debug-release        - run release binary with debugger"
	@echo " test                 - build and run tests"
	@echo " test-cov-hs   		 - build and run host stack tests with coverage"
	@echo " test-cov-both	  	 - build and run python and host stack tests, merge coverage data"
	@echo " test-help            - show help on test framework"
	@echo " run-vat              - run vpp-api-test tool"
	@echo " pkg-deb              - build DEB packages"
	@echo " pkg-deb-debug        - build DEB debug packages"
	@echo " pkg-snap             - build SNAP package"
	@echo " snap-clean           - clean up snap build environment"
	@echo " pkg-rpm              - build RPM packages"
	@echo " install-ext-dep[s]   - install external development dependencies"
	@echo " ctags                - (re)generate ctags database"
	@echo " gtags                - (re)generate gtags database"
	@echo " cscope               - (re)generate cscope database"
	@echo " compdb               - (re)generate compile_commands.json"
	@echo " checkstyle           - check coding style"
	@echo " checkstyle-commit    - check commit message format"
	@echo " checkstyle-python    - check python coding style using 'black' formatter"
	@echo " checkstyle-api       - check api for incompatible changes"
	@echo " fixstyle             - fix coding style"
	@echo " fixstyle-python      - fix python coding style using 'black' formatter"
	@echo " doxygen              - DEPRECATED - use 'make docs'"
	@echo " bootstrap-doxygen    - DEPRECATED"
	@echo " wipe-doxygen         - DEPRECATED"
	@echo " checkfeaturelist     - check FEATURE.yaml according to schema"
	@echo " featurelist          - dump feature list in markdown"
	@echo " json-api-files       - (re)-generate json api files"
	@echo " json-api-files-debug - (re)-generate json api files for debug target"
	@echo " go-api-files         - (re)-generate golang api files"
	@echo " docs                 - Build the Sphinx documentation"
	@echo " docs-venv            - Build the virtual environment for the Sphinx docs"
	@echo " docs-clean           - Remove the generated files from the Sphinx docs"
	@echo " docs-rebuild         - Rebuild all of the Sphinx documentation"
	@echo ""
	@echo "Make Arguments:"
	@echo " V=[0|1]                  - set build verbosity level"
	@echo " STARTUP_CONF=<path>      - startup configuration file"
	@echo "                            (e.g. /etc/vpp/startup.conf)"
	@echo " STARTUP_DIR=<path>       - startup directory (e.g. /etc/vpp)"
	@echo "                            It also sets STARTUP_CONF if"
	@echo "                            startup.conf file is present"
	@echo " GDB=<path>               - gdb binary to use for debugging"
	@echo " PLATFORM=<name>          - target platform. default is vpp"
	@echo " DPDK_CONFIG=<conf>       - add specified dpdk config commands to"
	@echo "                            autogenerated startup.conf"
	@echo "                            (e.g. \"no-pci\" )"
	@echo " SAMPLE_PLUGIN=yes        - in addition build/run/debug sample plugin"
	@echo " DISABLED_PLUGINS=<list>  - comma separated list of plugins which"
	@echo "                            should not be loaded"
	@echo ""
	@echo "Current Argument Values:"
	@echo " V                 = $(V)"
	@echo " STARTUP_CONF      = $(STARTUP_CONF)"
	@echo " STARTUP_DIR       = $(STARTUP_DIR)"
	@echo " GDB               = $(GDB)"
	@echo " PLATFORM          = $(PLATFORM)"
	@echo " DPDK_VERSION      = $(DPDK_VERSION)"
	@echo " DPDK_CONFIG       = $(DPDK_CONFIG)"
	@echo " SAMPLE_PLUGIN     = $(SAMPLE_PLUGIN)"
	@echo " DISABLED_PLUGINS  = $(DISABLED_PLUGINS)"

$(BR)/.deps.ok:
ifeq ($(findstring y,$(UNATTENDED)),y)
	$(MAKE) install-dep
endif
ifeq ($(filter ubuntu debian linuxmint,$(OS_ID)),$(OS_ID))
	@MISSING=$$(apt-get install -y -qq -s $(DEB_DEPENDS) | grep "^Inst ") ; \
	if [ -n "$$MISSING" ] ; then \
	  echo "\nPlease install missing packages: \n$$MISSING\n" ; \
	  echo "by executing \"make install-dep\"\n" ; \
	  exit 1 ; \
	fi ; \
	exit 0
else ifneq ("$(wildcard /etc/redhat-release)","")
	@for i in $(RPM_DEPENDS) ; do \
	    RPM=$$(basename -s .rpm "$${i##*/}" | cut -d- -f1,2,3,4)  ;	\
	    MISSING+=$$(rpm -q $$RPM | grep "^package")	   ;    \
	done							   ;	\
	if [ -n "$$MISSING" ] ; then \
	  echo "Please install missing RPMs: \n$$MISSING\n" ; \
	  echo "by executing \"make install-dep\"\n" ; \
	  exit 1 ; \
	fi ; \
	exit 0
endif
	@touch $@

.PHONY: bootstrap
bootstrap:
	@echo "'make bootstrap' is not needed anymore"

.PHONY: install-dep
install-dep:
ifeq ($(filter ubuntu debian linuxmint,$(OS_ID)),$(OS_ID))
	@sudo -E apt-get update
	@sudo -E apt-get $(APT_ARGS) $(CONFIRM) $(FORCE) install $(DEB_DEPENDS)
else ifneq ("$(wildcard /etc/redhat-release)","")
ifeq ($(OS_ID),rhel)
	@sudo -E yum-config-manager --enable rhel-server-rhscl-7-rpms
	@sudo -E yum groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E yum install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E debuginfo-install $(CONFIRM) glibc openssl-libs zlib
else ifeq ($(OS_ID),rocky)
	@sudo -E dnf install $(CONFIRM) dnf-plugins-core epel-release
	@sudo -E dnf config-manager --set-enabled \
          $(shell dnf repolist all 2>/dev/null|grep -i crb|cut -d' ' -f1|grep -v source)
	@sudo -E dnf groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E dnf install $(CONFIRM) $(RPM_DEPENDS)
else ifeq ($(OS_ID)-$(OS_VERSION_ID),centos-8)
	@sudo -E dnf install $(CONFIRM) dnf-plugins-core epel-release
	@sudo -E dnf config-manager --set-enabled \
          $(shell dnf repolist all 2>/dev/null|grep -i powertools|cut -d' ' -f1|grep -v source)
	@sudo -E dnf groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E dnf install --skip-broken $(CONFIRM) $(RPM_DEPENDS)
else ifeq ($(OS_ID),centos)
	@sudo -E yum install $(CONFIRM) centos-release-scl-rh epel-release
	@sudo -E yum groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E yum install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E yum install $(CONFIRM) --enablerepo=base-debuginfo $(RPM_DEPENDS_DEBUG)
else ifeq ($(OS_ID),fedora)
	@sudo -E dnf groupinstall $(CONFIRM) $(RPM_DEPENDS_GROUPS)
	@sudo -E dnf install $(CONFIRM) $(RPM_DEPENDS)
	@sudo -E debuginfo-install $(CONFIRM) glibc openssl-libs zlib
endif
else ifeq ($(filter opensuse-leap-15.3 opensuse-leap-15.4 ,$(OS_ID)-$(OS_VERSION_ID)),$(OS_ID)-$(OS_VERSION_ID))
	@sudo -E zypper refresh
	@sudo -E zypper install  -y $(RPM_SUSE_DEPENDS)
else
	$(error "This option currently works only on Ubuntu, Debian, RHEL, CentOS or openSUSE-leap systems")
endif
	git config commit.template .git_commit_template.txt

.PHONY: install-deps
install-deps: install-dep

define make
	@$(MAKE) -C $(BR) PLATFORM=$(PLATFORM) TAG=$(1) $(2)
endef

$(BR)/scripts/.version:
ifneq ("$(wildcard /etc/redhat-release)","")
	$(shell $(BR)/scripts/version rpm-string > $(BR)/scripts/.version)
else
	$(shell $(BR)/scripts/version > $(BR)/scripts/.version)
endif

DIST_FILE = $(BR)/vpp-$(shell src/scripts/version).tar
DIST_SUBDIR = vpp-$(shell src/scripts/version|cut -f1 -d-)

.PHONY: dist
dist:
	@if git rev-parse 2> /dev/null ; then \
	    git archive \
	      --prefix=$(DIST_SUBDIR)/ \
	      --format=tar \
	      -o $(DIST_FILE) \
	    HEAD ; \
	    git describe --long > $(BR)/.version ; \
	else \
	    (cd .. ; tar -cf $(DIST_FILE) $(DIST_SUBDIR) --exclude=*.tar) ; \
	    src/scripts/version > $(BR)/.version ; \
	fi
	@tar --append \
	  --file $(DIST_FILE) \
	  --transform='s,.*/.version,$(DIST_SUBDIR)/src/scripts/.version,' \
	  $(BR)/.version
	@$(RM) $(BR)/.version $(DIST_FILE).xz
	@xz -v --threads=0 $(DIST_FILE)
	@$(RM) $(BR)/vpp-latest.tar.xz
	@ln -rs $(DIST_FILE).xz $(BR)/vpp-latest.tar.xz

.PHONY: build
build: $(BR)/.deps.ok
	$(call make,$(PLATFORM)_debug,$(addsuffix -install,$(TARGETS)))

.PHONY: wipedist
wipedist:
	@$(RM) $(BR)/*.tar.xz

.PHONY: wipe
wipe: wipedist test-wipe $(BR)/.deps.ok
	$(call make,$(PLATFORM)_debug,$(addsuffix -wipe,$(TARGETS)))
	@find . -type f -name "*.api.json" ! -path "./src/*" -exec rm {} \;

.PHONY: rebuild
rebuild: wipe build

.PHONY: build-release
build-release: $(BR)/.deps.ok
	$(call make,$(PLATFORM),$(addsuffix -install,$(TARGETS)))

.PHONY: build-vpp-gcov
build-vpp-gcov:
	$(call test,vpp_gcov)

.PHONY: wipe-release
wipe-release: test-wipe $(BR)/.deps.ok
	$(call make,$(PLATFORM),$(addsuffix -wipe,$(TARGETS)))

.PHONY: rebuild-release
rebuild-release: wipe-release build-release

export TEST_DIR ?= $(WS_ROOT)/test

define test
	$(if $(filter-out $(2),retest),$(MAKE) -C $(BR) PLATFORM=vpp TAG=$(1) CC=$(CC) vpp-install,)
	$(eval libs:=lib lib64)
	$(MAKE) -C test \
	  VPP_BUILD_DIR=$(BR)/build-$(1)-native/vpp \
	  VPP_BIN=$(BR)/install-$(1)-native/vpp/bin/vpp \
	  VPP_INSTALL_PATH=$(BR)/install-$(1)-native/ \
	  EXTENDED_TESTS=$(EXTENDED_TESTS) \
	  TEST_GCOV=$(TEST_GCOV) \
	  PYTHON=$(PYTHON) \
	  OS_ID=$(OS_ID) \
	  RND_SEED=$(RND_SEED) \
	  CACHE_OUTPUT=$(CACHE_OUTPUT) \
	  TAG=$(1) \
	  $(2)
endef

.PHONY: test
test:
ifeq ($(CC),cc)
	$(eval CC=clang)
endif
	$(call test,vpp,test)

.PHONY: test-debug
test-debug:
ifeq ($(CC),cc)
	$(eval CC=clang)
endif
	$(call test,vpp_debug,test)

.PHONY: test-cov
test-cov:
	$(eval CC=gcc)
	$(eval TEST_GCOV=1)
	$(call test,vpp_gcov,cov)

.PHONY: test-cov-hs
test-cov-hs:
	@$(MAKE) -C extras/hs-test build-cov
	@$(MAKE) -C extras/hs-test test-cov

.PHONY: test-cov-both
test-cov-both:
	@echo "Running Python, Golang tests and merging coverage reports."
	find $(BR) -name '*.gcda' -delete
	@$(MAKE) test-cov
	find $(BR) -name '*.gcda' -delete
	@$(MAKE) test-cov-hs
	@$(MAKE) cov-merge

.PHONY: test-cov-build
test-cov-build:
	$(eval CC=gcc)
	$(eval TEST_GCOV=1)
	$(call test,vpp_gcov,test)

.PHONY: test-cov-prep
test-cov-prep:
	$(eval CC=gcc)
	$(call test,vpp_gcov,cov-prep)

.PHONY: test-cov-post
test-cov-post:
	$(eval CC=gcc)
	$(call test,vpp_gcov,cov-post)

.PHONY: cov-merge
cov-merge:
	@lcov --add-tracefile $(BR)/test-coverage-merged/coverage-filtered.info \
		-a $(BR)/test-coverage-merged/coverage-filtered1.info -o $(BR)/test-coverage-merged/coverage-merged.info
	@genhtml $(BR)/test-coverage-merged/coverage-merged.info \
		--output-directory $(BR)/test-coverage-merged/html
	@echo "Code coverage report is in $(BR)/test-coverage-merged/html/index.html"

.PHONY: test-all
test-all:
	$(eval EXTENDED_TESTS=1)
	$(call test,vpp,test)

.PHONY: test-all-debug
test-all-debug:
	$(eval EXTENDED_TESTS=1)
	$(call test,vpp_debug,test)

.PHONY: test-all-cov
test-all-cov:
	$(eval CC=gcc)
	$(eval TEST_GCOV=1)
	$(eval EXTENDED_TESTS=1)
	$(call test,vpp_gcov,test)

.PHONY: papi-wipe
papi-wipe: test-wipe-papi
	$(call banner,"This command is deprecated. Please use 'test-wipe-papi'")

.PHONY: test-wipe-papi
test-wipe-papi:
	@$(MAKE) -C test wipe-papi

.PHONY: test-help
test-help:
	@$(MAKE) -C test help

.PHONY: test-wipe
test-wipe:
	@$(MAKE) -C test wipe

.PHONY: test-shell
test-shell:
	$(call test,vpp,shell)

.PHONY: test-shell-debug
test-shell-debug:
	$(call test,vpp_debug,shell)

.PHONY: test-shell-cov
test-shell-cov:
	$(eval CC=gcc)
	$(eval TEST_GCOV=1)
	$(call test,vpp_gcov,shell)

.PHONY: test-dep
test-dep:
	@$(MAKE) -C test test-dep

.PHONY: test-doc
test-doc:
	@echo "make test-doc is DEPRECATED: use 'make docs'"
	sleep 300

.PHONY: test-wipe-doc
test-wipe-doc:
	@echo "make test-wipe-doc is DEPRECATED"
	sleep 300

.PHONY: test-wipe-cov
test-wipe-cov:
	$(call make,$(PLATFORM)_gcov,$(addsuffix -wipe,$(TARGETS)))
	@$(MAKE) -C test wipe-cov

.PHONY: test-wipe-all
test-wipe-all:
	@$(MAKE) -C test wipe-all

# Note: All python venv consolidated in test/Makefile, test/requirements*.txt
.PHONY: test-checkstyle
test-checkstyle:
	$(warning test-checkstyle is deprecated. Running checkstyle-python.")
	@$(MAKE) -C test checkstyle-python-all

# Note: All python venv consolidated in test/Makefile, test/requirements*.txt
.PHONY: test-checkstyle-diff
test-checkstyle-diff:
	$(warning test-checkstyle-diff is deprecated. Running checkstyle-python.")
	@$(MAKE) -C test checkstyle-python-all

.PHONY: test-refresh-deps
test-refresh-deps:
	@$(MAKE) -C test refresh-deps

.PHONY: retest
retest:
	$(call test,vpp,retest)

.PHONY: retest-debug
retest-debug:
	$(call test,vpp_debug,retest)

.PHONY: retest-all
retest-all:
	$(eval EXTENDED_TESTS=1)
	$(call test,vpp,retest)

.PHONY: retest-all-debug
retest-all-debug:
	$(eval EXTENDED_TESTS=1)
	$(call test,vpp_debug,retest)

.PHONY: test-start-vpp-in-gdb
test-start-vpp-in-gdb:
	$(call test,vpp,start-gdb)

.PHONY: test-start-vpp-debug-in-gdb
test-start-vpp-debug-in-gdb:
	$(call test,vpp_debug,start-gdb)

ifeq ("$(wildcard $(STARTUP_CONF))","")
define run
	@echo "WARNING: STARTUP_CONF not defined or file doesn't exist."
	@echo "         Running with minimal startup config: $(MINIMAL_STARTUP_CONF)\n"
	@cd $(STARTUP_DIR) && \
	  $(SUDO) $(2) $(1)/vpp/bin/vpp $(MINIMAL_STARTUP_CONF)
endef
else
define run
	@cd $(STARTUP_DIR) && \
	  $(SUDO) $(2) $(1)/vpp/bin/vpp $(shell cat $(STARTUP_CONF) | sed -e 's/#.*//')
endef
endif

%.files: .FORCE
	@find src -name '*.[chS]' > $@

.FORCE:

.PHONY: run
run:
	$(call run, $(BR)/install-$(PLATFORM)_debug-native)

.PHONY: run-release
run-release:
	$(call run, $(BR)/install-$(PLATFORM)-native)

.PHONY: debug
debug:
	$(call run, $(BR)/install-$(PLATFORM)_debug-native,$(GDB) $(GDB_ARGS) --args)

.PHONY: build-coverity
build-coverity:
	$(call make,$(PLATFORM)_coverity,install-packages)
	@$(MAKE) -C build-root PLATFORM=vpp TAG=vpp_coverity libmemif-install

.PHONY: debug-release
debug-release:
	$(call run, $(BR)/install-$(PLATFORM)-native,$(GDB) $(GDB_ARGS) --args)

.PHONY: build-vat
build-vat:
	$(call make,$(PLATFORM)_debug,vpp-api-test-install)

.PHONY: run-vat
run-vat:
	@$(SUDO) $(BR)/install-$(PLATFORM)_debug-native/vpp/bin/vpp_api_test

.PHONY: pkg-deb
pkg-deb:
	$(call make,$(PLATFORM),vpp-package-deb)

.PHONY: pkg-snap
pkg-snap:
	cd extras/snap ;			\
        ./prep ;				\
	SNAPCRAFT_BUILD_ENVIRONMENT_MEMORY=8G 	\
	SNAPCRAFT_BUILD_ENVIRONMENT_CPU=6 	\
	snapcraft --debug

.PHONY: snap-clean
snap-clean:
	cd extras/snap ;			\
        snapcraft clean ;			\
	rm -f *.snap *.tgz

.PHONY: pkg-deb-debug
pkg-deb-debug:
	$(call make,$(PLATFORM)_debug,vpp-package-deb)

.PHONY: pkg-rpm
pkg-rpm: dist
	$(MAKE) -C extras/rpm

.PHONY: pkg-srpm
pkg-srpm: dist
	$(MAKE) -C extras/rpm srpm

.PHONY: install-ext-deps
install-ext-deps:
	$(MAKE) -C build/external install-$(PKG)

.PHONY: install-ext-dep
install-ext-dep: install-ext-deps

.PHONY: json-api-files
json-api-files:
	$(WS_ROOT)/src/tools/vppapigen/generate_json.py

.PHONY: json-api-files-debug
json-api-files-debug:
	$(WS_ROOT)/src/tools/vppapigen/generate_json.py --debug-target

.PHONY: go-api-files
go-api-files: json-api-files
	$(WS_ROOT)/src/tools/vppapigen/generate_go.py $(ARGS)

.PHONY: ctags
ctags: ctags.files
	@ctags --totals --tag-relative=yes -L $<
	@rm $<

.PHONY: gtags
gtags: ctags
	@gtags --gtagslabel=ctags

.PHONY: cscope
cscope: cscope.files
	@cscope -b -q -v

.PHONY: compdb
compdb:
	@ninja -C build-root/build-vpp_debug-native/vpp build.ninja
	@ninja -C build-root/build-vpp_debug-native/vpp -t compdb | \
	  src/scripts/compdb_cleanup.py > compile_commands.json

.PHONY: checkstyle
checkstyle: checkfeaturelist
	@extras/scripts/checkstyle.sh

.PHONY: checkstyle-commit
checkstyle-commit:
	@extras/scripts/check_commit_msg.sh

.PHONY: checkstyle-test
checkstyle-test:
	$(warning test-checkstyle is deprecated. Running checkstyle-python.")
	@$(MAKE) -C test checkstyle-python-all

# Note: All python venv consolidated in test/Makefile, test/requirements*.txt
.PHONY: checkstyle-python
checkstyle-python:
	@$(MAKE) -C test checkstyle-python-all

.PHONY: checkstyle-go
checkstyle-go:
	@$(MAKE) -C extras/hs-test checkstyle-go

.PHONY: fixstyle-go
fixstyle-go:
	@$(MAKE) -C extras/hs-test fixstyle-go

.PHONY: checkstyle-all
checkstyle-all: checkstyle-commit checkstyle checkstyle-python docs-spell

.PHONY: fixstyle
fixstyle:
	@extras/scripts/checkstyle.sh --fix

# Note: All python venv consolidated in test/Makefile, test/requirements*.txt
.PHONY: fixstyle-python
fixstyle-python:
	@$(MAKE) -C test fixstyle-python-all

.PHONY: checkstyle-api
checkstyle-api:
	@extras/scripts/crcchecker.py --check-patchset

# necessary because Bug 1696324 - Update to python3.6 breaks PyYAML dependencies
# Status:	CLOSED CANTFIX
# https://bugzilla.redhat.com/show_bug.cgi?id=1696324
.PHONY: centos-pyyaml
centos-pyyaml:
ifeq ($(OS_ID)-$(OS_VERSION_ID),centos-8)
	@sudo -E yum install $(CONFIRM) python3-pyyaml
endif

.PHONY: featurelist
featurelist: centos-pyyaml
	@extras/scripts/fts.py --all --markdown

.PHONY: checkfeaturelist
checkfeaturelist: centos-pyyaml
	@extras/scripts/fts.py --validate --all

#
# Build the documentation
#

.PHONY: bootstrap-doxygen
bootstrap-doxygen:
	@echo "make bootstrap-doxygen is DEPRECATED"
	sleep 300

.PHONY: doxygen
doxygen: docs
	@echo "make doxygen is DEPRECATED: use 'make docs'"
	sleep 300

.PHONY: wipe-doxygen
wipe-doxygen:
	@echo "make wipe-doxygen is DEPRECATED"
	sleep 300

.PHONY: docs-%
docs-%:
	@$(MAKE) -C $(WS_ROOT)/docs $*

.PHONY: docs
docs:
	@$(MAKE) -C $(WS_ROOT)/docs docs

.PHONY: pkg-verify
pkg-verify: install-dep $(BR)/.deps.ok install-ext-deps
	$(call banner,"Building for PLATFORM=vpp")
	@$(MAKE) -C build-root PLATFORM=vpp TAG=vpp wipe-all install-packages
	$(call banner,"Building sample-plugin")
	@$(MAKE) -C build-root PLATFORM=vpp TAG=vpp sample-plugin-install
	$(call banner,"Building libmemif")
	@$(MAKE) -C build-root PLATFORM=vpp TAG=vpp libmemif-install
	$(call banner,"Building $(PKG) packages")
	@$(MAKE) pkg-$(PKG)

# Note: 'make verify' target is not used by ci-management scripts
MAKE_VERIFY_GATE_OS ?= ubuntu-22.04
.PHONY: verify
verify: pkg-verify
ifeq ($(OS_ID)-$(OS_VERSION_ID),$(MAKE_VERIFY_GATE_OS))
	$(call banner,"Testing vppapigen")
	@src/tools/vppapigen/test_vppapigen.py
	$(call banner,"Running tests")
	@$(MAKE) COMPRESS_FAILED_TEST_LOGS=yes RETRIES=3 test
else
	$(call banner,"Skipping tests. Tests under 'make verify' supported on $(MAKE_VERIFY_GATE_OS)")
endif

.PHONY: check-dpdk-mlx
check-dpdk-mlx:
	@[ $$($(MAKE) -sC build/external dpdk-show-DPDK_MLX_DEFAULT) = y ]