From 2aa96617e17e3d2a58112dc31b4e2e910ffbf48b Mon Sep 17 00:00:00 2001 From: Carlos Segarra Date: Mon, 12 Feb 2024 17:56:40 +0000 Subject: [PATCH] llvm: changes for latest wasi-libc and wasi-sdk --- LLVM.makefile | 145 ++++++++++++++++++++--------------------- WasiToolchain.cmake | 20 +++--- docker/llvm.dockerfile | 18 ++++- tasks/docker.py | 4 +- tasks/llvm.py | 13 ++-- third-party/wasi-libc | 2 +- 6 files changed, 110 insertions(+), 92 deletions(-) diff --git a/LLVM.makefile b/LLVM.makefile index 42a8597d..980679fb 100644 --- a/LLVM.makefile +++ b/LLVM.makefile @@ -1,13 +1,11 @@ # Project directories LLVM_PROJ_DIR=${FAASM_LLVM_DIR} -TOOLCHAIN_DIR=${FAASM_CPP_PROJ_ROOT} -TOOLCHAIN_FILE=$(TOOLCHAIN_DIR)/WasiToolchain.cmake - # Install dirs FAASM_LOCAL_DIR=${FAASM_LOCAL_DIR_ENV} -PREFIX=$(FAASM_LOCAL_DIR)/toolchain FAASM_SYSROOT=$(FAASM_LOCAL_DIR)/llvm-sysroot +FAASM_TOOLCHAIN_DIR=$(FAASM_LOCAL_DIR)/toolchain +FAASM_TOOLCHAIN_FILE=$(FAASM_TOOLCHAIN_DIR)/tools/WasiToolchain.cmake CLANG_VERSION=${FAASM_LLVM_VERSION} CLANG_VERSION_MAJOR := $(shell echo $(CLANG_VERSION) | cut -f1 -d.) @@ -27,7 +25,7 @@ default: build .PHONY: clean-libc clean-libc: - rm -rf $(BUILD_DIR)/libc.BUILT $(WASI_LIBC_DIR)/build + rm -rf $(BUILD_DIR)/wasi-libc.BUILT $(WASI_LIBC_DIR)/build .PHONY: very-clean-libc very-clean-libc: clean-libc @@ -38,56 +36,73 @@ very-clean-libc: clean-libc clean-libs: clean-libc rm -rf $(BUILD_DIR)/compiler-rt $(BUILD_DIR)/compiler-rt.BUILT rm -rf $(BUILD_DIR)/libcxx $(BUILD_DIR)/libcxx.BUILT - rm -rf $(BUILD_DIR)/libcxxabi $(BUILD_DIR)/libcxxabi.BUILT .PHONY: clean-all clean-all: - rm -rf $(BUILD_DIR) $(PREFIX) + rm -rf $(BUILD_DIR) $(FAASM_TOOLCHAIN_DIR)/bin $(FAASM_TOOLCHAIN_DIR)/libs $(FAASM_SYSROOT) $(BUILD_DIR)/llvm.BUILT: mkdir -p $(BUILD_DIR)/llvm cd $(BUILD_DIR)/llvm; cmake -G Ninja \ - -DCMAKE_C_COMPILER=/usr/bin/clang-$(CLANG_VERSION_MAJOR) \ - -DCMAKE_CXX_COMPILER=/usr/bin/clang++-$(CLANG_VERSION_MAJOR) \ -DCMAKE_BUILD_TYPE=MinSizeRel \ - -DCMAKE_INSTALL_PREFIX=$(PREFIX) \ + -DLLVM_ENABLE_TERMINFO=OFF \ + -DLLVM_ENABLE_ZLIB=OFF \ + -DLLVM_ENABLE_ZSTD=OFF \ + -DLLVM_STATIC_LINK_CXX_STDLIB=ON \ + -DLLVM_HAVE_LIBXAR=OFF \ + -DCMAKE_INSTALL_PREFIX=${FAASM_TOOLCHAIN_DIR} \ + -DLLVM_INCLUDE_TESTS=OFF \ + -DLLVM_INCLUDE_UTILS=OFF \ + -DLLVM_INCLUDE_BENCHMARKS=OFF \ + -DLLVM_INCLUDE_EXAMPLES=OFF \ -DLLVM_TARGETS_TO_BUILD=WebAssembly \ -DLLVM_DEFAULT_TARGET_TRIPLE=wasm32-wasi \ - -DLLVM_EXTERNAL_CLANG_SOURCE_DIR=$(LLVM_PROJ_DIR)/clang \ - -DLLVM_EXTERNAL_OPENMP_SOURCE_DIR=$(LLVM_PROJ_DIR)/openmp \ - -DLLVM_EXTERNAL_LLD_SOURCE_DIR=$(LLVM_PROJ_DIR)/lld \ -DLLVM_ENABLE_PROJECTS="lld;clang;openmp" \ -DDEFAULT_SYSROOT=$(FAASM_SYSROOT) \ + -DLLVM_INSTALL_BINUTILS_SYMLINKS=TRUE \ + -DLLVM_ENABLE_LIBXML2=OFF \ $(LLVM_PROJ_DIR)/llvm ninja -v -C $(BUILD_DIR)/llvm \ install-clang \ install-clang-resource-headers \ install-lld \ - install-llc \ - install-llvm-ar \ + install-llvm-mc \ install-llvm-ranlib \ + install-llvm-strip \ install-llvm-dwarfdump \ - install-llvm-nm \ - install-llvm-size \ - install-llvm-config + install-clang-resource-headers \ + install-ar \ + install-ranlib \ + install-strip \ + install-nm \ + install-size \ + install-strings \ + install-objdump \ + install-objcopy \ + install-c++filt \ + llvm-config touch $(BUILD_DIR)/llvm.BUILT # WASI libc -$(BUILD_DIR)/libc.BUILT: $(BUILD_DIR)/llvm.BUILT - mkdir -p $(WASI_LIBC_DIR)/build - cd $(WASI_LIBC_DIR); $(MAKE) \ +$(BUILD_DIR)/wasi-libc.BUILT: $(BUILD_DIR)/compiler-rt.BUILT + mkdir -p $(WASI_LIBC_DIR)/build/wasm32-wasi + $(MAKE) -C ${WASI_LIBC_DIR} \ + CC=$(FAASM_TOOLCHAIN_DIR)/bin/clang \ + AR=$(FAASM_TOOLCHAIN_DIR)/bin/llvm-ar \ + NM=$(FAASM_TOOLCHAIN_DIR)/bin/llvm-nm \ + SYSROOT=$(FAASM_SYSROOT) \ THREAD_MODEL=faasm \ - CC=$(PREFIX)/bin/clang \ - AR=$(PREFIX)/bin/llvm-ar \ - NM=$(PREFIX)/bin/llvm-nm \ - SYSROOT=$(FAASM_SYSROOT) - touch $(BUILD_DIR)/libc.BUILT + default + touch $(BUILD_DIR)/wasi-libc.BUILT -$(BUILD_DIR)/compiler-rt.BUILT: $(BUILD_DIR)/libc.BUILT +$(BUILD_DIR)/compiler-rt.BUILT: $(BUILD_DIR)/llvm.BUILT mkdir -p $(BUILD_DIR)/compiler-rt cd $(BUILD_DIR)/compiler-rt; cmake -G Ninja \ + -DCMAKE_SYSROOT=${FAASM_SYSROOT} \ + -DCMAKE_C_COMPILER_WORKS=ON \ + -DCMAKE_CXX_COMPILER_WORKS=ON \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ + -DCMAKE_TOOLCHAIN_FILE=${FAASM_TOOLCHAIN_FILE} \ -DCOMPILER_RT_BAREMETAL_BUILD=ON \ -DCOMPILER_RT_BUILD_XRAY=OFF \ -DCOMPILER_RT_INCLUDE_TESTS=OFF \ @@ -95,60 +110,43 @@ $(BUILD_DIR)/compiler-rt.BUILT: $(BUILD_DIR)/libc.BUILT -DCOMPILER_RT_ENABLE_IOS=OFF \ -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \ -DLLVM_CONFIG_PATH=$(LLVM_CONFIG) \ - -DCMAKE_INSTALL_PREFIX=$(PREFIX)/lib/clang/$(CLANG_VERSION)/ \ + -DCMAKE_INSTALL_PREFIX=$(FAASM_TOOLCHAIN_DIR)/lib/clang/$(CLANG_VERSION)/ \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ -DCOMPILER_RT_OS_DIR=wasi \ $(LLVM_PROJ_DIR)/compiler-rt/lib/builtins ninja -v -C $(BUILD_DIR)/compiler-rt install - cp -R $(BUILD_DIR)/llvm/lib/clang $(PREFIX)/lib/ + cp -R $(BUILD_DIR)/llvm/lib/clang $(FAASM_TOOLCHAIN_DIR)/lib/ touch $(BUILD_DIR)/compiler-rt.BUILT -$(BUILD_DIR)/libcxx.BUILT: $(BUILD_DIR)/compiler-rt.BUILT +$(BUILD_DIR)/libcxx.BUILT: $(BUILD_DIR)/llvm.BUILT ${BUILD_DIR}/wasi-libc.BUILT mkdir -p $(BUILD_DIR)/libcxx cd $(BUILD_DIR)/libcxx; cmake -G Ninja \ - -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ + -DCMAKE_C_COMPILER_WORKS=ON \ -DCMAKE_CXX_COMPILER_WORKS=ON \ - -DCMAKE_C_COMPILER_WORKS=ON \ - -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ - -DCMAKE_INSTALL_PREFIX=$(FAASM_SYSROOT) \ - -DLLVM_COMPILER_CHECKED=ON \ + -DCMAKE_AR=$(FAASM_TOOLCHAIN_DIR)/bin/ar \ + -DCMAKE_TOOLCHAIN_FILE=$(FAASM_TOOLCHAIN_FILE) \ + -DCMAKE_STAGING_PREFIX=$(FAASM_SYSROOT) \ + -DCMAKE_POSITION_INDEPENDENT_CODE=OFF \ -DLLVM_CONFIG_PATH=$(LLVM_CONFIG) \ - -DLIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB=ON \ - -DLIBCXX_USE_COMPILER_RT=ON \ + -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON \ + -DCXX_SUPPORTS_CXX11=ON \ -DLIBCXX_ENABLE_THREADS:BOOL=ON \ -DLIBCXX_HAS_PTHREAD_API:BOOL=ON \ -DLIBCXX_HAS_EXTERNAL_THREAD_API:BOOL=OFF \ -DLIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY:BOOL=OFF \ -DLIBCXX_HAS_WIN32_THREAD_API:BOOL=OFF \ + -DLLVM_COMPILER_CHECKED=ON \ + -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ -DLIBCXX_ENABLE_SHARED:BOOL=OFF \ - -DLIBCXX_ENABLE_PIC:BOOL=OFF \ -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY:BOOL=OFF \ -DLIBCXX_ENABLE_EXCEPTIONS:BOOL=OFF \ - -DLIBCXX_ENABLE_FILESYSTEM:BOOL=OFF \ + -DLIBCXX_ENABLE_FILESYSTEM:BOOL=ON \ + -DLIBCXX_ENABLE_ABI_LINKER_SCRIPT:BOOL=OFF \ + -DLIBCXX_USE_COMPILER_RT=ON \ -DLIBCXX_CXX_ABI=libcxxabi \ -DLIBCXX_CXX_ABI_INCLUDE_PATHS=$(LLVM_PROJ_DIR)/libcxxabi/include \ -DLIBCXX_HAS_MUSL_LIBC:BOOL=ON \ -DLIBCXX_ABI_VERSION=2 \ - -DLIBCXX_LIBDIR_SUFFIX=/wasm32-wasi \ - --debug-trycompile \ - $(LLVM_PROJ_DIR)/libcxx - ninja -v -C $(BUILD_DIR)/libcxx install - touch $(BUILD_DIR)/libcxx.BUILT - -$(BUILD_DIR)/libcxxabi.BUILT: $(BUILD_DIR)/libcxx.BUILT - mkdir -p $(BUILD_DIR)/libcxxabi - cd $(BUILD_DIR)/libcxxabi; cmake -G Ninja \ - -DCMAKE_BUILD_TYPE=RelWithDebugInfo \ - -DCMAKE_C_FLAGS="-I$(FAASM_SYSROOT)/include" \ - -DCMAKE_CXX_FLAGS="-I$(FAASM_SYSROOT)/include/c++/v1" \ - -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ - -DLLVM_CONFIG_PATH=$(LLVM_CONFIG) \ - -DCMAKE_CXX_COMPILER_WORKS=ON \ - -DCMAKE_C_COMPILER_WORKS=ON \ - -DCMAKE_INSTALL_PREFIX=$(FAASM_SYSROOT) \ - -DLLVM_COMPILER_CHECKED=ON \ - -DLIBCXXABI_USE_COMPILER_RT=ON \ -DLIBCXXABI_ENABLE_EXCEPTIONS:BOOL=OFF \ -DLIBCXXABI_ENABLE_SHARED:BOOL=OFF \ -DLIBCXXABI_SILENT_TERMINATE:BOOL=ON \ @@ -157,28 +155,29 @@ $(BUILD_DIR)/libcxxabi.BUILT: $(BUILD_DIR)/libcxx.BUILT -DLIBCXXABI_HAS_EXTERNAL_THREAD_API:BOOL=OFF \ -DLIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY:BOOL=OFF \ -DLIBCXXABI_HAS_WIN32_THREAD_API:BOOL=OFF \ - -DLIBCXXABI_ENABLE_PIC:BOOL=OFF \ - -DLIBCXXABI_LIBCXX_PATH=$(LLVM_PROJ_DIR)/libcxx \ - -DLIBCXXABI_LIBCXX_INCLUDES=$(FAASM_SYSROOT)/include/c++/v1 \ + -DLIBCXX_ENABLE_PIC:BOOL=OFF \ -DUNIX:BOOL=ON \ - -DLIBCXXABI_LIBDIR_SUFFIX=/wasm32-wasi \ --debug-trycompile \ - $(LLVM_PROJ_DIR)/libcxxabi - ninja -v -C $(BUILD_DIR)/libcxxabi install - touch $(BUILD_DIR)/libcxxabi.BUILT + -DCMAKE_SYSROOT=${FAASM_SYSROOT} \ + -DCMAKE_C_FLAGS="-I$(FAASM_SYSROOT)/include --target=wasm32-wasi" \ + -DCMAKE_CXX_FLAGS="-I$(FAASM_SYSROOT)/include -I$(FAASM_SYSROOT)/include/c++/v1 --target=wasm32-wasi" \ + -DLIBCXX_LIBDIR_SUFFIX=/wasm32-wasi \ + -DLIBCXXABI_LIBDIR_SUFFIX=/wasm32-wasi \ + -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ + $(LLVM_PROJ_DIR)/runtimes + ninja -v -C $(BUILD_DIR)/libcxx install + touch $(BUILD_DIR)/libcxx.BUILT .PHONY: extras -extras: $(BUILD_DIR)/libcxxabi.BUILT - cp $(TOOLCHAIN_DIR)/sysroot_extras/* $(FAASM_SYSROOT)/lib/wasm32-wasi/ +extras: $(BUILD_DIR)/libcxx.BUILT + cp $(FAASM_CPP_PROJ_ROOT)/sysroot_extras/* $(FAASM_SYSROOT)/lib/wasm32-wasi/ llvm: $(BUILD_DIR)/llvm.BUILT -libc: $(BUILD_DIR)/libc.BUILT +libc: $(BUILD_DIR)/wasi-libc.BUILT libcxx: $(BUILD_DIR)/libcxx.BUILT -libcxxabi: $(BUILD_DIR)/libcxxabi.BUILT - compiler-rt: $(BUILD_DIR)/compiler-rt.BUILT -build: $(BUILD_DIR)/llvm.BUILT $(BUILD_DIR)/libc.BUILT $(BUILD_DIR)/compiler-rt.BUILT $(BUILD_DIR)/libcxxabi.BUILT $(BUILD_DIR)/libcxx.BUILT extras +build: $(BUILD_DIR)/llvm.BUILT $(BUILD_DIR)/wasi-libc.BUILT $(BUILD_DIR)/compiler-rt.BUILT $(BUILD_DIR)/libcxx.BUILT extras diff --git a/WasiToolchain.cmake b/WasiToolchain.cmake index d2db1f5f..b0181df0 100644 --- a/WasiToolchain.cmake +++ b/WasiToolchain.cmake @@ -1,4 +1,5 @@ -cmake_minimum_required(VERSION 3.4.0) +cmake_minimum_required(VERSION 3.5.0) +# project("Faasm WASM compilation toolchain" C CXX) # ----------------------------------------- # A useful reference for this file is the wasi-sdk equivalent: @@ -11,15 +12,16 @@ cmake_minimum_required(VERSION 3.4.0) set(INSTALL_DIR $ENV{FAASM_WASM_INSTALL_DIR}) set(FAASM_SYSROOT $ENV{FAASM_WASM_SYSROOT}) -set(EXE_SUFFIX "") - set(UNIX 1) # Note that system name and processor here are crucial # Setting system name automatically switches on cross-compiling -set(CMAKE_SYSTEM_NAME Wasm) +set(CMAKE_SYSTEM_NAME WASI) set(CMAKE_SYSTEM_VERSION 1) set(CMAKE_SYSTEM_PROCESSOR wasm32) +set(WASM_TRIPLE wasm32-wasi) + +set(WASI_HOST_EXE_SUFFIX "") if(FAASM_BUILD_SHARED) message(STATUS "Faasm building SHARED libraries") @@ -32,16 +34,17 @@ else() set(WASM_TRIPLE $ENV{FAASM_WASM_HOST_STATIC}) endif() -set(CMAKE_C_COMPILER_TARGET ${WASM_TRIPLE} CACHE STRING "faasm build") -set(CMAKE_CXX_COMPILER_TARGET ${WASM_TRIPLE} CACHE STRING "faasm build") -message(STATUS "Faasm building target ${CMAKE_CXX_COMPILER_TARGET}") - # Specify LLVM toolchain set(CMAKE_C_COMPILER $ENV{FAASM_WASM_CC}) set(CMAKE_CXX_COMPILER $ENV{FAASM_WASM_CXX}) +set(CMAKE_ASM_COMPILER $ENV{FAASM_WASM_CC}) set(CMAKE_AR $ENV{FAASM_WASM_AR} CACHE STRING "faasm build") set(CMAKE_NM $ENV{FAASM_WASM_NM} CACHE STRING "faasm build") set(CMAKE_RANLIB $ENV{FAASM_WASM_RANLIB} CACHE STRING "faasm build") +set(CMAKE_C_COMPILER_TARGET ${WASM_TRIPLE} CACHE STRING "faasm build") +set(CMAKE_CXX_COMPILER_TARGET ${WASM_TRIPLE} CACHE STRING "faasm build") +set(CMAKE_ASM_COMPILER_TARGET ${WASM_TRIPLE} CACHE STRING "faasm build") +message(STATUS "Faasm building target ${CMAKE_CXX_COMPILER_TARGET}") # We define dynamic linking functions in Faasm unset(CMAKE_DL_LIBS CACHE) @@ -72,4 +75,3 @@ set(CMAKE_C_COMPILER_WORKS ON) set(CMAKE_CXX_COMPILER_WORKS ON) set(FAASM_BLAS_LIBS $ENV{FAASM_WASM_BLAS_LIBS}) - diff --git a/docker/llvm.dockerfile b/docker/llvm.dockerfile index 3d69e196..a4d0f39e 100644 --- a/docker/llvm.dockerfile +++ b/docker/llvm.dockerfile @@ -3,13 +3,26 @@ FROM ubuntu:22.04 SHELL ["/bin/bash", "-c"] ENV CPP_DOCKER="on" +# Configure APT repositories +ARG LLVM_VERSION_MAJOR +RUN apt update \ + && apt upgrade -y \ + && apt install -y \ + curl \ + gpg \ + software-properties-common \ + wget \ + && wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc \ + && add-apt-repository -y "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${LLVM_VERSION_MAJOR} main" + # Install APT dependencies ARG DEBIAN_FRONTEND=noninteractive RUN apt update \ && apt install -y \ autoconf \ build-essential \ - clang-13 \ + # This clang version is needed to help us build LLVM from source below + clang-${LLVM_VERSION_MAJOR} \ curl \ git \ gpg \ @@ -26,7 +39,7 @@ RUN apt remove --purge --auto-remove cmake \ && mkdir -p /setup \ && cd /setup \ && wget -q -O cmake-linux.sh \ - https://github.com/Kitware/CMake/releases/download/v3.24.2/cmake-3.24.2-linux-x86_64.sh \ + https://github.com/Kitware/CMake/releases/download/v3.28.0/cmake-3.28.0-linux-x86_64.sh \ && sh cmake-linux.sh -- --skip-license --prefix=/usr/local \ && apt clean autoclean -y \ && apt autoremove -y @@ -42,6 +55,7 @@ RUN mkdir -p /code \ && ./bin/create_venv.sh \ && source venv/bin/activate \ && inv install \ + # This task builds LLVM from source and reads the version from faasmtools/env.py && inv llvm.build \ && /usr/local/faasm/toolchain/bin/clang --version \ && rm -rf /code diff --git a/tasks/docker.py b/tasks/docker.py index 02cd0363..a38ee1f5 100644 --- a/tasks/docker.py +++ b/tasks/docker.py @@ -4,8 +4,9 @@ ACR_NAME, ) from faasmtools.env import ( - get_version, + LLVM_VERSION, PROJ_ROOT, + get_version, ) from invoke import task from os.path import join @@ -34,6 +35,7 @@ def build(ctx, c, nocache=False, push=False): build_args = {"SYSROOT_VERSION": get_version()} for ctr in c: if ctr == "llvm": + build_args["LLVM_VERSION_MAJOR"] = LLVM_VERSION.split(".")[0] dockerfile = LLVM_DOCKERFILE tag = get_llvm_tag() elif ctr == "cpp-sysroot": diff --git a/tasks/llvm.py b/tasks/llvm.py index 1f35097d..3ccd954c 100644 --- a/tasks/llvm.py +++ b/tasks/llvm.py @@ -45,10 +45,11 @@ def do_llvm_clone(): git_cmd = " ".join(git_cmd) run(git_cmd, shell=True, check=True) - llvm_patches_dir = join(PATCHES_DIR, "llvm-project") - for patch in listdir(llvm_patches_dir): - git_cmd = "git apply {}".format(join(llvm_patches_dir, patch)) - run(git_cmd, shell=True, check=True, cwd=LLVM_DIR) + # TODO: do we even need this patch anymore? + # llvm_patches_dir = join(PATCHES_DIR, "llvm-project") + # for patch in listdir(llvm_patches_dir): + # git_cmd = "git apply {}".format(join(llvm_patches_dir, patch)) + # run(git_cmd, shell=True, check=True, cwd=LLVM_DIR) def do_llvm_build(target, clean_target=None): @@ -92,10 +93,10 @@ def build(ctx, clean=False): @task() def libs(ctx, clean=False): """ - Build the compiler-rt, libcxx, and libcxxabi for our LLVM fork + Build the compiler-rt, and libcxx for our LLVM fork """ do_llvm_build( - "libcxx libcxxabi compiler-rt", "clean-libs" if clean else None + "libcxx compiler-rt", "clean-libs" if clean else None ) diff --git a/third-party/wasi-libc b/third-party/wasi-libc index 16fde82f..df72bea1 160000 --- a/third-party/wasi-libc +++ b/third-party/wasi-libc @@ -1 +1 @@ -Subproject commit 16fde82fe008aa2995cec65685a217cf469e4837 +Subproject commit df72bea123a7b1d670a9bfba15124e7e02e22baa