diff --git a/.travis.yml b/.travis.yml index 60b1666..52dbbc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,25 +1,20 @@ -language: cpp - -compiler: - - gcc - - clang - +language: minimal +services: +- docker addons: - apt: - update: true - packages: - - valgrind - + apt: + update: true before_install: - - ./install_deps.sh - - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib - - +- sudo apt-get install -y curl openssl ca-certificates +- sudo apt-get install -y make +- sudo apt-get install -y qemu-user-static +env: + global: + - PARALLELMFLAGS="-j2" + matrix: + - MARCH=amd64 CHECK_TARGET=memcheck + - MARCH=arm32v7 CHECK_TARGET=check before_script: - - mkdir .build - - cd .build - - cmake -DCMAKE_BUILD_TYPE=Debug .. - +- make MARCH=$MARCH script: - - make - - valgrind ./alltests +- make MARCH=$MARCH $CHECK_TARGET diff --git a/AUTHORS b/AUTHORS index 352b58e..01e215c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -4,3 +4,4 @@ # some cases, their employer may be the copyright holder. To see the full list # of contributors, see the revision history in source control. Falk Werner +Osama El Hosami diff --git a/CMakeLists.txt b/CMakeLists.txt index c017d3e..2b9fc85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.1) +cmake_minimum_required (VERSION 3.10) project(fuse-wsfs VERSION 0.1.0 DESCRIPTION "Websocket filesystem based on libfuse") option(WITHOUT_TESTS "disable unit tests" OFF) @@ -12,6 +12,8 @@ pkg_check_modules(FUSE3 REQUIRED fuse3) pkg_check_modules(LWS REQUIRED libwebsockets) pkg_check_modules(JANSSON REQUIRED jansson) +add_definitions(-D_FILE_OFFSET_BITS=64) + set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -182,7 +184,10 @@ endif(NOT WITHOUT_EXAMPLE) if(NOT WITHOUT_TESTS) +include (CTest) + pkg_check_modules(GTEST gtest_main) +include(GoogleTest) add_library(wsfs-adapter-static STATIC ${WSFS_ADAPTER_SOURCES}) set_target_properties(wsfs-adapter-static PROPERTIES OUTPUT_NAME wsfs-adapter) @@ -210,6 +215,6 @@ target_include_directories(alltests PUBLIC lib ${EXTRA_INCLUDE_DIRS} ${GTEST_INC target_compile_options(alltests PUBLIC ${EXTRA_CFLAGS} ${GTEST_CFLAGS}) enable_testing() -add_test(alltests alltests) +gtest_discover_tests(alltests TEST_PREFIX alltests:) -endif(NOT WITHOUT_TESTS) \ No newline at end of file +endif(NOT WITHOUT_TESTS) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3afe7b9 --- /dev/null +++ b/Makefile @@ -0,0 +1,216 @@ +.PHONY: default +default: all + +# Overridable defaults + +export SOURCE_DATE_EPOCH ?= $(shell $(PROJECT_ROOT)/build/get_source_date_epoch.sh) +export BUILDTIME ?= $(shell date -u -d '@$(SOURCE_DATE_EPOCH)' --rfc-3339 ns 2>/dev/null | sed -e 's/ /T/') + +VERBOSE ?= +MARCH ?= + +PROJECT_NAME ?= webfs +PROJECT_ROOT ?= . +VERSION ?= $(shell cat $(PROJECT_ROOT)/VERSION) +OUT ?= $(PROJECT_ROOT)/.build + +PARALLELMFLAGS ?= -j$(shell nproc) +UID ?= $(shell id -u) + +DOCKER ?= docker +DOCKER_BUILDKIT ?= + +CONTAINER_USER ?= $(UID) +CONTAINER_GROUP ?= $(shell id -g) +CONTAINER_WORKSPACE ?= /workspace + +UBUNTU_CODENAME ?= bionic + +# Dependencies + +GTEST_VERSION ?= 1.8.1 +DOCKER_BUILDARGS += GTEST_VERSION=$(GTEST_VERSION) +FETCH_TARGETS += $(OUT)/googletest-release-$(GTEST_VERSION).tar.gz +$(OUT)/googletest-release-$(GTEST_VERSION).tar.gz: URL := https://github.com/google/googletest/archive/release-$(GTEST_VERSION).tar.gz + +FUSE_VERSION ?= 3.1.1 +DOCKER_BUILDARGS += FUSE_VERSION=$(FUSE_VERSION) +FETCH_TARGETS += $(OUT)/libfuse-fuse-$(FUSE_VERSION).tar.gz +$(OUT)/libfuse-fuse-$(FUSE_VERSION).tar.gz: URL := https://github.com/libfuse/libfuse/archive/fuse-$(FUSE_VERSION).tar.gz + +WEBSOCKETS_VERSION ?= 3.1.0 +DOCKER_BUILDARGS += WEBSOCKETS_VERSION=$(WEBSOCKETS_VERSION) +FETCH_TARGETS += $(OUT)/libwebsockets-$(WEBSOCKETS_VERSION).tar.gz +$(OUT)/libwebsockets-$(WEBSOCKETS_VERSION).tar.gz: URL := https://github.com/warmcat/libwebsockets/archive/v$(WEBSOCKETS_VERSION).tar.gz + +JANSSON_VERSION ?= 2.12 +DOCKER_BUILDARGS += JANSSON_VERSION=$(JANSSON_VERSION) +FETCH_TARGETS += $(OUT)/jansson-$(JANSSON_VERSION).tar.gz +$(OUT)/jansson-$(JANSSON_VERSION).tar.gz: URL := https://github.com/akheron/jansson/archive/v$(JANSSON_VERSION).tar.gz + +QEMU_VERSION ?= v3.1.0-2 +FETCH_TARGETS += $(OUT)/docker/qemu-arm-static-$(QEMU_VERSION) +$(OUT)/docker/qemu-arm-static-$(QEMU_VERSION): URL := https://github.com/multiarch/qemu-user-static/releases/download/$(QEMU_VERSION)/qemu-arm-static + +# Architecture-specific rule target configuration + +MARCH_AMD64 := $(filter-out amd64,$(MARCH)) +$(MARCH_AMD64)MARCHS += amd64 +$(MARCH_AMD64)TARGETS += amd64-ubuntu-builder +$(OUT)/amd64-ubuntu-builder/rules.mk: TARGET := amd64-ubuntu-builder + +MARCH_ARM32V7 := $(filter-out arm32v7,$(MARCH)) +$(MARCH_ARM32V7)MARCHS += arm32v7 +$(MARCH_ARM32V7)TARGETS += arm32v7-ubuntu-builder +$(OUT)/arm32v7-ubuntu-builder/rules.mk: TARGET := arm32v7-ubuntu-builder + +$(MARCH_AMD64)MEMCHECK_TARGETS += $(addprefix memcheck-,$(TARGETS)) + +ARM_TARGETS = $(filter arm%,$(TARGETS)) +$(addprefix $(OUT)/docker/,$(ARM_TARGETS)): $(OUT)/docker/qemu-arm-static-$(QEMU_VERSION) + +UBUNTU_TARGETS = $(filter $(addsuffix -ubuntu%,$(MARCHS)),$(TARGETS)) +$(addprefix $(OUT)/docker/,$(UBUNTU_TARGETS)): CODENAME := $(UBUNTU_CODENAME) + +# Common rule target configuration + +MAKEFLAGS += $(PARALLELMFLAGS) --no-builtin-rules + +CMAKEFLAGS += -GNinja + +DOCKER_RUNFLAGS += --interactive +DOCKER_RUNFLAGS += --rm +DOCKER_RUNFLAGS += --init +DOCKER_RUNFLAGS += --user $(CONTAINER_USER):$(CONTAINER_GROUP) +DOCKER_RUNFLAGS += --device /dev/fuse --cap-add SYS_ADMIN --security-opt apparmor:unconfined +DOCKER_RUNFLAGS += --env SOURCE_DATE_EPOCH +DOCKER_RUNFLAGS += --env BUILDTIME + +DOCKER_BUILDARGS += CODENAME=$(CODENAME) +DOCKER_BUILDARGS += PARALLELMFLAGS=$(PARALLELMFLAGS) +DOCKER_BUILDARGS += USERID=$(UID) +DOCKER_BUILDARGS += WORKSPACE=$(CONTAINER_WORKSPACE) + +DOCKER_BUILDFLAGS += --rm +DOCKER_BUILDFLAGS += $(addprefix --build-arg ,$(DOCKER_BUILDARGS)) + +OUT_DIRS += $(OUT) +OUT_DIRS += $(OUT)/docker +OUT_DIRS += $(OUT)/src +OUT_DIRS += $(addprefix $(OUT)/,$(TARGETS)) + +BUILD_TARGETS += $(addprefix build-,$(TARGETS)) +CHECK_TARGETS += $(addprefix check-,$(TARGETS)) +EXTRACT_TARGETS += $(patsubst $(OUT)/%.tar.gz,$(OUT)/src/%,$(FETCH_TARGETS)) +RULE_TARGETS = $(addprefix $(OUT)/,$(addsuffix /rules.mk,$(TARGETS))) + +BUILD_TARGETS := $(BUILD_TARGETS) +CHECK_TARGETS := $(CHECK_TARGETS) +MEMCHECK_TARGETS := $(MEMCHECK_TARGETS) +CONTAINER_GROUP := $(CONTAINER_GROUP) +VERSION := $(VERSION) +PROJECT_ROOT := $(PROJECT_ROOT) +OUT := $(OUT) + +# Macros + +echo_if_silent = VERBOSE=1 +$(VERBOSE)echo_if_silent = echo $1 +$(VERBOSE)SILENT := @ + +image_rule = $$(OUT)/docker/$1: $$(OUT)/docker/$1.dockerfile $$(EXTRACT_TARGETS) $$(PROJECT_ROOT)/Makefile; $$(call image,$1) +image = $(SILENT) \ + $(call echo_if_silent,docker build $(PROJECT_NAME)-$1:$(VERSION) $(OUT)) \ + && $(DOCKER) build $(DOCKER_BUILDFLAGS) --iidfile $@ --file $< --tag $(PROJECT_NAME)-$1:$(VERSION) $(OUT) + +run_rule = run-$1: $$(OUT)/docker/$1; $$(call run,$1,/bin/bash,--tty) +run = $(SILENT) \ + $(call echo_if_silent,TARGET=$1 $2) \ + && $(DOCKER) run $(DOCKER_RUNFLAGS) $3 \ + --volume '$(realpath $(PROJECT_ROOT)):$(CONTAINER_WORKSPACE)' \ + --volume '$(realpath $(OUT)/$1):$(CONTAINER_WORKSPACE)/$(notdir $(OUT))' \ + --workdir '$(CONTAINER_WORKSPACE)/$(notdir $(OUT))' \ + $(PROJECT_NAME)-$1:$(VERSION) \ + $2 + +configure_rule = $$(OUT)/$1/CMakeCache.txt: $$(PROJECT_ROOT)/CMakeLists.txt $$(OUT)/docker/$1; $$(call configure,$1) +configure = $(call run,$1,cmake $(CMAKEFLAGS) ..) && touch $@ + +build_rule = build-$1: $$(OUT)/$1/CMakeCache.txt; $$(call build,$1) +build = $(call run,$1,ninja $(PARALLELMFLAGS) $(GLOAS)) + +check_rule = check-$1: build-$1; $$(call check,$1) +check = $(call run,$1,ctest $(CTESTFLAGS)) + +memcheck_rule = memcheck-$1: build-$1; $$(call memcheck,$1) +memcheck = $(call run,$1,ctest -T memcheck $(CTESTFLAGS)) + +# Rules + +ifneq ($(MAKECMDGOALS),clean) +-include $(RULE_TARGETS) +endif + +$(RULE_TARGETS): $(PROJECT_ROOT)/Makefile | $(OUT_DIRS) + $(SILENT) \ + { \ + echo; \ + echo '$(call image_rule,$(TARGET))'; \ + echo; \ + echo '$(call configure_rule,$(TARGET))'; \ + echo; \ + echo '$(call build_rule,$(TARGET))'; \ + echo; \ + echo '$(call check_rule,$(TARGET))'; \ + echo; \ + echo '$(call memcheck_rule,$(TARGET))'; \ + echo; \ + echo '$(call run_rule,$(TARGET))'; \ + } > $@ + +.PHONY: all +all: $(BUILD_TARGETS) + +.PHONY: check +check: $(CHECK_TARGETS) + +.PHONY: memcheck +memcheck: $(MEMCHECK_TARGETS) + +.PHONY: clean +clean: $(CLEAN_TARGETS) + $(SILENT)-rm -rf $(OUT_DIRS) + +.PHONY: get-deps +get-deps: $(EXTRACT_TARGETS) + +.PHONY: debug-print-% +debug-print-%: + @printf '%s\n' '$*:' $($*) + +$(CHECK_TARGETS) $(MEMCHECK_TARGETS): CONTAINER_USER := user + +$(OUT)/docker/qemu-arm-static-$(QEMU_VERSION): + $(SILENT) \ + $(call echo_if_silent,curl -fsSL -o $@ $(URL)) \ + && curl -fsSL -o $@ $(URL) \ + && chmod +x $@ + +$(OUT)/docker/% : $(PROJECT_ROOT)/build/% | $(OUT_DIRS) + cp $< $@ + +$(OUT)/%.tar.gz: | $(OUT_DIRS) + curl -fsSL -o $@ $(URL) + +$(OUT)/src/%: $(OUT)/%.tar.gz | $(OUT_DIRS) + $(SILENT) \ + $(call echo_if_silent,tar -C $(dir $@) -xf $<) \ + && tar -C $(dir $@) -xf $< \ + && touch $@ + +$(OUT_DIRS): + $(SILENT)mkdir -p $@ + +.PRECIOUS: $(OUT)/docker/% $(OUT)/%/CMakeCache.txt +.DELETE_ON_ERROR: $(OUT)/%/CMakeCache.txt + diff --git a/README.md b/README.md index f527e19..4badc14 100644 --- a/README.md +++ b/README.md @@ -328,7 +328,7 @@ By default, unit tests and example application are enabled. You can disable them - [Jansson](https://jansson.readthedocs.io) - [GoogleTest](https://github.com/google/googletest) *(optional)* -### Installation +### Installation from source #### libfuse @@ -353,12 +353,6 @@ By default, unit tests and example application are enabled. You can disable them #### Jansson -On many systems, libjansson can installed via apt: - - sudo apt install libjansson-dev - -Otherwise, it can be installed from source: - wget -O libjansson-2.12.tar.gz https://github.com/akheron/jansson/archive/v2.12.tar.gz tar -xf libjansson-2.12.tar.gz cd jansson-2.12 diff --git a/VERSION b/VERSION new file mode 100644 index 0000000..6e8bf73 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +0.1.0 diff --git a/build/amd64-ubuntu-builder.dockerfile b/build/amd64-ubuntu-builder.dockerfile new file mode 100644 index 0000000..6e98aed --- /dev/null +++ b/build/amd64-ubuntu-builder.dockerfile @@ -0,0 +1,81 @@ +ARG CODENAME=bionic + +FROM ubuntu:$CODENAME as builder + +RUN set -x \ + && apt update \ + && apt upgrade -y \ + && apt install --yes --no-install-recommends \ + build-essential \ + cmake \ + ninja-build \ + pkg-config \ + valgrind \ + && rm -rf /var/lib/apt/lists/* + +COPY src /usr/local/src + +ARG PARALLELMFLAGS=-j2 + +ARG GTEST_VERSION=1.8.1 + +RUN set -x \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake "/usr/local/src/googletest-release-$GTEST_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out + +ARG FUSE_VERSION=3.1.1 + +RUN set -x \ + && apt update \ + && apt install --yes --no-install-recommends \ + libtool \ + automake \ + gettext \ + && cd "/usr/local/src/libfuse-fuse-$FUSE_VERSION" \ + && ./makeconf.sh \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && "/usr/local/src/libfuse-fuse-$FUSE_VERSION/configure" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out \ + && rm -rf /var/lib/apt/lists/* + +ARG WEBSOCKETS_VERSION=3.1.0 + +RUN set -x \ + && apt update \ + && apt install --yes --no-install-recommends \ + openssl \ + libssl-dev \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake "/usr/local/src/libwebsockets-$WEBSOCKETS_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out \ + && rm -rf /var/lib/apt/lists/* + +ARG JANSSON_VERSION=2.12 + +RUN set -x \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake -DJANSSON_BUILD_DOCS=OFF "/usr/local/src/jansson-$JANSSON_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out + +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + +ARG USERID=1000 + +ARG WORKSPACE=/workspace + +RUN set -x \ + && useradd -u "$USERID" -ms /bin/bash user \ + && mkdir -p "$WORKSPACE" \ + && chown user:user "$WORKSPACE" + +WORKDIR "$WORKSPACE" + diff --git a/build/arm32v7-ubuntu-builder.dockerfile b/build/arm32v7-ubuntu-builder.dockerfile new file mode 100644 index 0000000..d706488 --- /dev/null +++ b/build/arm32v7-ubuntu-builder.dockerfile @@ -0,0 +1,82 @@ +ARG CODENAME=bionic + +FROM arm32v7/ubuntu:$CODENAME as builder + +COPY docker/qemu-arm-static-* /usr/bin/qemu-arm-static + +RUN set -x \ + && apt update \ + && apt upgrade -y \ + && apt install --yes --no-install-recommends \ + build-essential \ + cmake \ + ninja-build \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +COPY src /usr/local/src + +ARG PARALLELMFLAGS=-j2 + +ARG GTEST_VERSION=1.8.1 + +RUN set -x \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake "/usr/local/src/googletest-release-$GTEST_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out + +ARG FUSE_VERSION=3.1.1 + +RUN set -x \ + && apt update \ + && apt install --yes --no-install-recommends \ + libtool \ + automake \ + gettext \ + && cd "/usr/local/src/libfuse-fuse-$FUSE_VERSION" \ + && ./makeconf.sh \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && "/usr/local/src/libfuse-fuse-$FUSE_VERSION/configure" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out \ + && rm -rf /var/lib/apt/lists/* + +ARG WEBSOCKETS_VERSION=3.1.0 + +RUN set -x \ + && apt update \ + && apt install --yes --no-install-recommends \ + openssl \ + libssl-dev \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake "/usr/local/src/libwebsockets-$WEBSOCKETS_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out \ + && rm -rf /var/lib/apt/lists/* + +ARG JANSSON_VERSION=2.12 + +RUN set -x \ + && mkdir -p /tmp/out \ + && cd /tmp/out \ + && cmake -DJANSSON_BUILD_DOCS=OFF "/usr/local/src/jansson-$JANSSON_VERSION" \ + && make "$PARALLELMFLAGS" install \ + && rm -rf /tmp/out + +ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + +ARG USERID=1000 + +ARG WORKSPACE=/workspace + +RUN set -x \ + && useradd -u "$USERID" -ms /bin/bash user \ + && mkdir -p "$WORKSPACE" \ + && chown user:user "$WORKSPACE" + +WORKDIR "$WORKSPACE" + diff --git a/build/get_source_date_epoch.sh b/build/get_source_date_epoch.sh new file mode 100755 index 0000000..a8bb69a --- /dev/null +++ b/build/get_source_date_epoch.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +export LANG=C +export LC_ALL=C + +[ -n "$TOPDIR" ] && cd "$TOPDIR" + +try_git() { + [ -e .git ] || return 1 + SOURCE_DATE_EPOCH="$(git log -1 --format=format:%ct)" + [ -n "$SOURCE_DATE_EPOCH" ] +} + +try_hg() { + [ -d .hg ] || return 1 + SOURCE_DATE_EPOCH="$(hg log --template '{date}' -l 1 | cut -d. -f1)" + [ -n "$SOURCE_DATE_EPOCH" ] +} + +try_mtime() { + perl -e 'print((stat $ARGV[0])[9])' "$0" + [ -n "$SOURCE_DATE_EPOCH" ] +} + +try_git || try_hg || try_mtime || SOURCE_DATE_EPOCH="" +echo "$SOURCE_DATE_EPOCH"