github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/Makefile (about)

     1  .PHONY: help
     2  help:
     3  	@echo "Usage: \n"
     4  	@sed -n 's/^## //p' ${MAKEFILE_LIST} | sort | column -t -s ':' |  sed -e 's/^/ /'
     5  
     6  # Export this first, incase we want to change it in the included makefiles.
     7  export CGO_ENABLED=0
     8  
     9  include scripts/dqlite/Makefile
    10  
    11  #
    12  # Makefile for juju-core.
    13  #
    14  PROJECT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
    15  PROJECT := github.com/juju/juju
    16  
    17  GOOS=$(shell go env GOOS)
    18  GOARCH=$(shell go env GOARCH)
    19  GOHOSTOS=$(shell go env GOHOSTOS)
    20  GOHOSTARCH=$(shell go env GOHOSTARCH)
    21  GO_MOD_VERSION=$(shell grep "^go" go.mod | awk '{print $$2}')
    22  GO_INSTALLED_VERSION=$(shell go version | awk '{print $$3}' | sed -e /.*go/s///)
    23  GO_INSTALL_PATH=$(if $(value GOBIN),$(value GOBIN),$(shell go env GOPATH)/bin)
    24  
    25  # Build number passed in must be a monotonic int representing
    26  # the build.
    27  JUJU_BUILD_NUMBER ?=
    28  
    29  # JUJU_VERSION is the JUJU version currently being represented in this
    30  # repository.
    31  JUJU_VERSION=$(shell go run -ldflags "-X $(PROJECT)/version.build=$(JUJU_BUILD_NUMBER)" version/helper/main.go)
    32  
    33  # BUILD_DIR is the directory relative to this project where we place build
    34  # artifacts created by this Makefile.
    35  BUILD_DIR ?= $(PROJECT_DIR)/_build
    36  BIN_DIR ?= ${BUILD_DIR}/${GOOS}_${GOARCH}/bin
    37  
    38  # JUJU_METADATA_SOURCE is the directory where we place simple streams archives
    39  # for built juju binaries.
    40  JUJU_METADATA_SOURCE ?= ${BUILD_DIR}/simplestreams
    41  
    42  # TEST_PACKAGE_LIST is the path to a file that is a newline delimited list of
    43  # packages to test. This file must be sorted.
    44  TEST_PACKAGE_LIST ?=
    45  
    46  # bin_platform_path calculates the bin directory path for build artifacts for
    47  # the list of Go style platforms passed to this macro. For example
    48  # linux/amd64 linux/arm64
    49  bin_platform_paths = $(addprefix ${BUILD_DIR}/, $(addsuffix /bin, $(subst /,_,${1})))
    50  
    51  # tool_platform_paths takes a juju binary to be built and the platform that it
    52  # is to be built for and returns a list of paths for that binary to be output.
    53  tool_platform_paths = $(addsuffix /${1},$(call bin_platform_paths,${2}))
    54  
    55  # simplestream_paths takes a list of Go style platforms to calculate the
    56  # paths to their respective simplestreams agent binary archives.
    57  simplestream_paths = $(addprefix ${JUJU_METADATA_SOURCE}/, $(addprefix tools/released/juju-${JUJU_VERSION}-, $(addsuffix .tgz,$(subst /,-,${1}))))
    58  
    59  # CLIENT_PACKAGE_PLATFORMS defines a white space seperated list of platforms
    60  # to build the Juju client binaries for. Platforms are defined as GO style
    61  # OS_ARCH.
    62  CLIENT_PACKAGE_PLATFORMS ?= $(GOOS)/$(GOARCH)
    63  
    64  # AGENT_PACKAGE_PLATFORMS defines a white space seperated list of platforms
    65  # to build the Juju agent binaries for. Platforms are defined as GO style
    66  # OS_ARCH.
    67  AGENT_PACKAGE_PLATFORMS ?= $(GOOS)/$(GOARCH)
    68  
    69  # OCI_IMAGE_PLATFORMS defines a white space seperated list of platforms
    70  # to build the Juju OCI images for. Platforms are defined as GO style
    71  # OS_ARCH.
    72  OCI_IMAGE_PLATFORMS ?= linux/$(GOARCH)
    73  
    74  # Build tags passed to go install/build.
    75  # Passing no-dqlite will disable building with dqlite.
    76  # Example: BUILD_TAGS="minimal provider_kubernetes"
    77  BUILD_TAGS ?= 
    78  
    79  # EXTRA_BUILD_TAGS is not passed in, but built up from context.
    80  EXTRA_BUILD_TAGS =
    81  ifeq (,$(findstring no-dqlite,$(BUILD_TAGS)))
    82  EXTRA_BUILD_TAGS += libsqlite3
    83  EXTRA_BUILD_TAGS += dqlite
    84  endif
    85  
    86  # FINAL_BUILD_TAGS is the final list of build tags.
    87  FINAL_BUILD_TAGS=$(shell echo "$(BUILD_TAGS) $(EXTRA_BUILD_TAGS)" | awk '{$$1=$$1};1' | tr ' ' ',')
    88  
    89  # GIT_COMMIT the current git commit of this repository
    90  GIT_COMMIT ?= $(shell git -C $(PROJECT_DIR) rev-parse HEAD 2>/dev/null)
    91  
    92  # Build flag passed to go -mod defaults to readonly to support go workspaces.
    93  # CI should set this to vendor
    94  JUJU_GOMOD_MODE ?= readonly
    95  
    96  # If .git directory is missing, we are building out of an archive, otherwise report
    97  # if the tree that is checked out is dirty (modified) or clean.
    98  GIT_TREE_STATE = $(if $(shell git -C $(PROJECT_DIR) rev-parse --is-inside-work-tree 2>/dev/null | grep -e 'true'),$(if $(shell git -C $(PROJECT_DIR) status --porcelain),dirty,clean),archive)
    99  
   100  # BUILD_AGENT_TARGETS is a list of make targets that get built, that fall under
   101  # the category of Juju agents, that are not CGO. These targets are also the ones
   102  # we are more then likely wanting to cross compile.
   103  # NOTES:
   104  # - We filter pebble here for only linux builds as that is only what it will
   105  #   compile for at the moment.
   106  define BUILD_AGENT_TARGETS
   107  	$(call tool_platform_paths,jujuc,$(filter-out windows%,${AGENT_PACKAGE_PLATFORMS})) \
   108  	$(call tool_platform_paths,jujud,$(filter linux%,${AGENT_PACKAGE_PLATFORMS})) \
   109  	$(call tool_platform_paths,containeragent,$(filter-out windows%,${AGENT_PACKAGE_PLATFORMS})) \
   110  	$(call tool_platform_paths,pebble,$(filter linux%,${AGENT_PACKAGE_PLATFORMS}))
   111  endef
   112  
   113  # BUILD_CGO_AGENT_TARGETS is a list of make targets that get built, that fall
   114  # under the category of Juju agents, that are CGO. These targets are also the
   115  # ones we are more then likely wanting to cross compile.
   116  define BUILD_CGO_AGENT_TARGETS
   117  	$(call tool_platform_paths,jujud-controller,$(filter linux%,${AGENT_PACKAGE_PLATFORMS}))
   118  endef
   119  
   120  # BUILD_CLIENT_TARGETS is a list of make targets that get built that fall under
   121  # the category of Juju clients. These targets are also less likely to be cross
   122  # compiled
   123  define BUILD_CLIENT_TARGETS
   124  	$(call tool_platform_paths,juju,${CLIENT_PACKAGE_PLATFORMS}) \
   125  	$(call tool_platform_paths,juju-metadata,${CLIENT_PACKAGE_PLATFORMS})
   126  endef
   127  
   128  # SIMPLESTREAMS_TARGETS is a list of make targets that get built when a
   129  # user asks for simplestreams to be built. Because simplestreams are mainly
   130  # mainly concerned with that of packaging juju agent binaries we work off of
   131  # the Go style platforms.
   132  define SIMPLESTREAMS_TARGETS
   133  	$(call simplestream_paths,${AGENT_PACKAGE_PLATFORMS})
   134  endef
   135  
   136  # INSTALL_TARGETS is a list of make targets that get installed when make
   137  # install is run.
   138  define INSTALL_TARGETS
   139  	juju \
   140  	jujuc \
   141  	jujud \
   142  	jujud-controller \
   143  	containeragent \
   144  	juju-metadata
   145  endef
   146  
   147  # Windows doesn't support the agent binaries
   148  ifeq ($(GOOS), windows)
   149  	INSTALL_TARGETS = juju \
   150                        juju-metadata
   151  endif
   152  
   153  # We only add pebble to the list of install targets if we are building for linux
   154  ifeq ($(GOOS), linux)
   155  	INSTALL_TARGETS += pebble
   156  endif
   157  
   158  # Allow the tests to take longer on restricted platforms.
   159  ifeq ($(shell echo "${GOARCH}" | sed -E 's/.*(arm|arm64|ppc64le|ppc64|s390x).*/golang/'), golang)
   160  	TEST_TIMEOUT ?= 5400s
   161  else
   162  	TEST_TIMEOUT ?= 2700s
   163  endif
   164  TEST_TIMEOUT := $(TEST_TIMEOUT)
   165  
   166  TEST_ARGS ?=
   167  # Limit concurrency on s390x.
   168  ifeq ($(shell echo "${GOARCH}" | sed -E 's/.*(s390x).*/golang/'), golang)
   169  	TEST_ARGS += -p 4
   170  endif
   171  
   172  # Enable coverage testing.
   173  ifeq ($(COVERAGE_CHECK), 1)
   174  	TEST_ARGS += -coverprofile=coverage.txt -covermode=atomic
   175  endif
   176  
   177  # Enable verbose testing for reporting.
   178  ifeq ($(VERBOSE_CHECK), 1)
   179  	CHECK_ARGS = -v
   180  endif
   181  
   182  define link_flags_version
   183  -X $(PROJECT)/version.GitCommit=$(GIT_COMMIT) \
   184  -X $(PROJECT)/version.GitTreeState=$(GIT_TREE_STATE) \
   185  -X $(PROJECT)/version.build=$(JUJU_BUILD_NUMBER) \
   186  -X $(PROJECT)/version.GoBuildTags=$(FINAL_BUILD_TAGS)
   187  endef
   188  
   189  # Compile with debug flags if requested.
   190  ifeq ($(DEBUG_JUJU), 1)
   191      COMPILE_FLAGS = -gcflags "all=-N -l"
   192      LINK_FLAGS =  "$(link_flags_version)"
   193  	CGO_LINK_FLAGS = "-linkmode 'external' -extldflags '-static' $(link_flags_version)"
   194  else
   195      LINK_FLAGS = "-s -w -extldflags '-static' $(link_flags_version)"
   196  	CGO_LINK_FLAGS = "-s -w -linkmode 'external' -extldflags '-static' $(link_flags_version)"
   197  endif
   198  
   199  define DEPENDENCIES
   200    ca-certificates
   201    bzip2
   202    distro-info-data
   203    git
   204    zip
   205  endef
   206  
   207  # run_go_build is a canned command sequence for the steps required to build a
   208  # juju package. It's expected that the make target using this sequence has a
   209  # local variable defined for PACKAGE. An example of PACKAGE would be
   210  # PACKAGE=github.com/juju/juju
   211  #
   212  # This canned command also allows building for architectures defined as
   213  # ppc64el. Because of legacy Juju we use the arch ppc64el over the go defined
   214  # arch of ppc64le. This canned command will do a last minute transformation of
   215  # the string we build the "correct" go architecture. However the build result
   216  # will still be placed at the expected location with names matching ppc64el.
   217  define run_go_build
   218  	$(eval OS = $(word 1,$(subst _, ,$*)))
   219  	$(eval ARCH = $(word 2,$(subst _, ,$*)))
   220  	$(eval BBIN_DIR = ${BUILD_DIR}/${OS}_${ARCH}/bin)
   221  	$(eval BUILD_ARCH = $(subst ppc64el,ppc64le,${ARCH}))
   222  	@@mkdir -p ${BBIN_DIR}
   223  	@echo "Building ${PACKAGE} for ${OS}/${ARCH}"
   224  	@env GOOS=${OS} \
   225  		GOARCH=${BUILD_ARCH} \
   226  		go build \
   227  			-mod=$(JUJU_GOMOD_MODE) \
   228  			-tags=$(FINAL_BUILD_TAGS) \
   229  			-o ${BBIN_DIR} \
   230  			$(COMPILE_FLAGS) \
   231  			-ldflags $(LINK_FLAGS) \
   232  			-v ${PACKAGE}
   233  endef
   234  
   235  define run_cgo_build
   236  	$(eval OS = $(word 1,$(subst _, ,$*)))
   237  	$(eval ARCH = $(word 2,$(subst _, ,$*)))
   238  	$(eval BBIN_DIR = ${BUILD_DIR}/${OS}_${ARCH}/bin)
   239  	$(eval BUILD_ARCH = $(subst ppc64el,ppc64le,${ARCH}))
   240  	@@mkdir -p ${BBIN_DIR}
   241  	@echo "Building ${PACKAGE} for ${OS}/${ARCH}"
   242  	@env PATH="${MUSL_BIN_PATH}:${PATH}" \
   243  		CC="musl-gcc" \
   244  		CGO_CFLAGS="-I${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}/include" \
   245  		CGO_LDFLAGS="-L${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH} -luv -lraft -ldqlite -llz4 -lsqlite3" \
   246  		CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" \
   247  		LD_LIBRARY_PATH="${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}" \
   248  		CGO_ENABLED=1 \
   249  		GOOS=${OS} \
   250  		GOARCH=${BUILD_ARCH} \
   251  		go build \
   252  			-mod=$(JUJU_GOMOD_MODE) \
   253  			-tags=$(FINAL_BUILD_TAGS) \
   254  			-o ${BBIN_DIR} \
   255  			${COMPILE_FLAGS} \
   256  			-ldflags ${CGO_LINK_FLAGS} \
   257  			-v ${PACKAGE}
   258  endef
   259  
   260  define run_go_install
   261  	@echo "Installing ${PACKAGE}"
   262  	@go install \
   263  		-mod=$(JUJU_GOMOD_MODE) \
   264  		-tags=$(FINAL_BUILD_TAGS) \
   265  		$(COMPILE_FLAGS) \
   266  		-ldflags $(LINK_FLAGS) \
   267  		-v ${PACKAGE}
   268  endef
   269  
   270  define run_cgo_install
   271  	@echo "Installing ${PACKAGE}"
   272  	@env PATH="${MUSL_BIN_PATH}:${PATH}" \
   273  		CC="musl-gcc" \
   274  		CGO_CFLAGS="-I${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}/include" \
   275  		CGO_LDFLAGS="-L${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH} -luv -lraft -ldqlite -llz4 -lsqlite3" \
   276  		CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" \
   277  		LD_LIBRARY_PATH="${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}" \
   278  		CGO_ENABLED=1 \
   279  		GOOS=${GOOS} \
   280  		GOARCH=${GOARCH} \
   281  		go install \
   282  			-mod=$(JUJU_GOMOD_MODE) \
   283  			-tags=$(FINAL_BUILD_TAGS) \
   284  			${COMPILE_FLAGS} \
   285  			-ldflags ${CGO_LINK_FLAGS} \
   286  			-v ${PACKAGE}
   287  endef
   288  
   289  default: build
   290  
   291  .PHONY: juju
   292  juju: PACKAGE = github.com/juju/juju/cmd/juju
   293  juju:
   294  ## juju: Install juju without updating dependencies
   295  	${run_go_install}
   296  
   297  .PHONY: jujuc
   298  jujuc: PACKAGE = github.com/juju/juju/cmd/jujuc
   299  jujuc:
   300  ## jujuc: Install jujuc without updating dependencies
   301  	${run_go_install}
   302  
   303  .PHONY: jujud
   304  jujud: PACKAGE = github.com/juju/juju/cmd/jujud
   305  jujud:
   306  ## jujud: Install jujud without updating dependencies
   307  	${run_go_install}
   308  	mv $(GO_INSTALL_PATH)/jujud $(GO_INSTALL_PATH)/jujud-junk
   309  
   310  .PHONY: jujud-controller
   311  jujud-controller: PACKAGE = github.com/juju/juju/cmd/jujud-controller
   312  jujud-controller: musl-install-if-missing dqlite-install-if-missing
   313  ## jujud: Install jujud without updating dependencies
   314  	${run_cgo_install}
   315  	mv $(GO_INSTALL_PATH)/jujud-controller $(GO_INSTALL_PATH)/jujud
   316  
   317  .PHONY: containeragent
   318  containeragent: PACKAGE = github.com/juju/juju/cmd/containeragent
   319  containeragent:
   320  ## containeragent: Install containeragent without updating dependencies
   321  	${run_go_install}
   322  
   323  .PHONY: juju-metadata
   324  juju-metadata: PACKAGE = github.com/juju/juju/cmd/plugins/juju-metadata
   325  juju-metadata:
   326  ## juju-metadata: Install juju-metadata without updating dependencies
   327  	${run_go_install}
   328  
   329  .PHONY: pebble
   330  pebble: PACKAGE = github.com/canonical/pebble/cmd/pebble
   331  pebble:
   332  ## pebble: Install pebble without updating dependencies
   333  	${run_go_install}
   334  
   335  .PHONY: phony_explicit
   336  phony_explicit:
   337  # phone_explicit: is a dummy target that can be added to pattern targets to phony make.
   338  
   339  ${BUILD_DIR}/%/bin/juju: PACKAGE = github.com/juju/juju/cmd/juju
   340  ${BUILD_DIR}/%/bin/juju: phony_explicit
   341  # build for juju
   342  	$(run_go_build)
   343  
   344  ${BUILD_DIR}/%/bin/jujuc: PACKAGE = github.com/juju/juju/cmd/jujuc
   345  ${BUILD_DIR}/%/bin/jujuc: phony_explicit
   346  # build for jujuc
   347  	$(run_go_build)
   348  
   349  ${BUILD_DIR}/%/bin/jujud: PACKAGE = github.com/juju/juju/cmd/jujud
   350  ${BUILD_DIR}/%/bin/jujud: phony_explicit
   351  # build for jujud
   352  	$(run_go_build)
   353  	$(eval OS = $(word 1,$(subst _, ,$*)))
   354  	$(eval ARCH = $(word 2,$(subst _, ,$*)))
   355  	$(eval BBIN_DIR = ${BUILD_DIR}/${OS}_${ARCH}/bin)
   356  	mv ${BBIN_DIR}/jujud ${BBIN_DIR}/jujud-junk
   357  
   358  ${BUILD_DIR}/%/bin/jujud-controller: PACKAGE = github.com/juju/juju/cmd/jujud-controller
   359  ${BUILD_DIR}/%/bin/jujud-controller: phony_explicit musl-install-if-missing dqlite-install-if-missing
   360  # build for jujud-controller
   361  	$(run_cgo_build)
   362  	$(eval OS = $(word 1,$(subst _, ,$*)))
   363  	$(eval ARCH = $(word 2,$(subst _, ,$*)))
   364  	$(eval BBIN_DIR = ${BUILD_DIR}/${OS}_${ARCH}/bin)
   365  	mv ${BBIN_DIR}/jujud-controller ${BBIN_DIR}/jujud
   366  
   367  ${BUILD_DIR}/%/bin/containeragent: PACKAGE = github.com/juju/juju/cmd/containeragent
   368  ${BUILD_DIR}/%/bin/containeragent: phony_explicit
   369  # build for containeragent
   370  	$(run_go_build)
   371  
   372  ${BUILD_DIR}/%/bin/juju-metadata: PACKAGE = github.com/juju/juju/cmd/plugins/juju-metadata
   373  ${BUILD_DIR}/%/bin/juju-metadata: phony_explicit
   374  # build for juju-metadata
   375  	$(run_go_build)
   376  
   377  ${BUILD_DIR}/%/bin/pebble: PACKAGE = github.com/canonical/pebble/cmd/pebble
   378  ${BUILD_DIR}/%/bin/pebble: phony_explicit
   379  # build for pebble
   380  	$(run_go_build)
   381  
   382  ${JUJU_METADATA_SOURCE}/tools/released/juju-${JUJU_VERSION}-%.tgz: phony_explicit juju $(BUILD_AGENT_TARGETS)
   383  	@echo "Packaging simplestream tools for juju ${JUJU_VERSION} on $*"
   384  	@mkdir -p ${JUJU_METADATA_SOURCE}/tools/released
   385  	@tar czf "$@" -C $(call bin_platform_paths,$(subst -,/,$*)) .
   386  
   387  .PHONY: simplestreams
   388  simplestreams: juju juju-metadata ${SIMPLESTREAMS_TARGETS}
   389  	@juju metadata generate-agent-binaries -d ${JUJU_METADATA_SOURCE} --clean --prevent-fallback ;
   390  	@echo "\nRun export JUJU_METADATA_SOURCE=\"${JUJU_METADATA_SOURCE}\" if not defined in your env"
   391  
   392  .PHONY: build
   393  build: rebuild-schema go-build
   394  ## build: builds all the targets including rebuilding a new schema.
   395  
   396  .PHONY: go-agent-build
   397  go-agent-build: $(BUILD_AGENT_TARGETS) $(BUILD_CGO_AGENT_TARGETS)
   398  
   399  .PHONY: go-agent-build-no-cgo
   400  go-agent-build-no-cgo: $(BUILD_AGENT_TARGETS)
   401  
   402  .PHONY: go-client-build
   403  go-client-build: $(BUILD_CLIENT_TARGETS)
   404  
   405  .PHONY: go-build
   406  go-build: go-agent-build go-client-build
   407  ## build: builds all the targets withouth rebuilding a new schema.
   408  
   409  .PHONY: release-build
   410  release-build: go-agent-build
   411  ## release-build: Construct Juju binaries, without building schema
   412  
   413  .PHONY: release-install
   414  release-install: $(INSTALL_TARGETS)
   415  ## release-install: Install Juju binaries
   416  
   417  .PHONY: pre-check
   418  pre-check:
   419  ## pre-check: Verify go code via static analysis
   420  	@echo running pre-test checks
   421  	@INCLUDE_GOLINTERS=1 $(PROJECT_DIR)/scripts/verify.bash
   422  
   423  .PHONY: check
   424  check: pre-check run-tests
   425  ## check: Verify Juju code using static analysis and unit tests
   426  
   427  .PHONY: test
   428  test: run-tests
   429  ## test: Verify Juju code using unit tests
   430  
   431  .PHONY: race-test
   432  race-test:
   433  ## race-test: Verify Juju code using unit tests with the race detector enabled
   434  	+make run-tests TEST_ARGS="$(TEST_ARGS) -race"
   435  
   436  .PHONY: run-tests run-go-tests go-test-alias
   437  # Can't make the length of the TMP dir too long or it hits socket name length issues.
   438  run-tests: musl-install-if-missing dqlite-install-if-missing
   439  ## run-tests: Run the unit tests
   440  	$(eval OS = $(shell go env GOOS))
   441  	$(eval ARCH = $(shell go env GOARCH))
   442  	$(eval BUILD_ARCH = $(subst ppc64el,ppc64le,${ARCH}))
   443  	$(eval TMP := $(shell mktemp -d $${TMPDIR:-/tmp}/jj-XXX))
   444  	$(eval TEST_PACKAGES := $(shell go list $(PROJECT)/... | sort | ([ -f "$(TEST_PACKAGE_LIST)" ] && comm -12 "$(TEST_PACKAGE_LIST)" - || cat) | grep -v $(PROJECT)$$ | grep -v $(PROJECT)/vendor/ | grep -v $(PROJECT)/acceptancetests/ | grep -v $(PROJECT)/generate/ | grep -v mocks))
   445  	@echo 'go test -mod=$(JUJU_GOMOD_MODE) -tags=$(FINAL_BUILD_TAGS) $(TEST_ARGS) $(CHECK_ARGS) -test.timeout=$(TEST_TIMEOUT) $$TEST_PACKAGES -check.v'
   446  	@TMPDIR=$(TMP) \
   447  		PATH="${MUSL_BIN_PATH}:${PATH}" \
   448  		CC="musl-gcc" \
   449  		CGO_CFLAGS="-I${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}/include" \
   450  		CGO_LDFLAGS="-L${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH} -luv -lraft -ldqlite -llz4 -lsqlite3" \
   451  		CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" \
   452  		LD_LIBRARY_PATH="${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}" \
   453  		CGO_ENABLED=1 \
   454  		go test -v -mod=$(JUJU_GOMOD_MODE) -tags=$(FINAL_BUILD_TAGS) $(TEST_ARGS) $(CHECK_ARGS) -ldflags ${CGO_LINK_FLAGS} -test.timeout=$(TEST_TIMEOUT) $(TEST_PACKAGES) -check.v
   455  	@rm -r $(TMP)
   456  
   457  run-go-tests: musl-install-if-missing dqlite-install-if-missing
   458  ## run-go-tests: Run the unit tests
   459  	$(eval OS = $(shell go env GOOS))
   460  	$(eval ARCH = $(shell go env GOARCH))
   461  	$(eval BUILD_ARCH = $(subst ppc64el,ppc64le,${ARCH}))
   462  	$(eval TEST_PACKAGES ?= "./...")
   463  	$(eval TEST_FILTER ?= "")
   464  	@echo 'go test -mod=$(JUJU_GOMOD_MODE) -tags=$(FINAL_BUILD_TAGS) $(TEST_ARGS) $(CHECK_ARGS) -test.timeout=$(TEST_TIMEOUT) $$TEST_PACKAGES -check.v -check.f $(TEST_FILTER)'
   465  	@PATH="${MUSL_BIN_PATH}:${PATH}" \
   466  		CC="musl-gcc" \
   467  		CGO_CFLAGS="-I${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}/include" \
   468  		CGO_LDFLAGS="-L${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH} -luv -lraft -ldqlite -llz4 -lsqlite3" \
   469  		CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" \
   470  		LD_LIBRARY_PATH="${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}" \
   471  		CGO_ENABLED=1 \
   472  		go test -v -mod=$(JUJU_GOMOD_MODE) -tags=$(FINAL_BUILD_TAGS) $(TEST_ARGS) $(CHECK_ARGS) -ldflags ${CGO_LINK_FLAGS} -test.timeout=$(TEST_TIMEOUT) ${TEST_PACKAGES} -check.v -check.f $(TEST_FILTER)
   473  
   474  go-test-alias: musl-install-if-missing dqlite-install-if-missing
   475  ## go-test-alias: Prints out an alias command for easy running of tests.
   476  	$(eval PPATH := "PATH")
   477  	@echo alias jt=\'PATH=\"${MUSL_BIN_PATH}:$$${PPATH}\" \
   478  		CC=\"musl-gcc\" \
   479  		CGO_CFLAGS=\"-I${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}/include\" \
   480  		CGO_LDFLAGS=\"-L${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH} -luv -lraft -ldqlite -llz4 -lsqlite3\" \
   481  		CGO_LDFLAGS_ALLOW=\""(-Wl,-wrap,pthread_create)|(-Wl,-z,now)"\" \
   482  		LD_LIBRARY_PATH=\"${DQLITE_EXTRACTED_DEPS_ARCHIVE_PATH}\" \
   483  		CGO_ENABLED=\"1\" \
   484  		go test -mod=\"$(JUJU_GOMOD_MODE)\" -tags=\"$(FINAL_BUILD_TAGS)\" -ldflags \"${CGO_LINK_FLAGS}\"\'
   485  
   486  .PHONY: install
   487  install: rebuild-schema go-install
   488  ## install: Install Juju binaries with a rebuilt schema
   489  
   490  .PHONY: go-install
   491  go-install: $(INSTALL_TARGETS)
   492  ## go-install: Install Juju binaries
   493  
   494  .PHONY: clean
   495  clean:
   496  ## clean: Clean the cache and test caches
   497  	go clean -x --cache --testcache
   498  	go clean -x -r $(PROJECT)/...
   499  
   500  .PHONY: vendor-dependencies
   501  vendor-dependencies:
   502  ## vendor-dependencies: updates vendored dependencies
   503  	@go mod vendor
   504  
   505  .PHONY: format
   506  # Reformat source files.
   507  format:
   508  ## format: Format the go source code
   509  	gofmt -w -l .
   510  
   511  .PHONY: simplify
   512  # Reformat and simplify source files.
   513  simplify:
   514  ## simplify: Format and simplify the go source code
   515  	gofmt -w -l -s .
   516  
   517  .PHONY: rebuild-schema
   518  rebuild-schema:
   519  ## rebuild-schema: Rebuild the schema for clients with the latest facades
   520  	@echo "Generating facade schema..."
   521  # GOOS and GOARCH environment variables are cleared in case the user is trying to cross architecture compilation.
   522  ifdef SCHEMA_PATH
   523  	@env GOOS= GOARCH= go run $(COMPILE_FLAGS) $(PROJECT)/generate/schemagen -admin-facades "$(SCHEMA_PATH)"
   524  else
   525  	@env GOOS= GOARCH= go run $(COMPILE_FLAGS) $(PROJECT)/generate/schemagen -admin-facades \
   526  		./apiserver/facades/schema.json
   527  endif
   528  
   529  .PHONY: install-snap-dependencies
   530  # Install packages required to develop Juju and run tests. The stable
   531  # PPA includes the required mongodb-server binaries.
   532  install-snap-dependencies:
   533  ## install-snap-dependencies: Install the supported snap dependencies
   534  ifeq ($(shell if [ "$(GO_INSTALLED_VERSION)" \> "$(GO_MOD_VERSION)" -o "$(GO_INSTALLED_VERSION)" = "$(GO_MOD_VERSION)" ]; then echo 1; fi),1)
   535  	@echo 'Using installed go-$(GO_MOD_VERSION)'
   536  endif
   537  ifeq ("$(GO_INSTALLED_VERSION)","")
   538  	@echo 'Installing go-$(GO_MOD_VERSION) snap'
   539  	@sudo snap install go --channel=$(GO_MOD_VERSION)/stable --classic
   540  else
   541  ifeq ($(shell if [ "$(GO_INSTALLED_VERSION)" \< "$(GO_MOD_VERSION)" ]; then echo 1; fi),1)
   542  	$(warning "warning: version of go too low: use 'snap refresh go --channel=$(GO_MOD_VERSION)'")
   543  	$(error "error Installed go version '$(GO_INSTALLED_VERSION)' less than required go version '$(GO_MOD_VERSION)'")
   544  endif
   545  endif
   546  
   547  WAIT_FOR_DPKG=bash -c '. "${PROJECT_DIR}/make_functions.sh"; wait_for_dpkg "$$@"' wait_for_dpkg
   548  JUJU_DB_VERSION=4.4
   549  JUJU_DB_CHANNEL=${JUJU_DB_VERSION}/stable
   550  
   551  .PHONY: install-mongo-dependencies
   552  install-mongo-dependencies:
   553  ## install-mongo-dependencies: Install Mongo and its dependencies
   554  	@echo Installing ${JUJU_DB_CHANNEL} juju-db snap for mongodb
   555  	@sudo snap refresh juju-db --channel=${JUJU_DB_CHANNEL} 2> /dev/null; sudo snap install juju-db --channel=${JUJU_DB_CHANNEL} 2> /dev/null
   556  	@$(WAIT_FOR_DPKG)
   557  	@sudo apt-get --yes install  $(strip $(DEPENDENCIES))
   558  
   559  .PHONY: install-dependencies
   560  install-dependencies: install-snap-dependencies install-mongo-dependencies
   561  ## install-dependencies: Install all the dependencies
   562  	@echo "Installing dependencies"
   563  
   564  .PHONY: install-etc
   565  # Install bash_completion
   566  install-etc:
   567  ## install-etc: Install auto-completion
   568  	@echo Installing bash completion
   569  	@sudo install -o root -g root -m 644 etc/bash_completion.d/juju /usr/share/bash-completion/completions
   570  	@sudo install -o root -g root -m 644 etc/bash_completion.d/juju-version /usr/share/bash-completion/completions
   571  
   572  .PHONY: setup-lxd
   573  setup-lxd:
   574  ## setup-lxd: Auto configure LXD
   575  ifeq ($(shell ifconfig lxdbr0 2>&1 | grep -q "inet addr" && echo true),true)
   576  	@echo IPv4 networking is already setup for LXD.
   577  	@echo run "sudo scripts/setup-lxd.sh" to reconfigure IPv4 networking
   578  else
   579  	@echo Setting up IPv4 networking for LXD
   580  	@sudo scripts/setup-lxd.sh || true
   581  endif
   582  
   583  
   584  GOCHECK_COUNT="$(shell go list -f '{{join .Deps "\n"}}' ${PROJECT}/... | grep -c "gopkg.in/check.v*")"
   585  .PHONY: check-deps
   586  check-deps:
   587  ## check-deps: Check dependencies are correct versions
   588  	@echo "$(GOCHECK_COUNT) instances of gocheck not in test code"
   589  
   590  
   591  # CAAS related targets
   592  export OCI_BUILDER         ?= $(shell (which podman 2>&1 > /dev/null && echo podman) || echo docker )
   593  DOCKER_USERNAME            ?= docker.io/jujusolutions
   594  DOCKER_BUILDX_CONTEXT      ?= juju-make
   595  DOCKER_STAGING_DIR         ?= ${BUILD_DIR}/docker-staging
   596  JUJUD_STAGING_DIR          ?= ${DOCKER_STAGING_DIR}/jujud-operator
   597  JUJUD_BIN_DIR              ?= ${BIN_DIR}
   598  OPERATOR_IMAGE_BUILD_SRC   ?= true
   599  
   600  # Import shell functions from make_functions.sh
   601  # For the k8s operator.
   602  BUILD_OPERATOR_IMAGE=bash -c '. "${PROJECT_DIR}/make_functions.sh"; build_push_operator_image "$$@"' build_push_operator_image
   603  OPERATOR_IMAGE_PATH=bash -c '. "${PROJECT_DIR}/make_functions.sh"; operator_image_path "$$@"' operator_image_path
   604  OPERATOR_IMAGE_RELEASE_PATH=bash -c '. "${PROJECT_DIR}/make_functions.sh"; operator_image_release_path "$$@"' operator_image_release_path
   605  UPDATE_MICROK8S_OPERATOR=bash -c '. "${PROJECT_DIR}/make_functions.sh"; microk8s_operator_update "$$@"' microk8s_operator_update
   606  SEED_REPOSITORY=bash -c '. "${PROJECT_DIR}/make_functions.sh"; seed_repository "$$@"' seed_repository
   607  
   608  image_check_prereq=image-check-build
   609  ifneq ($(OPERATOR_IMAGE_BUILD_SRC),true)
   610  	image_check_prereq=image-check-build-skip
   611  endif
   612  
   613  .PHONY: image-check
   614  image-check: $(image_check_prereq)
   615  
   616  .PHONY: image-check-build
   617  image-check-build:
   618  	CLIENT_PACKAGE_PLATFORMS="$(OCI_IMAGE_PLATFORMS)" AGENT_PACKAGE_PLATFORMS="$(OCI_IMAGE_PLATFORMS)" make go-build
   619  
   620  .PHONY: image-check-build-skip
   621  image-check-build-skip:
   622  	@echo "skipping to build jujud bin, use existing one at ${JUJUD_BIN_DIR}/."
   623  
   624  .PHONY: docker-builder
   625  docker-builder:
   626  ## docker-builder: Makes sure that there is a buildx context for building the oci images
   627  ifeq ($(OCI_BUILDER),docker)
   628  	-@docker buildx create --name ${DOCKER_BUILDX_CONTEXT}
   629  endif
   630  
   631  .PHONY: image-check
   632  operator-image: image-check docker-builder
   633  ## operator-image: Build operator image via docker
   634  	${BUILD_OPERATOR_IMAGE} "$(OCI_IMAGE_PLATFORMS)" "$(PUSH_IMAGE)"
   635  
   636  push_operator_image_prereq=push-operator-image-defined
   637  ifeq ($(JUJU_BUILD_NUMBER),)
   638  	push_operator_image_prereq=push-operator-image-undefined
   639  endif
   640  
   641  .PHONY: push-operator-image-defined
   642  push-operator-image-defined: PUSH_IMAGE=true
   643  push-operator-image-defined: operator-image
   644  
   645  .PHONY: push-operator-image-undefined
   646  push-operator-image-undefined:
   647  	@echo "error Undefined JUJU_BUILD_NUMBER"
   648  
   649  .PHONY: push-operator-image
   650  push-operator-image: $(push_operator_image_prereq)
   651  ## push-operator-image: Push up the newly built operator image via docker
   652  
   653  .PHONY: push-release-operator-image
   654  push-release-operator-image: PUSH_IMAGE=true
   655  push-release-operator-image: operator-image
   656  ## push-release-operator-image: Push up the newly built release operator image via docker
   657  
   658  .PHONY: seed-repository
   659  seed-repository:
   660  ## seed-repository: Copy required juju images from docker.io/jujusolutions
   661  	JUJU_DB_VERSION=$(JUJU_DB_VERSION) $(SEED_REPOSITORY)
   662  
   663  
   664  .PHONY: host-install
   665  host-install:
   666  ## host-install: installs juju for host os/architecture
   667  	+GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) make juju
   668  
   669  .PHONY: minikube-operator-update
   670  minikube-operator-update: host-install operator-image
   671  ## minikube-operator-update: Inject the newly built operator image into minikube
   672  	$(OCI_BUILDER) save "$(shell ${OPERATOR_IMAGE_PATH})" | minikube image load --overwrite=true -
   673  
   674  .PHONY: microk8s-operator-update
   675  microk8s-operator-update: host-install operator-image
   676  ## microk8s-operator-update: Inject the newly built operator image into microk8s
   677  	@${UPDATE_MICROK8S_OPERATOR}
   678  
   679  .PHONY: k3s-operator-update
   680  k3s-operator-update: host-install operator-image
   681  ## k3s-operator-update: Inject the newly built operator image into k3s
   682  	$(OCI_BUILDER) save "$(shell ${OPERATOR_IMAGE_PATH})" | sudo k3s ctr images import -
   683  
   684  
   685  .PHONY: check-k8s-model
   686  check-k8s-model:
   687  ## check-k8s-model: Check if k8s model is present in show-model
   688  	@:$(if $(value JUJU_K8S_MODEL),, $(error Undefined JUJU_K8S_MODEL))
   689  	@juju show-model ${JUJU_K8S_MODEL} > /dev/null
   690  
   691  .PHONY: local-operator-update
   692  local-operator-update: check-k8s-model operator-image
   693  ## local-operator-update: Build then update local operator image
   694  	$(eval kubeworkers != juju status -m ${JUJU_K8S_MODEL} kubernetes-worker --format json | jq -c '.machines | keys' | tr  -c '[:digit:]' ' ' 2>&1)
   695  	$(OCI_BUILDER) save "$(shell ${OPERATOR_IMAGE_PATH})" | gzip > ${DOCKER_STAGING_DIR}/jujud-operator-image.tar.gz
   696  	$(foreach wm,$(kubeworkers), juju scp -m ${JUJU_K8S_MODEL} ${DOCKER_STAGING_DIR}/jujud-operator-image.tar.gz $(wm):/tmp/jujud-operator-image.tar.gz ; )
   697  	$(foreach wm,$(kubeworkers), juju ssh -m ${JUJU_K8S_MODEL} $(wm) -- "zcat /tmp/jujud-operator-image.tar.gz | docker load" ; )
   698  
   699  STATIC_ANALYSIS_JOB ?=
   700  
   701  .PHONY: static-analysis
   702  static-analysis: dqlite-install-if-missing
   703  ## static-analysis: Check the go code using static-analysis
   704  	@cd tests && CGO_ENABLED=1 \
   705  		CGO_LDFLAGS_ALLOW="(-Wl,-wrap,pthread_create)|(-Wl,-z,now)" \
   706  		./main.sh static_analysis ${STATIC_ANALYSIS_JOB}