diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 000000000..dad5dfe05 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,156 @@ +# Copyright (c) 2023, [Ribose Inc](https://www.ribose.com). +# All rights reserved. +# This file is a part of tamatebako +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +name: Windows + +on: + schedule: + - cron: "0 8 * * 6" + push: + branches: [ main ] + paths-ignore: + - 'docs/**' + - '**.adoc' + - '**.md' + - '.cirrus.yml' + - '.github/workflows/*.yml' + - '!.github/workflows/windows.yml' + pull_request: + paths-ignore: + - 'docs/**' + - '**.adoc' + - '**.md' + - '.cirrus.yml' + - '.github/workflows/*.yml' + - '!.github/workflows/windows.yml' + workflow_dispatch: + +concurrency: + group: '${{ github.workflow }}-${{ github.job }}-${{ github.head_ref || github.ref_name }}' + cancel-in-progress: true + +env: + VCPKG_DIR: C:/vcpkg + VCPKG_DEFAULT_BINARY_CACHE: ${{github.workspace}}\cache + CCACHE_DIR: ${{github.workspace}}\ccache + +jobs: + build: + name: ${{ matrix.config.os }} [ ${{ matrix.config.env.CC }}, scope ${{ matrix.setup.scope }}, ${{ matrix.config.build_type }} ${{ matrix.config.extra_opts }} ] + runs-on: ${{ matrix.config.os }} + strategy: + fail-fast: false + matrix: + config: + - { os: windows-2019, env: { CC: cl, CXX: cl }, build_type: Release, extra_opts: '' } + - { os: windows-2022, env: { CC: cl, CXX: cl }, build_type: Release, extra_opts: '' } + +# We are running two configurations: +# - ALL in order to run regression tests +# - MKD just to be sure that it build ok + setup: + - { scope: 'ALL', tests: 'ON' } + - { scope: 'MKD', tests: 'OFF' } + + env: ${{ matrix.config.env }} + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: true + + - name: Set MSVC Dev Environment + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install UPX + if: ${{ matrix.setup.scope == 'ALL' }} + uses: crazy-max/ghaction-upx@v3 + with: + install-only: true + +# Similar to fuse -- cannot mount in GHA container +# - name: Install WinFSP +# if: ${{ matrix.setup.scope == 'ALL' }} +# run: choco install winfsp +# copy "C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll" ${{ runner.temp }}\build + + - name: Install ccache + run: choco install ccache + + - name: Configure build environment + shell: cmd + run: | + vcpkg version >> vcpkg.version + mkdir ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + mkdir ${{ env.CCACHE_DIR }} + + + - name: Set number of CPU cores + shell: bash + run: | + echo "CORES=$(nproc --all)" >> $GITHUB_ENV + + - name: vcpkg cache + uses: actions/cache@v3 + with: + path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }} + key: vcpkg-${{ matrix.config.os }}-${{ hashFiles('vcpkg.version') }} + + - name: ccache cache + uses: actions/cache@v3 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ matrix.config.build_type }}-${{ matrix.config.os }}-${{ matrix.config.xcode }}${{ matrix.config.env.CC }}-${{ matrix.setup.scope }}-${{ matrix.config.extra_opts }}-${{ github.ref }}-${{ github.sha }} + restore-keys: | + ccache-${{ matrix.config.build_type }}-${{ matrix.config.os }}-${{ matrix.config.xcode }}${{ matrix.config.env.CC }}-${{ matrix.setup.scope }}-${{ matrix.config.extra_opts }}-${{ github.ref }}- + ccache-${{ matrix.config.build_type }}-${{ matrix.config.os }}-${{ matrix.config.xcode }}${{ matrix.config.env.CC }}-${{ matrix.setup.scope }}-${{ matrix.config.extra_opts }}- + + - name: Configure Build + shell: cmd + # Due to folly issue VCPKG_INSTALLED_DIR has to be outside of the project tree + run: | + cmake -B build -G Ninja ^ + -DVCPKG_INSTALLED_DIR="${{ runner.workspace }}/vcpkg-install-dwarfs" ^ + -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} ^ + -DTEBAKO_BUILD_SCOPE=${{ matrix.setup.scope }} ^ + -DWITH_TESTS=${{ matrix.setup.tests }} ^ + -DCMAKE_TOOLCHAIN_FILE=${{ env.VCPKG_DIR }}/scripts/buildsystems/vcpkg.cmake ^ + -DVCPKG_TARGET_TRIPLET=x64-windows-static ^ + -DFOLLY_NO_EXCEPTION_TRACER=ON ^ + -DWITH_MAN_PAGES=OFF ^ + -DNIXPKGS_DWARFS_VERSION_OVERRIDE=tebako ^ + ${{ matrix.config.extra_opts }} . + + - name: Run Build + shell: cmd + run: | + cmake --build build --parallel ${{ env.CORES }} + + - name: Test + shell: cmd + if: ${{ matrix.setup.tests == 'ON' }} + run: | + ctest --test-dir build --output-on-failure --parallel ${{ env.CORES }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cbe5a1c6..94d4636e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,9 @@ cmake_minimum_required(VERSION 3.24.0) +# Enable CMAKE_MSVC_RUNTIME_LIBRARY +cmake_policy(SET CMP0091 NEW) + project(dwarfs) include(ExternalProject) @@ -82,6 +85,10 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) CACHE STRING "Build Type" FORCE) endif() +# Apply /MT or /MTd (multithread, static version of the run-time library) +# This is ignored if we are not running Cl or Clang-Cl +set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") add_compile_options(-fdiagnostics-color=always) # For gcc, -O3 is *much* worse than -O2 @@ -99,6 +106,8 @@ endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") add_compile_options(/Zc:__cplusplus /utf-8 /wd4267 /wd4244 /wd5219) + # Apply /MT or /MTd (multithread, static version of the run-time library) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif() include(${CMAKE_SOURCE_DIR}/cmake/version.cmake) @@ -149,26 +158,31 @@ set(DEPS_SBIN_DIR ${DEPS}/sbin) set(TOOLS "${CMAKE_CURRENT_SOURCE_DIR}/tools") include(${TOOLS}/cmake-scripts/def-external-project.cmake) -include(${TOOLS}/cmake-scripts/setup-libarchive.cmake) include_directories(${DEPS_INCLUDE_DIR}) link_directories(${DEPS_LIB_DIR}) -execute_process( - COMMAND "${GNU_BASH}" - "-c" - "echo \$OSTYPE" - RESULT_VARIABLE OSTYPE_RES - OUTPUT_VARIABLE OSTYPE_TXT - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE -) +if(MSVC) + set(OSTYPE_TXT "Windows") +else(MSVC) + include(${TOOLS}/cmake-scripts/setup-libarchive.cmake) + + execute_process( + COMMAND "${GNU_BASH}" + "-c" + "echo \$OSTYPE" + RESULT_VARIABLE OSTYPE_RES + OUTPUT_VARIABLE OSTYPE_TXT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) -if(OSTYPE_RES EQUAL 0) - message(STATUS "OSTYPE: '${OSTYPE_TXT}'") -else(OSTYPE_RES EQUAL 0) - message(FATAL_ERROR "Failed to detect OSTYPE: ${OSTYPE_TXT}") -endif(OSTYPE_RES EQUAL 0) + if(OSTYPE_RES EQUAL 0) + message(STATUS "OSTYPE: '${OSTYPE_TXT}'") + else(OSTYPE_RES EQUAL 0) + message(FATAL_ERROR "Failed to detect OSTYPE: ${OSTYPE_TXT}") + endif(OSTYPE_RES EQUAL 0) +endif(MSVC) set(PATCH_FOLLY OFF) @@ -317,6 +331,9 @@ if(PKG_CONFIG_FOUND) pkg_check_modules(LIBBROTLIDEC IMPORTED_TARGET libbrotlidec>=1.0.9) pkg_check_modules(LIBBROTLIENC IMPORTED_TARGET libbrotlienc>=1.0.9) pkg_check_modules(LIBBROTLICOMMON IMPORTED_TARGET libbrotlicommon>=1.0.9) + if (MSVC) + pkg_check_modules(LIBARCHIVE IMPORTED_TARGET libarchive>=3.6.0) + endif(MSVC) pkg_check_modules(ZSTD IMPORTED_TARGET libzstd>=1.5.2) pkg_check_modules(XXHASH IMPORTED_TARGET libxxhash>=0.8.1) endif() @@ -341,7 +358,8 @@ if ("${TEBAKO_BUILD_SCOPE}" STREQUAL "ALL") endif() find_library(WINFSP winfsp-x64.lib "${WINFSP_PATH}/lib") if (NOT WINFSP) - message(FATAL_ERROR "No WinFsp library found") + message(WARNING "No WinFsp library found") + add_compile_definitions(WITHOUT_FUSE) endif() else() if(NOT FUSE_FOUND AND NOT FUSE3_FOUND) @@ -357,7 +375,6 @@ endif() if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") foreach(CompilerFlag CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE) - string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") string(REPLACE "/RTC1" "" ${CompilerFlag} "${${CompilerFlag}}") endforeach() @@ -954,7 +971,11 @@ if(LIBBROTLIDEC_FOUND AND LIBBROTLIENC_FOUND AND LIBBROTLICOMMON_FOUND) endif() if(NOT STATIC_BUILD_DO_NOT_USE) - target_link_libraries(dwarfs _LIBARCHIVE) + if(MSVC) + target_link_libraries(dwarfs PkgConfig::LIBARCHIVE) + else(MSVC) + target_link_libraries(dwarfs _LIBARCHIVE) + endif(MSVC) endif(NOT STATIC_BUILD_DO_NOT_USE) if(ZSTD_FOUND AND PREFER_SYSTEM_ZSTD) @@ -973,7 +994,11 @@ endif() foreach(tgt ${BINARY_TARGETS} ${MAIN_TARGETS}) target_link_libraries(${tgt} "$") - target_link_libraries(${tgt} dwarfs dwarfs_tool _LIBARCHIVE) + if(MSVC) + target_link_libraries(${tgt} dwarfs dwarfs_tool PkgConfig::LIBARCHIVE) + else(MSVC) + target_link_libraries(${tgt} dwarfs dwarfs_tool _LIBARCHIVE) + endif(MSVC) if(USE_JEMALLOC) target_link_libraries(${tgt} PkgConfig::JEMALLOC) endif(USE_JEMALLOC) @@ -1127,7 +1152,7 @@ if(STATIC_BUILD_DO_NOT_USE AND NOT WIN32) add_custom_target(strip COMMAND strip -s ${FILES_TO_STRIP}) endif() -if(STATIC_BUILD_DO_NOT_USE OR WIN32) +if(STATIC_BUILD_DO_NOT_USE OR (WIN32 AND "${TEBAKO_BUILD_SCOPE}" STREQUAL "ALL")) find_program(UPX_EXE upx upx.exe PATHS "c:/bin" DOC "ultimate packer for executables" REQUIRED) set(UNIVERSAL_PACKED diff --git a/include/dwarfs/block_range.h b/include/dwarfs/block_range.h index 3cb6446af..3860b7608 100644 --- a/include/dwarfs/block_range.h +++ b/include/dwarfs/block_range.h @@ -31,6 +31,7 @@ class cached_block; class block_range { public: + block_range(void) = default; // This is required for MSVC toolset v142 or less block_range(uint8_t const* data, size_t offset, size_t size); block_range(std::shared_ptr block, size_t offset, size_t size); diff --git a/include/dwarfs/fs_section.h b/include/dwarfs/fs_section.h index 6b56b13ba..3aa94019e 100644 --- a/include/dwarfs/fs_section.h +++ b/include/dwarfs/fs_section.h @@ -33,6 +33,7 @@ class mmif; class fs_section { public: + fs_section(void) = default; // This is required for MSVC toolset v142 or less fs_section(mmif const& mm, size_t offset, int version); fs_section(std::shared_ptr mm, section_type type, size_t offset, size_t size, int version); diff --git a/src/dwarfs/util.cpp b/src/dwarfs/util.cpp index 45df1d475..e88bab8a7 100644 --- a/src/dwarfs/util.cpp +++ b/src/dwarfs/util.cpp @@ -24,7 +24,11 @@ #include #include +#ifdef _WIN32 +#include +#else #include +#endif #include diff --git a/src/dwarfs/worker_group.cpp b/src/dwarfs/worker_group.cpp index 74d263190..c2fc32406 100644 --- a/src/dwarfs/worker_group.cpp +++ b/src/dwarfs/worker_group.cpp @@ -31,7 +31,9 @@ #include #include +#ifndef _WIN32 #include +#endif #if __MACH__ #include