# Makefile for fscrypt # # Copyright 2017 Google Inc. # Author: Joe Richey (joerichey@google.com) # # 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. # Update on each new release!! VERSION := v0.3.0 NAME := fscrypt PAM_NAME := pam_$(NAME) ###### Makefile Command Line Flags ###### # # BIN: The location where binaries will be built. Default: bin # DESTDIR: Installation destination directory. Default: "" # PREFIX: Installation path prefix. Default: /usr/local # BINDIR: Where to install the fscrypt binary. Default: $(PREFIX)/bin # PAM_MODULE_DIR: Where to install pam_fscrypt.so. Default: $(PREFIX)/lib/security # PAM_CONFIG_DIR: Where to install Ubuntu PAM config. Default: $(PREFIX)/share/pam-configs # If the empty string, then the Ubuntu PAM config will not be installed. # # MOUNT: The filesystem where our tests are run. Default: /mnt/fscrypt_mount # Ex: make test-setup MOUNT=/foo/bar # Creates a test filesystem at that location. # Ex: make test-teardown MOUNT=/foo/bar # Cleans up a test filesystem created with "make test-setup". # Ex: make test MOUNT=/foo/bar # Run all integration tests on that filesystem. This can be an existing # filesystem, or one created with "make test-setup" (this is the default). # # CFLAGS: The flags passed to the C compiler. Default: -O2 -Wall # Ex: make fscrypt "CFLAGS = -O3 -Werror" # Builds fscrypt with the C code failing on warnings and highly optimized. # # LDFLAGS: The flags passed to the C linker. Default empty # Ex: make fscrypt "LDFLAGS = -static -ldl -laudit -lcap-ng" # Builds fscrypt as a static binary. # # GO_FLAGS: The flags passed to "go build". Default empty # Ex: make fscrypt "GO_FLAGS = -race" # Builds fscrypt with race detection for the go code. # # GO_LINK_FLAGS: The flags passed to the go linker. Default: -s -w # Ex: make fscrypt GO_LINK_FLAGS="" # Builds fscrypt without stripping the binary. BIN := bin export PATH := $(BIN):$(PATH) PAM_MODULE := $(BIN)/$(PAM_NAME).so ###### Setup Build Flags ##### CFLAGS := -O2 -Wall # Pass CFLAGS to each cgo invocation. export CGO_CFLAGS = $(CFLAGS) # By default, we strip the binary to reduce size. GO_LINK_FLAGS := -s -w # Flag to embed the version (pulled from tags) into the binary. TAG_VERSION := $(shell git describe --tags) VERSION_FLAG := -X "main.version=$(if $(TAG_VERSION),$(TAG_VERSION),$(VERSION))" override GO_LINK_FLAGS += $(VERSION_FLAG) -extldflags "$(LDFLAGS)" override GO_FLAGS += --ldflags '$(GO_LINK_FLAGS)' # Always use Go modules export GO111MODULE = on # Use -trimpath if available ifneq "" "$(shell go help build | grep trimpath)" override GO_FLAGS += -trimpath endif ###### Find All Files and Directories ###### FILES := $(shell find . -path '*/.git*' -prune -o -type f -printf "%P\n") GO_FILES := $(filter %.go,$(FILES)) GO_NONGEN_FILES := $(filter-out %.pb.go,$(GO_FILES)) GO_DIRS := $(sort $(dir $(GO_FILES))) C_FILES := $(filter %.c %.h,$(FILES)) PROTO_FILES := $(filter %.proto,$(FILES)) ###### Build, Formatting, and Linting Commands ###### .PHONY: default all gen format lint clean default: $(BIN)/$(NAME) $(PAM_MODULE) all: tools gen default format lint test $(BIN)/$(NAME): $(GO_FILES) $(C_FILES) go build $(GO_FLAGS) -o $@ ./cmd/$(NAME) $(PAM_MODULE): $(GO_FILES) $(C_FILES) go build -buildmode=c-shared $(GO_FLAGS) -o $@ ./$(PAM_NAME) rm -f $(BIN)/$(PAM_NAME).h gen: $(BIN)/protoc $(BIN)/protoc-gen-go $(PROTO_FILES) protoc --go_out=. $(PROTO_FILES) format: $(BIN)/goimports goimports -w $(GO_NONGEN_FILES) clang-format -i -style=Google $(C_FILES) lint: $(BIN)/golint $(BIN)/staticcheck $(BIN)/misspell go vet ./... go list ./... | xargs -L1 golint -set_exit_status staticcheck ./... misspell -source=text $(FILES) shellcheck -s bash cmd/fscrypt/fscrypt_bash_completion ( cd cli-tests && shellcheck -x *.sh) clean: rm -f $(BIN)/$(NAME) $(PAM_MODULE) $(TOOLS) coverage.out $(COVERAGE_FILES) $(PAM_CONFIG) ###### Go tests ###### .PHONY: test test-setup test-teardown # If MOUNT exists signal that we should run integration tests. MOUNT := /tmp/$(NAME)-mount IMAGE := /tmp/$(NAME)-image ifneq ("$(wildcard $(MOUNT))","") export TEST_FILESYSTEM_ROOT = $(MOUNT) endif test: go test -p 1 ./... test-setup: dd if=/dev/zero of=$(IMAGE) bs=1M count=20 mkfs.ext4 -b 4096 -O encrypt $(IMAGE) -F mkdir -p $(MOUNT) sudo mount -o rw,loop,user $(IMAGE) $(MOUNT) sudo chmod +777 $(MOUNT) test-teardown: sudo umount $(MOUNT) rmdir $(MOUNT) rm -f $(IMAGE) ###### Command-line interface tests ###### .PHONY: cli-test cli-test-update cli-test: $(BIN)/$(NAME) sudo cli-tests/run.sh cli-test-update: $(BIN)/$(NAME) sudo cli-tests/run.sh --update-output # Runs tests and generates coverage COVERAGE_FILES := $(addsuffix coverage.out,$(GO_DIRS)) coverage.out: $(BIN)/gocovmerge $(COVERAGE_FILES) @gocovmerge $(COVERAGE_FILES) > $@ %/coverage.out: $(GO_FILES) $(C_FILES) @go test -coverpkg=./... -covermode=count -coverprofile=$@ -p 1 ./$* 2> /dev/null ###### Installation Commands (require sudo) ##### .PHONY: install install-bin install-pam uninstall install-completion install: install-bin install-pam install-completion PREFIX := /usr/local BINDIR := $(PREFIX)/bin install-bin: $(BIN)/$(NAME) install -d $(DESTDIR)$(BINDIR) install $< $(DESTDIR)$(BINDIR) PAM_MODULE_DIR := $(PREFIX)/lib/security PAM_INSTALL_PATH := $(PAM_MODULE_DIR)/$(PAM_NAME).so PAM_CONFIG := $(BIN)/config PAM_CONFIG_DIR := $(PREFIX)/share/pam-configs install-pam: $(PAM_MODULE) install -d $(DESTDIR)$(PAM_MODULE_DIR) install $(PAM_MODULE) $(DESTDIR)$(PAM_MODULE_DIR) ifdef PAM_CONFIG_DIR m4 --define=PAM_INSTALL_PATH=$(PAM_INSTALL_PATH) < $(PAM_NAME)/config > $(PAM_CONFIG) install -d $(DESTDIR)$(PAM_CONFIG_DIR) install $(PAM_CONFIG) $(DESTDIR)$(PAM_CONFIG_DIR)/$(NAME) endif COMPLETION_INSTALL_DIR := $(PREFIX)/share/bash-completion/completions install-completion: cmd/fscrypt/fscrypt_bash_completion install -Dm644 $< $(DESTDIR)$(COMPLETION_INSTALL_DIR)/fscrypt uninstall: rm -f $(DESTDIR)$(BINDIR)/$(NAME) \ $(DESTDIR)$(PAM_INSTALL_PATH) \ $(DESTDIR)$(COMPLETION_INSTALL_DIR)/fscrypt ifdef PAM_CONFIG_DIR rm -f $(DESTDIR)$(PAM_CONFIG_DIR)/$(NAME) endif #### Tool Building Commands #### TOOLS := $(addprefix $(BIN)/,protoc golint protoc-gen-go goimports staticcheck gocovmerge misspell) .PHONY: tools tools: $(TOOLS) $(BIN)/golint: go build -o $@ golang.org/x/lint/golint $(BIN)/protoc-gen-go: go build -o $@ github.com/golang/protobuf/protoc-gen-go $(BIN)/goimports: go build -o $@ golang.org/x/tools/cmd/goimports $(BIN)/staticcheck: go build -o $@ honnef.co/go/tools/cmd/staticcheck $(BIN)/gocovmerge: go build -o $@ github.com/wadey/gocovmerge $(BIN)/misspell: go build -o $@ github.com/client9/misspell/cmd/misspell # Non-go tools downloaded from appropriate repository PROTOC_VERSION := 3.6.1 ARCH := $(shell uname -m) ifeq (x86_64,$(ARCH)) PROTOC_ARCH := x86_64 else ifneq ($(filter i386 i686,$(ARCH)),) PROTOC_ARCH := x86_32 else ifneq ($(filter aarch64 armv8l,$(ARCH)),) PROTOC_ARCH := aarch_64 endif ifdef PROTOC_ARCH PROTOC_URL := https://github.com/google/protobuf/releases/download/v$(PROTOC_VERSION)/protoc-$(PROTOC_VERSION)-linux-$(PROTOC_ARCH).zip $(BIN)/protoc: wget -q $(PROTOC_URL) -O /tmp/protoc.zip unzip -q -j /tmp/protoc.zip bin/protoc -d $(BIN) else PROTOC_PATH := $(shell which protoc) $(BIN)/protoc: $(PROTOC_PATH) ifneq ($(wildcard $(PROTOC_PATH)),) cp $< $@ else $(error Could not download protoc binary or locate it on the system. Please install it) endif endif