diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 530a29f24190d4..b089cb30e9d47e 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -1,11 +1,6 @@ name: Ubuntu CI on: - push: - branches-ignore: - # Exclude the push event for exported diffs, because the CI for export - # should have been covered by GitHub Actions triggered by pull requests. - - 'export-D+' pull_request: concurrency: @@ -25,47 +20,29 @@ env: DEBIAN_FRONTEND: "noninteractive" jobs: - build_ubuntu_focal_nightly: - runs-on: 16-core - container: - image: ubuntu:focal - env: - DISTRO: ubuntu-20.04-focal - IS_NIGHTLY: 1 - CLANG_VERSION: 12 + build_ubuntu_noble_nightly: + timeout-minutes: 660 # 12 hours + runs-on: hhvm-builder steps: - - name: Installing dependencies to bootstrap env - run: apt update -y && apt install -y git wget lsb-release software-properties-common gpg - - name: Installing llvm - run: | - wget https://apt.llvm.org/llvm.sh - chmod +x llvm.sh - # Note: Keep this version in sync with the one in the Debian control file. - ./llvm.sh ${CLANG_VERSION} - - name: Making LLVM the default compiler - run: | - if [ -f /etc/alternatives/cc ] - then - update-alternatives --remove-all cc - fi - - if [ -f /etc/alternatives/c++ ] - then - update-alternatives --remove-all c++ - fi - - update-alternatives --install /usr/bin/cc cc /usr/bin/clang++-${CLANG_VERSION} 500 - update-alternatives --set cc /usr/bin/clang++-${CLANG_VERSION} - update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${CLANG_VERSION} 500 - update-alternatives --set c++ /usr/bin/clang++-${CLANG_VERSION} - - name: Fetching HHVM and its submodules - uses: actions/checkout@v3 - with: - submodules: 'recursive' - - name: Installing HHVM deps and building HHVM - run: ci/bin/make-debianish-package - - name: Uploading artifacts - uses: actions/upload-artifact@v3 - with: - name: out-directory - path: ${{ env.OUT }} + # The HHVM build requires more disk space than what is available + # on a default Actions runner, so remove some cruft. + #- name: Free up disk space + # uses: jlumbroso/free-disk-space@v1.3.1 + - name: Fetching HHVM and its submodules + uses: actions/checkout@v4 + with: + submodules: "recursive" + - name: Installing HHVM deps and building HHVM + uses: docker://ubuntu:noble + env: + DISTRO: ubuntu-24.04-noble + IS_NIGHTLY: 1 + CLANG_VERSION: 20 + with: + entrypoint: /bin/bash + args: ci/bin/make-debianish-package + - name: Uploading artifacts + uses: actions/upload-artifact@v4 + with: + name: out-directory + path: ${{ env.OUT }} diff --git a/.gitignore b/.gitignore index 881ca58c8b012a..82373bf8085b46 100644 --- a/.gitignore +++ b/.gitignore @@ -86,6 +86,9 @@ install_manifest.txt /hphp/hack/test/.mypy_cache /hphp/util/generated-hhjs-babel-transform.txt +# Generated core systemlib +/hphp/runtime/ext/core/ext_core.php + # CPack CPackConfig.cmake CPackSourceConfig.cmake diff --git a/.gitmodules b/.gitmodules index 2a7e687583373a..0cca4da87f0068 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "xed-xed"] path = third-party/xed/xed url = https://github.com/intelxed/xed.git +[submodule "third-party/mvfst/src"] + path = third-party/mvfst/src + url = https://github.com/facebook/mvfst.git diff --git a/CMake/FindBpf.cmake b/CMake/FindBpf.cmake new file mode 100644 index 00000000000000..1591ab2f73b051 --- /dev/null +++ b/CMake/FindBpf.cmake @@ -0,0 +1,15 @@ +find_path(BPF_INCLUDE_DIR bpf/bpf.h) +find_library(BPF_LIBRARY NAMES bpf) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BPF DEFAULT_MSG BPF_LIBRARY BPF_INCLUDE_DIR) + +if(BPF_FOUND) + set(BPF_LIBRARIES ${BPF_LIBRARY}) + set(BPF_INCLUDE_DIRS ${BPF_INCLUDE_DIR}) +else() + set(BPF_LIBRARIES) + set(BPF_INCLUDE_DIRS) +endif() + +mark_as_advanced(BPF_LIBRARIES BPF_INCLUDE_DIRS) diff --git a/CMake/FindLibDwarf.cmake b/CMake/FindLibDwarf.cmake index 2dc6142b47bed9..1e4eb649d584ad 100644 --- a/CMake/FindLibDwarf.cmake +++ b/CMake/FindLibDwarf.cmake @@ -25,36 +25,72 @@ endif (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS) find_package(PkgConfig) pkg_check_modules(PkgConfig_LibDwarf QUIET libdwarf) +set( + LIBDWARF_INCLUDE_PATHS + ${PkgConfig_LibDwarf_INCLUDE_DIRS} + /usr/include + /usr/include/libdwarf + /usr/local/include + /usr/local/include/libdwarf + /opt/local/include + /sw/include +) + find_path (DWARF_INCLUDE_DIR NAMES libdwarf.h dwarf.h PATHS - ${PkgConfig_LibDwarf_INCLUDE_DIRS} - /usr/include - /usr/include/libdwarf - /usr/local/include - /usr/local/include/libdwarf - /opt/local/include - /sw/include + ${LIBDWARF_INCLUDE_PATHS} ENV CPATH) # PATH and INCLUDE will also work if (DWARF_INCLUDE_DIR) set (LIBDWARF_INCLUDE_DIRS ${DWARF_INCLUDE_DIR}) endif () +set(LIBDWARF_LIBRARY_NAMES dwarf libdwarf) + +find_path (LIBDWARF_PRODUCER_PATHS + NAMES + libdwarfp.h + PATHS + ${LIBDWARF_INCLUDE_PATHS} + ENV CPATH +) + +set( + LIBDWARF_LIBRARY_PATHS + /usr/lib + /usr/local/lib + /opt/local/lib + /sw/lib + ${PkgConfig_LibDwarf_LIBRARY_DIRS} + ENV LIBRARY_PATH # PATH and LIB will also work + ENV LD_LIBRARY_PATH +) + +if (LIBDWARF_PRODUCER_PATHS) + set(LIBDWARF_USE_NEW_PRODUCER_API 1) +else() + set(LIBDWARF_USE_NEW_PRODUCER_API 0) +endif() + find_library (LIBDWARF_LIBRARIES NAMES dwarf libdwarf PATHS - /usr/lib - /usr/local/lib - /opt/local/lib - /sw/lib - ${PkgConfig_LibDwarf_LIBRARY_DIRS} - ENV LIBRARY_PATH # PATH and LIB will also work - ENV LD_LIBRARY_PATH) -include (FindPackageHandleStandardArgs) + ${LIBDWARF_LIBRARY_PATHS}) + +if (LIBDWARF_USE_NEW_PRODUCER_API) + find_library (LIBDWARFP_LIBRARIES + NAMES + dwarfp libdwarfp + PATHS + ${LIBDWARF_LIBRARY_PATHS}) + list(APPEND LIBDWARF_LIBRARIES ${LIBDWARFP_LIBRARIES}) +endif() + +include (FindPackageHandleStandardArgs) # handle the QUIETLY and REQUIRED arguments and set LIBDWARF_FOUND to TRUE # if all listed variables are TRUE @@ -106,7 +142,7 @@ if (LIBDWARF_LIBRARIES AND LIBDWARF_INCLUDE_DIRS) # Order is important, last one is used. CHECK_LIBDWARF_INIT("dwarf_producer_init" - "0, dwarfCallback, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr" 0) + "0, dwarfCallback, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr" 0) CHECK_LIBDWARF_INIT("dwarf_producer_init_c" "0, dwarfCallback, nullptr, nullptr, nullptr, nullptr" 1) set(CMAKE_REQUIRED_INCLUDES) @@ -127,3 +163,4 @@ endif() mark_as_advanced(LIBDW_INCLUDE_DIR DWARF_INCLUDE_DIR) mark_as_advanced(LIBDWARF_INCLUDE_DIRS LIBDWARF_LIBRARIES) mark_as_advanced(LIBDWARF_CONST_NAME LIBDWARF_USE_INIT_C) +mark_as_advanced(LIBDWARF_USE_NEW_PRODUCER_API) diff --git a/CMake/HHVMExtensionConfig.cmake b/CMake/HHVMExtensionConfig.cmake index 958d6e60dea00c..c4304f41710196 100644 --- a/CMake/HHVMExtensionConfig.cmake +++ b/CMake/HHVMExtensionConfig.cmake @@ -442,15 +442,7 @@ function (HHVM_EXTENSION_INTERNAL_SORT_OUT_SOURCES rootDir) elseif (${fileExtension} STREQUAL ".h" OR ${fileExtension} STREQUAL ".hpp") list(APPEND HEADER_SOURCES "${rootDir}/${fileName}") elseif (${fileExtension} STREQUAL ".s") - # AT&T syntax, MSVC doesn't like. - if (NOT MSVC) - list(APPEND ASM_SOURCES "${rootDir}/${fileName}") - endif() - elseif (${fileExtension} STREQUAL ".asm") - # MASM syntax. MSVC only. - if (MSVC) - list(APPEND ASM_SOURCES "${rootDir}/${fileName}") - endif() + list(APPEND ASM_SOURCES "${rootDir}/${fileName}") elseif (${fileExtension} STREQUAL ".php") list(APPEND PHP_SOURCES "${rootDir}/${fileName}") elseif (${fileExtension} STREQUAL ".hack") @@ -530,10 +522,6 @@ function(HHVM_EXTENSION_INTERNAL_RESOLVE_DEPENDENCIES_OF_EXTENSION resolvedDestV if (${listIDX} EQUAL 0) # OS Dependency if (${currentDependency} STREQUAL "osPosix") - if (MSVC) - HHVM_EXTENSION_INTERNAL_SET_FAILED_DEPENDENCY(${extensionID} ${currentDependency} ON) - break() - endif() else() message(FATAL_ERROR "The only OS restriction that is currently valid is 'osPosix', got '${currentDependency}'!") endif() @@ -781,15 +769,13 @@ function (HHVM_EXTENSION_INTERNAL_HANDLE_LIBRARY_DEPENDENCY extensionID dependen HHVM_EXTENSION_INTERNAL_ADD_DEFINES("-DHAVE_LIBGMP") endif() elseif (${libraryName} STREQUAL "heif") - find_package(Libheif ${requiredVersion} REQUIRED) - if (NOT LIBHEIF_INCLUDE_DIR OR NOT LIBHEIF_LIBRARY) - HHVM_EXTENSION_INTERNAL_SET_FAILED_DEPENDENCY(${extensionID} ${dependencyName}) - return() - endif() + find_package(libheif 1.19.8 CONFIG) - if (${addPaths}) - HHVM_EXTENSION_INTERNAL_ADD_INCLUDE_DIRS(${LIBHEIF_INCLUDE_DIR}) - HHVM_EXTENSION_INTERNAL_ADD_LINK_LIBRARIES(${LIBHEIF_LIBRARY}) + if (libheif_FOUND AND ${addPaths}) + get_target_property(DEPENDENCY_TARGET_INCLUDE_DIR heif INTERFACE_INCLUDE_DIRECTORIES) + HHVM_EXTENSION_INTERNAL_ADD_INCLUDE_DIRS("${DEPENDENCY_TARGET_INCLUDE_DIR}") + HHVM_EXTENSION_INTERNAL_ADD_LINK_LIBRARIES(heif) + HHVM_EXTENSION_INTERNAL_ADD_DEFINES("-DHAVE_LIBHEIF") endif() elseif (${libraryName} STREQUAL "iconv") find_package(Libiconv ${requiredVersion}) diff --git a/CMake/HHVMGenerateConfig.cmake b/CMake/HHVMGenerateConfig.cmake index 3a3cb2953d1e65..85d372b2eb5926 100644 --- a/CMake/HHVMGenerateConfig.cmake +++ b/CMake/HHVMGenerateConfig.cmake @@ -66,16 +66,6 @@ function(HHVM_GENERATE_CONFIG_FUNCTIONS_FOUND_DEFINE_STRING destVarName) "utimes" ) - # This is a list of functions that are known to be present under MSVC - # because they are implemented via Folly's portability headers. For an - # item in this list to have any effect, it must first fail to be found - # when checking the item in the main list. - set(HHVM_FUNCTIONS_KNOWN_TO_BE_PRESENT_MSVC) - list(APPEND HHVM_FUNCTIONS_KNOWN_TO_BE_PRESENT_MSVC - "mkstemp" - "mmap" - ) - set(builtString "") list(LENGTH HHVM_FUNCTIONS_TO_CHECK functionCount) set(i 0) @@ -86,12 +76,7 @@ function(HHVM_GENERATE_CONFIG_FUNCTIONS_FOUND_DEFINE_STRING destVarName) if (${HAVE_${curFuncUpper}}) set(builtString "${builtString}\n#define HAVE_${curFuncUpper} 1") else() - list(FIND HHVM_FUNCTIONS_KNOWN_TO_BE_PRESENT_MSVC "${curFunc}" curFuncIdx) - if (curFuncIdx EQUAL -1 OR NOT MSVC) - set(builtString "${builtString}\n/* #undef HAVE_${curFuncUpper} */") - else() - set(builtString "${builtString}\n#define HAVE_${curFuncUpper} 1 /* Implemented via Folly Portability header */") - endif() + set(builtString "${builtString}\n/* #undef HAVE_${curFuncUpper} */") endif() math(EXPR i "${i} + 1") endwhile() diff --git a/CMake/HPHPCompiler.cmake b/CMake/HPHPCompiler.cmake index fabdbd646299f2..0144091eb0321e 100644 --- a/CMake/HPHPCompiler.cmake +++ b/CMake/HPHPCompiler.cmake @@ -83,29 +83,52 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU set(GDB_SUBOPTION) # Enable GCC/LLVM stack-smashing protection - if(ENABLE_SSP) + if(ENABLE_HARDENING) list(APPEND GENERAL_OPTIONS + # Enable stack protection and stack-clash protection. # This needs two dashes in the name, so put one here. "-param=ssp-buffer-size=4" - "pie" - "fPIC" + "fstack-protector-strong" + "fstack-clash-protection" + + # Use hardened equivalents of various glibc functions + # to guard against buffer overflows. + "D_FORTIFY_SOURCE=3" + + # https://isisblogs.poly.edu/2011/06/01/relro-relocation-read-only/ + "Wl,-z,relro,-z,now" + # Mark stack as non-executable. + "Wl,-z,noexecstack" + # Separate ELF code into its own segment. + "Wl,-z,separate-code" ) + + # Enable control-flow / branch protection. + if (IS_X64) + list(APPEND GENERAL_OPTIONS "fcf-protection") + elseif (IS_AARCH64) + list(APPEND GENERAL_OPTIONS "mbranch-protection=standard") + endif() + + # Enable C++ standard library assertions. + if (CLANG_FORCE_LIBCPP) + list(APPEND GENERAL_CXX_OPTIONS "D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE") + else() + list(APPEND GENERAL_CXX_OPTIONS "D_GLIBCXX_ASSERTIONS") + endif() + endif() + + if (ENABLE_PIE) + list(APPEND GENERAL_OPTIONS "pie" "fPIC") + else() + list(APPEND GENERAL_OPTIONS "no-pie") endif() if (IS_X64) - # For unclear reasons, our detection for what crc32 intrinsics you have - # will cause Apple clang to ICE. Specifying a baseline here works around - # the issue. (SSE4.2 has been available on processors for quite some time now.) - if(ENABLE_SSE4_2 OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") - list(APPEND GENERAL_CXX_OPTIONS - # SSE4.2 has been available on processors for quite some time now. This - # allows enabling CRC hash function code - "msse4.2" - ) - # Also pass the right option to ASM files to avoid inconsistencies - # in CRC hash function handling - set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -msse4.2") - endif() + list(APPEND GENERAL_CXX_OPTIONS "march=x86-64-v3") + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -march=x86-64-v3") + elseif (IS_AARCH64) + list(APPEND GENERAL_CXX_OPTIONS "march=armv8.2-a") endif() if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") # using Clang @@ -121,23 +144,18 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU "unused-command-line-argument" ) - # Enabled GCC/LLVM stack-smashing protection - if(ENABLE_SSP) - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.6 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 3.6) - list(APPEND GENERAL_OPTIONS "fstack-protector-strong") - else() - list(APPEND GENERAL_OPTIONS "fstack-protector") - endif() - endif() - if(CLANG_FORCE_LIBCPP) list(APPEND GENERAL_CXX_OPTIONS "stdlib=libc++") endif() + + if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20) + list(APPEND GENERAL_OPTIONS "Wno-nontrivial-memcall") + endif() else() # using GCC list(APPEND DISABLED_NAMED_WARNINGS "deprecated-declarations" "maybe-uninitialized" + "bool-compare" ) list(APPEND DISABLED_C_NAMED_WARNINGS "maybe-uninitialized" @@ -145,12 +163,15 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU ) list(APPEND GENERAL_OPTIONS "ffunction-sections" + "fno-delete-null-pointer-checks" + "DFOLLY_HAVE_MALLOC_H" ) list(APPEND GENERAL_CXX_OPTIONS "fdata-sections" "fno-gcse" "fno-canonical-system-headers" "Wvla" + "Wno-misleading-indentation" ) list(APPEND RELEASE_CXX_OPTIONS "-param max-inline-insns-auto=100" @@ -160,51 +181,6 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU "-param=large-unit-insns=10000" ) - # Fix problem with GCC 4.9, https://kb.isc.org/article/AA-01167 - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9) - list(APPEND GENERAL_OPTIONS "fno-delete-null-pointer-checks") - else() - message(FATAL_ERROR "${PROJECT_NAME} requires g++ 4.9 or greater.") - endif() - - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.4) - message(WARNING "HHVM is primarily tested on GCC 7.4-11.3. Using other versions may produce unexpected results, or may not even build at all.") - endif() - - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 11.3 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 11.3) - message(WARNING "HHVM is primarily tested on GCC 7.4-11.3. Using other versions may produce unexpected results, or may not even build at all.") - endif() - - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5.1 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 5.1) - list(APPEND DISABLED_NAMED_WARNINGS "bool-compare") - list(APPEND GENERAL_OPTIONS "DFOLLY_HAVE_MALLOC_H") - endif() - - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.0 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 6.0) - list(APPEND GENERAL_CXX_OPTIONS "Wno-misleading-indentation") - endif() - - # Enabled GCC/LLVM stack-smashing protection - if(ENABLE_SSP) - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.8 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.8) - if(LINUX) - # https://isisblogs.poly.edu/2011/06/01/relro-relocation-read-only/ - list(APPEND GENERAL_OPTIONS "Wl,-z,relro,-z,now") - endif() - if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9 OR - CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 4.9) - list(APPEND GENERAL_OPTIONS "fstack-protector-strong") - endif() - else() - list(APPEND GENERAL_OPTIONS "fstack-protector") - endif() - endif() - # X64 if(IS_X64) list(APPEND GENERAL_CXX_OPTIONS "mcrc32") @@ -284,356 +260,6 @@ if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQU foreach(opt ${RELEASE_CXX_OPTIONS}) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -${opt}") endforeach() - - # The ASM part of this makes it more effort than it's worth - # to add these to the general flags system. - if(ENABLE_AVX2) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx2 -march=core-avx2") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2 -march=core-avx2") - set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -mavx2 -march=core-avx2") - endif() - # using Intel C++ -elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -w") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -no-ipo -fp-model precise -wd584 -wd1418 -wd1918 -wd383 -wd869 -wd981 -wd424 -wd1419 -wd444 -wd271 -wd2259 -wd1572 -wd1599 -wd82 -wd177 -wd593 -fno-omit-frame-pointer -Wall -Woverloaded-virtual -Wno-deprecated -w1 -Wno-strict-aliasing -Wno-write-strings -Wno-invalid-offsetof -fno-operator-names") - # using Visual Studio C++ -elseif (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") - message(WARNING "MSVC support is VERY experimental. It will likely not compile, and is intended for the utterly insane.") - - ############################################################ - # First we setup and account for the option sets. - ############################################################ - - set(MSVC_GENERAL_OPTIONS) - set(MSVC_DISABLED_WARNINGS) - set(MSVC_WARNINGS_AS_ERRORS) - set(MSVC_ADDITIONAL_DEFINES) - set(MSVC_EXE_LINKER_OPTIONS) - set(MSVC_DEBUG_OPTIONS) - set(MSVC_RELEASE_OPTIONS) - set(MSVC_RELEASE_LINKER_OPTIONS) - set(MSVC_DEBUG_EXE_LINKER_OPTIONS) - set(MSVC_RELEASE_EXE_LINKER_OPTIONS) - - # Some additional configuration options. - set(MSVC_ENABLE_ALL_WARNINGS ON CACHE BOOL "If enabled, pass /Wall to the compiler.") - set(MSVC_ENABLE_DEBUG_INLINING ON CACHE BOOL "If enabled, enable inlining in the debug configuration. This allows /Zc:inline to be far more effective, resulting in hphp_runtime_static being ~450mb smaller.") - set(MSVC_ENABLE_LTCG OFF CACHE BOOL "If enabled, use Link Time Code Generation for Release builds.") - set(MSVC_ENABLE_PARALLEL_BUILD ON CACHE BOOL "If enabled, build multiple source files in parallel.") - set(MSVC_ENABLE_PCH ON CACHE BOOL "If enabled, use precompiled headers to speed up the build.") - set(MSVC_ENABLE_STATIC_ANALYSIS OFF CACHE BOOL "If enabled, do more complex static analysis and generate warnings appropriately.") - set(MSVC_FAVORED_ARCHITECTURE "blend" CACHE STRING "One of 'blend', 'AMD64', 'INTEL64', or 'ATOM'. This tells the compiler to generate code optimized to run best on the specified architecture.") - - # The general options passed: - list(APPEND MSVC_GENERAL_OPTIONS - "bigobj" # Support objects with > 65k sections. Needed for folly due to templates. - "fp:precise" # Precise floating point model used in every other build, use it here as well. - "EHa" # Enable both SEH and C++ Exceptions. - "Oy-" # Disable elimination of stack frames. - "Zc:inline" # Have the compiler eliminate unreferenced COMDAT functions and data before emitting the object file. This produces significantly less input to the linker, resulting in MUCH faster linking. - "Zo" # Enable enhanced optimized debugging. Produces slightly larger pdb files, but the resulting optimized code is much much easier to debug. - ) - - # Enable all warnings if requested. - if (MSVC_ENABLE_ALL_WARNINGS) - list(APPEND MSVC_GENERAL_OPTIONS "Wall") - endif() - - # Enable static analysis if requested. - if (MSVC_ENABLE_STATIC_ANALYSIS) - list(APPEND MSVC_GENERAL_OPTIONS "analyze") - endif() - - # Enable multi-processor compilation if requested. - if (MSVC_ENABLE_PARALLEL_BUILD) - list(APPEND MSVC_GENERAL_OPTIONS "MP") - endif() - - # Enable AVX2 codegen if available and requested. - if (ENABLE_AVX2) - list(APPEND MSVC_GENERAL_OPTIONS "arch:AVX2") - endif() - - # Validate, and then add the favored architecture. - if (NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "blend" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "AMD64" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "INTEL64" AND NOT MSVC_FAVORED_ARCHITECTURE STREQUAL "ATOM") - message(FATAL_ERROR "MSVC_FAVORED_ARCHITECTURE must be set to one of exactly, 'blend', 'AMD64', 'INTEL64', or 'ATOM'! Got '${MSVC_FAVORED_ARCHITECTURE}' instead!") - endif() - list(APPEND MSVC_GENERAL_OPTIONS "favor:${MSVC_FAVORED_ARCHITECTURE}") - - # The warnings that are disabled: - list(APPEND MSVC_DISABLED_WARNINGS - "4068" # Unknown pragma. - "4091" # 'typedef' ignored on left of '' when no variable is declared. - "4101" # Unused variables - "4103" # Alignment changed after including header. This is needed because boost includes an ABI header that does some #pragma pack push/pop stuff, and we've passed our own packing - "4146" # Unary minus applied to unsigned type, result still unsigned. - "4250" # Function was inherited via dominance. - "4800" # Values being forced to bool, this happens many places, and is a "performance warning". - ) - - if (MSVC_ENABLE_ALL_WARNINGS) - # These warnings are disabled because we've - # enabled all warnings. If all warnings are - # not enabled, then these don't need to be - # disabled. - list(APPEND MSVC_DISABLED_WARNINGS - "4061" # Enum value not handled by a case in a switch on an enum. This isn't very helpful because it is produced even if a default statement is present. - "4100" # Unreferenced formal parameter. - "4127" # Conditional expression is constant. - "4131" # Old style declarator used. This is triggered by ext_bc's backend code. - "4189" # Local variable is initialized but not referenced. - "4191" # Unsafe type cast. - "4200" # Non-standard extension, zero sized array. - "4201" # Non-standard extension used: nameless struct/union. - "4232" # Non-standard extension used: 'pCurrent': address of dllimport. - "4245" # Implicit change from signed/unsigned when initializing. - "4255" # Implicitly converting function prototype from `()` to `(void)`. - "4265" # Class has virtual functions, but destructor is not virtual. - "4287" # Unsigned/negative constant mismatch. - "4296" # '<' Expression is always false. - "4315" # 'this' pointer for member may not be aligned to 8 bytes as expected by the constructor. - "4324" # Structure was padded due to alignment specifier. - "4355" # 'this' used in base member initializer list. - "4365" # Signed/unsigned mismatch. - "4371" # Layout of class may have changed due to fixes in packing. - "4388" # Signed/unsigned mismatch on relative comparison operator. - "4389" # Signed/unsigned mismatch on equality comparison operator. - "4435" # Object layout under /vd2 will change due to virtual base. - "4456" # Declaration of local hides previous definition of local by the same name. - "4457" # Declaration of local hides function parameter. - "4458" # Declaration of parameter hides class member. - "4459" # Declaration of parameter hides global declaration. - "4464" # Relative include path contains "..". This is triggered by the TBB headers. - "4505" # Unreferenced local function has been removed. This is mostly the result of things not being needed under MSVC. - "4514" # Unreferenced inline function has been removed. (caused by /Zc:inline) - "4548" # Expression before comma has no effect. I wouldn't disable this normally, but malloc.h triggers this warning. - "4555" # Expression has no effect; expected expression with side-effect. This is triggered by variant. - "4574" # ifdef'd macro was defined to 0. - "4582" # Constructor is not implicitly called. - "4583" # Destructor is not implicitly called. - "4608" # Member has already been initialized by another union member initializer. - "4619" # Invalid warning number used in #pragma warning. - "4623" # Default constructor was implicitly defined as deleted. - "4625" # Copy constructor was implicitly defined as deleted. - "4626" # Assignment operator was implicitly defined as deleted. - "4647" # __is_pod() has a different value in pervious versions of MSVC. - "4668" # Macro was not defined, replacing with 0. - "4701" # Potentially uninitialized local variable used. - "4702" # Unreachable code. - "4706" # Assignment within conditional expression. - "4709" # Comma operator within array index expression. This currently just produces false-positives. - "4710" # Function was not inlined. - "4711" # Function was selected for automated inlining. This produces tens of thousands of warnings in release mode if you leave it enabled, which will completely break Visual Studio, so don't enable it. - "4714" # Function marked as __forceinline not inlined. - "4774" # Format string expected in argument is not a string literal. - "4820" # Padding added after data member. - "4917" # A GUID can only be associated with a class. This is triggered by some standard windows headers. - "4946" # reinterpret_cast used between related types. - "5026" # Move constructor was implicitly defined as deleted. - "5027" # Move assignment operator was implicitly defined as deleted. - "5031" # #pragma warning(pop): likely mismatch, popping warning state pushed in different file. This is needed because of how boost does things. - ) - endif() - - if (MSVC_ENABLE_STATIC_ANALYSIS) - # Warnings disabled for /analyze - list(APPEND MSVC_DISABLED_WARNINGS - "6001" # Using uninitialized memory. This is disabled because it is wrong 99% of the time. - "6011" # Dereferencing potentially NULL pointer. - "6031" # Return value ignored. - "6235" # ( || ) is always a non-zero constant. - "6237" # ( && ) is always zero. is never evaluated and may have side effects. - "6239" # ( && ) always evaluates to the result of . - "6240" # ( && ) always evaluates to the result of . - "6246" # Local declaration hides declaration of same name in outer scope. - "6248" # Setting a SECURITY_DESCRIPTOR's DACL to NULL will result in an unprotected object. This is done by one of the boost headers. - "6255" # _alloca indicates failure by raising a stack overflow exception. - "6262" # Function uses more than x bytes of stack space. - "6271" # Extra parameter passed to format function. The analysis pass doesn't recognize %j or %z, even though the runtime does. - "6285" # ( || ) is always true. - "6297" # 32-bit value is shifted then cast to 64-bits. The places this occurs never use more than 32 bits. - "6308" # Realloc might return null pointer: assigning null pointer to '', which is passed as an argument to 'realloc', will cause the original memory to leak. - "6326" # Potential comparison of a constant with another constant. - "6330" # Unsigned/signed mismatch when passed as a parameter. - "6340" # Mismatch on sign when passed as format string value. - "6387" # '' could be '0': This does not adhere to the specification for a function. - "28182" # Dereferencing NULL pointer. '' contains the same NULL value as ''. - "28251" # Inconsistent annotation for function. This is because we only annotate the declaration and not the definition. - "28278" # Function appears with no prototype in scope. - ) - endif() - - # Warnings disabled to keep it quiet for now, - # most of these should be reviewed and re-enabled: - list(APPEND MSVC_DISABLED_WARNINGS - "4005" # Macro redefinition - "4018" # Signed/unsigned mismatch. - "4242" # Possible loss of data when returning a value. - "4244" # Implicit truncation of data. - "4267" # Implicit truncation of data. This really shouldn't be disabled. - "4291" # No matching destructor found. - "4302" # Pointer casting size difference - "4311" # Pointer casting size difference - "4312" # Pointer casting size difference - "4477" # Parameter to a formatting function isn't the same type as was passed in the format string. - "4624" # Destructor was implicitly undefined. - "4804" # Unsafe use of type 'bool' in operation. (comparing if bool is <=> scalar) - "4805" # Unsafe mix of scalar type and type 'bool' in operation. (comparing if bool is == scalar) - ) - - # Warnings to treat as errors: - list(APPEND MSVC_WARNINGS_AS_ERRORS - "4099" # Mixed use of struct and class on same type names. This was absolutely everywhere, and can cause errors at link-time if not fixed. - "4129" # Unknown escape sequence. This is usually caused by incorrect escaping. - "4566" # Character cannot be represented in current charset. This is remedied by prefixing string with "u8". - ) - - # And the extra defines: - list(APPEND MSVC_ADDITIONAL_DEFINES - "NOMINMAX" # This is needed because, for some absurd reason, one of the windows headers tries to define "min" and "max" as macros, which messes up most uses of std::numeric_limits. - "_CRT_NONSTDC_NO_WARNINGS" # Don't deprecate posix names of functions. - "_CRT_SECURE_NO_WARNINGS" # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps. - "_SCL_SECURE_NO_WARNINGS" # Don't deprecate the non _s versions of various standard library functions, because safety is for chumps. - "_WINSOCK_DEPRECATED_NO_WARNINGS" # Don't deprecate pieces of winsock - "YY_NO_UNISTD_H" # Because MSVC doesn't have unistd.h, which is requested by the YACC generated code. - ) - - # The options passed to the linker for EXE targets: - list(APPEND MSVC_EXE_LINKER_OPTIONS - "BASE:0x10000" # Base the program at just over 64k in memory, to play nice with the JIT. - "DYNAMICBASE:NO" # Don't randomize the base address. - "FIXED" # The program can only be loaded at its preferred base address. - "STACK:8388608,8388608" # Set the stack reserve,commit to 8mb. Reserve should probably be higher. - "time" # Output some timing information about the link. - ) - - # The options to pass to the compiler for debug builds: - list(APPEND MSVC_DEBUG_OPTIONS - "Gy-" # Disable function level linking. - "GF-" # Disable string pooling. - ) - - # Add /Ob2 if allowing inlining in debug mode: - if (MSVC_ENABLE_DEBUG_INLINING) - list(APPEND MSVC_DEBUG_OPTIONS "Ob2") - endif() - - # The options to pass to the compiler for release builds: - list(APPEND MSVC_RELEASE_OPTIONS - "GF" # Enable string pooling. (this is enabled by default by the optimization level, but we enable it here for clarity) - "Gw" # Optimize global data. (-fdata-sections) - "Gy" # Enable function level linking. (-ffunction-sections) - "Qpar" # Enable parallel code generation. HHVM itself doesn't currently use this, but it's dependencies, TBB for instance, might, so enable it. - "Oi" # Enable intrinsic functions. - "Ot" # Favor fast code. - ) - - # Add /GL to the compiler, and /LTCG to the linker - # if link time code generation is enabled. - if (MSVC_ENABLE_LTCG) - list(APPEND MSVC_RELEASE_OPTIONS "GL") - list(APPEND MSVC_RELEASE_LINKER_OPTIONS "LTCG") - endif() - - # The options to pass to the linker for debug builds for EXE targets: - list(APPEND MSVC_DEBUG_EXE_LINKER_OPTIONS - "OPT:NOREF" # No unreferenced data elimination. (well, mostly) - "OPT:NOICF" # No Identical COMDAT folding. - ) - - # The options to pass to the linker for release builds for EXE targets: - list(APPEND MSVC_RELEASE_EXE_LINKER_OPTIONS - "OPT:REF" # Remove unreferenced functions and data. - "OPT:ICF" # Identical COMDAT folding. - ) - - ############################################################ - # Now we need to adjust a couple of the default option sets. - ############################################################ - - # We need the static runtime. - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if (${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif() - endforeach() - - # In order for /Zc:inline, which speeds up the build significantly, to work - # we need to remove the /Ob0 parameter that CMake adds by default, because that - # would normally disable all inlining. - foreach(flag_var CMAKE_C_FLAGS_DEBUG CMAKE_CXX_FLAGS_DEBUG) - if (${flag_var} MATCHES "/Ob0") - string(REGEX REPLACE "/Ob0" "" ${flag_var} "${${flag_var}}") - endif() - endforeach() - - # Ignore a warning about an object file not defining any symbols, - # these are known, and we don't care. - set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") - - ############################################################ - # And finally, we can set all the flags we've built up. - ############################################################ - - foreach(opt ${MSVC_GENERAL_OPTIONS}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /${opt}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /${opt}") - endforeach() - - foreach(opt ${MSVC_DISABLED_WARNINGS}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd${opt}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd${opt}") - endforeach() - - foreach(opt ${MSVC_WARNINGS_AS_ERRORS}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /we${opt}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /we${opt}") - endforeach() - - foreach(opt ${MSVC_ADDITIONAL_DEFINES}) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D ${opt}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D ${opt}") - endforeach() - - foreach(opt ${MSVC_EXE_LINKER_OPTIONS}) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /${opt}") - endforeach() - - foreach(opt ${MSVC_RELEASE_LINKER_OPTIONS}) - foreach(flag_var - CMAKE_EXE_LINKER_FLAGS_RELEASE CMAKE_EXE_LINKER_FLAGS_MINSIZEREL CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO - CMAKE_SHARED_LINKER_FLAGS_RELEASE CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO - CMAKE_STATIC_LINKER_FLAGS_RELEASE CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO) - set(${flag_var} "${${flag_var}} /${opt}") - endforeach() - endforeach() - - foreach(opt ${MSVC_DEBUG_OPTIONS}) - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /${opt}") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /${opt}") - endforeach() - - foreach(opt ${MSVC_RELEASE_OPTIONS}) - foreach(flag_var - CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - set(${flag_var} "${${flag_var}} /${opt}") - endforeach() - endforeach() - - foreach(opt ${MSVC_DEBUG_EXE_LINKER_OPTIONS}) - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /${opt}") - endforeach() - - foreach(opt ${MSVC_RELEASE_EXE_LINKER_OPTIONS}) - set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /${opt}") - set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} /${opt}") - set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /${opt}") - endforeach() else() message("Warning: unknown/unsupported compiler, things may go wrong") endif() diff --git a/CMake/HPHPFindLibs.cmake b/CMake/HPHPFindLibs.cmake index 6baf472077f693..7b46d6e04e86a1 100644 --- a/CMake/HPHPFindLibs.cmake +++ b/CMake/HPHPFindLibs.cmake @@ -44,8 +44,8 @@ include_directories(${LIBEVENT_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES "${LIBEVENT_LIB}") CHECK_FUNCTION_EXISTS("evhttp_bind_socket_with_fd" HAVE_CUSTOM_LIBEVENT) if(HAVE_CUSTOM_LIBEVENT) - message("Using custom LIBEVENT") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CUSTOM_LIBEVENT") + message("Using custom LIBEVENT") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHAVE_CUSTOM_LIBEVENT") endif() set(CMAKE_REQUIRED_LIBRARIES) @@ -83,6 +83,9 @@ if (FASTLZ_INCLUDE_DIR) include_directories(${FASTLZ_INCLUDE_DIR}) endif() +# ldap +find_package(Ldap) + # ICU find_package(ICU REQUIRED) if (ICU_FOUND) @@ -235,6 +238,10 @@ if (NOT WINDOWS) add_definitions("-DLIBDWARF_USE_INIT_C") endif() + if (LIBDWARF_USE_NEW_PRODUCER_API) + add_definitions("-DLIBDWARF_USE_NEW_PRODUCER_API") + endif() + find_package(LibElf REQUIRED) include_directories(${LIBELF_INCLUDE_DIRS}) if (ELF_GETSHDRSTRNDX) @@ -271,6 +278,11 @@ if (APPLE) find_library(KERBEROS_LIB NAMES gssapi_krb5) endif() +if (LINUX) + find_package(LibUnwind REQUIRED) + find_package(Bpf REQUIRED) +endif() + # This is required by Homebrew's libc. See # https://github.com/facebook/hhvm/pull/5728#issuecomment-124290712 # for more info. @@ -279,6 +291,9 @@ if (PAM_INCLUDE_PATH) include_directories(${PAM_INCLUDE_PATH}) endif() +# Needed by fbthrift. +find_package(Xxhash REQUIRED) + include_directories(${HPHP_HOME}/hphp) macro(hphp_link target) @@ -332,6 +347,10 @@ macro(hphp_link target) target_link_libraries(${target} ${VISIBILITY} ${CURL_LIBRARIES}) target_link_libraries(${target} ${VISIBILITY} glog) + if (LINUX) + target_link_libraries(${target} ${VISIBILITY} ${LIBUNWIND_LIBRARIES} ${BPF_LIBRARIES}) + endif() + if (LIBINOTIFY_LIBRARY) target_link_libraries(${target} ${VISIBILITY} ${LIBINOTIFY_LIBRARY}) endif() @@ -370,6 +389,8 @@ macro(hphp_link target) target_link_libraries(${target} ${VISIBILITY} ${LBER_LIBRARIES}) + target_link_libraries(${target} ${VISIBILITY} ${Xxhash_LIBRARY}) + if (CRYPT_LIB) target_link_libraries(${target} ${VISIBILITY} ${CRYPT_LIB}) endif() @@ -408,17 +429,11 @@ macro(hphp_link target) target_link_libraries(${target} ${VISIBILITY} fizz) target_link_libraries(${target} ${VISIBILITY} brotli) target_link_libraries(${target} ${VISIBILITY} hhbc_ast_header) - target_link_libraries(${target} ${VISIBILITY} compiler_ffi) - target_link_libraries(${target} ${VISIBILITY} package_ffi) - target_link_libraries(${target} ${VISIBILITY} parser_ffi) - target_link_libraries(${target} ${VISIBILITY} hhvm_types_ffi) - target_link_libraries(${target} ${VISIBILITY} hhvm_hhbc_defs_ffi) + target_link_libraries(${target} ${VISIBILITY} hack_rust_ffi_bridge) target_link_libraries(${target} ${VISIBILITY} tbb) - if (NOT MSVC) - target_link_libraries(${target} ${VISIBILITY} afdt) - endif() + target_link_libraries(${target} ${VISIBILITY} afdt) target_link_libraries(${target} ${VISIBILITY} mbfl) if (EDITLINE_LIBRARIES) @@ -427,49 +442,20 @@ macro(hphp_link target) target_link_libraries(${target} ${VISIBILITY} ${READLINE_LIBRARY}) endif() - if (MSVC) - target_link_libraries(${target} ${VISIBILITY} dbghelp.lib dnsapi.lib) + find_library(ATOMIC_LIBRARY NAMES atomic libatomic.so.1) + if (ATOMIC_LIBRARY STREQUAL "ATOMIC_LIBRARY-NOTFOUND") + # -latomic should be available for gcc even when libatomic.so.1 is not + # in the library search path + target_link_libraries(${target} ${VISIBILITY} atomic) + else() + target_link_libraries(${target} ${VISIBILITY} ${ATOMIC_LIBRARY}) endif() -# Check whether atomic operations require -latomic or not -# See https://github.com/facebook/hhvm/issues/5217 - include(CheckCXXSourceCompiles) - set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-std=c++1y") - CHECK_CXX_SOURCE_COMPILES(" -#include -#include -#include -int main() { - struct Test { int64_t val1; int64_t val2; }; - std::atomic s; - // Do this to stop modern compilers from optimizing away the libatomic - // calls in release builds, making this test always pass in release builds, - // and incorrectly think that HHVM doesn't need linking against libatomic. - bool (std::atomic::* volatile x)(void) const = - &std::atomic::is_lock_free; - std::cout << (s.*x)() << std::endl; -} - " NOT_REQUIRE_ATOMIC_LINKER_FLAG) - - if(NOT "${NOT_REQUIRE_ATOMIC_LINKER_FLAG}") - message(STATUS "-latomic is required to link hhvm") - find_library(ATOMIC_LIBRARY NAMES atomic libatomic.so.1) - if (ATOMIC_LIBRARY STREQUAL "ATOMIC_LIBRARY-NOTFOUND") - # -latomic should be available for gcc even when libatomic.so.1 is not - # in the library search path - target_link_libraries(${target} ${VISIBILITY} atomic) - else() - target_link_libraries(${target} ${VISIBILITY} ${ATOMIC_LIBRARY}) - endif() - endif() - set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) - if (ENABLE_XED) if (LibXed_FOUND) - target_link_libraries(${target} ${VISIBILITY} ${LibXed_LIBRARY}) + target_link_libraries(${target} ${VISIBILITY} ${LibXed_LIBRARY}) else() - target_link_libraries(${target} ${VISIBILITY} xed) + target_link_libraries(${target} ${VISIBILITY} xed) endif() endif() diff --git a/CMake/HPHPFunctions.cmake b/CMake/HPHPFunctions.cmake index 9a3f47ddf36106..20f1d44efc4343 100644 --- a/CMake/HPHPFunctions.cmake +++ b/CMake/HPHPFunctions.cmake @@ -57,21 +57,12 @@ macro(HHVM_SELECT_SOURCES DIR) list(APPEND C_SOURCES ${f}) endif() endforeach() - if (MSVC) - auto_sources(files "*.asm" "RECURSE" "${DIR}") - foreach(f ${files}) - if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)")) - list(APPEND ASM_SOURCES ${f}) - endif() - endforeach() - else() - auto_sources(files "*.S" "RECURSE" "${DIR}") - foreach(f ${files}) - if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)")) - list(APPEND ASM_SOURCES ${f}) - endif() - endforeach() - endif() + auto_sources(files "*.S" "RECURSE" "${DIR}") + foreach(f ${files}) + if (NOT (${f} MATCHES "(ext_hhvm|/(old-)?tests?/)")) + list(APPEND ASM_SOURCES ${f}) + endif() + endforeach() auto_sources(files "*.h" "RECURSE" "${DIR}") foreach(f ${files}) if (NOT (${f} MATCHES "(/(old-)?tests?/)")) @@ -113,20 +104,10 @@ macro(MYSQL_SOCKET_SEARCH) endmacro() function(append_systemlib TARGET SOURCE SECTNAME) - if(MSVC) - list(APPEND ${TARGET}_SLIBS_NAMES "${SECTNAME}") - set(${TARGET}_SLIBS_NAMES ${${TARGET}_SLIBS_NAMES} PARENT_SCOPE) - list(APPEND ${TARGET}_SLIBS_SOURCES "${SOURCE}") - set(${TARGET}_SLIBS_SOURCES ${${TARGET}_SLIBS_SOURCES} PARENT_SCOPE) + if (APPLE) + set(${TARGET}_SLIBS ${${TARGET}_SLIBS} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE} PARENT_SCOPE) else() - if (APPLE) - set(${TARGET}_SLIBS ${${TARGET}_SLIBS} -Wl,-sectcreate,__text,${SECTNAME},${SOURCE} PARENT_SCOPE) - else() - set(${TARGET}_SLIBS ${${TARGET}_SLIBS} "--add-section" "${SECTNAME}=${SOURCE}" PARENT_SCOPE) - endif() - # Add the systemlib file to the "LINK_DEPENDS" for the systemlib, this will cause it - # to be relinked and the systemlib re-embedded - set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS ${SOURCE}) + set(${TARGET}_SLIBS ${${TARGET}_SLIBS} "--add-section" "${SECTNAME}=${SOURCE}" PARENT_SCOPE) endif() endfunction(append_systemlib) @@ -150,24 +131,6 @@ function(embed_sections TARGET DEST) set(REPO_SCHEMA -Wl,-sectcreate,__text,"repo_schema_id","${CMAKE_BINARY_DIR}/hphp/util/generated-repo-schema-id.txt") set(BUILD_ID -Wl,-sectcreate,__text,"build_id","${CMAKE_BINARY_DIR}/hphp/util/generated-build-id.txt") target_link_libraries(${TARGET} ${${TARGET}_SLIBS} ${COMPILER_ID} ${COMPILER_TIMESTAMP} ${REPO_SCHEMA} ${BUILD_ID}) - elseif(MSVC) - set(RESOURCE_FILE "#pragma code_page(1252)\n") - set(RESOURCE_FILE "${RESOURCE_FILE}LANGUAGE 0, 0\n") - set(RESOURCE_FILE "${RESOURCE_FILE}\n") - set(RESOURCE_FILE "${RESOURCE_FILE}#include \"${CMAKE_BINARY_DIR}/hphp/runtime/version.h\"\n") - file(READ "${CMAKE_BINARY_DIR}/hphp/hhvm/hhvm.rc" VERSION_INFO) - set(RESOURCE_FILE "${RESOURCE_FILE}compiler_id RCDATA \"${CMAKE_BINARY_DIR}/hphp/util/generated-compiler-id.txt\"\n") - set(RESOURCE_FILE "${RESOURCE_FILE}compiler_ts RCDATA \"${CMAKE_BINARY_DIR}/hphp/util/generated-compiler-timestamp.txt\"\n") - set(RESOURCE_FILE "${RESOURCE_FILE}repo_schema_id RCDATA \"${CMAKE_BINARY_DIR}/hphp/util/generated-repo-schema-id.txt\"\n") - set(RESOURCE_FILE "${RESOURCE_FILE}build_id RCDATA \"${CMAKE_BINARY_DIR}/hphp/util/generated-build-id.txt\"\n") - set(RESOURCE_FILE "${RESOURCE_FILE}${VERSION_INFO}\n") - set(i 0) - foreach (nm ${${TARGET}_SLIBS_NAMES}) - list(GET ${TARGET}_SLIBS_SOURCES ${i} source) - set(RESOURCE_FILE "${RESOURCE_FILE}${nm} RCDATA \"${source}\"\n") - math(EXPR i "${i} + 1") - endforeach() - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/embed.rc "${RESOURCE_FILE}") else() add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "objcopy" @@ -186,28 +149,43 @@ function(embed_sections TARGET DEST) endfunction(embed_sections) macro(embed_systemlib_byname TARGET SLIB) - get_filename_component(SLIB_BN ${SLIB} "NAME_WE") - string(LENGTH ${SLIB_BN} SLIB_BN_LEN) - math(EXPR SLIB_BN_REL_LEN "${SLIB_BN_LEN} - 4") - string(SUBSTRING ${SLIB_BN} 4 ${SLIB_BN_REL_LEN} SLIB_EXTNAME) + get_filename_component(SLIB_FILENAME ${SLIB} "NAME") + + set(SLIB_EXTNAME "/:${SLIB_FILENAME}") + string(MD5 SLIB_HASH_NAME ${SLIB_EXTNAME}) # Some platforms limit section names to 16 characters :( string(SUBSTRING ${SLIB_HASH_NAME} 0 12 SLIB_HASH_NAME_SHORT) - if (MSVC) - # The dot would be causing the RC lexer to begin a number in the - # middle of our resource name, so use an underscore instead. - append_systemlib(${TARGET} ${SLIB} "ext_${SLIB_HASH_NAME_SHORT}") - else() - append_systemlib(${TARGET} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}") - endif() + + append_systemlib(${TARGET} ${SLIB} "ext.${SLIB_HASH_NAME_SHORT}") endmacro() function(embed_all_systemlibs TARGET ROOT DEST) add_dependencies(${TARGET} systemlib) - append_systemlib(${TARGET} ${ROOT}/system/systemlib.php systemlib) + foreach(SLIB ${EXTENSION_SYSTEMLIB_SOURCES} ${EZC_SYSTEMLIB_SOURCES}) - embed_systemlib_byname(${TARGET} ${SLIB}) + get_filename_component(SLIB_FILENAME ${SLIB} NAME) + file(RELATIVE_PATH SLIB_RELATIVE_PATH ${CMAKE_SOURCE_DIR} ${SLIB}) + list(APPEND SLIB_RELATIVE_PATHS ${SLIB_RELATIVE_PATH}) + list( + APPEND PRECOMPILED_SYSTEMLIB_FILES + ${CMAKE_CURRENT_BINARY_DIR}/slib/${SLIB_FILENAME}.decls + ${CMAKE_CURRENT_BINARY_DIR}/slib/${SLIB_FILENAME}.ue + ) endforeach() + + add_custom_command( + TARGET ${TARGET} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/slib + COMMAND $ --compile-systemlib --input-dir ${CMAKE_SOURCE_DIR} --output-dir ${CMAKE_CURRENT_BINARY_DIR}/slib ${SLIB_RELATIVE_PATHS} + COMMENT "Precompiling systemlib files" + VERBATIM) + + foreach(PRECOMPILED_SLIB ${PRECOMPILED_SYSTEMLIB_FILES}) + get_filename_component(PRECOMPILED_SLIB_FILENAME ${PRECOMPILED_SLIB} NAME) + embed_systemlib_byname(${TARGET} ${PRECOMPILED_SLIB}) + endforeach() + embed_sections(${TARGET} ${DEST}) endfunction(embed_all_systemlibs) @@ -395,26 +373,13 @@ function(parse_version PREFIX VERSION) set(${PREFIX}SUFFIX ${SUFFIX} PARENT_SCOPE) endfunction() -# MSVC doesn't support a --whole-archive flag, but newer versions -# of CMake do support object libraries, which give the same result. -# As we can't easily upgrade the normal builds to CMake 3.0, we -# will just require CMake 3.0+ for MSVC builds only. function(add_object_library libraryName) - if (MSVC) - add_library(${libraryName} OBJECT ${ARGN}) - else() - add_library(${libraryName} STATIC ${ARGN}) - endif() + add_library(${libraryName} STATIC ${ARGN}) endfunction() # Get what might be the objects of the object libraries, if needed. function(get_object_libraries_objects targetVariable) set(OBJECTS) - if (MSVC) - foreach (fil ${ARGN}) - list(APPEND OBJECTS $) - endforeach() - endif() set(${targetVariable} ${OBJECTS} PARENT_SCOPE) endfunction() @@ -422,10 +387,6 @@ endfunction() # Add the additional link targets for a set of object libraries, # if needed. function(link_object_libraries target) - if (MSVC) - return() - endif() - set(WHOLE_ARCHIVE_LIBS) foreach (fil ${ARGN}) list(APPEND WHOLE_ARCHIVE_LIBS ${fil}) @@ -453,21 +414,14 @@ endfunction() # This should be called for object libraries, rather than calling # hphp_link directly. function(object_library_hphp_link target) - # MSVC can't have it. (see below) - if (NOT MSVC) - hphp_link(${target}) - endif() + hphp_link(${target}) endfunction() # If a library needs to be linked in to make GNU ld happy, # it should be done by calling this. function(object_library_ld_link_libraries target) if (${ARGC}) - # CMake doesn't allow calls to target_link_libraries if the target - # is an OBJECT library, so MSVC can't have this. - if (NOT MSVC) - target_link_libraries(${target} ${ARGN}) - endif() + target_link_libraries(${target} ${ARGN}) endif() endfunction() diff --git a/CMake/HPHPIZEFunctions.cmake b/CMake/HPHPIZEFunctions.cmake index fc4c80bf5ccdb7..240b5be0ad998a 100644 --- a/CMake/HPHPIZEFunctions.cmake +++ b/CMake/HPHPIZEFunctions.cmake @@ -31,8 +31,6 @@ endfunction() function(embed_systemlibs TARGET DEST) if (APPLE) target_link_libraries(${TARGET} ${${TARGET}_SLIBS}) - elseif (MSVC) - message(FATAL_ERROR "Shared extensions are not supported on Windows") else() add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "objcopy" diff --git a/CMake/HPHPSetup.cmake b/CMake/HPHPSetup.cmake index e2ecb3f083d6a1..54008edea8101e 100644 --- a/CMake/HPHPSetup.cmake +++ b/CMake/HPHPSetup.cmake @@ -101,20 +101,8 @@ if (LINUX) add_definitions(-D_GNU_SOURCE) endif() -if(MSVC) - add_definitions(-DGLOG_NO_ABBREVIATED_SEVERITIES) - add_definitions(-DWIN32_LEAN_AND_MEAN) -endif() - if(CMAKE_CONFIGURATION_TYPES) - if(NOT MSVC) - message(FATAL_ERROR "Adding the appropriate defines for multi-config targets using anything other than MSVC is not yet supported!") - endif() - foreach(flag_var - CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - set(${flag_var} "${${flag_var}} /D NDEBUG") - endforeach() + message(FATAL_ERROR "Adding the appropriate defines for multi-config targets is not yet supported!") elseif(${CMAKE_BUILD_TYPE} MATCHES "Debug" OR ${CMAKE_BUILD_TYPE} MATCHES "DebugOpt") message("Generating DEBUG build") @@ -127,7 +115,7 @@ if(ALWAYS_ASSERT) add_definitions(-DALWAYS_ASSERT=1) endif() -if(APPLE OR FREEBSD OR MSVC) +if(APPLE OR FREEBSD) add_definitions(-DSKIP_USER_CHANGE=1) endif() diff --git a/CMake/MSVCDefaults.cmake b/CMake/MSVCDefaults.cmake deleted file mode 100644 index 7a3a004d2fed5d..00000000000000 --- a/CMake/MSVCDefaults.cmake +++ /dev/null @@ -1,144 +0,0 @@ -# This file exists because, in order to handle the multi-config environment that -# Visual Studio allows, we'd have to modify quite a few of CMake's built-in -# scripts for finding specific libraries. Instead of doing that, we just set the -# required variables here if the /deps/ directory is present. - -# We assume in this that, if the directory exists, all libs that are part of -# the package are present. -if (EXISTS "${HPHP_HOME}/deps/") - message(STATUS "Using default paths for MSVC libs.") - - set(depRoot "${HPHP_HOME}/deps") - set(incRoot "${depRoot}/include") - set(libRoot "${depRoot}/lib") - - # First up a few variables to make things configure the first time. - - # Disable a few extensions that we can't currently build because we can't - # compile the library they depend on. - set(ENABLE_MCROUTER OFF CACHE BOOL "") - set(ENABLE_EXTENSION_MEMCACHE OFF CACHE BOOL "") - set(ENABLE_EXTENSION_MEMCACHED OFF CACHE BOOL "") - set(ENABLE_EXTENSION_MYSQL OFF CACHE BOOL "") - set(ENABLE_EXTENSION_MYSQLI OFF CACHE BOOL "") - set(ENABLE_EXTENSION_PDO_MYSQL OFF CACHE BOOL "") - set(MYSQL_UNIX_SOCK_ADDR "/dev/null" CACHE PATH "") - - # We need to link against the static library version of boost targeting the static - # runtime, so set the vars required by default. - set(BOOST_INCLUDEDIR "${incRoot}" CACHE PATH "") - set(BOOST_LIBRARYDIR "${libRoot}/lib64-msvc-14.0" CACHE PATH "") - set(Boost_USE_STATIC_LIBS ON CACHE BOOL "") - set(Boost_USE_STATIC_RUNTIME ON CACHE BOOL "") - - # GPerf is needed for proxygen, so a precompiled version of it is included - # in the deps package. - set(GPERF_EXECUTABLE "${depRoot}/bin/gperf.exe" CACHE STRING "") - - # And now the actual libs. Please keep them alphabetical, and keep the lib - # values with any system libs first, then the debug version, and finally the - # release version. Also, when setting the variables, set the include directory - # first, then any library variables, and finally any misc. variables. - - set(BZIP2_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(BZIP2_LIBRARIES "debug;${libRoot}/libbz2MTd.lib;optimized;${libRoot}/libbz2MT.lib" CACHE FILEPATH "") - - set(CURL_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(CURL_LIBRARY "Wldap32.lib;debug;${libRoot}/libcurlMTd.lib;optimized;${libRoot}/libcurlMT.lib" CACHE FILEPATH "") - set(CURL_STATIC ON CACHE BOOL "") - - set(EXPAT_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(EXPAT_LIBRARY "debug;${libRoot}/expatMTd.lib;optimized;${libRoot}/expatMT.lib" CACHE FILEPATH "") - set(EXPAT_STATIC ON CACHE BOOL "") - - set(FREETYPE_INCLUDE_DIRS "${incRoot}" CACHE PATH "") - set(FREETYPE_LIBRARIES "debug;${libRoot}/libfreetypeMTd.lib;optimized;${libRoot}/libfreetypeMT.lib" CACHE FILEPATH "") - - # Fribidi isn't part of the main package, as the extension isn't supported - # under MSVC yet, but we'll set the vars here if it's present. - if (EXISTS "${libRoot}/libfribidiMTd.lib") - set(FRIBIDI_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(FRIBIDI_LIBRARY "debug;${libRoot}/libfribidiMTd.lib;optimized;${libRoot}/libfribidiMT.lib" CACHE FILEPATH "") - endif() - - set(GMP_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(GMP_LIBRARY "debug;${libRoot}/libgmpMTd.lib;optimized;${libRoot}/libgmpMT.lib" CACHE FILEPATH "") - - set(ICU_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(ICU_DATA_LIBRARY "debug;${libRoot}/sicudtd.lib;optimized;${libRoot}/sicudt.lib" CACHE FILEPATH "") - set(ICU_I18N_LIBRARY "debug;${libRoot}/sicuind.lib;optimized;${libRoot}/sicuin.lib" CACHE FILEPATH "") - set(ICU_LIBRARY "debug;${libRoot}/sicuucd.lib;optimized;${libRoot}/sicuuc.lib" CACHE FILEPATH "") - set(ICU_STATIC ON CACHE BOOL "") - - set(LIBEVENT_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIBEVENT_LIB "general;Ws2_32.lib;debug;${libRoot}/eventMTd.lib;debug;${libRoot}/event_coreMTd.lib;debug;${libRoot}/event_extraMTd.lib;optimized;${libRoot}/eventMT.lib;optimized;${libRoot}/event_coreMT.lib;optimized;${libRoot}/event_extraMT.lib" CACHE FILEPATH "") - - set(GLOG_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(GLOG_LIBRARY "debug;${libRoot}/libglogMTd.lib;optimized;${libRoot}/libglogMT.lib" CACHE FILEPATH "") - set(GLOG_STATIC ON CACHE BOOL "") - - set(LIBICONV_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIBICONV_LIBRARY "debug;${libRoot}/iconvMTd.lib;optimized;${libRoot}/iconvMT.lib" CACHE FILEPATH "") - set(LIBICONV_CONST ON CACHE BOOL "") - - set(LIBINTL_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIBINTL_LIBRARY "debug;${libRoot}/libintlMTd.lib;optimized;${libRoot}/libintlMT.lib" CACHE FILEPATH "") - - set(LIBJPEG_INCLUDE_DIRS "${incRoot}" CACHE PATH "") - set(LIBJPEG_LIBRARIES "debug;${libRoot}/libjpegMTd.lib;optimized;${libRoot}/libjpegMT.lib" CACHE FILEPATH "") - - # LibMagicWand includes a LOT of dependent libraries, 17 here, and another 3 - # that other extensions are dependent on, so are set through those variables. - # Specifically, Freetype, libJpeg, and libPng. - set(LIBMAGICKWAND_INCLUDE_DIRS "${incRoot}" CACHE PATH "") - set(LIBMAGICKCORE_LIBRARIES "debug;${libRoot}/libcairoMTd.lib;debug;${libRoot}/libcodersMTd.lib;debug;${libRoot}/libcrocoMTd.lib;debug;${libRoot}/libexrMTd.lib;debug;${libRoot}/libffiMTd.lib;debug;${libRoot}/libfiltersMTd.lib;debug;${libRoot}/libglibMTd.lib;debug;${libRoot}/libjp2MTd.lib;debug;${libRoot}/liblcmsMTd.lib;debug;${libRoot}/liblqrMTd.lib;debug;${libRoot}/libmagickMTd.lib;debug;${libRoot}/libopenjpegMTd.lib;debug;${libRoot}/libpangoMTd.lib;debug;${libRoot}/libpixmanMTd.lib;debug;${libRoot}/librsvgMTd.lib;debug;${libRoot}/libtiffMTd.lib;debug;${libRoot}/libwebpMTd.lib;optimized;${libRoot}/libcairoMT.lib;optimized;${libRoot}/libcodersMT.lib;optimized;${libRoot}/libcrocoMT.lib;optimized;${libRoot}/libexrMT.lib;optimized;${libRoot}/libffiMT.lib;optimized;${libRoot}/libfiltersMT.lib;optimized;${libRoot}/libglibMT.lib;optimized;${libRoot}/libjp2MT.lib;optimized;${libRoot}/liblcmsMT.lib;optimized;${libRoot}/liblqrMT.lib;optimized;${libRoot}/libmagickMT.lib;optimized;${libRoot}/libopenjpegMT.lib;optimized;${libRoot}/libpangoMT.lib;optimized;${libRoot}/libpixmanMT.lib;optimized;${libRoot}/librsvgMT.lib;optimized;${libRoot}/libtiffMT.lib;optimized;${libRoot}/libwebpMT.lib" CACHE FILEPATH "") - set(LIBMAGICKWAND_LIBRARIES "debug;${libRoot}/libwandMTd.lib;optimized;${libRoot}/libwandMT.lib" CACHE FILEPATH "") - - set(LIBPNG_INCLUDE_DIRS "${incRoot}" CACHE PATH "") - set(LIBPNG_LIBRARIES "debug;${libRoot}/libpngMTd.lib;optimized;${libRoot}/libpngMT.lib" CACHE FILEPATH "") - - set(LIBPTHREAD_INCLUDE_DIRS "${incRoot}" CACHE PATH "") - set(LIBPTHREAD_LIBRARIES "debug;${libRoot}/libpthreadMTd.lib;optimized;${libRoot}/libpthreadMT.lib" CACHE FILEPATH "") - set(LIBPTHREAD_STATIC ON CACHE BOOL "") - - set(LIBXML2_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIBXML2_LIBRARIES "debug;${libRoot}/libxml2MTd.lib;optimized;${libRoot}/libxml2MT.lib" CACHE FILEPATH "") - set(LIBXML2_DEFINITIONS "-DLIBXML_STATIC" CACHE STRING "") - - # Due to being slightly lazy, exslt is built as part of xslt, so both set both - # variables to the same value, and let CMake get rid of the duplicates. - set(LIBXSLT_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIBXSLT_LIBRARIES "debug;${libRoot}/libxsltMTd.lib;optimized;${libRoot}/libxsltMT.lib" CACHE FILEPATH "") - set(LIBXSLT_EXSLT_LIBRARY "debug;${libRoot}/libxsltMTd.lib;optimized;${libRoot}/libxsltMT.lib" CACHE FILEPATH "") - set(LIBXSLT_STATIC ON CACHE BOOL "") - - set(Mcrypt_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(Mcrypt_LIB "debug;${libRoot}/libmcryptMTd.lib;optimized;${libRoot}/libmcryptMT.lib" CACHE FILEPATH "") - - # Oniguruma is just weird and grumpy, so we set that it's been found explicitly. - set(ONIGURUMA_FOUND ON CACHE BOOL "" FORCE) - set(ONIGURUMA_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(ONIGURUMA_LIBRARY "debug;${libRoot}/onigMTd.lib;optimized;${libRoot}/onigMT.lib" CACHE FILEPATH "") - set(ONIGURUMA_STATIC ON CACHE BOOL "") - - set(OPENSSL_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(LIB_EAY_DEBUG "${libRoot}/libeay32MTd.lib" CACHE FILEPATH "") - set(LIB_EAY_RELEASE "${libRoot}/libeay32MT.lib" CACHE FILEPATH "") - set(SSL_EAY_DEBUG "${libRoot}/ssleay32MTd.lib" CACHE FILEPATH "") - set(SSL_EAY_RELEASE "${libRoot}/ssleay32MT.lib" CACHE FILEPATH "") - - set(READLINE_INCLUDE_DIR "${incRoot}" CACHE PATH "") - set(READLINE_LIBRARY "debug;${libRoot}/readlineMTd.lib;optimized;${libRoot}/readlineMT.lib" CACHE FILEPATH "") - set(READLINE_STATIC ON CACHE BOOL "") - - # TBB's found detection is weird, so we have to set all of these. - set(TBB_INSTALL_DIR "${depRoot}" CACHE PATH "") - set(TBB_LIBRARY_DIRS "${depRoot}" CACHE PATH "") - set(TBB_LIBRARY "${libRoot}/tbb.lib" CACHE FILEPATH "") - set(TBB_LIBRARY_DEBUG "${libRoot}/tbb_debug.lib" CACHE FILEPATH "") - set(TBB_MALLOC_LIBRARY "${libRoot}/tbbmalloc.lib" CACHE FILEPATH "") - set(TBB_MALLOC_LIBRARY_DEBUG "${libRoot}/tbbmalloc_debug.lib" CACHE FILEPATH "") - - set(ZLIB_ROOT "${depRoot}" CACHE PATH "") - set(ZLIB_LIBRARY "debug;${libRoot}/zlibMTd.lib;optimized;${libRoot}/zlibMT.lib" CACHE FILEPATH "") -endif() diff --git a/CMake/Options.cmake b/CMake/Options.cmake index a26e8e47f80436..bd98f46948bf66 100644 --- a/CMake/Options.cmake +++ b/CMake/Options.cmake @@ -1,12 +1,11 @@ #set(CMAKE_BUILD_TYPE Debug) option(ALWAYS_ASSERT "Enabled asserts in a release build" OFF) -option(ENABLE_SSP "Enabled GCC/LLVM stack-smashing protection" OFF) +option(ENABLE_HARDENING "Set hardening flags and definitions, e.g. stack-smashing protection" OFF) +option(ENABLE_PIE "Produce position-independent executables" OFF) option(STATIC_CXX_LIB "Statically link libstd++ and libgcc." OFF) -option(ENABLE_AVX2 "Enable the use of AVX2 instructions" OFF) option(ENABLE_AARCH64_CRC "Enable the use of CRC instructions" OFF) option(ENABLE_FASTCGI "Enable the FastCGI interface." ON) -option(ENABLE_SSE4_2 "Enable SSE4.2 supported code." OFF) option(EXECUTION_PROFILER "Enable the execution profiler" OFF) @@ -24,27 +23,17 @@ option(USE_GOOGLE_CPU_PROFILER "Use Google cpu profiler" OFF) option(DISABLE_HARDWARE_COUNTERS "Disable hardware counters (for XenU systems)" OFF) option(ENABLE_TRACE "Enable tracing in release build" OFF) -option(CPACK_GENERATOR "Enable build of distribution packages using CPack" OFF) - -option(ENABLE_COTIRE "Speed up the build by precompiling headers" OFF) include(CheckCXXSymbolExists) -# Mcrouter uses Folly's AtomicSharedPtr, which only supports libstdc++ -# See https://github.com/facebook/hhvm/blob/156a77d5a301033200601ddefb4dcaf26eb1ff9c/third-party/folly/src/folly/concurrency/detail/AtomicSharedPtr-detail.h#L28-L34 -check_cxx_symbol_exists(__GLIBCXX__ cstdlib DEFAULT_STDLIB_IS_LIBSTDCXX) -if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CLANG_FORCE_LIBSTDCXX OR DEFAULT_STDLIB_IS_LIBSTDCXX) - option(ENABLE_MCROUTER "Build the mcrouter library and extension" ON) -else() - option(ENABLE_MCROUTER "Build the mcrouter library and extension" OFF) -endif() +option(ENABLE_MCROUTER "Build the mcrouter library and extension" OFF) option(ENABLE_PROXYGEN_SERVER "Build the Proxygen HTTP server" ON) option(ENABLE_SPLIT_DWARF "Reduce linker memory usage by putting debugging information into .dwo files" OFF) IF (LINUX) - option(MAP_TEXT_HUGE_PAGES "Remap hot static code onto huge pages" ON) + option(MAP_TEXT_HUGE_PAGES "Remap hot static code onto huge pages" ON) ENDIF() IF (NOT DEFAULT_CONFIG_DIR) diff --git a/CMake/VisualStudioToolset.cmake b/CMake/VisualStudioToolset.cmake deleted file mode 100644 index 70fec96217555d..00000000000000 --- a/CMake/VisualStudioToolset.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Due to HHVM's size, we need to use the native 64-bit toolchain to get a decent link time, -# and, in fact, it's also needed to be able to link at all in debug mode, due to the size of -# the hphp_runtime_static static library. However, Visual Studio defaults to using the 32-bit -# hosted cross compiler targeting 64-bit. Unfortunately, CMake doesn't provide us a way to -# do this, so we have to resort to a hack-around in order to make this possible. Because the -# toolset value is put into the project file unescaped, we can use it to add the PreferredToolArchitecture -# value that we need, as long as we make sure to properly close and re-open the current tags. -# -# To add support for newer MSVC versions, simply adjust the actual toolset value at the start -# and end of the string. -# -# Unfortunately, we can't rely on the MSVC and MSVC14 variables to check if we need to enable -# this, due to the fact they are set when the C/CXX languages are enabled, however, this value -# needs to be set before the languages are enabled in order to have any effect, so we set it -# based directly off of the name of the generator, which is set before configuration even begins. - -if ("${CMAKE_GENERATOR}" STREQUAL "Visual Studio 15( 2017)? Win64") - set(CMAKE_GENERATOR_TOOLSET "v141x64v141") -endif() diff --git a/CMake/cotire.cmake b/CMake/cotire.cmake deleted file mode 100644 index 16ef31d7bae056..00000000000000 --- a/CMake/cotire.cmake +++ /dev/null @@ -1,3551 +0,0 @@ -# - cotire (compile time reducer) -# -# See the cotire manual for usage hints. -# -#============================================================================= -# Copyright 2012-2014 Sascha Kratky -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -#============================================================================= - -if(__COTIRE_INCLUDED) - return() -endif() -set(__COTIRE_INCLUDED TRUE) - -# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode -# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(PUSH) -endif() -# we need the CMake variables CMAKE_SCRIPT_MODE_FILE and CMAKE_ARGV available since 2.8.5 -# we need APPEND_STRING option for set_property available since 2.8.6 -cmake_minimum_required(VERSION 2.8.6) -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(POP) -endif() - -set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") -set (COTIRE_CMAKE_MODULE_VERSION "1.6.6") - -include(CMakeParseArguments) -include(ProcessorCount) - -function (cotire_determine_compiler_version _language _versionPrefix) - if (NOT ${_versionPrefix}_VERSION) - # use CMake's predefined compiler version variable (available since CMake 2.8.8) - if (DEFINED CMAKE_${_language}_COMPILER_VERSION) - set (${_versionPrefix}_VERSION "${CMAKE_${_language}_COMPILER_VERSION}") - elseif (WIN32) - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - string (STRIP "${CMAKE_${_language}_COMPILER_ARG1}" _compilerArg1) - execute_process ( - COMMAND ${CMAKE_${_language}_COMPILER} ${_compilerArg1} - ERROR_VARIABLE _versionLine OUTPUT_QUIET TIMEOUT 10) - string (REGEX REPLACE ".*Version *([0-9]+(\\.[0-9]+)*).*" "\\1" ${_versionPrefix}_VERSION "${_versionLine}") - else() - # assume GCC like command line interface - string (STRIP "${CMAKE_${_language}_COMPILER_ARG1}" _compilerArg1) - execute_process ( - COMMAND ${CMAKE_${_language}_COMPILER} ${_compilerArg1} "-dumpversion" - OUTPUT_VARIABLE ${_versionPrefix}_VERSION - RESULT_VARIABLE _result - OUTPUT_STRIP_TRAILING_WHITESPACE TIMEOUT 10) - if (_result) - set (${_versionPrefix}_VERSION "") - endif() - endif() - if (${_versionPrefix}_VERSION) - set (${_versionPrefix}_VERSION "${${_versionPrefix}_VERSION}" CACHE INTERNAL "${_language} compiler version") - endif() - set (${_versionPrefix}_VERSION "${${_versionPrefix}_VERSION}" PARENT_SCOPE) - if (COTIRE_DEBUG) - message (STATUS "${CMAKE_${_language}_COMPILER} version ${${_versionPrefix}_VERSION}") - endif() - endif() -endfunction() - -function (cotire_get_source_file_extension _sourceFile _extVar) - # get_filename_component returns extension from first occurrence of . in file name - # this function computes the extension from last occurrence of . in file name - string (FIND "${_sourceFile}" "." _index REVERSE) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) - else() - set (_sourceExt "") - endif() - set (${_extVar} "${_sourceExt}" PARENT_SCOPE) -endfunction() - -macro (cotire_check_is_path_relative_to _path _isRelativeVar) - set (${_isRelativeVar} FALSE) - if (IS_ABSOLUTE "${_path}") - foreach (_dir ${ARGN}) - file (RELATIVE_PATH _relPath "${_dir}" "${_path}") - if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) - set (${_isRelativeVar} TRUE) - break() - endif() - endforeach() - endif() -endmacro() - -function (cotire_filter_language_source_files _language _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) - set (_sourceFiles "") - set (_excludedSourceFiles "") - set (_cotiredSourceFiles "") - if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") - else() - set (_languageExtensions "") - endif() - if (CMAKE_${_language}_IGNORE_EXTENSIONS) - set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") - else() - set (_ignoreExtensions "") - endif() - if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) - set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") - else() - set (_excludeExtensions "") - endif() - if (COTIRE_DEBUG) - message (STATUS "${_language} source file extensions: ${_languageExtensions}") - message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") - message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") - endif() - foreach (_sourceFile ${ARGN}) - get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) - get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) - get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) - get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) - set (_sourceIsFiltered FALSE) - if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) - cotire_get_source_file_extension("${_sourceFile}" _sourceExt) - if (_sourceExt) - list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) - if (_ignoreIndex LESS 0) - list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) - if (_excludeIndex GREATER -1) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) - if (_sourceIndex GREATER -1) - set (_sourceIsFiltered TRUE) - elseif ("${_sourceLanguage}" STREQUAL "${_language}") - # add to excluded sources, if file is not ignored and has correct language without having the correct extension - list (APPEND _excludedSourceFiles "${_sourceFile}") - endif() - endif() - endif() - endif() - endif() - if (COTIRE_DEBUG) - message (STATUS "${_sourceFile} filtered=${_sourceIsFiltered} language=${_sourceLanguage} header=${_sourceIsHeaderOnly}") - endif() - if (_sourceIsFiltered) - get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) - get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) - get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) - if (COTIRE_DEBUG) - message (STATUS "${_sourceFile} excluded=${_sourceIsExcluded} cotired=${_sourceIsCotired} compileFlags=${_sourceCompileFlags}") - endif() - if (_sourceIsCotired) - list (APPEND _cotiredSourceFiles "${_sourceFile}") - elseif (_sourceIsExcluded OR _sourceCompileFlags) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _sourceFiles "${_sourceFile}") - endif() - endif() - endforeach() - if (COTIRE_DEBUG) - message (STATUS "All: ${ARGN}") - message (STATUS "${_language}: ${_sourceFiles}") - message (STATUS "Excluded: ${_excludedSourceFiles}") - message (STATUS "Cotired: ${_cotiredSourceFiles}") - endif() - set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) - set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) - set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (NOT _propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_file_property_values _valuesVar _property) - set (_values "") - foreach (_sourceFile ${ARGN}) - get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) - if (_propertyValue) - list (APPEND _values "${_propertyValue}") - endif() - endforeach() - set (${_valuesVar} ${_values} PARENT_SCOPE) -endfunction() - -function (cotire_resolve_config_properties _configurations _propertiesVar) - set (_properties "") - foreach (_property ${ARGN}) - if ("${_property}" MATCHES "") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") - list (APPEND _properties ${_configProperty}) - endforeach() - else() - list (APPEND _properties ${_property}) - endif() - endforeach() - set (${_propertiesVar} ${_properties} PARENT_SCOPE) -endfunction() - -function (cotire_copy_set_properties _configurations _type _source _target) - cotire_resolve_config_properties("${_configurations}" _properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) - set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") - endif() - endforeach() -endfunction() - -function (cotire_get_target_link_libraries_for_usage_requirements _target _targetLinkLibrariesVar) - set (_targetLinkLibraries "") - get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) - while (_librariesToProcess) - # remove from head - list (GET _librariesToProcess 0 _library) - list (REMOVE_AT _librariesToProcess 0) - list (FIND _targetLinkLibraries ${_library} _index) - if (_index LESS 0) - list (APPEND _targetLinkLibraries ${_library}) - # process transitive libraries - if (TARGET ${_library}) - get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) - if (_libraries) - list (APPEND _librariesToProcess ${_libraries}) - endif() - endif() - endif() - endwhile() - set (${_targetLinkLibrariesVar} ${_targetLinkLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - set (_flagPrefix "[/-]") - else() - set (_flagPrefix "--?") - endif() - set (_optionFlag "") - set (_matchedOptions "") - set (_unmatchedOptions "") - foreach (_compileFlag ${ARGN}) - if (_compileFlag) - if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") - # option with separate argument - list (APPEND _matchedOptions "${_compileFlag}") - set (_optionFlag "") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") - # remember option - set (_optionFlag "${CMAKE_MATCH_2}") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") - # option with joined argument - list (APPEND _matchedOptions "${CMAKE_MATCH_3}") - set (_optionFlag "") - else() - # flush remembered option - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - set (_optionFlag "") - endif() - # add to unfiltered options - list (APPEND _unmatchedOptions "${_compileFlag}") - endif() - endif() - endforeach() - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - endif() - if (COTIRE_DEBUG) - message (STATUS "Filter ${_flagFilter}") - if (_matchedOptions) - message (STATUS "Matched ${_matchedOptions}") - endif() - if (_unmatchedOptions) - message (STATUS "Unmatched ${_unmatchedOptions}") - endif() - endif() - set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) - set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_flags _config _language _directory _target _flagsVar) - string (TOUPPER "${_config}" _upperConfig) - # collect options from CMake language variables - set (_compileFlags "") - if (CMAKE_${_language}_FLAGS) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") - endif() - if (CMAKE_${_language}_FLAGS_${_upperConfig}) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") - endif() - if (_target) - # add option from CMake target type variable - get_target_property(_targetType ${_target} TYPE) - if (POLICY CMP0018) - # handle POSITION_INDEPENDENT_CODE property introduced with CMake 2.8.9 if policy CMP0018 is turned on - cmake_policy(GET CMP0018 _PIC_Policy) - else() - # default to old behavior - set (_PIC_Policy "OLD") - endif() - if (COTIRE_DEBUG) - message(STATUS "CMP0018=${_PIC_Policy}") - endif() - if (_PIC_Policy STREQUAL "NEW") - # NEW behavior: honor the POSITION_INDEPENDENT_CODE target property - get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) - if (_targetPIC) - if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") - elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") - endif() - endif() - else() - # OLD behavior or policy not set: use the value of CMAKE_SHARED_LIBRARY__FLAGS - if (_targetType STREQUAL "MODULE_LIBRARY") - # flags variable for module library uses different name SHARED_MODULE - # (e.g., CMAKE_SHARED_MODULE_C_FLAGS) - set (_targetType SHARED_MODULE) - endif() - if (CMAKE_${_targetType}_${_language}_FLAGS) - set (_compileFlags "${_compileFlags} ${CMAKE_${_targetType}_${_language}_FLAGS}") - endif() - endif() - endif() - if (_directory) - # add_definitions may have been used to add flags to the compiler command - get_directory_property(_dirDefinitions DIRECTORY "${_directory}" DEFINITIONS) - if (_dirDefinitions) - set (_compileFlags "${_compileFlags} ${_dirDefinitions}") - endif() - endif() - if (_target) - # add target compile options - get_target_property(_targetflags ${_target} COMPILE_FLAGS) - if (_targetflags) - set (_compileFlags "${_compileFlags} ${_targetflags}") - endif() - get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) - if (_targetOptions) - set (_compileFlags "${_compileFlags} ${_targetOptions}") - endif() - # interface compile options from linked library targets - cotire_get_target_link_libraries_for_usage_requirements(${_target} _linkLibraries) - foreach (_library ${_linkLibraries}) - if (TARGET ${_library}) - get_target_property(_targetOptions ${_library} INTERFACE_COMPILE_OPTIONS) - if (_targetOptions) - set (_compileFlags "${_compileFlags} ${_targetOptions}") - endif() - endif() - endforeach() - endif() - if (UNIX) - separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") - elseif(WIN32) - separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") - else() - separate_arguments(_compileFlags) - endif() - # platform specific flags - if (APPLE) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) - if (NOT _architectures) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES) - endif() - if (_architectures) - foreach (_arch ${_architectures}) - list (APPEND _compileFlags "-arch" "${_arch}") - endforeach() - endif() - if (CMAKE_OSX_SYSROOT) - if (CMAKE_${_language}_SYSROOT_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") - else() - list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") - endif() - endif() - if (CMAKE_OSX_DEPLOYMENT_TARGET) - if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") - else() - list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - endif() - endif() - endif() - if (COTIRE_DEBUG AND _compileFlags) - message (STATUS "Target ${_target} compile flags ${_compileFlags}") - endif() - set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_include_directories _config _language _targetSourceDir _targetBinaryDir _target _includeDirsVar _systemIncludeDirsVar) - set (_includeDirs "") - set (_systemIncludeDirs "") - # default include dirs - if (CMAKE_INCLUDE_CURRENT_DIR) - list (APPEND _includeDirs "${_targetBinaryDir}") - list (APPEND _includeDirs "${_targetSourceDir}") - endif() - # parse additional include directories from target compile flags - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_targetSourceDir}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "I" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _includeDirs ${_dirs}) - endif() - # target include directories - get_directory_property(_dirs DIRECTORY "${_targetSourceDir}" INCLUDE_DIRECTORIES) - if (_target) - get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - - # interface include directories from linked library targets - cotire_get_target_link_libraries_for_usage_requirements(${_target} _linkLibraries) - foreach (_library ${_linkLibraries}) - if (TARGET ${_library}) - get_target_property(_targetDirs ${_library} INTERFACE_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_library} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endif() - endforeach() - endif() - if (dirs) - list (REMOVE_DUPLICATES _dirs) - endif() - list (LENGTH _includeDirs _projectInsertIndex) - foreach (_dir ${_dirs}) - if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) - cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") - if (_isRelative) - list (LENGTH _includeDirs _len) - if (_len EQUAL _projectInsertIndex) - list (APPEND _includeDirs "${_dir}") - else() - list (INSERT _includeDirs _projectInsertIndex "${_dir}") - endif() - math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") - else() - list (APPEND _includeDirs "${_dir}") - endif() - else() - list (APPEND _includeDirs "${_dir}") - endif() - endforeach() - list (REMOVE_DUPLICATES _includeDirs) - list (REMOVE_DUPLICATES _systemIncludeDirs) - if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) - list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) - endif() - if (COTIRE_DEBUG AND _includeDirs) - message (STATUS "Target ${_target} include dirs ${_includeDirs}") - endif() - set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) - if (COTIRE_DEBUG AND _systemIncludeDirs) - message (STATUS "Target ${_target} system include dirs ${_systemIncludeDirs}") - endif() - set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) -endfunction() - -macro (cotire_make_C_identifier _identifierVar _str) - if (CMAKE_VERSION VERSION_LESS "2.8.12") - # mimic CMake SystemTools::MakeCindentifier behavior - if ("${_str}" MATCHES "^[0-9].+$") - set (_str "_${str}") - endif() - string (REGEX REPLACE "[^a-zA-Z0-9]" "_" ${_identifierVar} "${_str}") - else() - string (MAKE_C_IDENTIFIER "${_str}" "${_identifierVar}") - endif() -endmacro() - -function (cotire_get_target_export_symbol _target _exportSymbolVar) - set (_exportSymbol "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_enableExports ${_target} ENABLE_EXPORTS) - if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR - (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) - get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) - if (NOT _exportSymbol) - set (_exportSymbol "${_target}_EXPORTS") - endif() - cotire_make_C_identifier(_exportSymbol "${_exportSymbol}") - endif() - set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_definitions _config _language _directory _target _definitionsVar) - string (TOUPPER "${_config}" _upperConfig) - set (_configDefinitions "") - # CMAKE_INTDIR for multi-configuration build systems - if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") - list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") - endif() - # target export define symbol - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - list (APPEND _configDefinitions "${_defineSymbol}") - endif() - # directory compile definitions - get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_directory_property(_definitions DIRECTORY "${_directory}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # target compile definitions - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # interface compile definitions from linked library targets - cotire_get_target_link_libraries_for_usage_requirements(${_target} _linkLibraries) - foreach (_library ${_linkLibraries}) - if (TARGET ${_library}) - get_target_property(_definitions ${_library} INTERFACE_COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - endif() - endforeach() - # parse additional compile definitions from target compile flags - # and don't look at directory compile definitions, which we already handled - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - list (REMOVE_DUPLICATES _configDefinitions) - if (COTIRE_DEBUG AND _configDefinitions) - message (STATUS "Target ${_target} compile definitions ${_configDefinitions}") - endif() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compiler_flags _config _language _directory _target _compilerFlagsVar) - # parse target compile flags omitting compile definitions and include directives - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_directory}" "${_target}" _targetFlags) - set (_compilerFlags "") - cotire_filter_compile_flags("${_language}" "[ID]" _ignore _compilerFlags ${_targetFlags}) - if (COTIRE_DEBUG AND _compilerFlags) - message (STATUS "Target ${_target} compiler flags ${_compilerFlags}") - endif() - set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) -endfunction() - -function (cotire_add_sys_root_paths _pathsVar) - if (APPLE) - if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) - foreach (_path IN LISTS ${_pathsVar}) - if (IS_ABSOLUTE "${_path}") - get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) - if (EXISTS "${_path}") - list (APPEND ${_pathsVar} "${_path}") - endif() - endif() - endforeach() - endif() - endif() - set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) - if (COTIRE_DEBUG) - message (STATUS "${_pathsVar}=${${_pathsVar}}") - endif() -endfunction() - -function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) - set (_extraProperties ${ARGN}) - set (_result "") - if (_extraProperties) - list (FIND _extraProperties "${_sourceFile}" _index) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - list (LENGTH _extraProperties _len) - math (EXPR _len "${_len} - 1") - foreach (_index RANGE ${_index} ${_len}) - list (GET _extraProperties ${_index} _value) - if (_value MATCHES "${_pattern}") - list (APPEND _result "${_value}") - else() - break() - endif() - endforeach() - endif() - endif() - set (${_resultVar} ${_result} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) - set (_compileDefinitions "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - string (TOUPPER "${_config}" _upperConfig) - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - if (COTIRE_DEBUG AND _compileDefinitions) - message (STATUS "Source ${_sourceFile} compile definitions ${_compileDefinitions}") - endif() - set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) - set (_configDefinitions "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) - if (_sourceDefinitions) - list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") - endif() - endforeach() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) - set (_sourceUndefs "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - get_source_file_property(_undefs "${_sourceFile}" ${_property}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - if (COTIRE_DEBUG AND _sourceUndefs) - message (STATUS "Source ${_sourceFile} ${_property} undefs ${_sourceUndefs}") - endif() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_undefs _property _sourceUndefsVar) - set (_sourceUndefs "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) - if (_undefs) - list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") - endif() - endforeach() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -macro (cotire_set_cmd_to_prologue _cmdVar) - set (${_cmdVar} "${CMAKE_COMMAND}") - if (COTIRE_DEBUG) - list (APPEND ${_cmdVar} "--warn-uninitialized") - endif() - list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") - if (COTIRE_VERBOSE) - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") - elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") - endif() -endmacro() - -function (cotire_init_compile_cmd _cmdVar _language _compilerExe _compilerArg1) - if (NOT _compilerExe) - set (_compilerExe "${CMAKE_${_language}_COMPILER}") - endif() - if (NOT _compilerArg1) - set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) - endif() - string (STRIP "${_compilerArg1}" _compilerArg1) - set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) -endfunction() - -macro (cotire_add_definitions_to_cmd _cmdVar _language) - foreach (_definition ${ARGN}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - list (APPEND ${_cmdVar} "/D${_definition}") - else() - list (APPEND ${_cmdVar} "-D${_definition}") - endif() - endforeach() -endmacro() - -macro (cotire_add_includes_to_cmd _cmdVar _language _includeSystemFlag _includesVar _systemIncludesVar) - foreach (_include ${${_includesVar}}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - file (TO_NATIVE_PATH "${_include}" _include) - list (APPEND ${_cmdVar} "/I${_include}") - else() - list (FIND ${_systemIncludesVar} ${_include} _index) - if(_index GREATER -1 AND NOT "${_includeSystemFlag}" STREQUAL "") - list (APPEND ${_cmdVar} "${_includeSystemFlag}${_include}") - else() - list (APPEND ${_cmdVar} "-I${_include}") - endif() - endif() - endforeach() -endmacro() - -macro (cotire_add_frameworks_to_cmd _cmdVar _language) - if (APPLE) - set (_frameWorkDirs "") - foreach (_include ${ARGN}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameWorkDir "${_include}" PATH) - list (APPEND _frameWorkDirs "${_frameWorkDir}") - endif() - endforeach() - if (_frameWorkDirs) - list (REMOVE_DUPLICATES _frameWorkDirs) - foreach (_frameWorkDir ${_frameWorkDirs}) - list (APPEND ${_cmdVar} "-F${_frameWorkDir}") - endforeach() - endif() - endif() -endmacro() - -macro (cotire_add_compile_flags_to_cmd _cmdVar) - foreach (_flag ${ARGN}) - list (APPEND ${_cmdVar} "${_flag}") - endforeach() -endmacro() - -function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - set (_triggerFile "") - foreach (_dependencyFile ${ARGN}) - if (EXISTS "${_dependencyFile}" AND "${_dependencyFile}" IS_NEWER_THAN "${_file}") - set (_triggerFile "${_dependencyFile}") - break() - endif() - endforeach() - get_filename_component(_fileName "${_file}" NAME) - if (EXISTS "${_file}") - if (_triggerFile) - if (COTIRE_VERBOSE) - message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") - endif() - else() - if (COTIRE_VERBOSE) - message (STATUS "${_fileName} is up-to-date.") - endif() - set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) - endif() - else() - if (COTIRE_VERBOSE) - message (STATUS "${_fileName} does not exist yet.") - endif() - endif() -endfunction() - -macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) - set (${_relPathVar} "") - foreach (_includeDir ${_includeDirs}) - if (IS_DIRECTORY "${_includeDir}") - file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") - if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") - string (LENGTH "${${_relPathVar}}" _closestLen) - string (LENGTH "${_relPath}" _relLen) - if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) - set (${_relPathVar} "${_relPath}") - endif() - endif() - elseif ("${_includeDir}" STREQUAL "${_headerFile}") - # if path matches exactly, return short non-empty string - set (${_relPathVar} "1") - break() - endif() - endforeach() -endmacro() - -macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) - # check header path against ignored and honored include directories - cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) - if (_insideRelPath) - # header is inside, but could be become outside if there is a shorter outside match - cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) - if (_outsideRelPath) - string (LENGTH "${_insideRelPath}" _insideRelPathLen) - string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) - if (_outsideRelPathLen LESS _insideRelPathLen) - set (${_headerIsInside} FALSE) - else() - set (${_headerIsInside} TRUE) - endif() - else() - set (${_headerIsInside} TRUE) - endif() - else() - # header is outside - set (${_headerIsInside} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) - if (NOT EXISTS "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif (IS_DIRECTORY "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") - # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path - # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation - # with the error message "error: no include path in which to search for header.h" - set (${_headerIsIgnoredVar} TRUE) - else() - set (${_headerIsIgnoredVar} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) - # check header file extension - cotire_get_source_file_extension("${_headerFile}" _headerFileExt) - set (${_headerIsIgnoredVar} FALSE) - if (_headerFileExt) - list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) - if (_index GREATER -1) - set (${_headerIsIgnoredVar} TRUE) - endif() - endif() -endmacro() - -macro (cotire_parse_line _line _headerFileVar _headerDepthVar) - if (MSVC) - # cl.exe /showIncludes output looks different depending on the language pack used, e.g.: - # English: "Note: including file: C:\directory\file" - # German: "Hinweis: Einlesen der Datei: C:\directory\file" - # We use a very general regular expression, relying on the presence of the : characters - if (_line MATCHES ":( +)([^:]+:[^:]+)$") - # Visual Studio compiler output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - else() - if (_line MATCHES "^(\\.+) (.*)$") - # GCC like output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - if (IS_ABSOLUTE "${CMAKE_MATCH_2}") - set (${_headerFileVar} "${CMAKE_MATCH_2}") - else() - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) - endif() - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - endif() -endmacro() - -function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) - if (WIN32) - # prevent CMake macro invocation errors due to backslash characters in Windows paths - string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") - endif() - # canonize slashes - string (REPLACE "//" "/" _scanOutput "${_scanOutput}") - # prevent semicolon from being interpreted as a line separator - string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") - # then separate lines - string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") - list (LENGTH _scanOutput _len) - # remove duplicate lines to speed up parsing - list (REMOVE_DUPLICATES _scanOutput) - list (LENGTH _scanOutput _uniqueLen) - if (COTIRE_VERBOSE OR COTIRE_DEBUG) - message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") - if (_ignoredExtensions) - message (STATUS "Ignored extensions: ${_ignoredExtensions}") - endif() - if (_ignoredIncludeDirs) - message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") - endif() - if (_honoredIncludeDirs) - message (STATUS "Included paths: ${_honoredIncludeDirs}") - endif() - endif() - set (_sourceFiles ${ARGN}) - set (_selectedIncludes "") - set (_unparsedLines "") - # stack keeps track of inside/outside project status of processed header files - set (_headerIsInsideStack "") - foreach (_line IN LISTS _scanOutput) - if (_line) - cotire_parse_line("${_line}" _headerFile _headerDepth) - if (_headerFile) - cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) - if (COTIRE_DEBUG) - message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") - endif() - # update stack - list (LENGTH _headerIsInsideStack _stackLen) - if (_headerDepth GREATER _stackLen) - math (EXPR _stackLen "${_stackLen} + 1") - foreach (_index RANGE ${_stackLen} ${_headerDepth}) - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endforeach() - else() - foreach (_index RANGE ${_headerDepth} ${_stackLen}) - list (REMOVE_AT _headerIsInsideStack -1) - endforeach() - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerIsInsideStack}") - endif() - # header is a candidate if it is outside project - if (NOT _headerIsInside) - # get parent header file's inside/outside status - if (_headerDepth GREATER 1) - math (EXPR _index "${_headerDepth} - 2") - list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) - else() - set (_parentHeaderIsInside TRUE) - endif() - # select header file if parent header file is inside project - # (e.g., a project header file that includes a standard header file) - if (_parentHeaderIsInside) - cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) - if (NOT _headerIsIgnored) - cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) - if (NOT _headerIsIgnored) - list (APPEND _selectedIncludes "${_headerFile}") - else() - # fix header's inside status on stack, it is ignored by extension now - list (REMOVE_AT _headerIsInsideStack -1) - list (APPEND _headerIsInsideStack TRUE) - endif() - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") - endif() - endif() - endif() - else() - if (MSVC) - # for cl.exe do not keep unparsed lines which solely consist of a source file name - string (FIND "${_sourceFiles}" "${_line}" _index) - if (_index LESS 0) - list (APPEND _unparsedLines "${_line}") - endif() - else() - list (APPEND _unparsedLines "${_line}") - endif() - endif() - endif() - endforeach() - list (REMOVE_DUPLICATES _selectedIncludes) - set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) - set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) -endfunction() - -function (cotire_scan_includes _includesVar) - set(_options "") - set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_VERSION INCLUDE_SYSTEM_FLAG LANGUAGE UNPARSED_LINES) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - set (_cmd "${_option_COMPILER_EXECUTABLE}" ${_option_COMPILER_ARG1}) - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" "${_option_INCLUDE_SYSTEM_FLAG}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_INCLUDE_DIRECTORIES}) - cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) - # only consider existing source files for scanning - set (_existingSourceFiles "") - foreach (_sourceFile ${_sourceFiles}) - if (EXISTS "${_sourceFile}") - list (APPEND _existingSourceFiles "${_sourceFile}") - endif() - endforeach() - if (NOT _existingSourceFiles) - set (${_includesVar} "" PARENT_SCOPE) - return() - endif() - list (APPEND _cmd ${_existingSourceFiles}) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (_option_COMPILER_ID MATCHES "MSVC") - if (COTIRE_DEBUG) - message (STATUS "clearing VS_UNICODE_OUTPUT") - endif() - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result OUTPUT_QUIET ERROR_VARIABLE _output) - if (_result) - message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") - endif() - cotire_parse_includes( - "${_option_LANGUAGE}" "${_output}" - "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" - "${_option_IGNORE_EXTENSIONS}" - _includes _unparsedLines - ${_sourceFiles}) - set (${_includesVar} ${_includes} PARENT_SCOPE) - if (_option_UNPARSED_LINES) - set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_append_undefs _contentsVar) - set (_undefs ${ARGN}) - if (_undefs) - list (REMOVE_DUPLICATES _undefs) - foreach (_definition ${_undefs}) - list (APPEND ${_contentsVar} "#undef ${_definition}") - endforeach() - endif() -endmacro() - -macro (cotire_comment_str _language _commentText _commentVar) - if ("${_language}" STREQUAL "CMAKE") - set (${_commentVar} "# ${_commentText}") - else() - set (${_commentVar} "/* ${_commentText} */") - endif() -endmacro() - -function (cotire_write_file _language _file _contents _force) - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) - cotire_comment_str("${_language}" "${_file}" _header2) - set (_contents "${_header1}\n${_header2}\n${_contents}") - if (COTIRE_DEBUG) - message (STATUS "${_contents}") - endif() - if (_force OR NOT EXISTS "${_file}") - file (WRITE "${_file}" "${_contents}") - else() - file (READ "${_file}" _oldContents) - if (NOT "${_oldContents}" STREQUAL "${_contents}") - file (WRITE "${_file}" "${_contents}") - else() - if (COTIRE_DEBUG) - message (STATUS "${_file} unchanged") - endif() - endif() - endif() -endfunction() - -function (cotire_generate_unity_source _unityFile) - set(_options "") - set(_oneValueArgs LANGUAGE) - set(_multiValueArgs - DEPENDS SOURCES_COMPILE_DEFINITIONS - PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (_option_DEPENDS) - cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) - if (_unityFileIsUpToDate) - return() - endif() - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_PRE_UNDEFS) - set (_option_PRE_UNDEFS "") - endif() - if (NOT _option_SOURCES_PRE_UNDEFS) - set (_option_SOURCES_PRE_UNDEFS "") - endif() - if (NOT _option_POST_UNDEFS) - set (_option_POST_UNDEFS "") - endif() - if (NOT _option_SOURCES_POST_UNDEFS) - set (_option_SOURCES_POST_UNDEFS "") - endif() - set (_contents "") - if (_option_PROLOGUE) - list (APPEND _contents ${_option_PROLOGUE}) - endif() - if (_option_LANGUAGE AND _sourceFiles) - if ("${_option_LANGUAGE}" STREQUAL "CXX") - list (APPEND _contents "#ifdef __cplusplus") - elseif ("${_option_LANGUAGE}" STREQUAL "C") - list (APPEND _contents "#ifndef __cplusplus") - endif() - endif() - set (_compileUndefinitions "") - foreach (_sourceFile ${_sourceFiles}) - cotire_get_source_compile_definitions( - "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions - ${_option_SOURCES_COMPILE_DEFINITIONS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) - if (_option_PRE_UNDEFS) - list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) - endif() - if (_sourcePreUndefs) - list (APPEND _compileUndefinitions ${_sourcePreUndefs}) - endif() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_sourcePostUndefs) - list (APPEND _compileUndefinitions ${_sourcePostUndefs}) - endif() - if (_option_POST_UNDEFS) - list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) - endif() - foreach (_definition ${_compileDefinitions}) - if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") - list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") - list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") - else() - list (APPEND _contents "#define ${_definition}") - list (INSERT _compileUndefinitions 0 "${_definition}") - endif() - endforeach() - get_filename_component(_sourceFile "${_sourceFile}" ABSOLUTE) - if (WIN32) - file (TO_NATIVE_PATH "${_sourceFile}" _sourceFile) - endif() - list (APPEND _contents "#include \"${_sourceFile}\"") - endforeach() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_option_LANGUAGE AND _sourceFiles) - list (APPEND _contents "#endif") - endif() - if (_option_EPILOGUE) - list (APPEND _contents ${_option_EPILOGUE}) - endif() - list (APPEND _contents "") - string (REPLACE ";" "\n" _contents "${_contents}") - if (COTIRE_VERBOSE) - message ("${_contents}") - endif() - cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) -endfunction() - -function (cotire_generate_prefix_header _prefixFile) - set(_options "") - set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION INCLUDE_SYSTEM_FLAG) - set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS - INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (_option_DEPENDS) - cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) - if (_prefixFileIsUpToDate) - set (_unparsedLinesFile "${_prefixFile}.log") - file (WRITE "${_unparsedLinesFile}" "") - return() - endif() - endif() - set (_prologue "") - set (_epilogue "") - if (_option_COMPILER_ID MATCHES "Clang") - set (_prologue "#pragma clang system_header") - elseif (_option_COMPILER_ID MATCHES "GNU") - set (_prologue "#pragma GCC system_header") - elseif (_option_COMPILER_ID MATCHES "MSVC") - set (_prologue "#pragma warning(push, 0)") - set (_epilogue "#pragma warning(pop)") - elseif (_option_COMPILER_ID MATCHES "Intel") - # Intel compiler requires hdrstop pragma to stop generating PCH file - set (_epilogue "#pragma hdrstop") - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - cotire_scan_includes(_selectedHeaders ${_sourceFiles} - LANGUAGE "${_option_LANGUAGE}" - COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" - COMPILER_ID "${_option_COMPILER_ID}" - COMPILER_VERSION "${_option_COMPILER_VERSION}" - COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} - COMPILE_FLAGS ${_option_COMPILE_FLAGS} - INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} - INCLUDE_SYSTEM_FLAG ${_option_INCLUDE_SYSTEM_FLAG} - SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} - IGNORE_PATH ${_option_IGNORE_PATH} - INCLUDE_PATH ${_option_INCLUDE_PATH} - IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} - UNPARSED_LINES _unparsedLines) - cotire_generate_unity_source("${_prefixFile}" - PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) - set (_unparsedLinesFile "${_prefixFile}.log") - if (_unparsedLines) - if (COTIRE_VERBOSE OR NOT _selectedHeaders) - list (LENGTH _unparsedLines _skippedLineCount) - file (RELATIVE_PATH _unparsedLinesFileRelPath "${CMAKE_BINARY_DIR}" "${_unparsedLinesFile}") - message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesFileRelPath}") - endif() - string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") - endif() - file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}") -endfunction() - -function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - # cl.exe options used - # /nologo suppresses display of sign-on banner - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # /showIncludes list include files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /showIncludes") - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fdirectives-only do not expand macros, requires GCC >= 4.3 - if (_flags) - # append to list - list (APPEND _flags -H -E) - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - list (APPEND _flags "-fdirectives-only") - endif() - else() - # return as a flag string - set (_flags "-H -E") - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - set (_flags "${_flags} -fdirectives-only") - endif() - endif() - elseif (_compilerID MATCHES "Clang") - # Clang options used - # -H print the name of each header file used - # -E invoke preprocessor - if (_flags) - # append to list - list (APPEND _flags -H -E) - else() - # return as a flag string - set (_flags "-H -E") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - # Windows Intel options used - # /nologo do not display compiler version information - # /QH display the include file order - # /EP preprocess to stdout, omitting #line directives - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /QH") - endif() - else() - # Linux / Mac OS X Intel options used - # -H print the name of each header file used - # -EP preprocess to stdout, omitting #line directives - # -Kc++ process all source or unrecognized file types as C++ source files - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -H -EP) - else() - # return as a flag string - if ("${_language}" STREQUAL "CXX") - set (_flags "-Kc++ ") - endif() - set (_flags "${_flags}-H -EP") - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /Zs syntax check only - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - endif() - elseif (_compilerID MATCHES "GNU|Clang") - # GCC / Clang options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may - # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags "-x" "${_xLanguage_${_language}}" "-c" "${_prefixFile}" -o "${_pchFile}") - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # Windows Intel options used - # /nologo do not display compiler version information - # /Yc create a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - # /Zs syntax check only - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-create name of the precompiled header (PCH) to create - # -Kc++ process all source or unrecognized file types as C++ source files - # -fsyntax-only check only for correct syntax - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - get_filename_component(_pchDir "${_pchFile}" PATH) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-create" "${_pchName}" "-fsyntax-only" "${_hostFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "-Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -include process include file as the first line of the primary source file - # -Winvalid-pch warns if precompiled header is found but cannot be used - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags "-Winvalid-pch" "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - # Clang options used - # -include process include file as the first line of the primary source file - # -include-pch include precompiled header file - # -Qunused-arguments don't emit warning for unused driver arguments - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags "-Qunused-arguments" "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Qunused-arguments -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # Windows Intel options used - # /Yu use a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-use name of the precompiled header (PCH) to use - # -include process include file as the first line of the primary source file - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - get_filename_component(_pchDir "${_pchFile}" PATH) - get_filename_component(_pchName "${_pchFile}" NAME) - if (_flags) - # append to list - list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-use" "${_pchName}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "-Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) - set(_options "") - set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION INCLUDE_SYSTEM_FLAG LANGUAGE) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" "${_option_INCLUDE_SYSTEM_FLAG}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_INCLUDE_DIRECTORIES}) - cotire_add_pch_compilation_flags( - "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (_option_COMPILER_ID MATCHES "MSVC") - if (COTIRE_DEBUG) - message (STATUS "clearing VS_UNICODE_OUTPUT") - endif() - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result) - if (_result) - message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") - endif() -endfunction() - -function (cotire_check_precompiled_header_support _language _targetSourceDir _target _msgVar) - set (_unsupportedCompiler - "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # supported since Visual Studio C++ 6.0 - # and CMake does not support an earlier version - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC PCH support requires version >= 3.4 - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - if ("${COTIRE_${_language}_COMPILER_VERSION}" MATCHES ".+" AND - "${COTIRE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") - set (${_msgVar} "${_unsupportedCompiler} version ${COTIRE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # all Clang versions have PCH support - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel PCH support requires version >= 8.0.0 - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - if ("${COTIRE_${_language}_COMPILER_VERSION}" MATCHES ".+" AND - "${COTIRE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") - set (${_msgVar} "${_unsupportedCompiler} version ${COTIRE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - else() - set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) - endif() - if (CMAKE_${_language}_COMPILER MATCHES "ccache") - if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros") - set (${_msgVar} - "ccache requires the environment variable CCACHE_SLOPPINESS to be set to time_macros." - PARENT_SCOPE) - endif() - endif() - if (APPLE) - # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) - if (CMAKE_CONFIGURATION_TYPES) - set (_configs ${CMAKE_CONFIGURATION_TYPES}) - elseif (CMAKE_BUILD_TYPE) - set (_configs ${CMAKE_BUILD_TYPE}) - else() - set (_configs "None") - endif() - foreach (_config ${_configs}) - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_targetSourceDir}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) - list (LENGTH _architectures _numberOfArchitectures) - if (_numberOfArchitectures GREATER 1) - string (REPLACE ";" ", " _architectureStr "${_architectures}") - set (${_msgVar} - "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." - PARENT_SCOPE) - break() - endif() - endforeach() - endif() -endfunction() - -macro (cotire_get_intermediate_dir _cotireDir) - get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) -endmacro() - -macro (cotire_setup_file_extension_variables) - set (_unityFileExt_C ".c") - set (_unityFileExt_CXX ".cxx") - set (_prefixFileExt_C ".h") - set (_prefixFileExt_CXX ".hxx") - set (_prefixSourceFileExt_C ".c") - set (_prefixSourceFileExt_CXX ".cxx") -endmacro() - -function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") - cotire_get_intermediate_dir(_baseDir) - set (_unityFile "${_baseDir}/${_unityFileName}") - set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) - if (COTIRE_DEBUG) - message(STATUS "${_unityFile}") - endif() -endfunction() - -function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - cotire_get_intermediate_dir(_baseDir) - set (_startIndex 0) - set (_index 0) - set (_unityFiles "") - set (_sourceFiles ${ARGN}) - foreach (_sourceFile ${_sourceFiles}) - get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) - math (EXPR _unityFileCount "${_index} - ${_startIndex}") - if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) - if (_index GREATER 0) - # start new unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (_startIndex ${_index}) - endif() - math (EXPR _index "${_index} + 1") - endforeach() - list (LENGTH _sourceFiles _numberOfSources) - if (_startIndex EQUAL 0) - # there is only a single unity file - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) - elseif (_startIndex LESS _numberOfSources) - # end with final unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) - if (COTIRE_DEBUG) - message(STATUS "${_unityFiles}") - endif() -endfunction() - -function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_prefixFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") - string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") - set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) -endfunction() - -function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _prefixSourceFileExt_${_language}) - set (${_prefixSourceFileVar} "" PARENT_SCOPE) - return() - endif() - string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") - set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) - cotire_setup_file_extension_variables() - if (NOT _language) - set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") - elseif (DEFINED _prefixFileExt_${_language}) - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") - else() - set (_prefixFileBaseName "") - set (_prefixFileName "") - endif() - set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) - set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_path _language _target _prefixFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_prefixFileVar} "" PARENT_SCOPE) - if (_prefixFileName) - if (NOT _language) - set (_language "C") - endif() - if (MSVC OR CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel") - cotire_get_intermediate_dir(_baseDir) - set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) - endif() - endif() -endfunction() - -function (cotire_make_pch_file_path _language _targetSourceDir _target _pchFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_pchFileVar} "" PARENT_SCOPE) - if (_prefixFileBaseName AND _prefixFileName) - cotire_check_precompiled_header_support("${_language}" "${_targetSourceDir}" "${_target}" _msg) - if (NOT _msg) - if (XCODE) - # For Xcode, we completely hand off the compilation of the prefix header to the IDE - return() - endif() - cotire_get_intermediate_dir(_baseDir) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # MSVC uses the extension .pch added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel uses the extension .pchi added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -function (cotire_select_unity_source_files _unityFile _sourcesVar) - set (_sourceFiles ${ARGN}) - if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") - set (_startIndex ${CMAKE_MATCH_1}) - set (_endIndex ${CMAKE_MATCH_2}) - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _startIndex LESS _numberOfSources) - math (EXPR _startIndex "${_numberOfSources} - 1") - endif() - if (NOT _endIndex LESS _numberOfSources) - math (EXPR _endIndex "${_numberOfSources} - 1") - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${_endIndex}) - list (GET _sourceFiles ${_index} _file) - list (APPEND _files "${_file}") - endforeach() - else() - set (_files ${_sourceFiles}) - endif() - set (${_sourcesVar} ${_files} PARENT_SCOPE) -endfunction() - -function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target's generated source files - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${ARGN}) - if (_generatedSources) - # but omit all generated source files that have the COTIRE_EXCLUDED property set to true - cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) - if (_excludedGeneratedSources) - list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) - endif() - # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly - cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) - if (_excludedNonDependencySources) - list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) - endif() - if (_generatedSources) - list (APPEND _dependencySources ${_generatedSources}) - endif() - endif() - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} unity source depends on ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) - # depend on target source files marked with custom COTIRE_DEPENDENCY property - set (_dependencySources "") - cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GCC and clang raise a fatal error if a file is not found during preprocessing - # thus we depend on target's generated source files for prefix header generation - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${ARGN}) - if (_generatedSources) - list (APPEND _dependencySources ${_generatedSources}) - endif() - endif() - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} prefix header DEPENDS ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_generate_target_script _language _configurations _targetSourceDir _targetBinaryDir _target _targetScriptVar _targetConfigScriptVar) - set (COTIRE_TARGET_SOURCES ${ARGN}) - cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${COTIRE_TARGET_SOURCES}) - cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${COTIRE_TARGET_SOURCES}) - # set up variables to be configured - set (COTIRE_TARGET_LANGUAGE "${_language}") - cotire_determine_compiler_version("${COTIRE_TARGET_LANGUAGE}" COTIRE_${_language}_COMPILER) - get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) - get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) - get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) - get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) - get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${COTIRE_TARGET_SOURCES}) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${COTIRE_TARGET_SOURCES}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" COTIRE_INCLUDE_SYSTEM_FLAG) - set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - cotire_get_target_include_directories( - "${_config}" "${_language}" "${_targetSourceDir}" "${_targetBinaryDir}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) - cotire_get_target_compile_definitions( - "${_config}" "${_language}" "${_targetSourceDir}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) - cotire_get_target_compiler_flags( - "${_config}" "${_language}" "${_targetSourceDir}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) - cotire_get_source_files_compile_definitions( - "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${COTIRE_TARGET_SOURCES}) - endforeach() - get_cmake_property(_vars VARIABLES) - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") - # remove COTIRE_VERBOSE which is passed as a CMake define on command line - list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) - set (_contents "") - set (_contentsHasGeneratorExpressions FALSE) - foreach (_var IN LISTS _matchVars ITEMS - MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES - CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 - CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - if (DEFINED ${_var}) - string (REPLACE "\"" "\\\"" _value "${${_var}}") - set (_contents "${_contents}set (${_var} \"${_value}\")\n") - if (NOT _contentsHasGeneratorExpressions) - if ("${_value}" MATCHES "\\$<.*>") - set (_contentsHasGeneratorExpressions TRUE) - endif() - endif() - endif() - endforeach() - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") - cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) - if (_contentsHasGeneratorExpressions) - # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time - if (NOT CMAKE_VERSION VERSION_LESS "2.8.12") - # the file(GENERATE ...) command requires cmake 2.8.12 or later - set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") - set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") - file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") - else() - message (WARNING "cotire: generator expression used in target ${_target}. This requires CMake 2.8.12 or later.") - set (_targetCotireConfigScript "${_targetCotireScript}") - endif() - else() - set (_targetCotireConfigScript "${_targetCotireScript}") - endif() - set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) - set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) -endfunction() - -function (cotire_setup_pch_file_compilation _language _target _targetSourceDir _targetScript _prefixFile _pchFile) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # for Visual Studio and Intel, we attach the precompiled header compilation to the first source file - # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion - if (_sourceFiles) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - list (GET _sourceFiles 0 _hostFile) - set (_flags "") - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - cotire_add_pch_compilation_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) - set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") - # make first source file depend on prefix header - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") - # mark first source file as cotired to prevent it from being used in another cotired target - set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") - # for makefile based generator, we add a custom command to precompile the prefix header - if (_targetScript) - cotire_set_cmd_to_prologue(_cmds) - list (GET _sourceFiles 0 _hostFile) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") - file (RELATIVE_PATH _pchFileRelPath "${CMAKE_BINARY_DIR}" "${_pchFile}") - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") - endif() - set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) - add_custom_command( - OUTPUT "${_pchFile}" - COMMAND ${_cmds} - DEPENDS "${_prefixFile}" - IMPLICIT_DEPENDS ${_language} "${_prefixFile}" - WORKING_DIRECTORY "${_targetSourceDir}" - COMMENT "Building ${_language} precompiled header ${_pchFileRelPath}" VERBATIM) - endif() - endif() -endfunction() - -function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # for Visual Studio and Intel, we include the precompiled header in all but the first source file - # the first source file does the precompiled header compilation, see cotire_setup_pch_file_compilation - list (LENGTH _sourceFiles _numberOfSourceFiles) - if (_numberOfSourceFiles GREATER 1) - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - list (REMOVE_AT _sourceFiles 0) - set (_flags "") - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # make source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") - if (NOT _wholeTarget) - # for makefile based generator, we force the inclusion of the prefix header for a subset - # of the source files, if this is a multi-language target or has excluded files - set (_flags "") - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - endif() - # make source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() -endfunction() - -function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) - set (_sourceFiles ${ARGN}) - # force the inclusion of the prefix header for the given source files - set (_flags "") - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - # make source files depend on prefix header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") -endfunction() - -function (cotire_get_first_set_property_value _propertyValueVar _type _object) - set (_properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) - return() - endif() - endforeach() - set (${_propertyValueVar} "" PARENT_SCOPE) -endfunction() - -function (cotire_setup_combine_command _language _sourceDir _targetScript _joinedFile _cmdsVar) - set (_files ${ARGN}) - set (_filesPaths "") - foreach (_file ${_files}) - if (IS_ABSOLUTE "${_file}") - set (_filePath "${_file}") - else() - get_filename_component(_filePath "${_sourceDir}/${_file}" ABSOLUTE) - endif() - file (RELATIVE_PATH _fileRelPath "${_sourceDir}" "${_filePath}") - if (NOT IS_ABSOLUTE "${_fileRelPath}" AND NOT "${_fileRelPath}" MATCHES "^\\.\\.") - list (APPEND _filesPaths "${_fileRelPath}") - else() - list (APPEND _filesPaths "${_filePath}") - endif() - endforeach() - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") - if (_targetScript) - list (APPEND _prefixCmd "${_targetScript}") - endif() - list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") - endif() - set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) - file (RELATIVE_PATH _joinedFileRelPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") - get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) - get_filename_component(_joinedFileExt "${_joinedFile}" EXT) - if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") - set (_comment "Generating ${_language} unity source ${_joinedFileRelPath}") - elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") - if (_joinedFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_joinedFileRelPath}") - else() - set (_comment "Generating ${_language} prefix header ${_joinedFileRelPath}") - endif() - else() - set (_comment "Generating ${_joinedFileRelPath}") - endif() - add_custom_command( - OUTPUT "${_joinedFile}" - COMMAND ${_prefixCmd} - DEPENDS ${_files} - COMMENT "${_comment}" - WORKING_DIRECTORY "${_sourceDir}" VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_target_pch_usage _languages _targetSourceDir _target _wholeTarget) - if (XCODE) - # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers - # if necessary, we also generate a single prefix header which includes all language specific prefix headers - set (_prefixFiles "") - foreach (_language ${_languages}) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - list (APPEND _prefixFiles "${_prefixFile}") - endif() - endforeach() - set (_cmds ${ARGN}) - list (LENGTH _prefixFiles _numberOfPrefixFiles) - if (_numberOfPrefixFiles GREATER 1) - cotire_make_prefix_file_path("" ${_target} _prefixHeader) - cotire_setup_combine_command("" "${_targetSourceDir}" "" "${_prefixHeader}" _cmds ${_prefixFiles}) - else() - set (_prefixHeader "${_prefixFiles}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") - endif() - add_custom_command(TARGET "${_target}" - PRE_BUILD ${_cmds} - WORKING_DIRECTORY "${_targetSourceDir}" - COMMENT "Updating target ${_target} prefix headers" VERBATIM) - # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") - elseif ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") - # for makefile based generator, we force inclusion of the prefix header for all target source files - # if this is a single-language target without any excluded files - if (_wholeTarget) - set (_language "${_languages}") - # for Visual Studio and Intel, precompiled header inclusion is always done on the source file level - # see cotire_setup_pch_file_inclusion - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) - set (_flags "") - cotire_determine_compiler_version("${_language}" COTIRE_${_language}_COMPILER) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${COTIRE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property(TARGET ${_target} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - endif() - endif() - endif() -endfunction() - -function (cotire_setup_unity_generation_commands _language _targetSourceDir _target _targetScript _targetConfigScript _unityFiles _cmdsVar) - set (_dependencySources "") - cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) - foreach (_unityFile ${_unityFiles}) - file (RELATIVE_PATH _unityFileRelPath "${CMAKE_BINARY_DIR}" "${_unityFile}") - set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) - # set up compiled unity source dependencies - # this ensures that missing source files are generated before the unity file is compiled - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") - endif() - if (_dependencySources) - set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_dependencySources}) - endif() - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # unity file compilation results in potentially huge object file, thus use /bigobj by default under MSVC and Windows Intel - set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") - endif() - cotire_set_cmd_to_prologue(_unityCmd) - list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_targetScript}") - endif() - add_custom_command( - OUTPUT "${_unityFile}" - COMMAND ${_unityCmd} - DEPENDS "${_targetScript}" - COMMENT "Generating ${_language} unity source ${_unityFileRelPath}" - WORKING_DIRECTORY "${_targetSourceDir}" VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) - endforeach() - list (LENGTH _unityFiles _numberOfUnityFiles) - if (_numberOfUnityFiles GREATER 1) - # create a joint unity file from all unity file segments - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) - cotire_setup_combine_command(${_language} "${_targetSourceDir}" "${_targetConfigScript}" "${_unityFile}" ${_cmdsVar} ${_unityFiles}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_command _language _target _targetSourceDir _targetScript _prefixFile _unityFile _cmdsVar) - set (_sourceFiles ${ARGN}) - set (_dependencySources "") - cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" "${_unityFile}") - set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources}") - endif() - file (RELATIVE_PATH _prefixFileRelPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") - get_filename_component(_prefixFileExt "${_prefixFile}" EXT) - if (_prefixFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_prefixFileRelPath}") - else() - set (_comment "Generating ${_language} prefix header ${_prefixFileRelPath}") - endif() - add_custom_command( - OUTPUT "${_prefixFile}" "${_prefixFile}.log" - COMMAND ${_prefixCmd} - DEPENDS "${_unityFile}" ${_dependencySources} - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_unity_command _language _target _targetSourceDir _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - list (LENGTH _unityFiles _numberOfUnityFiles) - if (_numberOfUnityFiles GREATER 1) - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) - cotire_setup_prefix_generation_command( - ${_language} ${_target} "${_targetSourceDir}" "${_targetScript}" - "${_prefixSourceFile}" "${_unityFile}" ${_cmdsVar} ${_sourceFiles}) - else() - cotire_setup_prefix_generation_command( - ${_language} ${_target} "${_targetSourceDir}" "${_targetScript}" - "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) - endif() - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - cotire_setup_combine_command(${_language} "${_targetSourceDir}" "${_targetScript}" "${_prefixFile}" ${_cmdsVar} ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_provided_command _language _target _targetSourceDir _targetScript _prefixFile _cmdsVar) - set (_prefixHeaderFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_combine_command(${_language} "${_targetSourceDir}" "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - cotire_setup_combine_command(${_language} "${_targetSourceDir}" "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_init_cotire_target_properties _target) - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") - cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") - if (NOT _isRelative) - set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") - endif() - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) - if (NOT _isSet) - if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") - else() - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") - endif() - endif() -endfunction() - -function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - string (REPLACE ";" " " _languagesStr "${_languages}") - math (EXPR _numberOfExcludedFiles "${ARGC} - 4") - if (_numberOfExcludedFiles EQUAL 0) - set (_excludedStr "") - elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) - string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") - else() - set (_excludedStr "excluding ${_numberOfExcludedFiles} files") - endif() - set (_targetMsg "") - if (NOT _languages) - set (_targetMsg "Target ${_target} cannot be cotired.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH AND NOT _targetAddSCU) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetAddSCU) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") - endif() - else() - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired.") - endif() - endif() - set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) -endfunction() - -function (cotire_choose_target_languages _targetSourceDir _target _targetLanguagesVar) - set (_languages ${ARGN}) - set (_allSourceFiles "") - set (_allExcludedSourceFiles "") - set (_allCotiredSourceFiles "") - set (_targetLanguages "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - set (_disableMsg "") - foreach (_language ${_languages}) - get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) - get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) - if (_prefixHeader OR _unityBuildFile) - message (STATUS "cotire: target ${_target} has already been cotired.") - set (${_targetLanguagesVar} "" PARENT_SCOPE) - return() - endif() - if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$") - cotire_check_precompiled_header_support("${_language}" "${_targetSourceDir}" "${_target}" _disableMsg) - if (_disableMsg) - set (_targetUsePCH FALSE) - endif() - endif() - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _excludedSources OR _cotiredSources) - list (APPEND _targetLanguages ${_language}) - endif() - if (_sourceFiles) - list (APPEND _allSourceFiles ${_sourceFiles}) - endif() - if (_excludedSources) - list (APPEND _allExcludedSourceFiles ${_excludedSources}) - endif() - if (_cotiredSources) - list (APPEND _allCotiredSourceFiles ${_cotiredSources}) - endif() - endforeach() - set (_targetMsgLevel STATUS) - if (NOT _targetLanguages) - string (REPLACE ";" " or " _languagesStr "${_languages}") - set (_disableMsg "No ${_languagesStr} source files.") - set (_targetUsePCH FALSE) - set (_targetAddSCU FALSE) - endif() - if (_targetUsePCH) - list (LENGTH _allSourceFiles _numberOfSources) - if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - set (_disableMsg "Too few applicable sources.") - set (_targetUsePCH FALSE) - elseif (_allCotiredSourceFiles) - cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) - list (REMOVE_DUPLICATES _cotireTargets) - string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") - set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") - set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") - set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") - set (_targetMsgLevel SEND_ERROR) - set (_targetUsePCH FALSE) - elseif (XCODE AND _allExcludedSourceFiles) - # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target - set (_disableMsg "Exclusion of source files not supported for generator Xcode.") - set (_targetUsePCH FALSE) - elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") - # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target - set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") - set (_targetUsePCH FALSE) - endif() - endif() - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) - cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) - if (_targetMsg) - if (NOT DEFINED COTIREMSG_${_target}) - set (COTIREMSG_${_target} "") - endif() - if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR - NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") - # cache message to avoid redundant messages on re-configure - set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") - message (${_targetMsgLevel} "${_targetMsg}") - endif() - endif() - set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) -endfunction() - -function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) - set (_sourceFiles ${ARGN}) - get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") - set (_numberOfThreads "${CMAKE_MATCH_2}") - if (NOT _numberOfThreads) - # use all available cores - ProcessorCount(_numberOfThreads) - endif() - list (LENGTH _sourceFiles _numberOfSources) - math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") - # a unity source segment must not contain less than COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES files - if (_maxIncludes LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - set (_maxIncludes ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - endif() - elseif (NOT _maxIncludes MATCHES "[0-9]+") - set (_maxIncludes 0) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_target} unity source max includes = ${_maxIncludes}") - endif() - set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) -endfunction() - -function (cotire_process_target_language _language _configurations _targetSourceDir _targetBinaryDir _target _wholeTargetVar _cmdsVar) - set (${_cmdsVar} "" PARENT_SCOPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (NOT _sourceFiles AND NOT _cotiredSources) - return() - endif() - set (_wholeTarget ${${_wholeTargetVar}}) - set (_cmds "") - # check for user provided unity source file list - get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) - if (NOT _unitySourceFiles) - set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) - endif() - cotire_generate_target_script( - ${_language} "${_configurations}" "${_targetSourceDir}" "${_targetBinaryDir}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) - cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) - cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) - if (NOT _unityFiles) - return() - endif() - cotire_setup_unity_generation_commands( - ${_language} "${_targetSourceDir}" ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) - cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) - if (_prefixFile) - # check for user provided prefix header files - get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - if (_prefixHeaderFiles) - cotire_setup_prefix_generation_from_provided_command( - ${_language} ${_target} "${_targetSourceDir}" "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) - else() - cotire_setup_prefix_generation_from_unity_command( - ${_language} ${_target} "${_targetSourceDir}" "${_targetConfigScript}" "${_prefixFile}" "${_unityFiles}" _cmds ${_unitySourceFiles}) - endif() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - if (_targetUsePCH) - cotire_make_pch_file_path(${_language} "${_targetSourceDir}" ${_target} _pchFile) - if (_pchFile) - cotire_setup_pch_file_compilation( - ${_language} ${_target} "${_targetSourceDir}" "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - if (_excludedSources) - set (_wholeTarget FALSE) - endif() - cotire_setup_pch_file_inclusion( - ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - endif() - elseif (_prefixHeaderFiles) - # user provided prefix header must be included - cotire_setup_prefix_file_inclusion( - ${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) - endif() - endif() - # mark target as cotired for language - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") - if (_prefixFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") - if (_targetUsePCH AND _pchFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") - endif() - endif() - set (${_wholeTargetVar} ${_wholeTarget} PARENT_SCOPE) - set (${_cmdsVar} ${_cmds} PARENT_SCOPE) -endfunction() - -function (cotire_setup_clean_target _target) - set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") - if (NOT TARGET "${_cleanTargetName}") - cotire_set_cmd_to_prologue(_cmds) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") - add_custom_target(${_cleanTargetName} COMMAND ${_cmds} WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up target ${_target} cotire generated files" VERBATIM) - cotire_init_target("${_cleanTargetName}") - endif() -endfunction() - -function (cotire_setup_pch_target _languages _configurations _target) - if ("${CMAKE_GENERATOR}" MATCHES "Makefiles|Ninja") - # for makefile based generators, we add a custom target to trigger the generation of the cotire related files - set (_dependsFiles "") - foreach (_language ${_languages}) - set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # Visual Studio and Intel only create precompiled header as a side effect - list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) - endif() - cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) - if (_dependsFile) - list (APPEND _dependsFiles "${_dependsFile}") - endif() - endforeach() - if (_dependsFiles) - set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") - add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) - cotire_init_target("${_pchTargetName}") - cotire_add_to_pch_all_target(${_pchTargetName}) - endif() - else() - # for other generators, we add the "clean all" target to clean up the precompiled header - cotire_setup_clean_all_target() - endif() -endfunction() - -function (cotire_setup_unity_build_target _languages _configurations _targetSourceDir _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (NOT _unityTargetName) - set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") - endif() - # determine unity target sub type - get_target_property(_targetType ${_target} TYPE) - if ("${_targetType}" STREQUAL "EXECUTABLE") - set (_unityTargetSubType "") - elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (_unityTargetSubType "${CMAKE_MATCH_1}") - else() - message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") - return() - endif() - # determine unity target sources - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_unityTargetSources ${_targetSourceFiles}) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - # remove source files that are included in the unity source - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _cotiredSources) - list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) - endif() - # if cotire is applied to a target which has not been added in the current source dir, - # non-existing files cannot be referenced from the unity build target (this is a CMake restriction) - if (NOT "${_targetSourceDir}" STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}") - set (_nonExistingFiles "") - foreach (_file ${_unityTargetSources}) - if (NOT EXISTS "${_file}") - list (APPEND _nonExistingFiles "${_file}") - endif() - endforeach() - if (_nonExistingFiles) - if (COTIRE_VERBOSE) - message (STATUS "removing non-existing ${_nonExistingFiles} from ${_unityTargetName}") - endif() - list (REMOVE_ITEM _unityTargetSources ${_nonExistingFiles}) - endif() - endif() - # add unity source files instead - list (APPEND _unityTargetSources ${_unityFiles}) - endif() - endforeach() - if (COTIRE_DEBUG) - message (STATUS "add ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") - endif() - # generate unity target - if ("${_targetType}" STREQUAL "EXECUTABLE") - add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - else() - add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - endif() - set (_outputDirProperties - ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ - LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ - RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) - # copy output location properties - if (COTIRE_UNITY_OUTPUT_DIRECTORY) - set (_setDefaultOutputDir TRUE) - if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - else() - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) - cotire_resolve_config_properties("${_configurations}" _properties ${_outputDirProperties}) - foreach (_property ${_properties}) - get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) - if (_outputDir) - get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") - set (_setDefaultOutputDir FALSE) - endif() - endforeach() - if (_setDefaultOutputDir) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - endif() - endif() - if (_setDefaultOutputDir) - set_target_properties(${_unityTargetName} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" - LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" - RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") - endif() - else() - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) - endif() - # copy output name - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ - LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ - OUTPUT_NAME OUTPUT_NAME_ - RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ - PREFIX _POSTFIX SUFFIX) - # copy compile stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ - COMPILE_FLAGS COMPILE_OPTIONS - Fortran_FORMAT Fortran_MODULE_DIRECTORY - INCLUDE_DIRECTORIES - INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ - POSITION_INDEPENDENT_CODE - C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN) - # copy interface stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING - INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES - INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES - INTERFACE_AUTOUIC_OPTIONS) - # copy link stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUILD_WITH_INSTALL_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH - LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED - LINK_FLAGS LINK_FLAGS_ - LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ - LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ - LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC - STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ - NO_SONAME SOVERSION VERSION) - # copy Qt stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - AUTOMOC AUTOMOC_MOC_OPTIONS AUTOUIC AUTOUIC_OPTIONS AUTORCC AUTORCC_OPTIONS - AUTOGEN_TARGET_DEPENDS) - # copy cmake stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) - # copy Apple platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUNDLE BUNDLE_EXTENSION FRAMEWORK INSTALL_NAME_DIR MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST - MACOSX_RPATH OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE) - # copy Windows platform specific stuff - cotire_copy_set_properties("${_configurations}" TARGET ${_target} ${_unityTargetName} - GNUtoMS - PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ - VS_DOTNET_REFERENCES VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_KEYWORD - VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER - VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES WIN32_EXECUTABLE) - # use output name from original target - get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) - if (NOT _targetOutputName) - set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") - endif() - # use export symbol from original target - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") - if ("${_targetType}" STREQUAL "EXECUTABLE") - set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) - endif() - endif() - cotire_init_target(${_unityTargetName}) - cotire_add_to_unity_all_target(${_unityTargetName}) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") -endfunction(cotire_setup_unity_build_target) - -function (cotire_target _target) - set(_options "") - set(_oneValueArgs SOURCE_DIR BINARY_DIR) - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_SOURCE_DIR) - set (_option_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - if (NOT _option_BINARY_DIR) - set (_option_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") - endif() - if (NOT _option_LANGUAGES) - get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) - endif() - if (NOT _option_CONFIGURATIONS) - if (CMAKE_CONFIGURATION_TYPES) - set (_option_CONFIGURATIONS ${CMAKE_CONFIGURATION_TYPES}) - elseif (CMAKE_BUILD_TYPE) - set (_option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}") - else() - set (_option_CONFIGURATIONS "None") - endif() - endif() - # trivial checks - get_target_property(_imported ${_target} IMPORTED) - if (_imported) - message (WARNING "cotire: imported target ${_target} cannot be cotired.") - return() - endif() - # resolve alias - get_target_property(_aliasName ${_target} ALIASED_TARGET) - if (_aliasName) - if (COTIRE_DEBUG) - message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") - endif() - set (_target ${_aliasName}) - endif() - # check if target needs to be cotired for build type - # when using configuration types, the test is performed at build time - cotire_init_cotire_target_properties(${_target}) - if (NOT CMAKE_CONFIGURATION_TYPES) - if (CMAKE_BUILD_TYPE) - list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) - else() - list (FIND _option_CONFIGURATIONS "None" _index) - endif() - if (_index EQUAL -1) - if (COTIRE_DEBUG) - message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") - endif() - return() - endif() - endif() - # choose languages that apply to the target - cotire_choose_target_languages("${_option_SOURCE_DIR}" "${_target}" _targetLanguages ${_option_LANGUAGES}) - if (NOT _targetLanguages) - return() - endif() - list (LENGTH _targetLanguages _numberOfLanguages) - if (_numberOfLanguages GREATER 1) - set (_wholeTarget FALSE) - else() - set (_wholeTarget TRUE) - endif() - set (_cmds "") - foreach (_language ${_targetLanguages}) - cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" - "${_option_SOURCE_DIR}" "${_option_BINARY_DIR}" ${_target} _wholeTarget _cmd) - if (_cmd) - list (APPEND _cmds ${_cmd}) - endif() - endforeach() - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - if (_targetAddSCU) - cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" "${_option_SOURCE_DIR}" ${_target}) - endif() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - if (_targetUsePCH) - cotire_setup_target_pch_usage("${_targetLanguages}" "${_option_SOURCE_DIR}" ${_target} ${_wholeTarget} ${_cmds}) - cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - endif() - get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) - if (_targetAddCleanTarget) - cotire_setup_clean_target(${_target}) - endif() -endfunction(cotire_target) - -function (cotire_map_libraries _strategy _mappedLibrariesVar) - set (_mappedLibraries "") - foreach (_library ${ARGN}) - if (TARGET "${_library}" AND "${_strategy}" MATCHES "COPY_UNITY") - get_target_property(_libraryUnityTargetName ${_library} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_libraryUnityTargetName}") - list (APPEND _mappedLibraries "${_libraryUnityTargetName}") - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - endforeach() - list (REMOVE_DUPLICATES _mappedLibraries) - set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_target_link_libraries _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_unityTargetName}") - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") - endif() - if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") - if (CMAKE_VERSION VERSION_LESS "2.8.11") - message (WARNING "cotire: unity target link strategy ${_linkLibrariesStrategy} requires CMake 2.8.11 or later. Defaulting to NONE for ${_target}.") - else() - get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) - get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries} ${_interfaceLinkLibraries}) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} libraries: ${_unityLinkLibraries}") - endif() - if (_unityLinkLibraries) - target_link_libraries(${_unityTargetName} ${_unityLinkLibraries}) - endif() - endif() - endif() - endif() -endfunction(cotire_target_link_libraries) - -function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) - if (_targetName) - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") - else() - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") - endif() - # filter files in intermediate directory - set (_filesToRemove "") - foreach (_file ${_cotireFiles}) - get_filename_component(_dir "${_file}" PATH) - get_filename_component(_dirName "${_dir}" NAME) - if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") - list (APPEND _filesToRemove "${_file}") - endif() - endforeach() - if (_filesToRemove) - if (COTIRE_VERBOSE) - message (STATUS "removing ${_filesToRemove}") - endif() - file (REMOVE ${_filesToRemove}) - endif() -endfunction() - -function (cotire_init_target _targetName) - if (COTIRE_TARGETS_FOLDER) - set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") - endif() - if (MSVC_IDE) - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) - endif() -endfunction() - -function (cotire_add_to_pch_all_target _pchTargetName) - set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_pchTargetName}) -endfunction() - -function (cotire_add_to_unity_all_target _unityTargetName) - set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_unityTargetName}) -endfunction() - -function (cotire_setup_clean_all_target) - set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") - add_custom_target(${_targetName} COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" COMMENT "Cleaning up all cotire generated files" VERBATIM) - cotire_init_target("${_targetName}") - endif() -endfunction() - -function (cotire) - set(_options "") - set(_oneValueArgs SOURCE_DIR BINARY_DIR) - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_targets ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_SOURCE_DIR) - set (_option_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - if (NOT _option_BINARY_DIR) - set (_option_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}") - endif() - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS} - SOURCE_DIR "${_option_SOURCE_DIR}" BINARY_DIR "${_option_BINARY_DIR}") - else() - message (WARNING "cotire: ${_target} is not a target.") - endif() - endforeach() - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target_link_libraries(${_target}) - endif() - endforeach() -endfunction() - -if (CMAKE_SCRIPT_MODE_FILE) - - # cotire is being run in script mode - # locate -P on command args - set (COTIRE_ARGC -1) - foreach (_index RANGE ${CMAKE_ARGC}) - if (COTIRE_ARGC GREATER -1) - set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") - math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") - elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") - set (COTIRE_ARGC 0) - endif() - endforeach() - - # include target script if available - if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") - # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) - include("${COTIRE_ARGV2}") - endif() - - if (COTIRE_DEBUG) - message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") - endif() - - if (WIN32) - # for MSVC, compiler IDs may not always be set correctly - if (MSVC) - set (CMAKE_C_COMPILER_ID "MSVC") - set (CMAKE_CXX_COMPILER_ID "MSVC") - endif() - endif() - - if (NOT COTIRE_BUILD_TYPE) - set (COTIRE_BUILD_TYPE "None") - endif() - string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) - # check if target has been cotired for actual build type COTIRE_BUILD_TYPE - list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) - if (_index GREATER -1) - set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) - else() - if (COTIRE_DEBUG) - message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") - endif() - set (_sources "") - set (_sourcesDefinitions "") - endif() - set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) - set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) - set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) - set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) - - if ("${COTIRE_ARGV1}" STREQUAL "unity") - - cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) - cotire_generate_unity_source( - "${COTIRE_ARGV3}" ${_sources} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - DEPENDS "${COTIRE_ARGV0}" "${COTIRE_ARGV2}" - SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} - PRE_UNDEFS ${_targetPreUndefs} - POST_UNDEFS ${_targetPostUndefs} - SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} - SOURCES_POST_UNDEFS ${_sourcesPostUndefs}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") - - set (_files "") - foreach (_index RANGE 4 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_generate_prefix_header( - "${COTIRE_ARGV3}" ${_files} - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${COTIRE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - DEPENDS "${COTIRE_ARGV0}" "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS} - IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" - INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} - IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" - INCLUDE_SYSTEM_FLAG "${COTIRE_INCLUDE_SYSTEM_FLAG}" - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") - - set (_files "") - foreach (_index RANGE 5 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_precompile_prefix_header( - "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${COTIRE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - INCLUDE_SYSTEM_FLAG "${COTIRE_INCLUDE_SYSTEM_FLAG}" - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "combine") - - if (COTIRE_TARGET_LANGUAGE) - set (_startIndex 3) - else() - set (_startIndex 2) - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - if (COTIRE_TARGET_LANGUAGE) - cotire_generate_unity_source(${_files} LANGUAGE "${COTIRE_TARGET_LANGUAGE}") - else() - cotire_generate_unity_source(${_files}) - endif() - - elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") - - cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") - - else() - message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") - endif() - -else() - - # cotire is being run in include mode - # set up all variable and property definitions - - unset (COTIRE_C_COMPILER_VERSION CACHE) - unset (COTIRE_CXX_COMPILER_VERSION CACHE) - - if (NOT DEFINED COTIRE_DEBUG_INIT) - if (DEFINED COTIRE_DEBUG) - set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) - else() - set (COTIRE_DEBUG_INIT FALSE) - endif() - endif() - option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) - - if (NOT DEFINED COTIRE_VERBOSE_INIT) - if (DEFINED COTIRE_VERBOSE) - set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) - else() - set (COTIRE_VERBOSE_INIT FALSE) - endif() - endif() - option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING - "Ignore headers with the listed file extensions from the generated prefix header.") - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING - "Ignore headers from these directories when generating the prefix header.") - - set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING - "Ignore sources with the listed file extensions from the generated unity source.") - - set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "3" CACHE STRING - "Minimum number of sources in target required to enable use of precompiled header.") - - if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) - if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) - elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") - # enable parallelization for generators that run multiple jobs by default - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") - else() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") - endif() - endif() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING - "Maximum number of source files to include in a single unity source file.") - - if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) - set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") - endif() - if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) - set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") - endif() - if (NOT COTIRE_INTDIR) - set (COTIRE_INTDIR "cotire") - endif() - if (NOT COTIRE_PCH_ALL_TARGET_NAME) - set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") - endif() - if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) - set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") - endif() - if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) - set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") - endif() - if (NOT COTIRE_CLEAN_TARGET_SUFFIX) - set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") - endif() - if (NOT COTIRE_PCH_TARGET_SUFFIX) - set (COTIRE_PCH_TARGET_SUFFIX "_pch") - endif() - if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) - set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") - endif() - if (NOT DEFINED COTIRE_TARGETS_FOLDER) - set (COTIRE_TARGETS_FOLDER "cotire") - endif() - if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) - if ("${CMAKE_GENERATOR}" MATCHES "Ninja") - # generated Ninja build files do not work if the unity target produces the same output file as the cotired target - set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") - else() - set (COTIRE_UNITY_OUTPUT_DIRECTORY "") - endif() - endif() - - # define cotire cache variables - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of include directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "If not defined, defaults to empty list." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" - BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a header file extension matches one in the list, it will be excluded from the generated prefix header." - "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." - "If not defined, defaults to inc;inl;ipp." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" - BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a source file extension matches one in the list, it will be excluded from the generated unity source file." - "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." - "If not defined, defaults to m;mm." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" - BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." - FULL_DOCS - "The variable can be set to an integer > 0." - "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." - "If not defined, defaults to 3." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer >= 0." - "If 0, cotire will only create a single unity source file." - "If a target contains more than that number of source files, cotire will create multiple unity source files for it." - "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." - "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." - "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." - ) - - # define cotire directory properties - - define_property( - DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" - BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." - FULL_DOCS - "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" - BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_UNITY_BUILD." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" - BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_CLEAN." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" - BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." - FULL_DOCS - "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." - ) - - # define cotire target properties - - define_property( - TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED - BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." - FULL_DOCS - "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." - "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." - "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." - "The target name will be set to this target's name with the suffix _pch appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED - BRIEF_DOCS "Add a new target that performs a unity build for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." - "Most of the relevant target properties will be copied from this target to the new unity build target." - "Target dependencies and linked libraries have to be manually set up for the new unity build target." - "The unity target name will be set to this target's name with the suffix _unity appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED - BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." - "The clean target name will be set to this target's name with the suffix _clean_cotire appended." - "Inherited from directory." - "Defaults to FALSE." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "Inherited from directory." - "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." - "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," - "the option which yields the closer relative path match wins." - "Inherited from directory." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer > 0." - "If a target contains more than that number of source files, cotire will create multiple unity build files for it." - "If not set, cotire will only create a single unity source file." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" - BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will only add the given file(s) to the generated unity source file." - "If not set, cotire will add all the target source files to the generated unity source file." - "The property can be set to a user provided unity source file." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" - BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will add the given header file(s) to the generated prefix header file." - "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." - "The property can be set to a user provided prefix header file (e.g., stdafx.h)." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED - BRIEF_DOCS "Define strategy for setting up unity target's link libraries." - FULL_DOCS - "If this property is empty, the generated unity target's link libraries have to be set up manually." - "If this property is set to COPY, the unity target's link libraries will be copied from this target." - "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE" - BRIEF_DOCS "Read-only property. The generated unity source file(s)." - FULL_DOCS - "cotire sets this property to the path of the generated single computation unit source file for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER" - BRIEF_DOCS "Read-only property. The generated prefix header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language prefix header for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" - BRIEF_DOCS "Read-only property. The generated precompiled header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language precompiled header binary for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" - BRIEF_DOCS "The name of the generated unity build target corresponding to this target." - FULL_DOCS - "This property can be set to the desired name of the unity target that will be created by cotire." - "If not set, the unity target name will be set to this target's name with the suffix _unity appended." - "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." - "Defaults to empty string." - ) - - # define cotire source properties - - define_property( - SOURCE PROPERTY "COTIRE_EXCLUDED" - BRIEF_DOCS "Do not modify source file's build command." - FULL_DOCS - "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." - "The source file will also be excluded from the generated unity source file." - "Source files that have their COMPILE_FLAGS property set will be excluded by default." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_DEPENDENCY" - BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." - FULL_DOCS - "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." - "If the file is modified, cotire will re-generate the prefix header source upon build." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" - BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." - FULL_DOCS - "If this property is set to TRUE, cotire will complete the current unity file and start a new one." - "The new unity source file will include this source file as the first one." - "This property essentially works as a separator for unity source files." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_TARGET" - BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." - FULL_DOCS - "cotire sets this property to the name of target, that the source file's build command has been altered for." - "Defaults to empty string." - ) - - message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") - -endif() \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index b5738e26bef7d4..b58d38bbe43cd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,10 +3,6 @@ cmake_minimum_required(VERSION 3.18 FATAL_ERROR) set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# This needs to be done before any languages are enabled or -# projects are created. -INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/CMake/VisualStudioToolset.cmake") - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # includes @@ -22,10 +18,6 @@ PROJECT(hhvm C CXX ASM) include(HHVMProject) -if (MSVC) - enable_language(ASM_MASM) -endif() - MARK_AS_ADVANCED(CLEAR CMAKE_INSTALL_PREFIX) IF(APPLE) # CMake really likes finding libraries inside OS X frameworks. This can @@ -69,7 +61,6 @@ SET(HPHP_HOME ${CMAKE_CURRENT_SOURCE_DIR}) SET(TP_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third-party") SET(TP_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/third-party") -include(MSVCDefaults) include(Options) include(HPHPCompiler) include(HPHPFindLibs) diff --git a/build/deps/github_hashes/facebook/fbthrift-rev.txt b/build/deps/github_hashes/facebook/fbthrift-rev.txt index 9ea59532ca8cfd..85c1090d39de22 100644 --- a/build/deps/github_hashes/facebook/fbthrift-rev.txt +++ b/build/deps/github_hashes/facebook/fbthrift-rev.txt @@ -1 +1 @@ -Subproject commit 66c709f77e3b43068060de5602f5f8bb648a374e +Subproject commit 1d131510c870e669ae9ac8cf21830d8988427f90 diff --git a/build/deps/github_hashes/facebook/folly-rev.txt b/build/deps/github_hashes/facebook/folly-rev.txt index 7a03734ec5b476..3a3a82d3bdd291 100644 --- a/build/deps/github_hashes/facebook/folly-rev.txt +++ b/build/deps/github_hashes/facebook/folly-rev.txt @@ -1 +1 @@ -Subproject commit df842d4d121b37bb88ba955cdf0ca61e641ef65a +Subproject commit 70bb0b7ddcd689ea41db294dec238879febaee0c diff --git a/build/deps/github_hashes/facebook/mvfst-rev.txt b/build/deps/github_hashes/facebook/mvfst-rev.txt index 457aaea3b8db1b..920bcb317d5571 100644 --- a/build/deps/github_hashes/facebook/mvfst-rev.txt +++ b/build/deps/github_hashes/facebook/mvfst-rev.txt @@ -1 +1 @@ -Subproject commit deae0f7d8e22169e0a5521499b806e2d9efca65d +Subproject commit dbd1fc69303410eb91d5a6ee633a043d62497bef diff --git a/build/deps/github_hashes/facebook/wangle-rev.txt b/build/deps/github_hashes/facebook/wangle-rev.txt index 465495972545a0..4475943c9626fa 100644 --- a/build/deps/github_hashes/facebook/wangle-rev.txt +++ b/build/deps/github_hashes/facebook/wangle-rev.txt @@ -1 +1 @@ -Subproject commit f970eec3a663cf1986974f85a4e255730b121c00 +Subproject commit 75142caf7393511c035d58e1007745299e2e2305 diff --git a/build/deps/github_hashes/facebookincubator/fizz-rev.txt b/build/deps/github_hashes/facebookincubator/fizz-rev.txt index febf86dbad8ec2..175edc98cbd173 100644 --- a/build/deps/github_hashes/facebookincubator/fizz-rev.txt +++ b/build/deps/github_hashes/facebookincubator/fizz-rev.txt @@ -1 +1 @@ -Subproject commit 0f403c2f6de14be64b2fe718678c1a287f955d64 +Subproject commit 00b4adb195ecd9f53b125fffa6d7b285eb09edac diff --git a/build/fbcode_builder/getdeps.py b/build/fbcode_builder/getdeps.py index 32ae483ec35898..d6131356c0900b 100755 --- a/build/fbcode_builder/getdeps.py +++ b/build/fbcode_builder/getdeps.py @@ -940,6 +940,7 @@ def run_project_cmd(self, args, loader, manifest): test_filter=args.filter, retry=args.retry, no_testpilot=args.no_testpilot, + timeout=args.timeout, ) def setup_project_cmd_parser(self, parser): @@ -957,6 +958,12 @@ def setup_project_cmd_parser(self, parser): help="Do not use Test Pilot even when available", action="store_true", ) + parser.add_argument( + "--timeout", + type=int, + default=None, + help="Timeout in seconds for each individual test", + ) @cmd( diff --git a/build/fbcode_builder/getdeps/builder.py b/build/fbcode_builder/getdeps/builder.py index 95bc591b7597c0..73da36cfad8f5e 100644 --- a/build/fbcode_builder/getdeps/builder.py +++ b/build/fbcode_builder/getdeps/builder.py @@ -238,7 +238,9 @@ def num_jobs(self) -> int: ) ) - def run_tests(self, schedule_type, owner, test_filter, retry, no_testpilot) -> None: + def run_tests( + self, schedule_type, owner, test_filter, retry, no_testpilot, timeout=None + ) -> None: """Execute any tests that we know how to run. If they fail, raise an exception.""" pass @@ -343,7 +345,9 @@ def _build(self, reconfigure) -> None: for file in glob.glob(srcpattern): shutil.copy(file, libdir) - def run_tests(self, schedule_type, owner, test_filter, retry, no_testpilot) -> None: + def run_tests( + self, schedule_type, owner, test_filter, retry, no_testpilot, timeout=None + ) -> None: if not self.test_args: return @@ -358,6 +362,9 @@ def run_tests(self, schedule_type, owner, test_filter, retry, no_testpilot) -> N else: env["GETDEPS_TEST_RETRY"] = 0 + if timeout is not None: + env["GETDEPS_TEST_TIMEOUT"] = str(timeout) + cmd = ( [self._make_binary, "-j%s" % self.num_jobs] + self.test_args @@ -919,7 +926,7 @@ def _build(self, reconfigure: bool) -> None: ) def run_tests( - self, schedule_type, owner, test_filter, retry: int, no_testpilot + self, schedule_type, owner, test_filter, retry: int, no_testpilot, timeout=None ) -> None: env = self._compute_env() ctest = path_search(env, "ctest") @@ -1066,6 +1073,9 @@ def list_tests(): if run_id is not None: testpilot_args += ["--run-id", run_id] + if timeout is not None: + testpilot_args += ["--timeout", str(timeout)] + if test_filter: testpilot_args += ["--", test_filter] @@ -1126,6 +1136,8 @@ def list_tests(): ] if test_filter: args += ["-R", test_filter] + if timeout is not None: + args += ["--timeout", str(timeout)] count = 0 retcode = -1 @@ -1421,7 +1433,9 @@ def _build(self, reconfigure) -> None: with open(os.path.join(self.inst_dir, ".built-by-getdeps"), "w") as f: f.write("built") - def run_tests(self, schedule_type, owner, test_filter, retry, no_testpilot) -> None: + def run_tests( + self, schedule_type, owner, test_filter, retry, no_testpilot, timeout=None + ) -> None: # setup.py actually no longer has a standard command for running tests. # Instead we let manifest files specify an arbitrary Python file to run # as a test. diff --git a/build/fbcode_builder/getdeps/cargo.py b/build/fbcode_builder/getdeps/cargo.py index 2f87d65088c724..fa788c15d79bb3 100644 --- a/build/fbcode_builder/getdeps/cargo.py +++ b/build/fbcode_builder/getdeps/cargo.py @@ -203,7 +203,9 @@ def _build(self, reconfigure) -> None: build_source_dir, os.path.join(self.inst_dir, "source") ) - def run_tests(self, schedule_type, owner, test_filter, retry, no_testpilot) -> None: + def run_tests( + self, schedule_type, owner, test_filter, retry, no_testpilot, timeout=None + ) -> None: if test_filter: args = ["--", test_filter] else: diff --git a/ci/bin/make-debianish-package b/ci/bin/make-debianish-package index caf60b799a2773..eb3dbb8c02d929 100755 --- a/ci/bin/make-debianish-package +++ b/ci/bin/make-debianish-package @@ -34,9 +34,23 @@ OUT=${OUT:-/var/out} mkdir -p "$OUT" # Environment set up -apt-get -o Acquire::Retries=3 update -y -apt-get clean -apt-get -o Acquire::Retries=3 install -y devscripts equivs +apt update -y && apt install -y devscripts equivs git wget lsb-release software-properties-common gpg clang clang-${CLANG_VERSION} libc++-${CLANG_VERSION}-dev libc++abi-${CLANG_VERSION}-dev + +# Making LLVM the default compiler +if [ -f /etc/alternatives/cc ] +then + update-alternatives --remove-all cc +fi + +if [ -f /etc/alternatives/c++ ] +then + update-alternatives --remove-all c++ +fi + +update-alternatives --install /usr/bin/cc cc /usr/bin/clang++-${CLANG_VERSION} 500 +update-alternatives --set cc /usr/bin/clang++-${CLANG_VERSION} +update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${CLANG_VERSION} 500 +update-alternatives --set c++ /usr/bin/clang++-${CLANG_VERSION} # Copy the debian directory to the root of the git repo # so that all the devscripts command work. @@ -57,8 +71,7 @@ dch --create -v "${FULL_VERSION}" --package "${PKGBASE}" --controlmaint --distri # Build debian package that depends on build-depends, and install it mk-build-deps -dpkg -i --force-depends "$BUILD_DEPS" -apt-get -o Acquire::Retries=3 install -y -f +apt-get -o Acquire::Retries=3 install -y ./"$BUILD_DEPS" mv "$BUILD_DEPS" "$OUT" # Build the actual debian packages @@ -67,7 +80,7 @@ if [ -x "$PREBUILD" ]; then #shellcheck disable=SC1090 source $PREBUILD fi -debuild -us -uc +debuild --no-lintian -us -uc cd .. FILES=$(awk '/^Files:/ { files=1; next } /^[^ ]/ { files=0; next } files==1 { print $NF }' ./*.changes) diff --git a/ci/ubuntu-20.04-focal/DISTRIBUTION b/ci/ubuntu-20.04-focal/DISTRIBUTION deleted file mode 100644 index 037d3d33e19161..00000000000000 --- a/ci/ubuntu-20.04-focal/DISTRIBUTION +++ /dev/null @@ -1 +0,0 @@ -focal diff --git a/ci/ubuntu-20.04-focal/PKGVER b/ci/ubuntu-20.04-focal/PKGVER deleted file mode 100644 index a76b84049d42b9..00000000000000 --- a/ci/ubuntu-20.04-focal/PKGVER +++ /dev/null @@ -1 +0,0 @@ -1~focal diff --git a/ci/ubuntu-24.04-noble/DISTRIBUTION b/ci/ubuntu-24.04-noble/DISTRIBUTION new file mode 100644 index 00000000000000..465786fba6f71b --- /dev/null +++ b/ci/ubuntu-24.04-noble/DISTRIBUTION @@ -0,0 +1 @@ +noble diff --git a/ci/ubuntu-24.04-noble/PKGVER b/ci/ubuntu-24.04-noble/PKGVER new file mode 100644 index 00000000000000..a75f79b8bac1df --- /dev/null +++ b/ci/ubuntu-24.04-noble/PKGVER @@ -0,0 +1 @@ +1~noble diff --git a/ci/ubuntu-20.04-focal/debian/compat b/ci/ubuntu-24.04-noble/debian/compat similarity index 100% rename from ci/ubuntu-20.04-focal/debian/compat rename to ci/ubuntu-24.04-noble/debian/compat diff --git a/ci/ubuntu-20.04-focal/debian/conffiles b/ci/ubuntu-24.04-noble/debian/conffiles similarity index 100% rename from ci/ubuntu-20.04-focal/debian/conffiles rename to ci/ubuntu-24.04-noble/debian/conffiles diff --git a/ci/ubuntu-20.04-focal/debian/control b/ci/ubuntu-24.04-noble/debian/control similarity index 93% rename from ci/ubuntu-20.04-focal/debian/control rename to ci/ubuntu-24.04-noble/debian/control index 238f2ad69f1a74..a9978b2b1de734 100644 --- a/ci/ubuntu-20.04-focal/debian/control +++ b/ci/ubuntu-24.04-noble/debian/control @@ -14,16 +14,19 @@ Build-Depends: curl, debhelper (>= 9), flex, - clang-12, + clang-20, gawk, git, gperf, libboost-all-dev, + libbpf-dev, libbz2-dev, + libc-ares-dev, libc-client-dev, libc-client2007e-dev, libcap-dev, libcurl4-openssl-dev, + libdouble-conversion-dev, libdwarf-dev, libedit-dev, libelf-dev, @@ -40,6 +43,8 @@ Build-Depends: libjemalloc-dev, libkrb5-dev, libldap2-dev, + liblmdb-dev, + liblz4-dev, libmagickwand-dev, libmcrypt-dev, libmemcached-dev, @@ -56,6 +61,7 @@ Build-Depends: libtool, libxml2-dev, libxslt1-dev, + libxxhash-dev, libyaml-dev, python3, re2c, diff --git a/ci/ubuntu-20.04-focal/debian/copying b/ci/ubuntu-24.04-noble/debian/copying similarity index 100% rename from ci/ubuntu-20.04-focal/debian/copying rename to ci/ubuntu-24.04-noble/debian/copying diff --git a/ci/ubuntu-20.04-focal/debian/format b/ci/ubuntu-24.04-noble/debian/format similarity index 100% rename from ci/ubuntu-20.04-focal/debian/format rename to ci/ubuntu-24.04-noble/debian/format diff --git a/ci/ubuntu-20.04-focal/debian/hhvm-nightly-dev.install.in b/ci/ubuntu-24.04-noble/debian/hhvm-nightly-dev.install.in similarity index 100% rename from ci/ubuntu-20.04-focal/debian/hhvm-nightly-dev.install.in rename to ci/ubuntu-24.04-noble/debian/hhvm-nightly-dev.install.in diff --git a/ci/ubuntu-20.04-focal/debian/hhvm-nightly.dirs b/ci/ubuntu-24.04-noble/debian/hhvm-nightly.dirs similarity index 100% rename from ci/ubuntu-20.04-focal/debian/hhvm-nightly.dirs rename to ci/ubuntu-24.04-noble/debian/hhvm-nightly.dirs diff --git a/ci/ubuntu-20.04-focal/debian/hhvm-nightly.install.in b/ci/ubuntu-24.04-noble/debian/hhvm-nightly.install.in similarity index 100% rename from ci/ubuntu-20.04-focal/debian/hhvm-nightly.install.in rename to ci/ubuntu-24.04-noble/debian/hhvm-nightly.install.in diff --git a/ci/ubuntu-20.04-focal/debian/postinst.in b/ci/ubuntu-24.04-noble/debian/postinst.in similarity index 100% rename from ci/ubuntu-20.04-focal/debian/postinst.in rename to ci/ubuntu-24.04-noble/debian/postinst.in diff --git a/ci/ubuntu-20.04-focal/debian/postrm b/ci/ubuntu-24.04-noble/debian/postrm similarity index 100% rename from ci/ubuntu-20.04-focal/debian/postrm rename to ci/ubuntu-24.04-noble/debian/postrm diff --git a/ci/ubuntu-20.04-focal/debian/preinst b/ci/ubuntu-24.04-noble/debian/preinst similarity index 100% rename from ci/ubuntu-20.04-focal/debian/preinst rename to ci/ubuntu-24.04-noble/debian/preinst diff --git a/ci/ubuntu-20.04-focal/debian/prerm.in b/ci/ubuntu-24.04-noble/debian/prerm.in similarity index 100% rename from ci/ubuntu-20.04-focal/debian/prerm.in rename to ci/ubuntu-24.04-noble/debian/prerm.in diff --git a/ci/ubuntu-20.04-focal/debian/rules b/ci/ubuntu-24.04-noble/debian/rules similarity index 55% rename from ci/ubuntu-20.04-focal/debian/rules rename to ci/ubuntu-24.04-noble/debian/rules index 52bdafec30d41f..41926fd875d63e 100644 --- a/ci/ubuntu-20.04-focal/debian/rules +++ b/ci/ubuntu-24.04-noble/debian/rules @@ -1,6 +1,10 @@ #!/usr/bin/make -f include /usr/share/dpkg/pkg-info.mk +export DPKG_EXPORT_BUILDFLAGS=1 +export DEB_BUILD_MAINT_OPTIONS=optimize=-lto +include /usr/share/dpkg/buildflags.mk + %: dh $@ --buildsystem=cmake --parallel @@ -9,11 +13,18 @@ override_dh_auto_configure: -Wno-dev \ -DCMAKE_INSTALL_PREFIX=/opt/hhvm/$(DEB_VERSION_UPSTREAM) \ -DMYSQL_UNIX_SOCK_ADDR=/var/run/mysqld/mysqld.sock \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DFORCE_BUNDLED_LZ4=Off \ + -DENABLE_XED=On \ + -DENABLE_EXTENSION_MCRYPT=Off \ + -DENABLE_MCROUTER=On \ + -DENABLE_EXTENSION_IMAGICK=Off + chmod -R 777 obj-x86_64-linux-gnu override_dh_auto_build: - dh_auto_build -- -j1 hack hack_rust_ffi_bridge_targets hhbc_ast_cbindgen hack_dune - dh_auto_build -- -j8 + dh_auto_build --parallel -- bundled_folly + dh_auto_build --no-parallel -- hack hack_rust_ffi_bridge hhbc_ast_cbindgen hack_dune || dh_auto_build --no-parallel -- hack hack_rust_ffi_bridge hhbc_ast_cbindgen hack_dune + dh_auto_build --parallel override_dh_strip: dh_strip --dbg-package=hhvm-nightly-dbg diff --git a/hphp/CMakeLists.txt b/hphp/CMakeLists.txt index cc8b48e371eabe..21866c7ecf8ef6 100644 --- a/hphp/CMakeLists.txt +++ b/hphp/CMakeLists.txt @@ -71,51 +71,6 @@ add_library(hhvm_base_headers INTERFACE) hphp_link(hhvm_base_headers INTERFACE) target_include_directories(hhvm_base_headers INTERFACE ${CMAKE_SOURCE_DIR}) -if (ENABLE_COTIRE) - include(cotire) - FIND_PATH(LIBC_INCLUDE_PATH stdlib.h) - - # Detect the architecture-specific include directory - IF("${CMAKE_LIBRARY_ARCHITECTURE}" STREQUAL "") - # For CentOS/Red Hat where they store it directly in /usr/include - SET(ARCH_INCLUDE_PATH "${LIBC_INCLUDE_PATH}/bits") - ELSE() - FIND_PATH(ARCH_INCLUDE_PATH ${CMAKE_LIBRARY_ARCHITECTURE}) - SET(ARCH_INCLUDE_PATH "${ARCH_INCLUDE_PATH}/${CMAKE_LIBRARY_ARCHITECTURE}") - ENDIF() - - set_property(DIRECTORY - PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH - "${LIBC_INCLUDE_PATH}/stdlib.h" - "${LIBC_INCLUDE_PATH}/string.h" - "${LIBC_INCLUDE_PATH}/ansidecl.h" - "${LIBC_INCLUDE_PATH}/bfd.h" - "${LIBC_INCLUDE_PATH}/libelf.h" - "${LIBC_INCLUDE_PATH}/elf.h" - "${LIBC_INCLUDE_PATH}/gelf.h" - "${LIBC_INCLUDE_PATH}/resolv.h" - "${ARCH_INCLUDE_PATH}" - "${CCLIENT_INCLUDE_PATH}" - "${LIBPNG_INCLUDE_DIRS}/png.h" - "${LDAP_INCLUDE_DIR}/ldap.h" - "${LIBSQLITE3_INCLUDE_DIR}/sqlite3ext.h" - "${CMAKE_SOURCE_DIR}" - "${CMAKE_BINARY_DIR}") - - # XED headers need to be wrapped in extern "C" - if (ENABLE_XED) - if (LibXed_INCLUDE_DIR) - set_property(DIRECTORY - APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH - "${LibXed_INCLUDE_DIR}") - else() - set_property(DIRECTORY - APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH - "${TP_DIR}/xed/xed/build/include/xed") - endif() - endif() -endif() - # Only thing to do directly in tools is install this one script. Tools also has # its own Makefile, so just do it here instead of dealing with moving that all # around. @@ -134,7 +89,6 @@ endif() add_subdirectory(tools/hfsort) add_subdirectory(tools/version) -add_subdirectory(tools/tc-print) add_subdirectory(compiler) add_subdirectory(hack) @@ -144,6 +98,10 @@ add_subdirectory(neo) add_subdirectory(runtime) add_subdirectory(runtime/ext) +# Note: tc-print depends on EXTENSION_SYSTEMLIB_SOURCES being already set +# and therefore should be added after extensions. +add_subdirectory(tools/tc-print) + # The runtime/test binary require GTest and GMock to be installed globally option(RUNTIME_TEST_BIN "Create the HHVM runtime/test binary" OFF) if (RUNTIME_TEST_BIN) diff --git a/hphp/compiler/CMakeLists.txt b/hphp/compiler/CMakeLists.txt index f271ee3a600368..703ab2b063da13 100644 --- a/hphp/compiler/CMakeLists.txt +++ b/hphp/compiler/CMakeLists.txt @@ -33,6 +33,3 @@ add_library(hphp_analysis STATIC ${CXX_SOURCES} ${C_SOURCES} ${HEADER_SOURCES}) auto_source_group("hphp_analysis" "${CMAKE_CURRENT_SOURCE_DIR}" ${CXX_SOURCES} ${C_SOURCES} ${HEADER_SOURCES}) target_link_libraries(hphp_analysis boost hphp_util hphp_system) -if (ENABLE_COTIRE) - cotire(hphp_analysis) -endif() diff --git a/hphp/compiler/compiler-systemlib.cpp b/hphp/compiler/compiler-systemlib.cpp index dca139764159a0..a952a141ea4642 100644 --- a/hphp/compiler/compiler-systemlib.cpp +++ b/hphp/compiler/compiler-systemlib.cpp @@ -16,7 +16,7 @@ #include "hphp/compiler/compiler-systemlib.h" -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/hhvm/process-init.h" @@ -35,7 +35,6 @@ #include "hphp/util/rds-local.h" #include "hphp/util/timer.h" -#include #include #include #include @@ -43,6 +42,7 @@ #include +#include #include using namespace boost::program_options; @@ -151,9 +151,23 @@ int prepareOptions(CompilerOptions &po, int argc, char **argv) { return 0; } +void load_string_file(const std::filesystem::path& path, std::string& content) { + std::ifstream file(path, std::ios_base::binary); + auto file_size = std::filesystem::file_size(path); + + content.resize(static_cast(file_size), '\0'); + file.read(&content[0], static_cast(file_size)); +} + +void save_string_file(const std::filesystem::path& path, const std::string& content) { + std::ofstream file(path, std::ios_base::binary); + file.write(content.data(), static_cast(content.size())); +} + bool compile_systemlib(const std::filesystem::path& path, std::string output_dir, const Extension* extension) { std::string content; - boost::filesystem::load_string_file(path.string(), content); + + load_string_file(path, content); // Create Unit Emitter std::string fname = "/:"+path.filename().string(); @@ -178,7 +192,7 @@ bool compile_systemlib(const std::filesystem::path& path, std::string output_dir BlobEncoder uew_encoder; uew.serde(uew_encoder); - boost::filesystem::save_string_file(output_dir + "/" + path.filename().string() + ".ue", std::string(static_cast(uew_encoder.data()), uew_encoder.size())); + save_string_file(output_dir + "/" + path.filename().string() + ".ue", std::string(static_cast(uew_encoder.data()), uew_encoder.size())); // Create Decls auto const& defaults = RepoOptions::defaultsForSystemlib(); @@ -201,7 +215,7 @@ bool compile_systemlib(const std::filesystem::path& path, std::string output_dir } auto serialized = hackc::decls_holder_to_binary(*decls.decls); - boost::filesystem::save_string_file(output_dir + "/" + path.filename().string() + ".decls", std::string(serialized.begin(), serialized.end())); + save_string_file(output_dir + "/" + path.filename().string() + ".decls", std::string(serialized.begin(), serialized.end())); return true; } @@ -229,7 +243,7 @@ bool process(CompilerOptions &po) { for (auto extension : ExtensionRegistry::getExtensions()) { for (auto file : extension->hackFiles()) { - if (!files.contains(file)) { + if (!files.contains("ext_" + file)) { Logger::Error( "Error while compiling stdlib: %s not found in input files - did you add an extension without any hack files? If so, override hackFiles to return an empty vector.", file.c_str()); } diff --git a/hphp/compiler/compiler.cpp b/hphp/compiler/compiler.cpp index f4679533c6c3d0..565f3b69859cab 100644 --- a/hphp/compiler/compiler.cpp +++ b/hphp/compiler/compiler.cpp @@ -19,7 +19,7 @@ #include "hphp/compiler/option.h" #include "hphp/compiler/package.h" -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/hhbbc/hhbbc.h" #include "hphp/hhbbc/misc.h" diff --git a/hphp/compiler/package.cpp b/hphp/compiler/package.cpp index 57f9c7658c08a1..c915f3ed603b3d 100644 --- a/hphp/compiler/package.cpp +++ b/hphp/compiler/package.cpp @@ -31,7 +31,7 @@ #include "hphp/compiler/decl-provider.h" #include "hphp/compiler/option.h" -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/hhvm/process-init.h" #include "hphp/runtime/base/file-util-defs.h" #include "hphp/runtime/base/file-util.h" diff --git a/hphp/hack/CMakeLists.txt b/hphp/hack/CMakeLists.txt index f8e1c8c24e69f8..99d80848a4ec97 100644 --- a/hphp/hack/CMakeLists.txt +++ b/hphp/hack/CMakeLists.txt @@ -162,9 +162,12 @@ set(NAMING_SPECIAL_NAMES_SRCS "${NAMING_SPECIAL_NAMES_PREFIX}/naming_special_names_ffi_cbindgen.rs" ) -set(FFI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ffi") + +set(FFI_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/ffi") set(FFI_SRCS - "${FFI_PREFIX}/ffi.rs" +# "${FFI_PREFIX}/ffi.rs" + "${FFI_PREFIX}/maybe.rs" + "${FFI_PREFIX}/vector.rs" "${FFI_PREFIX}/ffi_ffi_cbindgen.rs" ) @@ -177,7 +180,7 @@ add_custom_command( ${INVOKE_CARGO} dump-opcodes dump-opcodes --bin dump_opcodes -o "${RUST_OPCODES}" COMMENT "Generating Rust opcode struct for cbindgen to use to generate hhbc-unit.h" - DEPENDS "${OPCODE_DATA}" + DEPENDS opam_setup "${OPCODE_DATA}" ) set(HHBC_AST_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/hackc/hhbc-unit.h") @@ -185,9 +188,10 @@ set(FFI_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/utils/ffi.h") set(NAMING_SPECIAL_NAMES_HEADER "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/naming/naming-special-names.h") set(TYPE_CONSTRAINT_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/type-constraint-flags.h") set(FCALL_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/fcall-args-flags.h") +set(ITER_ARGS_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/iter-args-flags.h") set(HHBC_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/vm/hhbc-shared.h") set(ATTR_HEADER "${CMAKE_SOURCE_DIR}/hphp/runtime/base/attr.h") -set(FFI_EXTRA_HEADER "${CMAKE_SOURCE_DIR}/hphp/hack/src/utils/ffi/ffi_extra.h") +set(FFI_EXTRA_HEADER "${CMAKE_SOURCE_DIR}/hphp/hack/src/hackc/ffi/ffi_extra.h") add_custom_command( OUTPUT ${HHBC_AST_HEADER} @@ -203,9 +207,9 @@ add_custom_command( ${NAMING_SPECIAL_NAMES_SRCS} && ${INVOKE_CARGO} ffi_cbindgen ffi_cbindgen --bin ffi_cbindgen --header "${HHBC_AST_HEADER}" --namespaces "HPHP,hackc,hhbc" - --includes "${FFI_HEADER},${NAMING_SPECIAL_NAMES_HEADER},${TYPE_CONSTRAINT_HEADER},${ATTR_HEADER},${FCALL_HEADER},${HHBC_HEADER}" + --includes "${FFI_HEADER},${NAMING_SPECIAL_NAMES_HEADER},${TYPE_CONSTRAINT_HEADER},${ATTR_HEADER},${FCALL_HEADER},${ITER_ARGS_HEADER},${HHBC_HEADER}" ${HHBC_AST_SRCS} - DEPENDS rustc cargo "${RUST_OPCODES}" + DEPENDS opam_setup rustc cargo "${RUST_OPCODES}" COMMENT "Generating hhbc-unit.h" ) @@ -225,115 +229,83 @@ HHVM_RENDER_CONFIG_SPECIFICATION( OUTPUT_PATH "${CMAKE_BINARY_DIR}/hphp/hack/src/hackc/compile" ) -# Compiling cxx entrypoints for hhvm -# -# Usage: -# build_cxx_bridge( -# name -# DIR directory -# [EXTRA_SRCS src [src ...]] -# [LINK_LIBS lib [lib ...]] -# ) -# -# Where: -# `name` is the target name of the cxx_bridge. -# `directory` is the required directory of the cxx_bridge sources. -# `src` are extra source files to include in the bridge. -# `lib` are extra link libraries to include in the bridge. -# -function(build_cxx_bridge NAME) - cmake_parse_arguments(CXX_BRIDGE "" "DIR" "EXTRA_SRCS;LINK_LIBS" ${ARGN}) +set( + FFI_CRATES + "package_ffi" + "parser_ffi" + "compiler_ffi" + "hdf" + "hhvm_types_ffi" + "hhvm_hhbc_defs_ffi" +) - if ("${CXX_BRIDGE_DIR}" STREQUAL "") - message(FATAL_ERROR "Missing DIR parameter") - endif() - if (NOT "${CXX_BRIDGE_UNPARSED_ARGUMENTS}" STREQUAL "") - message(FATAL_ERROR "Unexpected parameters: ${CXX_BRIDGE_UNPARSED_ARGUMENTS}") - endif() +set(FFI_BRIDGE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/hhvm_ffi") +set(FFI_BRIDGE_BIN "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/hhvm_ffi") +set(RUST_PART_LIB "${RUST_FFI_BUILD_ROOT}/hphp/hack/src/hhvm_ffi/${PROFILE}/${CMAKE_STATIC_LIBRARY_PREFIX}hhvm_ffi${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(FFI_BRIDGE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${CXX_BRIDGE_DIR}") - set(FFI_BRIDGE_BIN "${RUST_FFI_BUILD_ROOT}/hphp/hack/${CXX_BRIDGE_DIR}") - - set(RUST_PART_LIB "${FFI_BRIDGE_BIN}/${PROFILE}/${CMAKE_STATIC_LIBRARY_PREFIX}${NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}") - set(RUST_PART_CXX "${FFI_BRIDGE_BIN}/${NAME}.cpp") - set(RUST_PART_HEADER "${FFI_BRIDGE_BIN}/${NAME}.rs.h") - set(GENERATED "${FFI_BRIDGE_BIN}/cxxbridge/${NAME}/${NAME}") - set(GENERATED_CXXBRIDGE "${FFI_BRIDGE_BIN}/cxxbridge") - - add_custom_command( - OUTPUT - ${RUST_PART_CXX} - ${RUST_PART_HEADER} - ${RUST_PART_LIB} - ${GENERATED_CXXBRIDGE} - COMMAND - ${CMAKE_COMMAND} -E make_directory "${FFI_BRIDGE_BIN}" && - . "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" && - ${INVOKE_CARGO} "${NAME}" "${NAME}" --target-dir "${FFI_BRIDGE_BIN}" && - ${CMAKE_COMMAND} -E copy "${GENERATED}.rs.cc" "${RUST_PART_CXX}" && - ${CMAKE_COMMAND} -E copy "${GENERATED}.rs.h" "${RUST_PART_HEADER}" - WORKING_DIRECTORY ${FFI_BRIDGE_SRC} - DEPENDS rustc cargo "${OPCODE_DATA}" - ) - add_custom_target( - "${NAME}_cxx" - DEPENDS ${RUST_PART_LIB} - ) - add_library("${NAME}" STATIC ${RUST_PART_CXX} ${CXX_BRIDGE_EXTRA_SRCS} ) - add_dependencies(hack_rust_ffi_bridge_targets "${NAME}") - add_library("${NAME}_rust_part" STATIC IMPORTED) - add_dependencies("${NAME}_rust_part" "${NAME}_cxx") - - # Intentionally create link-time cyclic dependency between ${NAME}_rust_part - # and ${NAME} so that CMake will automatically construct the link line so - # that the linker will scan through involved static libraries multiple times. - set_target_properties( - "${NAME}_rust_part" - PROPERTIES - IMPORTED_LOCATION ${RUST_PART_LIB} - IMPORTED_LINK_DEPENDENT_LIBRARIES "${NAME}" - ) - target_link_libraries( - "${NAME}" - PUBLIC - "${NAME}_rust_part" - ${CXX_BRIDGE_LINK_LIBS} - ) - target_include_directories("${NAME}" INTERFACE "${RUST_FFI_BUILD_ROOT}") - target_include_directories("${NAME}" PRIVATE "${GENERATED_CXXBRIDGE}") -endfunction() +foreach(NAME ${FFI_CRATES}) + list(APPEND FFI_CXXBRIDGE_ORIG_SRCS "${FFI_BRIDGE_BIN}/cxxbridge/${NAME}/${NAME}.rs.cc") + list(APPEND FFI_CXXBRIDGE_SRCS "${FFI_BRIDGE_BIN}/${NAME}.rs.cc") + + list(APPEND FFI_CXXBRIDGE_ORIG_HEADERS "${FFI_BRIDGE_BIN}/cxxbridge/${NAME}/${NAME}.rs.h") + list(APPEND FFI_CXXBRIDGE_HEADERS "${FFI_BRIDGE_BIN}/${NAME}.rs.h") +endforeach() -build_cxx_bridge( - package_ffi - DIR "src/package/ffi_bridge" +add_custom_command( + OUTPUT + ${RUST_PART_LIB} ${FFI_CXXBRIDGE_ORIG_SRCS} ${FFI_CXXBRIDGE_ORIG_HEADERS} + COMMAND + ${CMAKE_COMMAND} -E make_directory "${FFI_BRIDGE_BIN}" && + . "${CMAKE_CURRENT_BINARY_DIR}/dev_env_rust_only.sh" && + ${CMAKE_COMMAND} -E env CXX=${CMAKE_CXX_COMPILER} CXXFLAGS=${CMAKE_CXX_FLAGS} ${INVOKE_CARGO} hhvm_ffi hhvm_ffi --target-dir "${FFI_BRIDGE_BIN}" + WORKING_DIRECTORY ${FFI_BRIDGE_SRC} + DEPENDS opam_setup rustc cargo hackc_options "${OPCODE_DATA}" ) -build_cxx_bridge( - parser_ffi - DIR "src/parser/ffi_bridge" + +add_custom_target( + hack_rust_ffi_bridge_rust_build + DEPENDS ${RUST_PART_LIB} ) -build_cxx_bridge( - compiler_ffi - DIR "src/hackc/ffi_bridge" - EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/ffi_bridge/external_decl_provider.cpp" - LINK_LIBS hdf + +add_custom_command( + OUTPUT ${FFI_CXXBRIDGE_HEADERS} ${FFI_CXXBRIDGE_SRCS} + COMMAND + ${CMAKE_COMMAND} -E make_directory "${FFI_BRIDGE_BIN}" && + ${CMAKE_COMMAND} -E copy_if_different ${FFI_CXXBRIDGE_ORIG_HEADERS} ${FFI_BRIDGE_BIN} && + ${CMAKE_COMMAND} -E copy_if_different ${FFI_CXXBRIDGE_ORIG_SRCS} ${FFI_BRIDGE_BIN} + DEPENDS ${FFI_CXXBRIDGE_ORIG_HEADERS} ${FFI_CXXBRIDGE_ORIG_SRCS} ) -build_cxx_bridge( - hdf - DIR "src/utils/hdf" - EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/utils/hdf/hdf-wrap.cpp" - LINK_LIBS folly + +add_custom_target( + hack_rust_ffi_bridge_copy_cxxbridge + DEPENDS ${FFI_CXXBRIDGE_HEADERS} ${FFI_CXXBRIDGE_SRCS} ) -build_cxx_bridge( - hhvm_types_ffi - DIR "src/hackc/hhvm_cxx/hhvm_types" - EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_types/as-base-ffi.cpp" + +add_library(hack_rust_ffi_bridge_rust_part STATIC IMPORTED) +add_dependencies(hack_rust_ffi_bridge_rust_part hack_rust_ffi_bridge_rust_build hack_rust_ffi_bridge_copy_cxxbridge) +set_target_properties( + hack_rust_ffi_bridge_rust_part + PROPERTIES + IMPORTED_LOCATION ${RUST_PART_LIB} + # Intentionally create a link-time cyclic dependency between the Rust library + # and the dependent C++ library so that CMake will automatically construct the link line, + # causing the linker to scan through involved static libraries multiple times. + IMPORTED_LINK_DEPENDENT_LIBRARIES hack_rust_ffi_bridge ) -build_cxx_bridge( - hhvm_hhbc_defs_ffi - DIR "src/hackc/hhvm_cxx/hhvm_hhbc_defs" - EXTRA_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_hhbc_defs/as-hhbc-ffi.cpp" + +add_library( + hack_rust_ffi_bridge + ${FFI_CXXBRIDGE_SRCS} + "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/ffi_bridge/external_decl_provider.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_types/as-base-ffi.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/hackc/hhvm_cxx/hhvm_hhbc_defs/as-hhbc-ffi.cpp" ) +target_link_libraries(hack_rust_ffi_bridge PRIVATE folly hack_rust_ffi_bridge_rust_part) +target_include_directories(hack_rust_ffi_bridge INTERFACE "${RUST_FFI_BUILD_ROOT}") +target_include_directories(hack_rust_ffi_bridge PRIVATE "${FFI_BRIDGE_BIN}/cxxbridge") + + if (NOT LZ4_FOUND) add_dependencies(hack_dune lz4) add_dependencies(hack_dune_debug lz4) diff --git a/hphp/hack/dev_env_rust_only.sh.in b/hphp/hack/dev_env_rust_only.sh.in index 1bc915f88eb104..6d432d5802c1d3 100644 --- a/hphp/hack/dev_env_rust_only.sh.in +++ b/hphp/hack/dev_env_rust_only.sh.in @@ -11,4 +11,6 @@ # . $BUILD_DIR/hphp/hack/dev_env_rust_only.sh . "@CMAKE_CURRENT_BINARY_DIR@/dev_env_common.sh" -# Nothing else to do for rust :) + +# Export OCaml variables, needed by ocamlrep +eval $(opam env) diff --git a/hphp/hack/ocaml_deps_data.sh b/hphp/hack/ocaml_deps_data.sh index 9fbe85bd0eb40e..390f69efb83824 100644 --- a/hphp/hack/ocaml_deps_data.sh +++ b/hphp/hack/ocaml_deps_data.sh @@ -6,21 +6,21 @@ export HACK_OPAM_DEPS=( base.v0.16.3 base64.3.5.0 camlp-streams.5.0.1 - cmdliner.1.1.1 + cmdliner.1.3.0 core_kernel.v0.16.0 core_unix.v0.16.0 dtoa.0.3.2 - dune.3.6.0 + dune.3.20.1 fileutils.0.6.4 fmt.0.9.0 iomux.0.3 - landmarks-ppx.1.4 + landmarks-ppx.1.5 lru.0.3.1 lwt.5.7.0 lwt_log.1.1.2 lwt_ppx.2.1.0 memtrace.0.2.3 - merlin.5.0-502 + merlin.5.3-502 mtime.1.4.0 ocp-indent.1.8.1 ounit2.2.2.6 diff --git a/hphp/hack/scripts/invoke_cargo.sh b/hphp/hack/scripts/invoke_cargo.sh index 84a3b9e620b0e3..1f00e081b3ad74 100755 --- a/hphp/hack/scripts/invoke_cargo.sh +++ b/hphp/hack/scripts/invoke_cargo.sh @@ -54,6 +54,8 @@ BUILD_PARAMS+=(--target-dir "${TARGET_DIR}") BUILD_PARAMS+=(--package "$pkg") BUILD_PARAMS+=("$profile_flags") +export RUSTFLAGS="-A non-local-definitions" + ( # add CARGO_BIN to PATH so that rustc and other tools can be invoked [[ -n "$CARGO_BIN" ]] && PATH="$CARGO_BIN:$PATH"; # note: --manifest-path doesn't work with custom toolchain, so do cd diff --git a/hphp/hack/src/Cargo.lock b/hphp/hack/src/Cargo.lock index 066d67afdef515..7ceddcb9734e6a 100644 --- a/hphp/hack/src/Cargo.lock +++ b/hphp/hack/src/Cargo.lock @@ -1966,6 +1966,7 @@ version = "0.0.0" dependencies = [ "anyhow", "cc", + "clap 4.5.20", "convert_case 0.4.0", "nom 8.0.0", ] @@ -2506,6 +2507,18 @@ dependencies = [ "options", ] +[[package]] +name = "hhvm_ffi" +version = "0.0.0" +dependencies = [ + "compiler_ffi", + "hdf", + "hhvm_hhbc_defs_ffi", + "hhvm_types_ffi", + "package_ffi", + "parser_ffi", +] + [[package]] name = "hhvm_hhbc_defs_ffi" version = "0.0.0" @@ -3419,7 +3432,7 @@ dependencies = [ "bumpalo", "indexmap 2.12.0", "ocamlrep_derive", - "rustc-hash", + "rustc-hash 1.1.0", "serde", ] @@ -4378,7 +4391,13 @@ version = "0.0.0" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" diff --git a/hphp/hack/src/Cargo.toml b/hphp/hack/src/Cargo.toml index 57decf6562cc50..4dae49be2197ac 100644 --- a/hphp/hack/src/Cargo.toml +++ b/hphp/hack/src/Cargo.toml @@ -41,6 +41,7 @@ members = [ "hh_fanout/cargo/hh_fanout_dep_graph_is_subgraph_rust", "hh_fanout/cargo/hh_fanout_dep_graph_stats_rust", "hh_naming_table_builder/cargo/naming_table_builder_ffi", + "hhvm_ffi", "naming", "naming/cargo/elaborate_namespaces", "naming/cargo/naming_attributes", diff --git a/hphp/hack/src/client/dune b/hphp/hack/src/client/dune index c33725fd2581f7..6ff4fdb375cbd1 100644 --- a/hphp/hack/src/client/dune +++ b/hphp/hack/src/client/dune @@ -29,6 +29,7 @@ pos rage redeclarations + sandcastle server server_command_types server_monitor diff --git a/hphp/hack/src/client_and_server/dune b/hphp/hack/src/client_and_server/dune index 23e40a7c04bdd7..4e819b01fa38e5 100644 --- a/hphp/hack/src/client_and_server/dune +++ b/hphp/hack/src/client_and_server/dune @@ -396,6 +396,7 @@ (libraries ci_util client_provider + sandcastle server_config server_notifier) (preprocess diff --git a/hphp/hack/src/hackc/compile/cargo/options/Cargo.toml b/hphp/hack/src/hackc/compile/cargo/options/Cargo.toml index ce0e3f215d5155..93e8e74cb7e75a 100644 --- a/hphp/hack/src/hackc/compile/cargo/options/Cargo.toml +++ b/hphp/hack/src/hackc/compile/cargo/options/Cargo.toml @@ -19,5 +19,6 @@ oxidized = { version = "0.0.0", path = "../../../../oxidized" } serde = { version = "1.0.219", features = ["derive", "rc"] } [build-dependencies] +generate_configs_lib = { version = "0.0.0", path = "../../../../../../tools/configs" } nom = "8" nom-language = "0.1" diff --git a/hphp/hack/src/hackc/ffi_bridge/Cargo.toml b/hphp/hack/src/hackc/ffi_bridge/Cargo.toml index e33bc262e8096b..90cfbff666e9f2 100644 --- a/hphp/hack/src/hackc/ffi_bridge/Cargo.toml +++ b/hphp/hack/src/hackc/ffi_bridge/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" [lib] path = "compiler_ffi.rs" -crate-type = ["lib", "staticlib"] +crate-type = ["rlib"] [dependencies] anyhow = "1.0.98" diff --git a/hphp/hack/src/hackc/ffi_bridge/decl_provider.h b/hphp/hack/src/hackc/ffi_bridge/decl_provider.h index 44a7a2f5c002be..3ede4f832bf6f4 100644 --- a/hphp/hack/src/hackc/ffi_bridge/decl_provider.h +++ b/hphp/hack/src/hackc/ffi_bridge/decl_provider.h @@ -6,7 +6,7 @@ #pragma once #include -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" namespace HPHP { namespace hackc { diff --git a/hphp/hack/src/hackc/hhvm_cxx/hhvm_hhbc_defs/Cargo.toml b/hphp/hack/src/hackc/hhvm_cxx/hhvm_hhbc_defs/Cargo.toml index 13223d31acabdc..f4c56866b21f97 100644 --- a/hphp/hack/src/hackc/hhvm_cxx/hhvm_hhbc_defs/Cargo.toml +++ b/hphp/hack/src/hackc/hhvm_cxx/hhvm_hhbc_defs/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" [lib] path = "hhvm_hhbc_defs_ffi.rs" -crate-type = ["lib", "staticlib"] +crate-type = ["rlib"] [dependencies] cxx = "1.0.119" diff --git a/hphp/hack/src/hackc/hhvm_cxx/hhvm_types/Cargo.toml b/hphp/hack/src/hackc/hhvm_cxx/hhvm_types/Cargo.toml index 82a5a6dfd2e32b..ad52a4f8948158 100644 --- a/hphp/hack/src/hackc/hhvm_cxx/hhvm_types/Cargo.toml +++ b/hphp/hack/src/hackc/hhvm_cxx/hhvm_types/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" [lib] path = "hhvm_types_ffi.rs" -crate-type = ["lib", "staticlib"] +crate-type = ["rlib"] [dependencies] cxx = "1.0.119" diff --git a/hphp/hack/src/hhvm_ffi/Cargo.toml b/hphp/hack/src/hhvm_ffi/Cargo.toml new file mode 100644 index 00000000000000..c4f98995c8c919 --- /dev/null +++ b/hphp/hack/src/hhvm_ffi/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "hhvm_ffi" +version = "0.0.0" +edition = "2021" +repository = "https://github.com/facebook/hhvm" +license = "MIT" + +[lib] +path = "lib.rs" +crate-type = ["staticlib"] + +[dependencies] +hdf = { path = "../utils/hdf" } +compiler_ffi = { path = "../hackc/ffi_bridge" } +package_ffi = { path = "../package/ffi_bridge" } +parser_ffi = { path = "../parser/ffi_bridge" } +hhvm_hhbc_defs_ffi = { path = "../hackc/hhvm_cxx/hhvm_hhbc_defs" } +hhvm_types_ffi = { path = "../hackc/hhvm_cxx/hhvm_types" } diff --git a/hphp/hack/src/hhvm_ffi/lib.rs b/hphp/hack/src/hhvm_ffi/lib.rs new file mode 100644 index 00000000000000..78421b0831ce07 --- /dev/null +++ b/hphp/hack/src/hhvm_ffi/lib.rs @@ -0,0 +1,6 @@ +extern crate hdf; +extern crate compiler_ffi; +extern crate package_ffi; +extern crate parser_ffi; +extern crate hhvm_hhbc_defs_ffi; +extern crate hhvm_types_ffi; diff --git a/hphp/hack/src/ocamlrep_marshal/dune b/hphp/hack/src/ocamlrep_marshal/dune index 3dd5ac45b6fc3e..6b9bc5ed236bb1 100644 --- a/hphp/hack/src/ocamlrep_marshal/dune +++ b/hphp/hack/src/ocamlrep_marshal/dune @@ -11,6 +11,6 @@ (targets libocamlrep_marshal_ffi_bindings.a) (deps (source_tree %{workspace_root}/hack/src)) - (locks cargo) + (locks /cargo) (action (run %{workspace_root}/hack/scripts/invoke_cargo.sh ocamlrep_marshal_ffi_bindings ocamlrep_marshal_ffi_bindings))) diff --git a/hphp/hack/src/parser/ffi_bridge/Cargo.toml b/hphp/hack/src/parser/ffi_bridge/Cargo.toml index 2e4d365f369a4d..dcbc038e7a1442 100644 --- a/hphp/hack/src/parser/ffi_bridge/Cargo.toml +++ b/hphp/hack/src/parser/ffi_bridge/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT" path = "parser_ffi.rs" test = false doctest = false -crate-type = ["lib", "staticlib"] +crate-type = ["rlib"] [dependencies] bumpalo = { version = "3.14.0", features = ["allocator_api", "collections"] } diff --git a/hphp/hack/src/parser/readonly_check.rs b/hphp/hack/src/parser/readonly_check.rs index 416de5d29e9e2d..71ebbeb1dace44 100644 --- a/hphp/hack/src/parser/readonly_check.rs +++ b/hphp/hack/src/parser/readonly_check.rs @@ -201,14 +201,20 @@ fn rty_expr(context: &mut Context, expr: &Expr) -> Rty { } Eif(e) => { // $x ? a : b is readonly if either a or b are readonly - let (_, exp1_opt, exp2) = &**e; + let (cond, exp1_opt, exp2) = &**e; if let Some(exp1) = exp1_opt { match (rty_expr(context, exp1), rty_expr(context, exp2)) { (_, Rty::Readonly) | (Rty::Readonly, _) => Rty::Readonly, (Rty::Mutable, Rty::Mutable) => Rty::Mutable, } } else { - rty_expr(context, exp2) + // Elvis operator: cond ?: exp2 + // Result is cond if truthy, exp2 if falsy + // So readonly if either cond or exp2 is readonly + match (rty_expr(context, cond), rty_expr(context, exp2)) { + (_, Rty::Readonly) | (Rty::Readonly, _) => Rty::Readonly, + (Rty::Mutable, Rty::Mutable) => Rty::Mutable, + } } } Pair(p) => { diff --git a/hphp/hack/src/stubs/declarationsRewriter.ml b/hphp/hack/src/stubs/declarationsRewriter.ml new file mode 100644 index 00000000000000..e0248cd880201b --- /dev/null +++ b/hphp/hack/src/stubs/declarationsRewriter.ml @@ -0,0 +1,3 @@ +let start _ ~file_whose_existence_indicates_hhvm_is_paused:_ = () + +let rename_decls ~rename:_ ~hack_source_code:_ = "" diff --git a/hphp/hack/src/stubs/dune b/hphp/hack/src/stubs/dune index 95775f3be72d5f..a3454452dcb381 100644 --- a/hphp/hack/src/stubs/dune +++ b/hphp/hack/src/stubs/dune @@ -59,11 +59,16 @@ (preprocess (pps lwt_ppx ppx_deriving.std))) - ; this stub file is used by both buck2 and dune -(rule - (target remote_old_decls_ffi.ml) - (action - (copy# ../facebook/remote_old_decls/stubs/remote_old_decls_ffi.ml remote_old_decls_ffi.ml))) +(library + (name state_loader_stubs) + (wrapped false) + (modules saved_state_loader state_loader_futures state_loader_lwt) + (libraries + hg + server_env + typechecker_options) + (preprocess + (pps lwt_ppx ppx_deriving.std))) (library (name remote_old_decls_ffi) @@ -74,12 +79,6 @@ (preprocess (pps lwt_ppx ppx_deriving.std))) -; this stub file is used by both buck2 and dune -(rule - (target hh_distc_ffi.ml) - (action - (copy# ../facebook/hh_distc/check_ffi/stubs/hh_distc_ffi.ml hh_distc_ffi.ml))) - (library (name hh_distc_ffi) (wrapped false) @@ -159,6 +158,21 @@ (preprocess (pps lwt_ppx ppx_deriving.std))) +(library + (name redeclarations) + (wrapped false) + (modules declarationsRewriter)) + +(library + (name linttool) + (wrapped false) + (modules linttool)) + + (library + (name sandcastle_stubs) + (wrapped false) + (modules sandcastle)) + (library (name startup_initializer_stubs) (wrapped false) diff --git a/hphp/hack/src/stubs/hh_distc_ffi.ml b/hphp/hack/src/stubs/hh_distc_ffi.ml new file mode 100644 index 00000000000000..6a5dce0b6bbb7f --- /dev/null +++ b/hphp/hack/src/stubs/hh_distc_ffi.ml @@ -0,0 +1,23 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +type handle + +let spawn ~root:_ ~ss_dir:_ ~hhdg_path:_ ~fanout:_ _ = failwith "start not implemented" + +let join _ = failwith "join_handle not implemented" + +let cancel _ = failwith "cancel not implemented" + +let is_finished _ = failwith "is_finished not implemented" + +let get_fd _ = failwith "get_fd not implemented" + +let get_re_session_id _ = failwith "get_re_session_id not implemented" + +let recv _ = failwith "recv not implemented" diff --git a/hphp/hack/src/stubs/linttool.ml b/hphp/hack/src/stubs/linttool.ml new file mode 100644 index 00000000000000..70d0128ddee24f --- /dev/null +++ b/hphp/hack/src/stubs/linttool.ml @@ -0,0 +1,2 @@ + +let run _ ~severity:_ = () diff --git a/hphp/hack/src/stubs/logging/hackEventLogger.ml b/hphp/hack/src/stubs/logging/hackEventLogger.ml index 2a4cc81588f86e..df837460bcbe46 100644 --- a/hphp/hack/src/stubs/logging/hackEventLogger.ml +++ b/hphp/hack/src/stubs/logging/hackEventLogger.ml @@ -31,6 +31,8 @@ let set_changed_mergebase _ = () let set_hhconfig_version _ = () +let set_mergebase_globalrev _ = () + let set_rollout_group _ = () let set_rollout_flags _ = () @@ -111,7 +113,7 @@ let type_check_dirty ~start_t:_ ~dirty_count:_ ~recheck_count:_ = () let lock_stolen _ = () -let client_init ~init_id:_ ~from:_ ~custom_columns:_ _ = () +let client_init ~init_id:_ ~from:_ ~is_interactive:_ ~custom_columns:_ _ = () let serverless_ide_init ~init_id:_ = () @@ -585,3 +587,15 @@ module Fanouts = struct let log ~changes_cardinal:_ ~fanout_cardinal:_ ~max_class_fanout_cardinal:_ = () end + +module TypingErrors = struct + let log_errors ~type_check_end_id:_ ~data:_ = () +end + +module Diagnostics = struct + let log ~activity_id:_ _ = () +end + +module LogFileErrors = struct + let log _ ~from:_ = () +end diff --git a/hphp/hack/src/stubs/remote_old_decls_ffi.ml b/hphp/hack/src/stubs/remote_old_decls_ffi.ml new file mode 100644 index 00000000000000..d45c6cc989573d --- /dev/null +++ b/hphp/hack/src/stubs/remote_old_decls_ffi.ml @@ -0,0 +1,10 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +let get_decls_via_file_hashes _ _ = + failwith "get_decls_via_file_hashes not implemented" diff --git a/hphp/hack/src/stubs/sandcastle.ml b/hphp/hack/src/stubs/sandcastle.ml new file mode 100644 index 00000000000000..75c448d076d60f --- /dev/null +++ b/hphp/hack/src/stubs/sandcastle.ml @@ -0,0 +1 @@ +let is_sandcastle(): bool = false diff --git a/hphp/hack/src/stubs/sandcastle/dune b/hphp/hack/src/stubs/sandcastle/dune new file mode 100644 index 00000000000000..51d791c38eec74 --- /dev/null +++ b/hphp/hack/src/stubs/sandcastle/dune @@ -0,0 +1,35 @@ +(* -*- tuareg -*- *) + +let library_entry name suffix = + Printf.sprintf +"(library + (name %s) + (wrapped false) + (modules) + (libraries %s_%s))" name name suffix + +let fb_entry name = + library_entry name "fb" + +let stubs_entry name = + library_entry name "stubs" + +let entry is_fb name = + if is_fb then + fb_entry name + else + stubs_entry name + +let () = + (* test presence of fb subfolder *) + let current_dir = Sys.getcwd () in + (* we are in src/stubs/xxx, locate src/utils/facebook *) + let src_dir = Filename.dirname @@ Filename.dirname current_dir in + let utils_dir = Filename.concat src_dir "utils" in + let fb_utils_dir = Filename.concat utils_dir "facebook" in + (* locate src/utils/facebook/dune *) + let fb_dune = Filename.concat fb_utils_dir "dune" in + let is_fb = Sys.file_exists fb_dune in + let lib_name = entry is_fb "sandcastle" in + Jbuild_plugin.V1.send lib_name + diff --git a/hphp/hack/src/stubs/saved_state_loader.ml b/hphp/hack/src/stubs/saved_state_loader.ml index 46cc932b66d3b6..bf35d95efd17b1 100644 --- a/hphp/hack/src/stubs/saved_state_loader.ml +++ b/hphp/hack/src/stubs/saved_state_loader.ml @@ -35,7 +35,9 @@ module Naming_and_dep_table_info = struct naming_table_path: Path.t; naming_sqlite_table_path: Path.t; dep_table_path: Path.t; + compressed_dep_table_path: Path.t; errors_path: Path.t; + warning_hashes_path: Path.t; } type dirty_files = { @@ -44,11 +46,15 @@ module Naming_and_dep_table_info = struct } type additional_info = { - mergebase_global_rev: Hg.global_rev option; + (**mergebase_global_rev: Hg.global_rev option;*) dirty_files_promise: dirty_files Future.t; - saved_state_distance: int option; - saved_state_age: int option; + (** saved_state_distance: int option; + saved_state_age: int option;*) + saved_state_revs_info: ServerEnv.saved_state_revs_info; } + + let additional_info_of_yojson _ : additional_info = failwith "Not implemented" + let yojson_of_additional_info _ = failwith "Not implemented" end module Naming_table_info = struct @@ -80,13 +86,16 @@ include files other than Hack files, so the caller should filter the given list as necessary. *) type changed_files = Relative_path.t list -type ('main_artifacts, 'additional_info) load_result = { - main_artifacts: 'main_artifacts; - additional_info: 'additional_info; +let changed_files_of_yojson _ = failwith "Not implemented" +let yojson_of_changed_files _ = failwith "Not implemented" + +type load_result = { + main_artifacts: Naming_and_dep_table_info.main_artifacts; + additional_info: Naming_and_dep_table_info.additional_info; manifold_path: string; changed_files_according_to_watchman: changed_files; - corresponding_rev: Hg.Rev.t; - mergebase_rev: Hg.Rev.t; +(** corresponding_rev: Hg.Rev.t; + mergebase_rev: Hg.Rev.t;*) is_cached: bool; } diff --git a/hphp/hack/src/stubs/state_loader.mli b/hphp/hack/src/stubs/state_loader.mli new file mode 100644 index 00000000000000..c56c324d0befb8 --- /dev/null +++ b/hphp/hack/src/stubs/state_loader.mli @@ -0,0 +1,74 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +type dirty_files = { + master_changes: Relative_path.t list; + local_changes: Relative_path.t list; +} + +type hot_decls_paths = { + legacy_hot_decls_path: string; + shallow_hot_decls_path: string; +} + +type native_load_result = { + naming_table_path: string; + corresponding_rev: Hg.rev; + mergebase_rev: Hg.global_rev option; + mergebase: Hg.Rev.t option Future.t; + is_cached: bool; + state_distance: int; + deptable_fn: string; + dirty_files: dirty_files Future.t; + hot_decls_paths: hot_decls_paths; + errors_path: string; +} + +type saved_state_handle = { + saved_state_for_rev: Hg.rev; + saved_state_everstore_handle: string; + watchman_mergebase: MonitorUtils.watchman_mergebase option; +} + +type error = unit + +type verbose_error = { + message: string; + stack: Utils.callstack; + auto_retry: bool; + environment: string option; +} +[@@deriving show] + +val error_string_verbose : error -> verbose_error + +val cached_state : + load_64bit:bool -> + ?saved_state_handle:saved_state_handle -> + config_hash:string -> + rev:Hg.rev -> + (Hg.rev * string * MonitorUtils.watchman_mergebase option) option + +val fetch_saved_state : + load_64bit:bool -> + ?cache_limit:int -> + config:State_loader_config.timeouts -> + config_hash:string -> + saved_state_handle -> + (string, error) result Future.t + +val mk_state_future : + config:State_loader_config.timeouts -> + load_64bit:bool -> + ?saved_state_handle:saved_state_handle -> + config_hash:string option -> + ignore_hh_version:bool -> + ignore_hhconfig:bool -> + use_prechecked_files:bool -> + Path.t -> + (native_load_result, error) result Future.t diff --git a/hphp/hack/src/stubs/state_loader_futures.ml b/hphp/hack/src/stubs/state_loader_futures.ml new file mode 100644 index 00000000000000..44d8d24f711928 --- /dev/null +++ b/hphp/hack/src/stubs/state_loader_futures.ml @@ -0,0 +1,30 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +let get_project_metadata + ~progress_callback:_ + ~saved_state_type:_ + ~repo:_ + ~ignore_hh_version:_ + ~opts:_ = + failwith "Not implemented" + +let load ~ssopt:_ ~progress_callback:_ ~watchman_opts:_ ~ignore_hh_version:_ = + Future.of_value (Error "Not implemented") + +let wait_for_finish _ = failwith "Not implemented" + +let wait_for_finish_with_debug_details _ = failwith "Not implemented" + +let download_and_unpack_saved_state_from_manifold + ~ssopt:_ + ~progress_callback:_ + ~manifold_path:_ + ~target_path:_ + ~saved_state_type:_ = + failwith "Not implemented" diff --git a/hphp/hack/src/stubs/state_loader_lwt.ml b/hphp/hack/src/stubs/state_loader_lwt.ml new file mode 100644 index 00000000000000..e7e1914f8307be --- /dev/null +++ b/hphp/hack/src/stubs/state_loader_lwt.ml @@ -0,0 +1,40 @@ +(** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the "hack" directory of this source tree. + * + *) + +let get_project_metadata ~repo:_ ~ignore_hh_version:_ ~opts:_ = + Lwt.return (Error ("Not implemented", Telemetry.create ())) + +let load ~ssopt:_ ~progress_callback:_ ~watchman_opts:_ ~ignore_hh_version:_ = + Lwt.return (Error "Not implemented") + +let load_internal + ~ssopt:_ + ~progress_callback:_ + ~watchman_opts:_ + ~ignore_hh_version:_ + ~saved_state_type:_ = + failwith "Not implemented" + +let prepare_download_dir () = failwith "Not implemented" + +let get_saved_state_target_path ~download_dir:_ ~manifold_path:_ = + failwith "Not implemented" + +let download_and_unpack_saved_state_from_manifold + ~ssopt:_ ~progress_callback:_ ~manifold_path:_ ~target_path:_ = + failwith "Not implemented" + +module FromDisk = struct + type load_result = { + naming_table_path: Path.t; + warning_saved_state_path: Path.t; + files_changed: Saved_state_loader.changed_files; + } + + let load ~project_metadata:_ ~threshold:_ ~root:_ = Error "Not implemented" +end diff --git a/hphp/hack/src/typing/typing_array_access.ml b/hphp/hack/src/typing/typing_array_access.ml index f897e1a338b458..fc8feb70135da8 100644 --- a/hphp/hack/src/typing/typing_array_access.ml +++ b/hphp/hack/src/typing/typing_array_access.ml @@ -784,16 +784,21 @@ let rec array_get | From_alias (_, Some pos) -> pos | _ -> Reason.to_pos r in - Typing_error_utils.add_typing_error - ~env - Typing_error.( - primary - @@ Primary.Undefined_field - { - pos = p; - name = TUtils.get_printable_shape_field_name field; - decl_pos; - }); + (* Don't generate an error under dynamic assumptions because we can implicit upcast to dynamic *) + if + not + (Tast.is_under_dynamic_assumptions env.Typing_env_types.checked) + then + Typing_error_utils.add_typing_error + ~env + Typing_error.( + primary + @@ Primary.Undefined_field + { + pos = p; + name = TUtils.get_printable_shape_field_name field; + decl_pos; + }); (* Even though this is an error, we can produce a sound type for the field *) (env, (s_unknown_value, dflt_arr_res, Ok ty2)) | Some { sft_optional; sft_ty } -> diff --git a/hphp/hack/src/typing/typing_subtype.ml b/hphp/hack/src/typing/typing_subtype.ml index 7c46a5bcbbe3ec..6172663396138e 100644 --- a/hphp/hack/src/typing/typing_subtype.ml +++ b/hphp/hack/src/typing/typing_subtype.ml @@ -6468,7 +6468,7 @@ end = struct } env) in - let do_shape r_sub { s_fields = fdm; s_origin; s_unknown_value = _ } = + let do_shape r_sub { s_fields = fdm; s_origin; s_unknown_value } = let (_, p, _) = can_index.ci_index_expr in match Typing_shapes.tshape_field_name_with_ty_err env can_index.ci_index_expr @@ -6499,18 +6499,23 @@ end = struct | From_alias (_, Some pos) -> pos | _ -> Reason.to_pos r_sub in - invalid - ~fail: - (Some - Typing_error.( - primary - @@ Primary.Undefined_field - { - pos = p; - name = TUtils.get_printable_shape_field_name field; - decl_pos; - })) - env + (* Don't generate an error under dynamic assumptions because we can implicit upcast to dynamic *) + if Tast.is_under_dynamic_assumptions env.Typing_env_types.checked + then + return_val s_unknown_value env + else + invalid + ~fail: + (Some + Typing_error.( + primary + @@ Primary.Undefined_field + { + pos = p; + name = TUtils.get_printable_shape_field_name field; + decl_pos; + })) + env | Some { sft_optional; sft_ty } -> if sft_optional && not can_index.ci_lhs_of_null_coalesce then let declared_field = diff --git a/hphp/hack/src/utils/hdf/Cargo.toml b/hphp/hack/src/utils/hdf/Cargo.toml index 78f5edf0463eb8..f1f55d0c1ca1e2 100644 --- a/hphp/hack/src/utils/hdf/Cargo.toml +++ b/hphp/hack/src/utils/hdf/Cargo.toml @@ -9,7 +9,7 @@ license = "MIT" [lib] path = "lib.rs" -crate-type = ["lib", "staticlib"] +crate-type = ["rlib"] [dependencies] cxx = "1.0.119" diff --git a/hphp/hack/src/utils/ignore/filesToIgnore.stubs.ml b/hphp/hack/src/utils/ignore/filesToIgnore.stubs.ml index 2ece706c29ba12..b376498bc3d8c0 100644 --- a/hphp/hack/src/utils/ignore/filesToIgnore.stubs.ml +++ b/hphp/hack/src/utils/ignore/filesToIgnore.stubs.ml @@ -23,8 +23,6 @@ let svn_dirname = J.strlist ["dirname"; ".svn"] type watch_spec = { include_extensions: string list; include_file_names: string list; - exclude_directories: string list; - exclude_vcs_directories: bool; } let server_watch_spec = @@ -32,8 +30,6 @@ let server_watch_spec = include_extensions = ["php"; "phpt"; "hack"; "hackpartial"; "hck"; "hh"; "hhi"; "xhp"]; include_file_names = [".hhconfig"; "PACKAGES.toml"]; - exclude_directories = ["scripts/build/artifacts/sqlfacts"]; - exclude_vcs_directories = true; } let watchman_server_expression_terms = diff --git a/hphp/hack/src/watchman/dune b/hphp/hack/src/watchman/dune index 3d95cba15dd2ea..a73f37d773c352 100644 --- a/hphp/hack/src/watchman/dune +++ b/hphp/hack/src/watchman/dune @@ -20,7 +20,7 @@ (name watchman_utils) (wrapped false) (modules watchman_utils) - (libraries hh_json logging utils_core) + (libraries hg hh_json logging utils_core) (preprocess (pps lwt_ppx ppx_deriving.std))) diff --git a/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php b/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php new file mode 100644 index 00000000000000..d322b571013549 --- /dev/null +++ b/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php @@ -0,0 +1,21 @@ +> +class C { + const type TC = int; +} + +function get_dyn():dynamic { + return shape('a' => 3); +} + +<<__SupportDynamicType>> +function test_key_exists(C::TC $_):void { + $x = get_dyn(); + if (Shapes::keyExists($x, 'b')) { + $y = $x['a']; + } + if (Shapes::keyExists($x, 'c')) { + $y = $x['a']; + } +} diff --git a/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php.exp b/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php.exp new file mode 100644 index 00000000000000..4269126fcebc19 --- /dev/null +++ b/hphp/hack/test/sound_dynamic/typing/shape_key_exists.good.php.exp @@ -0,0 +1 @@ +No errors diff --git a/hphp/hack/test/typecheck/readonly/elvis.php b/hphp/hack/test/typecheck/readonly/elvis.php new file mode 100644 index 00000000000000..4f7eb5271a4024 --- /dev/null +++ b/hphp/hack/test/typecheck/readonly/elvis.php @@ -0,0 +1,13 @@ +(readonly HH\Lib\Ref $ref): ?T { + return $ref->value ?: null; // expect readonly error +} + +function get_value_from_ref_via_ternary(readonly HH\Lib\Ref $ref): ?T { + return $ref->value ? $ref->value : null; // expect readonly error +} + +function use_value_as_condition(readonly HH\Lib\Ref $ref): ?int { + return $ref->value ? 1 : null; // expect no error +} diff --git a/hphp/hack/test/typecheck/readonly/elvis.php.exp b/hphp/hack/test/typecheck/readonly/elvis.php.exp new file mode 100644 index 00000000000000..d354e30d8d4196 --- /dev/null +++ b/hphp/hack/test/typecheck/readonly/elvis.php.exp @@ -0,0 +1,4 @@ +ERROR: File "elvis.php", line 4, characters 10-28: +This expression is readonly, but we expected a mutable value because this function does not return readonly. Please mark it to return readonly if needed. (Parsing[1002]) +ERROR: File "elvis.php", line 8, characters 10-41: +This expression is readonly, but we expected a mutable value because this function does not return readonly. Please mark it to return readonly if needed. (Parsing[1002]) diff --git a/hphp/hhbbc/CMakeLists.txt b/hphp/hhbbc/CMakeLists.txt index d85e8a6b3b776f..02908ccba1d7dc 100644 --- a/hphp/hhbbc/CMakeLists.txt +++ b/hphp/hhbbc/CMakeLists.txt @@ -15,6 +15,3 @@ add_library(hphp_hhbbc STATIC ${CXX_SOURCES} ${HEADER_SOURCES}) auto_source_group("hphp_hhbbc" "${CMAKE_CURRENT_SOURCE_DIR}" ${CXX_SOURCES} ${HEADER_SOURCES}) target_link_libraries(hphp_hhbbc hphp_system) -if (ENABLE_COTIRE) - cotire(hphp_hhbbc) -endif() diff --git a/hphp/hhbbc/index.cpp b/hphp/hhbbc/index.cpp index 049243025fdf31..b5501f0fb6e194 100644 --- a/hphp/hhbbc/index.cpp +++ b/hphp/hhbbc/index.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -17347,7 +17348,7 @@ void make_class_infos_local( } ); capacities.clear(); - capacities.shrink_to_fit(); + //capacities.shrink_to_fit(); // Different threads can touch the same FuncInfo when adding to the // func family list, so use sharded locking scheme. diff --git a/hphp/hhvm/CMakeLists.txt b/hphp/hhvm/CMakeLists.txt index 46bc48050038bd..996c3396258bcf 100644 --- a/hphp/hhvm/CMakeLists.txt +++ b/hphp/hhvm/CMakeLists.txt @@ -4,11 +4,6 @@ set(CXX_SOURCES) auto_sources(files "*.cpp" "") list(APPEND CXX_SOURCES ${files}) -# Windows targets use a generated rc file for embedding libraries -if(MSVC) - list(APPEND CXX_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/embed.rc) -endif() - option(ENABLE_LD_GOLD "Enable Hot Linker script using ld-gold" On) set(SECTION_ORDERING_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../tools/oss_hot_section_ordering CACHE FILEPATH "File used by ld-gold for the relocation of sections") @@ -64,10 +59,6 @@ if (CMAKE_HOST_UNIX) COMMENT "Creating symlinks for hhvm") endif() -if (ENABLE_COTIRE) - cotire(hhvm) -endif() - HHVM_INSTALL(hhvm bin) auto_sources(files "*.h" "") diff --git a/hphp/neo/CMakeLists.txt b/hphp/neo/CMakeLists.txt index 8161788157c968..cb1caebf73ce51 100644 --- a/hphp/neo/CMakeLists.txt +++ b/hphp/neo/CMakeLists.txt @@ -10,7 +10,3 @@ HHVM_PUBLIC_HEADERS(neo ${files}) add_library(neo STATIC ${C_SOURCES} ${HEADER_SOURCES}) auto_source_group("neo" "${CMAKE_CURRENT_SOURCE_DIR}" ${C_SOURCES} ${HEADER_SOURCES}) - -if (ENABLE_COTIRE) - cotire(neo) -endif() diff --git a/hphp/runtime/CMakeLists.txt b/hphp/runtime/CMakeLists.txt index 55a3af5186ed79..c08c4418df4f01 100644 --- a/hphp/runtime/CMakeLists.txt +++ b/hphp/runtime/CMakeLists.txt @@ -61,7 +61,3 @@ object_library_ld_link_libraries(hphp_runtime_static hphp_util proxygen mvfst vi HHVM_CONFIGURE_TARGET_FOR_EXTENSION_DEPENDENCIES(hphp_runtime_static) HHVM_PUBLIC_HEADERS(runtime ${HEADER_SOURCES}) - -if (ENABLE_COTIRE) - cotire(hphp_runtime_static) -endif() diff --git a/hphp/runtime/base/package.cpp b/hphp/runtime/base/package.cpp index 7135973d30b82a..3f99d5c80ab1bc 100644 --- a/hphp/runtime/base/package.cpp +++ b/hphp/runtime/base/package.cpp @@ -27,7 +27,7 @@ #include #include "hphp/util/rds-local.h" -#include "hphp/hack/src/package/ffi_bridge/package_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/package_ffi.rs.h" #include #include diff --git a/hphp/runtime/base/program-functions.cpp b/hphp/runtime/base/program-functions.cpp index 0cd15bc68839b1..1bf56599d783c1 100644 --- a/hphp/runtime/base/program-functions.cpp +++ b/hphp/runtime/base/program-functions.cpp @@ -1764,7 +1764,7 @@ static int execute_program_impl(int argc, char** argv) { cout << "HipHop VM"; cout << " " << HHVM_VERSION; cout << " (" << (debug ? "dbg" : "rel") << ")"; - cout << " (" << (use_lowptr ? "lowptr" : "non-lowptr") << ")\n"; + cout << " (" << (use_packedptr ? "packedptr" : use_lowptr ? "lowptr" : "non-lowptr") << ")\n"; cout << "Compiler: " << compilerId() << "\n"; cout << "Repo schema: " << repoSchemaId() << "\n"; return 0; @@ -2055,13 +2055,15 @@ static int execute_program_impl(int argc, char** argv) { } #if USE_JEMALLOC - if (Cfg::Server::Mode) { - purge_all(); - setup_auto_arenas({Cfg::Eval::Num1GPagesForA0, Cfg::Eval::Num2MPagesForA0}); - } - if (Cfg::Eval::FileBackedColdArena) { - set_cold_file_dir(Cfg::Eval::ColdArenaFileDir.c_str()); - enable_high_cold_file(); + if constexpr (use_position_dependent_jemalloc_arenas) { + if (Cfg::Server::Mode) { + purge_all(); + setup_auto_arenas({Cfg::Eval::Num1GPagesForA0, Cfg::Eval::Num2MPagesForA0}); + } + if (Cfg::Eval::FileBackedColdArena) { + set_cold_file_dir(Cfg::Eval::ColdArenaFileDir.c_str()); + enable_high_cold_file(); + } } #endif @@ -2991,7 +2993,7 @@ static bool hphp_warmup(ExecutionContext *context, void hphp_session_init(Treadmill::SessionKind session_kind, Transport* transport, - RequestId id, + RequestId id, RequestId root_req_id) { if (id.unallocated()) id = RequestId::allocate(); assertx(!*s_sessionInitialized); diff --git a/hphp/runtime/base/runtime-option.cpp b/hphp/runtime/base/runtime-option.cpp index 7c7d95ebdc50ca..753c471037aa7f 100644 --- a/hphp/runtime/base/runtime-option.cpp +++ b/hphp/runtime/base/runtime-option.cpp @@ -17,7 +17,7 @@ #include "hphp/runtime/base/runtime-option.h" #include "hphp/hack/src/hackc/compile/options_gen.h" -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/runtime/base/autoload-handler.h" #include "hphp/runtime/base/bespoke-array.h" #include "hphp/runtime/base/builtin-functions.h" diff --git a/hphp/runtime/base/runtime-option.h b/hphp/runtime/base/runtime-option.h index a73e9dde908786..4f251f6e1d50dc 100644 --- a/hphp/runtime/base/runtime-option.h +++ b/hphp/runtime/base/runtime-option.h @@ -45,7 +45,7 @@ #include "hphp/util/hash-map.h" #include "hphp/util/sha1.h" -#include "hphp/hack/src/parser/ffi_bridge/parser_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/parser_ffi.rs.h" namespace HPHP { /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/ext/async_mysql/ext_async_mysql.cpp b/hphp/runtime/ext/async_mysql/ext_async_mysql.cpp index cb481d53a6bb82..a9b09382ab3b39 100644 --- a/hphp/runtime/ext/async_mysql/ext_async_mysql.cpp +++ b/hphp/runtime/ext/async_mysql/ext_async_mysql.cpp @@ -326,9 +326,11 @@ static String HHLibSQLQuery__toString__FOR_DEBUGGING_ONLY( val(this_->propRvalAtOffset(s_query_format_idx).tv()).pstr; const auto args = val(this_->propRvalAtOffset(s_query_args_idx).tv()).parr; const auto query = amquery_from_queryf(format, args); - auto mysql = Native::data(conn) - ->m_conn - ->mysql_for_testing_only(); + + auto* data = Native::data(conn); + data->verifyValidConnection(); + + auto mysql = data->m_conn->mysql_for_testing_only(); const auto str = query.render(mysql); return String(str.data(), str.length(), CopyString); } @@ -1244,6 +1246,8 @@ static void HHVM_METHOD(AsyncMysqlConnection, close) { static String HHVM_METHOD(AsyncMysqlConnection, getSslCertCn) { auto* data = Native::data(this_); + data->verifyValidConnection(); + const auto* context = data->m_conn->getConnectionContext(); if (context && context->sslCertCn.hasValue()) { return context->sslCertCn.value(); @@ -1254,6 +1258,8 @@ static String HHVM_METHOD(AsyncMysqlConnection, getSslCertCn) { static Object HHVM_METHOD(AsyncMysqlConnection, getSslCertSan) { auto* data = Native::data(this_); + data->verifyValidConnection(); + auto ret = req::make(); const auto* context = data->m_conn->getConnectionContext(); if (context && context->sslCertSan.hasValue()) { @@ -1266,6 +1272,8 @@ static Object HHVM_METHOD(AsyncMysqlConnection, getSslCertSan) { static Object HHVM_METHOD(AsyncMysqlConnection, getSslCertExtensions) { auto* data = Native::data(this_); + data->verifyValidConnection(); + auto ret = req::make(); const auto* context = data->m_conn->getConnectionContext(); if (context && context->sslCertIdentities.hasValue()) { @@ -1278,6 +1286,8 @@ static Object HHVM_METHOD(AsyncMysqlConnection, getSslCertExtensions) { static bool HHVM_METHOD(AsyncMysqlConnection, isSslCertValidationEnforced) { auto* data = Native::data(this_); + data->verifyValidConnection(); + const auto* context = data->m_conn->getConnectionContext(); return context && context->isServerCertValidated; } diff --git a/hphp/runtime/ext/core/make_systemlib.sh b/hphp/runtime/ext/core/make_systemlib.sh index cb5e628ebc602c..d30e4a8f59d97d 100755 --- a/hphp/runtime/ext/core/make_systemlib.sh +++ b/hphp/runtime/ext/core/make_systemlib.sh @@ -4,7 +4,7 @@ OUTDIR=$1; shift OUTFILE=$1; shift SYSTEMLIB="${OUTDIR}/${OUTFILE}" -mkdir "${OUTDIR}" +mkdir -p "${OUTDIR}" # If we put the line we're generating into this file, then the linter will think # the generator itself is generated. Encode it into a variable for safe diff --git a/hphp/runtime/ext/core/php.txt b/hphp/runtime/ext/core/php.txt index 5db7e0b08292df..ce779111007411 100644 --- a/hphp/runtime/ext/core/php.txt +++ b/hphp/runtime/ext/core/php.txt @@ -6,158 +6,158 @@ # These restrictions may be lifted at some point in the future. # Order matters here. Put parent classes in this list before child classes -hphp/system/php/lang/stdClass.php -hphp/system/php/lang/Closure.php -hphp/system/php/lang/pinitSentinel.php -hphp/system/php/lang/uninitSentinel.php -hphp/system/php/lang/string.php -hphp/system/php/lang/resource.php - -hphp/system/php/lang/AsyncIterator.ns.php -hphp/system/php/lang/AsyncKeyedIterator.ns.php -hphp/system/php/lang/Traversable.ns.php -hphp/system/php/lang/Iterator.ns.php -hphp/system/php/lang/IteratorAggregate.ns.php -hphp/system/php/lang/KeyedIterator.ns.php -hphp/system/php/lang/KeyedIterable.ns.php -hphp/system/php/lang/Throwable.php -hphp/system/php/lang/BaseException.ns.php -hphp/system/php/lang/Error.php -hphp/system/php/lang/Exception.php -hphp/system/php/spl/exceptions/exceptions.php -hphp/system/php/spl/interfaces/Countable.php -hphp/system/php/spl/interfaces/RecursiveIterator.php - -hphp/system/php/lang/Container.ns.php - -hphp/system/php/spl/datastructures/SplHeap.php - -hphp/system/php/spl/file_handling/SplFileInfo.php -hphp/system/php/spl/interfaces/SeekableIterator.php -hphp/system/php/spl/iterators/DirectoryIterator.php -hphp/system/php/spl/iterators/FilesystemIterator.php -hphp/system/php/spl/iterators/GlobIterator.php -hphp/system/php/spl/iterators/RecursiveDirectoryIterator.php -hphp/system/php/spl/file_handling/SplFileObject.php -hphp/system/php/spl/file_handling/SplTempFileObject.php - -hphp/system/php/lang/ArrayAccess.php -hphp/system/php/lang/Serializeable.php -hphp/system/php/spl/datastructures/SplDoublyLinkedList.php -hphp/system/php/spl/datastructures/SplQueue.php -hphp/system/php/spl/datastructures/SplStack.php - -hphp/system/php/spl/interfaces/OuterIterator.php -hphp/system/php/spl/iterators/IteratorIterator.php -hphp/system/php/spl/iterators/FilterIterator.php -hphp/system/php/spl/iterators/RecursiveFilterIterator.php -hphp/system/php/spl/iterators/RegexIterator.php -hphp/system/php/spl/iterators/RecursiveRegexIterator.php - -hphp/system/php/spl/iterators/ArrayIterator.php - -hphp/system/php/filter/filter_var_array.php - -hphp/system/php/date/datetimeinterface.php -hphp/system/php/date/datetimeimmutable.php - -hphp/system/php/collections/collection_interfaces.ns.php -hphp/system/php/collections/LazyConcatIterable.php -hphp/system/php/collections/LazyConcatIterator.php -hphp/system/php/collections/LazyFilterIterable.php -hphp/system/php/collections/LazyFilterIterator.php -hphp/system/php/collections/LazyFilterKeyedIterable.php -hphp/system/php/collections/LazyFilterKeyedIterator.php -hphp/system/php/collections/LazyFilterWithKeyIterable.php -hphp/system/php/collections/LazyFilterWithKeyIterator.php -hphp/system/php/collections/LazyIterable.php -hphp/system/php/collections/LazyIterableView.php -hphp/system/php/collections/LazyKVZipIterable.php -hphp/system/php/collections/LazyKVZipIterator.php -hphp/system/php/collections/LazyKeyedIterable.php -hphp/system/php/collections/LazyKeyedIterableView.php -hphp/system/php/collections/LazyKeysIterable.php -hphp/system/php/collections/LazyKeysIterator.php -hphp/system/php/collections/LazyMapIterable.php -hphp/system/php/collections/LazyMapIterator.php -hphp/system/php/collections/LazyMapKeyedIterable.php -hphp/system/php/collections/LazyMapKeyedIterator.php -hphp/system/php/collections/LazyMapWithKeyIterable.php -hphp/system/php/collections/LazyMapWithKeyIterator.php -hphp/system/php/collections/LazySkipIterable.php -hphp/system/php/collections/LazySkipIterator.php -hphp/system/php/collections/LazySkipKeyedIterable.php -hphp/system/php/collections/LazySkipKeyedIterator.php -hphp/system/php/collections/LazySkipWhileIterable.php -hphp/system/php/collections/LazySkipWhileIterator.php -hphp/system/php/collections/LazySkipWhileKeyedIterable.php -hphp/system/php/collections/LazySkipWhileKeyedIterator.php -hphp/system/php/collections/LazySliceIterable.php -hphp/system/php/collections/LazySliceIterator.php -hphp/system/php/collections/LazySliceKeyedIterable.php -hphp/system/php/collections/LazySliceKeyedIterator.php -hphp/system/php/collections/LazyTakeIterable.php -hphp/system/php/collections/LazyTakeIterator.php -hphp/system/php/collections/LazyTakeKeyedIterable.php -hphp/system/php/collections/LazyTakeKeyedIterator.php -hphp/system/php/collections/LazyTakeWhileIterable.php -hphp/system/php/collections/LazyTakeWhileIterator.php -hphp/system/php/collections/LazyTakeWhileKeyedIterable.php -hphp/system/php/collections/LazyTakeWhileKeyedIterator.php -hphp/system/php/collections/LazyValuesIterable.php -hphp/system/php/collections/LazyValuesIterator.php -hphp/system/php/collections/LazyZipIterable.php -hphp/system/php/collections/LazyZipIterator.php -hphp/system/php/collections/LazyZipKeyedIterable.php -hphp/system/php/collections/LazyZipKeyedIterator.php -hphp/system/php/collections/StrictIterable.php -hphp/system/php/collections/StrictKeyedIterable.php - -hphp/system/php/async/ResultOrExceptionWrapper.ns.php -hphp/system/php/async/WrappedException.ns.php -hphp/system/php/async/WrappedResult.ns.php -hphp/system/php/async/convenience.ns.php - -hphp/system/php/async/vm.ns.php -hphp/system/php/async/maps.ns.php -hphp/system/php/async/vectors.ns.php +hphp/runtime/ext/core/php/lang/stdClass.php +hphp/runtime/ext/core/php/lang/Closure.php +hphp/runtime/ext/core/php/lang/pinitSentinel.php +hphp/runtime/ext/core/php/lang/uninitSentinel.php +hphp/runtime/ext/core/php/lang/string.php +hphp/runtime/ext/core/php/lang/resource.php + +hphp/runtime/ext/core/php/lang/AsyncIterator.ns.php +hphp/runtime/ext/core/php/lang/AsyncKeyedIterator.ns.php +hphp/runtime/ext/core/php/lang/Traversable.ns.php +hphp/runtime/ext/core/php/lang/Iterator.ns.php +hphp/runtime/ext/core/php/lang/IteratorAggregate.ns.php +hphp/runtime/ext/core/php/lang/KeyedIterator.ns.php +hphp/runtime/ext/core/php/lang/KeyedIterable.ns.php +hphp/runtime/ext/core/php/lang/Throwable.php +hphp/runtime/ext/core/php/lang/BaseException.ns.php +hphp/runtime/ext/core/php/lang/Error.php +hphp/runtime/ext/core/php/lang/Exception.php +hphp/runtime/ext/core/php/spl/exceptions/exceptions.php +hphp/runtime/ext/core/php/spl/interfaces/Countable.php +hphp/runtime/ext/core/php/spl/interfaces/RecursiveIterator.php + +hphp/runtime/ext/core/php/lang/Container.ns.php + +hphp/runtime/ext/core/php/spl/datastructures/SplHeap.php + +hphp/runtime/ext/core/php/spl/file_handling/SplFileInfo.php +hphp/runtime/ext/core/php/spl/interfaces/SeekableIterator.php +hphp/runtime/ext/core/php/spl/iterators/DirectoryIterator.php +hphp/runtime/ext/core/php/spl/iterators/FilesystemIterator.php +hphp/runtime/ext/core/php/spl/iterators/GlobIterator.php +hphp/runtime/ext/core/php/spl/iterators/RecursiveDirectoryIterator.php +hphp/runtime/ext/core/php/spl/file_handling/SplFileObject.php +hphp/runtime/ext/core/php/spl/file_handling/SplTempFileObject.php + +hphp/runtime/ext/core/php/lang/ArrayAccess.php +hphp/runtime/ext/core/php/lang/Serializeable.php +hphp/runtime/ext/core/php/spl/datastructures/SplDoublyLinkedList.php +hphp/runtime/ext/core/php/spl/datastructures/SplQueue.php +hphp/runtime/ext/core/php/spl/datastructures/SplStack.php + +hphp/runtime/ext/core/php/spl/interfaces/OuterIterator.php +hphp/runtime/ext/core/php/spl/iterators/IteratorIterator.php +hphp/runtime/ext/core/php/spl/iterators/FilterIterator.php +hphp/runtime/ext/core/php/spl/iterators/RecursiveFilterIterator.php +hphp/runtime/ext/core/php/spl/iterators/RegexIterator.php +hphp/runtime/ext/core/php/spl/iterators/RecursiveRegexIterator.php + +hphp/runtime/ext/core/php/spl/iterators/ArrayIterator.php + +hphp/runtime/ext/core/php/filter/filter_var_array.php + +hphp/runtime/ext/core/php/date/datetimeinterface.php +hphp/runtime/ext/core/php/date/datetimeimmutable.php + +hphp/runtime/ext/core/php/collections/collection_interfaces.ns.php +hphp/runtime/ext/core/php/collections/LazyConcatIterable.php +hphp/runtime/ext/core/php/collections/LazyConcatIterator.php +hphp/runtime/ext/core/php/collections/LazyFilterIterable.php +hphp/runtime/ext/core/php/collections/LazyFilterIterator.php +hphp/runtime/ext/core/php/collections/LazyFilterKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyFilterKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazyFilterWithKeyIterable.php +hphp/runtime/ext/core/php/collections/LazyFilterWithKeyIterator.php +hphp/runtime/ext/core/php/collections/LazyIterable.php +hphp/runtime/ext/core/php/collections/LazyIterableView.php +hphp/runtime/ext/core/php/collections/LazyKVZipIterable.php +hphp/runtime/ext/core/php/collections/LazyKVZipIterator.php +hphp/runtime/ext/core/php/collections/LazyKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyKeyedIterableView.php +hphp/runtime/ext/core/php/collections/LazyKeysIterable.php +hphp/runtime/ext/core/php/collections/LazyKeysIterator.php +hphp/runtime/ext/core/php/collections/LazyMapIterable.php +hphp/runtime/ext/core/php/collections/LazyMapIterator.php +hphp/runtime/ext/core/php/collections/LazyMapKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyMapKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazyMapWithKeyIterable.php +hphp/runtime/ext/core/php/collections/LazyMapWithKeyIterator.php +hphp/runtime/ext/core/php/collections/LazySkipIterable.php +hphp/runtime/ext/core/php/collections/LazySkipIterator.php +hphp/runtime/ext/core/php/collections/LazySkipKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazySkipKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazySkipWhileIterable.php +hphp/runtime/ext/core/php/collections/LazySkipWhileIterator.php +hphp/runtime/ext/core/php/collections/LazySkipWhileKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazySkipWhileKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazySliceIterable.php +hphp/runtime/ext/core/php/collections/LazySliceIterator.php +hphp/runtime/ext/core/php/collections/LazySliceKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazySliceKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazyTakeIterable.php +hphp/runtime/ext/core/php/collections/LazyTakeIterator.php +hphp/runtime/ext/core/php/collections/LazyTakeKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyTakeKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazyTakeWhileIterable.php +hphp/runtime/ext/core/php/collections/LazyTakeWhileIterator.php +hphp/runtime/ext/core/php/collections/LazyTakeWhileKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyTakeWhileKeyedIterator.php +hphp/runtime/ext/core/php/collections/LazyValuesIterable.php +hphp/runtime/ext/core/php/collections/LazyValuesIterator.php +hphp/runtime/ext/core/php/collections/LazyZipIterable.php +hphp/runtime/ext/core/php/collections/LazyZipIterator.php +hphp/runtime/ext/core/php/collections/LazyZipKeyedIterable.php +hphp/runtime/ext/core/php/collections/LazyZipKeyedIterator.php +hphp/runtime/ext/core/php/collections/StrictIterable.php +hphp/runtime/ext/core/php/collections/StrictKeyedIterable.php + +hphp/runtime/ext/core/php/async/ResultOrExceptionWrapper.ns.php +hphp/runtime/ext/core/php/async/WrappedException.ns.php +hphp/runtime/ext/core/php/async/WrappedResult.ns.php +hphp/runtime/ext/core/php/async/convenience.ns.php + +hphp/runtime/ext/core/php/async/vm.ns.php +hphp/runtime/ext/core/php/async/maps.ns.php +hphp/runtime/ext/core/php/async/vectors.ns.php # If you have no inheritance relationship, go here in alphabetical order -hphp/system/php/array_filter.php -hphp/system/php/array_map.php -hphp/system/php/array_reduce.php -hphp/system/php/asio/InvalidOperationException.php -hphp/system/php/async/EntryPoint.ns.php -hphp/system/php/curl/CURLFile.php -hphp/system/php/date/dateperiod.php -hphp/system/php/date/datetime_funcs.php -hphp/system/php/dom/DOMException.php -hphp/system/php/file_system/Directory.php -hphp/system/php/lang/Disposable.php -hphp/system/php/lang/ErrorException.php -hphp/system/php/lang/fun.ns.php -hphp/system/php/lang/invariant.ns.php -hphp/system/php/lang/null.ns.php -hphp/system/php/lang/readonly.ns.php -hphp/system/php/misc/idx.php -hphp/system/php/pdo/PDOException.php -hphp/system/php/rx/mutable.php -hphp/system/php/shapes/ext_shapes.php -hphp/system/php/soap/SoapFault.php -hphp/system/php/spl/datastructures/SplPriorityQueue.php -hphp/system/php/spl/interfaces/SplObserver.php -hphp/system/php/spl/interfaces/SplSubject.php -hphp/system/php/spl/iterators/EmptyIterator.php -hphp/system/php/spl/iterators/InfiniteIterator.php -hphp/system/php/spl/iterators/NoRewindIterator.php -hphp/system/php/spl/iterators/RecursiveIteratorIterator.php -hphp/system/php/experimental_parser_utils.php +hphp/runtime/ext/core/php/array_filter.php +hphp/runtime/ext/core/php/array_map.php +hphp/runtime/ext/core/php/array_reduce.php +hphp/runtime/ext/core/php/asio/InvalidOperationException.php +hphp/runtime/ext/core/php/async/EntryPoint.ns.php +hphp/runtime/ext/core/php/curl/CURLFile.php +hphp/runtime/ext/core/php/date/dateperiod.php +hphp/runtime/ext/core/php/date/datetime_funcs.php +hphp/runtime/ext/core/php/dom/DOMException.php +hphp/runtime/ext/core/php/file_system/Directory.php +hphp/runtime/ext/core/php/lang/Disposable.php +hphp/runtime/ext/core/php/lang/ErrorException.php +hphp/runtime/ext/core/php/lang/fun.ns.php +hphp/runtime/ext/core/php/lang/invariant.ns.php +hphp/runtime/ext/core/php/lang/null.ns.php +hphp/runtime/ext/core/php/lang/readonly.ns.php +hphp/runtime/ext/core/php/misc/idx.php +hphp/runtime/ext/core/php/pdo/PDOException.php +hphp/runtime/ext/core/php/rx/mutable.php +hphp/runtime/ext/core/php/shapes/ext_shapes.php +hphp/runtime/ext/core/php/soap/SoapFault.php +hphp/runtime/ext/core/php/spl/datastructures/SplPriorityQueue.php +hphp/runtime/ext/core/php/spl/interfaces/SplObserver.php +hphp/runtime/ext/core/php/spl/interfaces/SplSubject.php +hphp/runtime/ext/core/php/spl/iterators/EmptyIterator.php +hphp/runtime/ext/core/php/spl/iterators/InfiniteIterator.php +hphp/runtime/ext/core/php/spl/iterators/NoRewindIterator.php +hphp/runtime/ext/core/php/spl/iterators/RecursiveIteratorIterator.php +hphp/runtime/ext/core/php/experimental_parser_utils.php # This provides a temporary workaround for renamed lz4 methods -hphp/system/php/zlib/ext_zlib.php +hphp/runtime/ext/core/php/zlib/ext_zlib.php -hphp/system/php/member_of.ns.php +hphp/runtime/ext/core/php/member_of.ns.php -hphp/system/php/attributes.php +hphp/runtime/ext/core/php/attributes.php -hphp/system/php/password/password.php +hphp/runtime/ext/core/php/password/password.php diff --git a/hphp/runtime/ext/decl/decl-extractor.cpp b/hphp/runtime/ext/decl/decl-extractor.cpp index 25e604f1e1ccdd..98cb4def3393c3 100644 --- a/hphp/runtime/ext/decl/decl-extractor.cpp +++ b/hphp/runtime/ext/decl/decl-extractor.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/runtime/base/stream-wrapper-registry.h" #include "hphp/runtime/base/unit-cache.h" #include "hphp/runtime/ext/decl/decl-extractor.h" diff --git a/hphp/runtime/ext/decl/decl-extractor.h b/hphp/runtime/ext/decl/decl-extractor.h index 4c38e0166bb6c6..71948680ffbaf4 100644 --- a/hphp/runtime/ext/decl/decl-extractor.h +++ b/hphp/runtime/ext/decl/decl-extractor.h @@ -9,7 +9,7 @@ #include #include #include -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/runtime/ext/facts/path-and-hash.h" namespace HPHP { diff --git a/hphp/runtime/ext/facts/file-facts.h b/hphp/runtime/ext/facts/file-facts.h index 6420de3f0e70f9..02ae67b6afbad6 100644 --- a/hphp/runtime/ext/facts/file-facts.h +++ b/hphp/runtime/ext/facts/file-facts.h @@ -24,7 +24,7 @@ #include #include #include -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" namespace HPHP { namespace Facts { diff --git a/hphp/runtime/ext/gd/ext_gd.cpp b/hphp/runtime/ext/gd/ext_gd.cpp index abd1f167bb2d72..3ba2b812e258a7 100644 --- a/hphp/runtime/ext/gd/ext_gd.cpp +++ b/hphp/runtime/ext/gd/ext_gd.cpp @@ -42,7 +42,9 @@ #include #include #include +#ifdef HAVE_LIBHEIF #include +#endif /* Section Filters Declarations */ /* IMPORTANT NOTE FOR NEW FILTER @@ -1509,6 +1511,7 @@ static struct gfxinfo *php_handle_webp(const req::ptr& stream) { return result; } +#ifdef HAVE_LIBHEIF static int64_t heif_get_position(void* userdata) { auto stream = static_cast(userdata); return stream->tell(); @@ -1633,6 +1636,7 @@ static heif_brand2 php_get_heif(const req::ptr& stream) { return heif_read_main_brand(reinterpret_cast( fileType.c_str()), 12); } +#endif /* Convert internal image_type to mime type */ static const char *php_image_type_to_mime_type(int image_type) { @@ -1756,6 +1760,7 @@ static int php_getimagetype(const req::ptr& file) { return IMAGE_FILETYPE_JP2; } +#ifdef HAVE_LIBHEIF /* AFTER ALL ABOVE FAILED */ auto heifBrand = php_get_heif(file); if (heifBrand == heif_brand2_heic || heifBrand == heif_brand2_heix) { @@ -1763,6 +1768,8 @@ static int php_getimagetype(const req::ptr& file) { } else if (heifBrand == heif_brand2_avif) { return IMAGE_FILETYPE_AVIF; } +#endif + if (php_get_wbmp(file, nullptr, 1)) { return IMAGE_FILETYPE_WBMP; } @@ -1930,12 +1937,14 @@ Variant getImageSize(const req::ptr& stream, Array& imageinfo) { case IMAGE_FILETYPE_WEBP: result = php_handle_webp(stream); break; +#ifdef HAVE_LIBHEIF case IMAGE_FILETYPE_AVIF: result = php_handle_heif(stream); break; case IMAGE_FILETYPE_HEIC: result = php_handle_heif(stream); break; +#endif default: case IMAGE_FILETYPE_UNKNOWN: break; diff --git a/hphp/runtime/ext/hash/ext_hash.cpp b/hphp/runtime/ext/hash/ext_hash.cpp index f65d9c98d893f7..3ab429c88f0085 100644 --- a/hphp/runtime/ext/hash/ext_hash.cpp +++ b/hphp/runtime/ext/hash/ext_hash.cpp @@ -37,7 +37,7 @@ #include "hphp/runtime/ext/std/ext_std_file.h" #include "hphp/runtime/ext/string/ext_string.h" #include "hphp/runtime/ext/hash/hash_blake3.h" -#include "hphp/runtime/ext/hash/hash_keyed_blake3.h" +// #include "hphp/runtime/ext/hash/hash_keyed_blake3.h" #include #include @@ -124,7 +124,7 @@ struct HashEngineMapInitializer { HashEngines["sha3-256"] = HashEnginePtr(new hash_keccak( 512, 32)); HashEngines["sha3-384"] = HashEnginePtr(new hash_keccak( 768, 48)); HashEngines["sha3-512"] = HashEnginePtr(new hash_keccak(1024, 64)); - HashEngines["blake3"] = HashEnginePtr(new hash_blake3()); + // HashEngines["blake3"] = HashEnginePtr(new hash_blake3()); #ifndef HPHP_OSS HashEngines["keyed-blake3"] = HashEnginePtr(new hash_keyed_blake3()); #endif diff --git a/hphp/runtime/ext/mcrouter/config.cmake b/hphp/runtime/ext/mcrouter/config.cmake index 6022bb06640fe2..e48dadcc884169 100644 --- a/hphp/runtime/ext/mcrouter/config.cmake +++ b/hphp/runtime/ext/mcrouter/config.cmake @@ -1,4 +1,4 @@ -option(ENABLE_EXTENSION_MCROUTER "Build the imap extension" ${ENABLE_MCROUTER}) +option(ENABLE_EXTENSION_MCROUTER "Build the mcrouter extension" ${ENABLE_MCROUTER}) HHVM_DEFINE_EXTENSION("mcrouter" SOURCES diff --git a/hphp/runtime/ext/mysql/ext_mysql.cpp b/hphp/runtime/ext/mysql/ext_mysql.cpp index 388a67a619783d..04e316ace78cd2 100644 --- a/hphp/runtime/ext/mysql/ext_mysql.cpp +++ b/hphp/runtime/ext/mysql/ext_mysql.cpp @@ -825,7 +825,11 @@ void mysqlExtension::moduleRegisterNative() { HHVM_RC_INT(MYSQL_CLIENT_CR_INSECURE_API_ERR, CR_INSECURE_API_ERR) HHVM_RC_INT(MYSQL_CLIENT_CR_FILE_NAME_TOO_LONG, CR_FILE_NAME_TOO_LONG) HHVM_RC_INT(MYSQL_CLIENT_CR_SSL_FIPS_MODE_ERR, CR_SSL_FIPS_MODE_ERR) +#ifdef CR_DEPRECATED_COMPRESSION_NOT_SUPPORTED HHVM_RC_INT(MYSQL_CLIENT_CR_COMPRESSION_NOT_SUPPORTED, CR_DEPRECATED_COMPRESSION_NOT_SUPPORTED) +#else + HHVM_RC_INT(MYSQL_CLIENT_CR_COMPRESSION_NOT_SUPPORTED, CR_COMPRESSION_NOT_SUPPORTED) +#endif // We can't add the following yet as some builds are not using a new enough MySQL client diff --git a/hphp/runtime/ext/openssl/ext_openssl.cpp b/hphp/runtime/ext/openssl/ext_openssl.cpp index 2de4b207e28435..ada451040a3b69 100644 --- a/hphp/runtime/ext/openssl/ext_openssl.cpp +++ b/hphp/runtime/ext/openssl/ext_openssl.cpp @@ -1977,7 +1977,7 @@ Array HHVM_FUNCTION(openssl_pkey_get_details, const OptResource& key) { case EVP_PKEY_RSA2: { ktype = OPENSSL_KEYTYPE_RSA; - RSA *rsa = EVP_PKEY_get0_RSA(pkey); + auto rsa = EVP_PKEY_get0_RSA(pkey); assertx(rsa); const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; RSA_get0_key(rsa, &n, &e, &d); @@ -2000,7 +2000,7 @@ Array HHVM_FUNCTION(openssl_pkey_get_details, const OptResource& key) { case EVP_PKEY_DSA4: { ktype = OPENSSL_KEYTYPE_DSA; - DSA *dsa = EVP_PKEY_get0_DSA(pkey); + auto dsa = EVP_PKEY_get0_DSA(pkey); assertx(dsa); const BIGNUM *p, *q, *g, *pub_key, *priv_key; DSA_get0_pqg(dsa, &p, &q, &g); @@ -2016,7 +2016,7 @@ Array HHVM_FUNCTION(openssl_pkey_get_details, const OptResource& key) { case EVP_PKEY_DH: { ktype = OPENSSL_KEYTYPE_DH; - DH *dh = EVP_PKEY_get0_DH(pkey); + auto dh = EVP_PKEY_get0_DH(pkey); assertx(dh); const BIGNUM *p, *q, *g, *pub_key, *priv_key; DH_get0_pqg(dh, &p, &q, &g); @@ -2140,11 +2140,17 @@ bool HHVM_FUNCTION(openssl_private_decrypt, const String& data, switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - cryptedlen = RSA_private_decrypt(data.size(), - (unsigned char *)data.data(), - cryptedbuf, - EVP_PKEY_get0_RSA(pkey), - padding); + { + auto rsa = EVP_PKEY_get1_RSA(pkey); + SCOPE_EXIT { + RSA_free(rsa); + }; + cryptedlen = RSA_private_decrypt(data.size(), + (unsigned char *)data.data(), + cryptedbuf, + rsa, + padding); + } if (cryptedlen != -1) { successful = 1; } @@ -2180,11 +2186,17 @@ bool HHVM_FUNCTION(openssl_private_encrypt, const String& data, switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - successful = (RSA_private_encrypt(data.size(), - (unsigned char *)data.data(), - cryptedbuf, - EVP_PKEY_get0_RSA(pkey), - padding) == cryptedlen); + { + auto rsa = EVP_PKEY_get1_RSA(pkey); + SCOPE_EXIT { + RSA_free(rsa); + }; + successful = (RSA_private_encrypt(data.size(), + (unsigned char *)data.data(), + cryptedbuf, + rsa, + padding) == cryptedlen); + } break; default: raise_warning("key type not supported"); @@ -2216,11 +2228,17 @@ bool HHVM_FUNCTION(openssl_public_decrypt, const String& data, switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - cryptedlen = RSA_public_decrypt(data.size(), - (unsigned char *)data.data(), - cryptedbuf, - EVP_PKEY_get0_RSA(pkey), - padding); + { + auto rsa = EVP_PKEY_get1_RSA(pkey); + SCOPE_EXIT { + RSA_free(rsa); + }; + cryptedlen = RSA_public_decrypt(data.size(), + (unsigned char *)data.data(), + cryptedbuf, + rsa, + padding); + } if (cryptedlen != -1) { successful = 1; } @@ -2256,11 +2274,17 @@ bool HHVM_FUNCTION(openssl_public_encrypt, const String& data, switch (EVP_PKEY_id(pkey)) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: - successful = (RSA_public_encrypt(data.size(), - (unsigned char *)data.data(), - cryptedbuf, - EVP_PKEY_get0_RSA(pkey), - padding) == cryptedlen); + { + auto rsa = EVP_PKEY_get1_RSA(pkey); + SCOPE_EXIT { + RSA_free(rsa); + }; + successful = (RSA_public_encrypt(data.size(), + (unsigned char *)data.data(), + cryptedbuf, + rsa, + padding) == cryptedlen); + } break; default: raise_warning("key type not supported"); diff --git a/hphp/runtime/ext/watcher/config.cmake b/hphp/runtime/ext/watcher/config.cmake index 3611da745fbc2d..16cc03cebaafa1 100644 --- a/hphp/runtime/ext/watcher/config.cmake +++ b/hphp/runtime/ext/watcher/config.cmake @@ -1,6 +1,8 @@ -HHVM_DEFINE_EXTENSION("watchman" IMPLICIT +HHVM_DEFINE_EXTENSION("watcher" IMPLICIT SOURCES ext_watcher.cpp + watcher-clock.cpp + watcher-options.cpp SYSTEMLIB ext_watcher.php DEPENDS diff --git a/hphp/runtime/server/transport.h b/hphp/runtime/server/transport.h index 2f81e65107e3ee..91bc64c26d5f11 100644 --- a/hphp/runtime/server/transport.h +++ b/hphp/runtime/server/transport.h @@ -165,7 +165,7 @@ struct Transport : IDebuggable, ITransportHeaders { /** * Request URI. */ - virtual const char *getUrl() = 0; + virtual const char *getUrl() override = 0; virtual const char *getRemoteHost() = 0; virtual uint16_t getRemotePort() = 0; // The transport can override REMOTE_ADDR if it has one @@ -220,7 +220,7 @@ struct Transport : IDebuggable, ITransportHeaders { /** * POST request's data. */ - virtual const void *getPostData(size_t &size) = 0; + virtual const void *getPostData(size_t &size) override = 0; virtual bool hasMorePostData() { return false; } virtual const void *getMorePostData(size_t &size) { size = 0;return nullptr; } virtual bool getFiles(std::string& /*files*/) { return false; } @@ -235,7 +235,7 @@ struct Transport : IDebuggable, ITransportHeaders { /** * Is this a GET, POST or anything? */ - virtual Method getMethod() = 0; + virtual Method getMethod() override = 0; virtual const char *getExtendedMethod() { return nullptr;} const char *getMethodName() override; @@ -394,7 +394,7 @@ struct Transport : IDebuggable, ITransportHeaders { * foo/bar?x=1 command is "foo/bar" * /foo/bar?x=1 command is "foo/bar" */ - std::string getCommand(); + std::string getCommand() override; /** * Get value of a parameter. Returns empty string is not present. diff --git a/hphp/runtime/test/CMakeLists.txt b/hphp/runtime/test/CMakeLists.txt index 6cba69a487b75d..dd8483563e27bd 100644 --- a/hphp/runtime/test/CMakeLists.txt +++ b/hphp/runtime/test/CMakeLists.txt @@ -18,6 +18,3 @@ embed_all_systemlibs(hphp_runtime_test "${CMAKE_CURRENT_BINARY_DIR}/../.." auto_source_group("hphp_runtime_test" "${CMAKE_CURRENT_SOURCE_DIR}" ${CXX_SOURCES} ${HEADER_SOURCES}) target_link_libraries(hphp_runtime_test hphp_system) -if (ENABLE_COTIRE) - cotire(hphp_runtime_test) -endif() diff --git a/hphp/runtime/vm/builtin-symbol-map.cpp b/hphp/runtime/vm/builtin-symbol-map.cpp index c213d1db1a0c31..e663d1b716b0e0 100644 --- a/hphp/runtime/vm/builtin-symbol-map.cpp +++ b/hphp/runtime/vm/builtin-symbol-map.cpp @@ -15,7 +15,7 @@ */ #include "hphp/hack/src/hackc/ffi_bridge/decl_provider.h" -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/runtime/base/autoload-map.h" #include "hphp/runtime/base/static-string-table.h" diff --git a/hphp/runtime/vm/debug/dwarf.h b/hphp/runtime/vm/debug/dwarf.h index 2ef1f8beb2f1ad..3e8c82c3821d8e 100644 --- a/hphp/runtime/vm/debug/dwarf.h +++ b/hphp/runtime/vm/debug/dwarf.h @@ -50,7 +50,7 @@ typedef enum { const int DWARF_CODE_ALIGN = 1; const int DWARF_DATA_ALIGN = 8; -#if (defined(HHVM_FACEBOOK) || defined(LIBDWARF_CONST_NAME)) +#if (defined(HHVM_FACEBOOK) || defined(LIBDWARF_CONST_NAME) || defined(LIBDWARF_USE_NEW_PRODUCER_API)) #define LIBDWARF_CALLBACK_NAME_TYPE const char* #else #define LIBDWARF_CALLBACK_NAME_TYPE char* diff --git a/hphp/runtime/vm/debug/elfwriter.cpp b/hphp/runtime/vm/debug/elfwriter.cpp index c7d24a514153db..827c9e5ccb0571 100644 --- a/hphp/runtime/vm/debug/elfwriter.cpp +++ b/hphp/runtime/vm/debug/elfwriter.cpp @@ -16,9 +16,14 @@ #include "hphp/runtime/vm/debug/elfwriter.h" #include "hphp/runtime/vm/debug/gdb-jit.h" #include +#include +#ifdef LIBDWARF_USE_NEW_PRODUCER_API +#include +#endif #include #include #include +#include #include #include @@ -36,6 +41,10 @@ namespace Debug { TRACE_SET_MOD(debuginfo) static const uint8_t CFA_OFFSET = 16; +#ifdef LIBDWARF_USE_NEW_PRODUCER_API +#define DW_DLV_NOCOUNT ((Dwarf_Signed) -1) +#endif + void ElfWriter::logError(const std::string& msg) { perror(""); std::cerr << msg << '\n'; @@ -116,7 +125,7 @@ bool ElfWriter::initDwarfProducer() { bool ElfWriter::initDwarfProducer() { Dwarf_Error error = 0; auto ret = dwarf_producer_init( - DW_DLC_WRITE | DW_DLC_SIZE_64 | DW_DLC_SYMBOLIC_RELOCATIONS, + DW_DLC_SIZE_64 | DW_DLC_SYMBOLIC_RELOCATIONS, g_dwarfCallback, nullptr, nullptr, @@ -134,13 +143,326 @@ bool ElfWriter::initDwarfProducer() { } #endif +Dwarf_Unsigned dwarf_add_expr_gen_compat( + Dwarf_P_Expr expr, + Dwarf_Small opcode, + Dwarf_Unsigned val1, + Dwarf_Unsigned val2, + Dwarf_Error* error +) { + Dwarf_Unsigned len = 0; + int res = dwarf_add_expr_gen_a(expr, opcode, val1, val2, &len, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + + return len; +} + +Dwarf_P_Die dwarf_new_die_compat( + Dwarf_P_Debug producer, + Dwarf_Tag tag, + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, + Dwarf_P_Die right, + Dwarf_Error* error +) { + Dwarf_P_Die die = nullptr; + int res = dwarf_new_die_a(producer, tag, parent, child, left, right, &die, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return die; +} + +Dwarf_P_Attribute dwarf_add_AT_name_compat(Dwarf_P_Die die, char* name, Dwarf_Error* error) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_name_a(die, name, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + +Dwarf_P_Attribute dwarf_add_AT_targ_address_compat( + Dwarf_P_Debug producer, + Dwarf_P_Die ownerDie, + Dwarf_Half attr, + Dwarf_Unsigned value, + Dwarf_Unsigned symbolIndex, + Dwarf_Error* error +) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_targ_address_c(producer, ownerDie, attr, value, symbolIndex, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + + +Dwarf_P_Attribute dwarf_add_AT_location_expr_compat( + Dwarf_P_Debug producer, + Dwarf_P_Die ownerDie, + Dwarf_Half attr, + Dwarf_P_Expr locExpr, + Dwarf_Error* error +) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_location_expr_a(producer, ownerDie, attr, locExpr, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + +Dwarf_P_Attribute dwarf_add_AT_reference_compat( + Dwarf_P_Debug dbg, + Dwarf_P_Die ownerDie, + Dwarf_Half attr, + Dwarf_P_Die otherDie, + Dwarf_Error* error +) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_reference_c(dbg, ownerDie, attr, otherDie, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + +Dwarf_P_Die dwarf_die_link_compat( + Dwarf_P_Die newDie, + Dwarf_P_Die parent, + Dwarf_P_Die child, + Dwarf_P_Die left, + Dwarf_P_Die right, + Dwarf_Error* error +) { + int res = dwarf_die_link_a(newDie, parent, child, left, right, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return newDie; +} + +Dwarf_P_Attribute dwarf_add_AT_flag_compat( + Dwarf_P_Debug dbg, + Dwarf_P_Die ownerDie, + Dwarf_Half attr, + Dwarf_Small flag, + Dwarf_Error* error +) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_flag_a(dbg, ownerDie, attr, flag, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + +Dwarf_P_Attribute dwarf_add_AT_unsigned_const_compat( + Dwarf_P_Debug dbg, + Dwarf_P_Die ownerDie, + Dwarf_Half attr, + Dwarf_Unsigned value, + Dwarf_Error* error +) { + Dwarf_P_Attribute attribute = nullptr; + int res = dwarf_add_AT_unsigned_const_a(dbg, ownerDie, attr, value, &attribute, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return attribute; +} + +Dwarf_P_Fde dwarf_new_fde_compat( + Dwarf_P_Debug producer, + Dwarf_Error* error +) { + Dwarf_P_Fde fde = nullptr; + int res = dwarf_new_fde_a(producer, &fde, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + return fde; +} + +Dwarf_Unsigned dwarf_add_frame_fde_compat( + Dwarf_P_Debug dbg, + Dwarf_P_Fde fde, + Dwarf_P_Die die, + Dwarf_Unsigned cie, + Dwarf_Unsigned virtAddr, + Dwarf_Unsigned codeLen, + Dwarf_Unsigned symbolIndex, + Dwarf_Error* error +) { + Dwarf_Unsigned index = 0; + int res = dwarf_add_frame_fde_c(dbg, fde, die, cie, virtAddr, codeLen, symbolIndex, 0, 0, &index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; +} + +Dwarf_Unsigned dwarf_add_file_decl_compat( + Dwarf_P_Debug dbg, + char* name, + Dwarf_Unsigned dirIndex, + Dwarf_Unsigned lastMod, + Dwarf_Unsigned length, + Dwarf_Error* error +) { + Dwarf_Unsigned index = 0; + int res = dwarf_add_file_decl_a(dbg, name, dirIndex, lastMod, length, &index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; +} + +Dwarf_Unsigned dwarf_lne_set_address_compat( + Dwarf_P_Debug dbg, + Dwarf_Addr addr, + Dwarf_Unsigned fileIndex, + Dwarf_Error* error +) { + int res = dwarf_lne_set_address_a(dbg, addr, fileIndex, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return 0; +} + +Dwarf_Unsigned dwarf_add_line_entry_compat( + Dwarf_P_Debug dbg, + Dwarf_Unsigned fileIndex, + Dwarf_Addr codeAddress, + Dwarf_Unsigned lineNo, + Dwarf_Signed colNo, + Dwarf_Bool isStmtBegin, + Dwarf_Bool isBBBegin, + Dwarf_Error* error +) { + int res = dwarf_add_line_entry_c(dbg, fileIndex, codeAddress, lineNo, colNo, isStmtBegin, isBBBegin, 0, 0, 0, 0, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return 0; +} + +Dwarf_Unsigned dwarf_lne_end_sequence_compat( + Dwarf_P_Debug dbg, + Dwarf_Addr endAddress, + Dwarf_Error* error +) { + int res = dwarf_lne_end_sequence_a(dbg, endAddress, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return 0; +} + +Dwarf_P_Expr dwarf_new_expr_compat(Dwarf_P_Debug producer, Dwarf_Error* error) { + Dwarf_P_Expr expr = nullptr; + int res = dwarf_new_expr_a(producer, &expr, error); + if (res != DW_DLV_OK) { + return nullptr; + } + return expr; +} + +Dwarf_Unsigned dwarf_add_die_to_debug_compat( + Dwarf_P_Debug dbg, + Dwarf_P_Die die, + Dwarf_Error* error +) { + int res = dwarf_add_die_to_debug_a(dbg, die, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return 0; +} + +Dwarf_Unsigned dwarf_add_frame_cie_compat( + Dwarf_P_Debug dbg, + char* augmenter, + Dwarf_Small codeAlign, + Dwarf_Small dataAlign, + Dwarf_Small returnReg, + Dwarf_Ptr initBytes, + Dwarf_Unsigned initNBytes, + Dwarf_Error* error +) { + Dwarf_Unsigned index = 0; + int res = dwarf_add_frame_cie_a(dbg, augmenter, codeAlign, dataAlign, returnReg, initBytes, initNBytes, &index, error); + if (res != DW_DLV_OK) { + return DW_DLV_NOCOUNT; + } + return index; +} + +Dwarf_Unsigned dwarf_transform_to_disk_form_compat( + Dwarf_P_Debug dbg, + Dwarf_Error* error +) { + std::conditional< + std::is_invocable::value, + Dwarf_Unsigned, + Dwarf_Signed + >::type count; + + int res = dwarf_transform_to_disk_form_a(dbg, &count, error); + if (res == DW_DLV_ERROR) { + return DW_DLV_NOCOUNT; + } + + return static_cast(count); +} + +Dwarf_Ptr dwarf_get_section_bytes_compat( + Dwarf_P_Debug dbg, + Dwarf_Unsigned* sectionIndex, + Dwarf_Unsigned* length, + Dwarf_Error* error +) { + Dwarf_Signed unused; + Dwarf_Ptr bytes = nullptr; + + std::conditional< + std::is_invocable::value, + Dwarf_Unsigned, + Dwarf_Signed + >::type bcSectionIndex; + + int res = dwarf_get_section_bytes_a(dbg, unused, &bcSectionIndex, length, &bytes, error); + if (res != DW_DLV_OK) { + return nullptr; + } + + *sectionIndex = static_cast(bcSectionIndex); + + return bytes; +} + Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { Dwarf_Error error = 0; /* top level DIE for each function */ - Dwarf_P_Die func = dwarf_new_die(m_dwarfProducer, + Dwarf_P_Die func = dwarf_new_die_compat(m_dwarfProducer, DW_TAG_subprogram, nullptr, nullptr, nullptr, nullptr, &error); - if (reinterpret_cast(func) == DW_DLV_BADADDR) { + if (func == nullptr) { logError("unable to create child DIE"); return nullptr; } @@ -150,7 +472,7 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { /* if this function is from an unseen file, register file name * and get index to file name */ if (it == m_fileDB.end()) { - file = dwarf_add_file_decl(m_dwarfProducer, + file = dwarf_add_file_decl_compat(m_dwarfProducer, (char *)f->file, 0, 0, 1000, &error); if (file == DW_DLV_NOCOUNT) { logError("unable to add file declaration"); @@ -163,24 +485,24 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { /* add function name attribute to function DIE */ Dwarf_P_Attribute at; - at = dwarf_add_AT_name(func, (char *)f->name.c_str(), &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + at = dwarf_add_AT_name_compat(func, (char *)f->name.c_str(), &error); + if (at == nullptr) { logError("unable to add name attribute to function"); return nullptr; } /* Add lower PC bound to function DIE */ - at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_low_pc, + at = dwarf_add_AT_targ_address_compat(m_dwarfProducer, func, DW_AT_low_pc, reinterpret_cast(f->range.begin()), 0, &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + if (at == nullptr) { logError("unable to add low_pc attribute to function"); return nullptr; } /* add upper PC bound to function DIE */ - at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_high_pc, + at = dwarf_add_AT_targ_address_compat(m_dwarfProducer, func, DW_AT_high_pc, reinterpret_cast(f->range.end()), 0, &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + if (at == nullptr) { logError("unable to add high_pc attribute to function"); return nullptr; } @@ -188,7 +510,7 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { /* register line number information for function: * 1. register start address */ Dwarf_Unsigned u; - u = dwarf_lne_set_address(m_dwarfProducer, + u = dwarf_lne_set_address_compat(m_dwarfProducer, reinterpret_cast(f->range.begin()), 0, &error); if (u != 0) { logError("unable to set line start address"); @@ -198,7 +520,7 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { /* 2. register line number info for each tracelet in function */ std::vector::iterator it2; for (it2 = f->m_lineTable.begin(); it2 != f->m_lineTable.end(); it2++) { - u = dwarf_add_line_entry(m_dwarfProducer, + u = dwarf_add_line_entry_compat(m_dwarfProducer, file, reinterpret_cast(it2->range.begin()), it2->lineNumber, 0, 1, 0, &error); if (u != 0) { @@ -210,7 +532,7 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { } /* 3. register end address of function */ - u = dwarf_lne_end_sequence(m_dwarfProducer, + u = dwarf_lne_end_sequence_compat(m_dwarfProducer, reinterpret_cast(f->range.end()), &error); if (u != 0) { logError("unable to set line end address"); @@ -219,33 +541,33 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { { /* 4. register frame base of function */ - Dwarf_P_Expr locExpr = dwarf_new_expr(m_dwarfProducer, &error); + Dwarf_P_Expr locExpr = dwarf_new_expr_compat(m_dwarfProducer, &error); if (locExpr == nullptr) { logError("unable to create new location expression"); return nullptr; } - u = dwarf_add_expr_gen(locExpr, DW_OP_call_frame_cfa, 0, 0, &error); + u = dwarf_add_expr_gen_compat(locExpr, DW_OP_call_frame_cfa, 0, 0, &error); if (u == DW_DLV_NOCOUNT) { logError("unable to add subexpression to location expression"); return nullptr; } - u = dwarf_add_expr_gen(locExpr, DW_OP_const1u, CFA_OFFSET, 0, &error); + u = dwarf_add_expr_gen_compat(locExpr, DW_OP_const1u, CFA_OFFSET, 0, &error); if (u == DW_DLV_NOCOUNT) { logError("unable to add subexpression to location expression"); return nullptr; } - u = dwarf_add_expr_gen(locExpr, DW_OP_minus, 0, 0, &error); + u = dwarf_add_expr_gen_compat(locExpr, DW_OP_minus, 0, 0, &error); if (u == DW_DLV_NOCOUNT) { logError("unable to add subexpression to location expression"); return nullptr; } - Dwarf_P_Attribute frameBaseAttr = dwarf_add_AT_location_expr( + Dwarf_P_Attribute frameBaseAttr = dwarf_add_AT_location_expr_compat( m_dwarfProducer, func, DW_AT_frame_base, locExpr, &error); - if (reinterpret_cast(frameBaseAttr) == DW_DLV_BADADDR) { + if (frameBaseAttr == nullptr) { logError("unable to add frame_base attribute"); return nullptr; } @@ -256,21 +578,21 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { int i = 1; for (std::vector::iterator it = f->m_namedLocals.begin(); it != f->m_namedLocals.end(); it++) { - Dwarf_P_Die localVar = dwarf_new_die(m_dwarfProducer, + Dwarf_P_Die localVar = dwarf_new_die_compat(m_dwarfProducer, DW_TAG_variable, nullptr, nullptr, nullptr, nullptr, &error); - if (reinterpret_cast(localVar) == DW_DLV_BADADDR) { + if (localVar == nullptr) { logError("unable to create new DIE for local variable"); return nullptr; } /* Create location expression defined w.r.t DW_AT_frame_base */ - Dwarf_P_Expr locExpr = dwarf_new_expr(m_dwarfProducer, &error); + Dwarf_P_Expr locExpr = dwarf_new_expr_compat(m_dwarfProducer, &error); if (locExpr == nullptr) { logError("unable to create new location expression"); return nullptr; } - u = dwarf_add_expr_gen(locExpr, DW_OP_fbreg, + u = dwarf_add_expr_gen_compat(locExpr, DW_OP_fbreg, -(i * sizeof(TypedValue)), 0, &error); ++i; if (u == DW_DLV_NOCOUNT) { @@ -278,33 +600,33 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { return nullptr; } - Dwarf_P_Attribute locAttr = dwarf_add_AT_location_expr(m_dwarfProducer, + Dwarf_P_Attribute locAttr = dwarf_add_AT_location_expr_compat(m_dwarfProducer, localVar, DW_AT_location, locExpr, &error); - if (reinterpret_cast(locAttr) == DW_DLV_BADADDR) { + if (locAttr == nullptr) { logError("unable to add location attribute to local variable"); return nullptr; } - Dwarf_P_Attribute nameAttr = dwarf_add_AT_name(localVar, const_cast(it->data()), &error); - if (reinterpret_cast(nameAttr) == DW_DLV_BADADDR) { + Dwarf_P_Attribute nameAttr = dwarf_add_AT_name_compat(localVar, const_cast(it->data()), &error); + if (nameAttr == nullptr) { logError("unable to add name attribute to local variable"); return nullptr; } - Dwarf_P_Attribute varTypeAttr = dwarf_add_AT_reference(m_dwarfProducer, + Dwarf_P_Attribute varTypeAttr = dwarf_add_AT_reference_compat(m_dwarfProducer, localVar, DW_AT_type, type, &error); - if (reinterpret_cast(varTypeAttr) == DW_DLV_BADADDR) { + if (varTypeAttr == nullptr) { logError("unable to add type attribute to local variable DIE"); return nullptr; } Dwarf_P_Die res = 0; if (lastLocal != nullptr) { - res = dwarf_die_link(localVar, nullptr, nullptr, lastLocal, nullptr, &error); + res = dwarf_die_link_compat(localVar, nullptr, nullptr, lastLocal, nullptr, &error); } else { - res = dwarf_die_link(localVar, func, nullptr, nullptr, nullptr, &error); + res = dwarf_die_link_compat(localVar, func, nullptr, nullptr, nullptr, &error); } - if (reinterpret_cast(res) == DW_DLV_BADADDR) { + if (res == nullptr) { logError("unable to link die"); return nullptr; } @@ -316,31 +638,31 @@ Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) { Dwarf_P_Die ElfWriter::makeLocalTypeDie() { Dwarf_Error error = 0; - Dwarf_P_Die typedValueType = dwarf_new_die(m_dwarfProducer, + Dwarf_P_Die typedValueType = dwarf_new_die_compat(m_dwarfProducer, DW_TAG_structure_type, nullptr, nullptr, nullptr, nullptr, &error); - if (reinterpret_cast(typedValueType) == DW_DLV_BADADDR) { + if (typedValueType == nullptr) { logError("unable to create new DIE for TypedValue type"); return nullptr; } /* hard coding the name of 'HPHP::TypedValue' */ Dwarf_P_Attribute at; - at = dwarf_add_AT_name(typedValueType, "HPHP::TypedValue", &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + at = dwarf_add_AT_name_compat(typedValueType, "HPHP::TypedValue", &error); + if (at == nullptr) { logError("unable to add name attribute to TypedValue type DIE"); return nullptr; } - at = dwarf_add_AT_flag(m_dwarfProducer, + at = dwarf_add_AT_flag_compat(m_dwarfProducer, typedValueType, DW_AT_declaration, 1, &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + if (at == nullptr) { logError("unable to add declaration attribute to TypedValue type DIE"); return nullptr; } - at = dwarf_add_AT_unsigned_const(m_dwarfProducer, + at = dwarf_add_AT_unsigned_const_compat(m_dwarfProducer, typedValueType, DW_AT_byte_size, sizeof(TypedValue), &error); - if (reinterpret_cast(at) == DW_DLV_BADADDR) { + if (at == nullptr) { logError("unable to add byte_size attribute to TypedValue type DIE"); return nullptr; } @@ -353,9 +675,9 @@ bool ElfWriter::addSymbolInfo(DwarfChunk* d) { /* create a top level DIE (debug information entry) * all subsequent DIEs' will be children of this DIE */ - Dwarf_P_Die codeUnit = dwarf_new_die(m_dwarfProducer, + Dwarf_P_Die codeUnit = dwarf_new_die_compat(m_dwarfProducer, DW_TAG_compile_unit, nullptr, nullptr, nullptr, nullptr, &error); - if (reinterpret_cast(codeUnit) == DW_DLV_BADADDR) { + if (codeUnit == nullptr) { logError("unable to create code unit DIE"); return false; } @@ -368,8 +690,8 @@ bool ElfWriter::addSymbolInfo(DwarfChunk* d) { return false; } Dwarf_P_Die linkRes; - linkRes = dwarf_die_link(type, codeUnit, nullptr, nullptr, nullptr, &error); - if (reinterpret_cast(linkRes) == DW_DLV_BADADDR) { + linkRes = dwarf_die_link_compat(type, codeUnit, nullptr, nullptr, nullptr, &error); + if (linkRes == nullptr) { logError("unable to link die"); return false; } @@ -384,11 +706,11 @@ bool ElfWriter::addSymbolInfo(DwarfChunk* d) { } if (lastChild) { - linkRes = dwarf_die_link(func, nullptr, nullptr, lastChild, nullptr, &error); + linkRes = dwarf_die_link_compat(func, nullptr, nullptr, lastChild, nullptr, &error); } else { - linkRes = dwarf_die_link(func, codeUnit, nullptr, nullptr, nullptr, &error); + linkRes = dwarf_die_link_compat(func, codeUnit, nullptr, nullptr, nullptr, &error); } - if (reinterpret_cast(linkRes) == DW_DLV_BADADDR) { + if (linkRes == nullptr) { logError("unable to link die"); return false; } @@ -396,7 +718,7 @@ bool ElfWriter::addSymbolInfo(DwarfChunk* d) { } /* register top level DIE */ - Dwarf_Unsigned res = dwarf_add_die_to_debug(m_dwarfProducer, + Dwarf_Unsigned res = dwarf_add_die_to_debug_compat(m_dwarfProducer, codeUnit, &error); if (res != DW_DLV_OK) { logError("unable to add DIE to DWARF"); @@ -430,7 +752,7 @@ bool ElfWriter::addFrameInfo(DwarfChunk* d) { b.dwarf_cfa_same_value(RSP); /* register above rules in a CIE (common information entry) */ - Dwarf_Signed cie_index = dwarf_add_frame_cie( + Dwarf_Signed cie_index = dwarf_add_frame_cie_compat( m_dwarfProducer, "", DWARF_CODE_ALIGN, @@ -449,8 +771,8 @@ bool ElfWriter::addFrameInfo(DwarfChunk* d) { * an FDE (Frame Description entry) */ FuncPtrDB::iterator it; for (it = d->m_functions.begin(); it != d->m_functions.end(); it++) { - Dwarf_P_Fde fde = dwarf_new_fde(m_dwarfProducer, &error); - if (reinterpret_cast(fde) == DW_DLV_BADADDR) { + Dwarf_P_Fde fde = dwarf_new_fde_compat(m_dwarfProducer, &error); + if (fde == nullptr) { logError("Unable to create FDE"); return false; } @@ -461,12 +783,12 @@ bool ElfWriter::addFrameInfo(DwarfChunk* d) { logError("Unable to add instructions to fde"); return false; } - Dwarf_Unsigned fde_index = dwarf_add_frame_fde( + Dwarf_Unsigned fde_index = dwarf_add_frame_fde_compat( m_dwarfProducer, fde, 0, cie_index, (Dwarf_Unsigned)((*it)->range.begin()), (*it)->range.size(), 0, &error); - if (fde_index == DW_DLV_BADADDR) { + if (fde_index == DW_DLV_NOCOUNT) { logError("Unable to add FDE"); return false; } @@ -523,15 +845,20 @@ bool ElfWriter::addSectionData(int section_index, void *data, uint64_t size) { } bool ElfWriter::writeDwarfInfo() { - Dwarf_Signed sections = dwarf_transform_to_disk_form (m_dwarfProducer, 0); + Dwarf_Unsigned sections = dwarf_transform_to_disk_form_compat(m_dwarfProducer, 0); Dwarf_Signed i = 0; - Dwarf_Signed elf_section_index = 0; + Dwarf_Unsigned elf_section_index = 0; Dwarf_Unsigned length = 0; for (i = 0; i < sections; i++) { - Dwarf_Ptr bytes = dwarf_get_section_bytes( - m_dwarfProducer, 0, &elf_section_index, &length, 0); + Dwarf_Ptr bytes = dwarf_get_section_bytes_compat( + m_dwarfProducer, &elf_section_index, &length, 0); + + if (bytes == nullptr) { + logError("Unable to create section"); + return false; + } if (!addSectionData(elf_section_index, bytes, length)) { logError("Unable to create section"); @@ -632,7 +959,7 @@ ElfWriter::~ElfWriter() { unlink(m_filename.c_str()); } if (m_dwarfProducer != nullptr) - dwarf_producer_finish(m_dwarfProducer, 0); + dwarf_producer_finish_a(m_dwarfProducer, 0); } } diff --git a/hphp/runtime/vm/func.h b/hphp/runtime/vm/func.h index 42667e51bbec3d..011ae639647319 100644 --- a/hphp/runtime/vm/func.h +++ b/hphp/runtime/vm/func.h @@ -1854,8 +1854,10 @@ struct Func final { // should not be inherited from. jit::AtomicLowTCA m_prologueTable[1]; }; -static constexpr size_t kFuncSize = debug ? (use_lowptr ? 72 : 96) - : (use_lowptr ? 64 : 88); + +static constexpr size_t kTCAPtrDiff = sizeof(jit::AtomicLowTCA) == 8 ? 16 : 0; +static constexpr size_t kFuncSize = kTCAPtrDiff + (debug ? (use_lowptr ? 72 : 96) + : (use_lowptr ? 64 : 88)); static_assert(CheckSize(), ""); /////////////////////////////////////////////////////////////////////////////// diff --git a/hphp/runtime/vm/hackc-translator.h b/hphp/runtime/vm/hackc-translator.h index 65384f7a962187..4b13f6e7088c17 100644 --- a/hphp/runtime/vm/hackc-translator.h +++ b/hphp/runtime/vm/hackc-translator.h @@ -16,7 +16,7 @@ #pragma once -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/hack/src/hackc/hhbc-unit.h" #include "hphp/runtime/vm/native-func-table.h" #include "hphp/runtime/vm/unit-emitter.h" diff --git a/hphp/runtime/vm/jit/code-cache.cpp b/hphp/runtime/vm/jit/code-cache.cpp index 5a7c6bc350179c..b8d353d800ff75 100644 --- a/hphp/runtime/vm/jit/code-cache.cpp +++ b/hphp/runtime/vm/jit/code-cache.cpp @@ -27,6 +27,7 @@ #include "hphp/util/hugetlb.h" #include "hphp/util/numa.h" #include "hphp/util/trace.h" +#include "util/alloc-defs.h" namespace HPHP::jit { @@ -117,29 +118,31 @@ CodeCache::CodeCache() { } #if USE_JEMALLOC - // When we have a low arena, TC must fit below lowArenaMinAddr(). If it - // doesn't, we shrink things to make it so. - auto const lowArenaStart = lowArenaMinAddr(); - if (Cfg::Server::Mode) { - Logger::Info("lowArenaMinAddr(): 0x%lx", lowArenaStart); - } - always_assert_flog( - usedBase + (32u << 20) <= lowArenaStart, - "brk is too big for LOWPTR build (usedBase = {}, lowArenaStart = {})", - usedBase, lowArenaStart - ); + if constexpr (use_position_dependent_jemalloc_arenas) { + // When we have a low arena, TC must fit below lowArenaMinAddr(). If it + // doesn't, we shrink things to make it so. + auto const lowArenaStart = lowArenaMinAddr(); + if (Cfg::Server::Mode) { + Logger::Info("lowArenaMinAddr(): 0x%lx", lowArenaStart); + } + always_assert_flog( + usedBase + (32u << 20) <= lowArenaStart, + "brk is too big for LOWPTR build (usedBase = {}, lowArenaStart = {})", + usedBase, lowArenaStart + ); - if (usedBase + m_totalSize > lowArenaStart) { - cutTCSizeTo(lowArenaStart - usedBase - thread_local_size); - new (this) CodeCache; - return; + if (usedBase + m_totalSize > lowArenaStart) { + cutTCSizeTo(lowArenaStart - usedBase - thread_local_size); + new (this) CodeCache; + return; + } + always_assert_flog( + usedBase + m_totalSize <= lowArenaStart, + "computed allocationSize ({}) is too large to fit within " + "lowArenaStart ({}), usedBase = {}\n", + m_totalSize, lowArenaStart, usedBase + ); } - always_assert_flog( - usedBase + m_totalSize <= lowArenaStart, - "computed allocationSize ({}) is too large to fit within " - "lowArenaStart ({}), usedBase = {}\n", - m_totalSize, lowArenaStart, usedBase - ); #endif // Use MAP_FIXED_NOREPLACE instead of MAP_FIXED so we actually get // an error if we overlap with an existing mapping. diff --git a/hphp/runtime/vm/jit/code-gen-helpers.h b/hphp/runtime/vm/jit/code-gen-helpers.h index 136f8f00235f15..210b90c4cfe0df 100644 --- a/hphp/runtime/vm/jit/code-gen-helpers.h +++ b/hphp/runtime/vm/jit/code-gen-helpers.h @@ -63,6 +63,10 @@ void emitLdPackedPtr(Vout& v, Vptr mem, Vreg reg) { ldLowPtrImpl(v, mem, reg, PackedPtr::bits); } +inline void emitLdTCAPtr(Vout& v, Vptr mem, Vreg reg) { + ldLowPtrImpl(v, mem, reg, LowTCA::bits); +} + /* * Store the LowPtr in `reg' into `mem', with storage size `size'. */ diff --git a/hphp/runtime/vm/jit/ir-opcode.h b/hphp/runtime/vm/jit/ir-opcode.h index 4b8062f43aa58e..601b0f6dfa8d05 100644 --- a/hphp/runtime/vm/jit/ir-opcode.h +++ b/hphp/runtime/vm/jit/ir-opcode.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "hphp/runtime/vm/jit/types.h" diff --git a/hphp/runtime/vm/jit/ir-unit-inl.h b/hphp/runtime/vm/jit/ir-unit-inl.h index ff37f7acbb27c8..d242b7d8d859c4 100644 --- a/hphp/runtime/vm/jit/ir-unit-inl.h +++ b/hphp/runtime/vm/jit/ir-unit-inl.h @@ -129,7 +129,7 @@ struct InstructionBuilder { */ void setter(IRInstruction* inst, Block* target) { assert_flog(!target || inst->hasEdges(), - fmt::format("{}: Mismatch between declared edges and specified target", inst->op()) + fmt::format("{}: Mismatch between declared edges and specified target", fmt::underlying(inst->op())) ); inst->setTaken(target); } diff --git a/hphp/runtime/vm/jit/irlower-call.cpp b/hphp/runtime/vm/jit/irlower-call.cpp index 115672ae10d193..ade93b7215dfc8 100644 --- a/hphp/runtime/vm/jit/irlower-call.cpp +++ b/hphp/runtime/vm/jit/irlower-call.cpp @@ -156,7 +156,7 @@ void cgCall(IRLS& env, const IRInstruction* inst) { auto const pTabOff = safe_cast(Func::prologueTableOff()); auto const ptrSize = safe_cast(sizeof(LowTCA)); auto const dest = v.makeReg(); - v << loadzlq{r_func_prologue_callee()[numArgsInclUnpack * ptrSize + pTabOff], dest}; + emitLdTCAPtr(v, r_func_prologue_callee()[numArgsInclUnpack * ptrSize + pTabOff], dest); v << callphpr{dest, func_prologue_regs(withCtx)}; } else { // It was not statically determined that the arguments are passed in a way @@ -236,7 +236,7 @@ void cgCallFuncEntry(IRLS& env, const IRInstruction* inst) { // Load the FuncEntry address dynamically from the function. auto dest = v.makeReg(); auto const funcEntryOff = safe_cast(Func::funcEntryOff()); - v << loadzlq{callee[funcEntryOff], dest}; + emitLdTCAPtr(v, callee[funcEntryOff], dest); // We have to use an ifdef instead of `if (use_lowptr)` here due to // funcIdOffset only being defined in non-lowptr mode. #ifdef USE_LOWPTR diff --git a/hphp/runtime/vm/jit/types.h b/hphp/runtime/vm/jit/types.h index d706c3591081d2..4320ffffa24286 100644 --- a/hphp/runtime/vm/jit/types.h +++ b/hphp/runtime/vm/jit/types.h @@ -40,8 +40,13 @@ using CTCA = const unsigned char*; using TcaRange = folly::Range; +#ifndef HHVM_PIE using LowTCA = SmallPtr; using AtomicLowTCA = AtomicSmallPtr; +#else +using LowTCA = FullPtr; +using AtomicLowTCA = AtomicFullPtr; +#endif struct ctca_identity_hash { size_t operator()(CTCA val) const { diff --git a/hphp/runtime/vm/jit/unique-stubs.cpp b/hphp/runtime/vm/jit/unique-stubs.cpp index ae32cc73a38bbb..652dd4fdedfedf 100644 --- a/hphp/runtime/vm/jit/unique-stubs.cpp +++ b/hphp/runtime/vm/jit/unique-stubs.cpp @@ -75,6 +75,9 @@ #include +#include +#include + namespace HPHP::jit { /////////////////////////////////////////////////////////////////////////////// @@ -297,7 +300,7 @@ TCA emitFuncPrologueRedispatch(CodeBlock& cb, DataBlock& data, const char* name) ifThen(v, CC_LE, sf, [&] (Vout& v) { // Fast path (numArgs <= numNonVariadicParams). Call the numArgs prologue. auto const dest = v.makeReg(); - v << loadzlq{callee[numArgs * ptrSize + pTabOff], dest}; + emitLdTCAPtr(v, callee[numArgs * ptrSize + pTabOff], dest); v << jmpr{dest, func_prologue_regs(true)}; }); @@ -361,7 +364,11 @@ TCA emitFuncPrologueRedispatch(CodeBlock& cb, DataBlock& data, const char* name) // Call the numNonVariadicParams + 1 prologue. auto const dest = v.makeReg(); - v << loadzlq{Vreg(r_func_prologue_callee())[numNewArgs * ptrSize + pTabOff], dest}; + emitLdTCAPtr( + v, + Vreg(r_func_prologue_callee())[numNewArgs * ptrSize + pTabOff], + dest + ); v << tailcallstubr{dest, func_prologue_regs(true)}; }, name); } @@ -419,7 +426,7 @@ TCA emitFuncPrologueRedispatchUnpack(CodeBlock& main, CodeBlock& cold, auto const pTabOff = safe_cast(Func::prologueTableOff()); auto const ptrSize = safe_cast(sizeof(LowTCA)); auto const dest = v.makeReg(); - v << loadzlq{callee[numNewArgs * ptrSize + pTabOff], dest}; + emitLdTCAPtr(v, callee[numNewArgs * ptrSize + pTabOff], dest); v << tailcallstubr{dest, func_prologue_regs(true)}; }, name); diff --git a/hphp/runtime/vm/unit-parser.cpp b/hphp/runtime/vm/unit-parser.cpp index 690f1e2edcb329..e1a69275eee89d 100644 --- a/hphp/runtime/vm/unit-parser.cpp +++ b/hphp/runtime/vm/unit-parser.cpp @@ -25,9 +25,9 @@ #include #include -#include "hphp/hack/src/hackc/ffi_bridge/compiler_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/compiler_ffi.rs.h" #include "hphp/hack/src/hackc/hhbc-unit.h" -#include "hphp/hack/src/parser/ffi_bridge/parser_ffi.rs.h" +#include "hphp/hack/src/hhvm_ffi/parser_ffi.rs.h" #include "hphp/runtime/base/autoload-map.h" #include "hphp/runtime/base/file-stream-wrapper.h" #include "hphp/runtime/base/stream-wrapper-registry.h" @@ -224,7 +224,7 @@ ParseFactsResult extract_facts( if (!f) { throwErrno( folly::sformat( - "Failed to extract facts: Could not read source code for %s", + "Failed to extract facts: Could not read source code for {}", filename ).c_str()); } diff --git a/hphp/system/CMakeLists.txt b/hphp/system/CMakeLists.txt index b287e66452e88a..d741df679d6993 100644 --- a/hphp/system/CMakeLists.txt +++ b/hphp/system/CMakeLists.txt @@ -6,31 +6,32 @@ target_link_libraries(hphp_system hphp_util proxygen hhvm_base_headers) auto_sources(files "*.h" "${CMAKE_CURRENT_SOURCE_DIR}") HHVM_PUBLIC_HEADERS(system ${files}) -FILE(STRINGS "php.txt" SYSTEMLIB_CLASSES) +FILE(STRINGS ${CMAKE_SOURCE_DIR}/hphp/runtime/ext/core/php.txt SYSTEMLIB_CLASSES) set(SYSTEMLIB_SRCS) -set(SYSTEMLIB_SRCS_STR) + foreach(cls ${SYSTEMLIB_CLASSES}) STRING(REGEX REPLACE "[ \t]*#.*" "" cls "${cls}") if (NOT "${cls}" STREQUAL "") - list(APPEND SYSTEMLIB_SRCS "../../${cls}") - set( - SYSTEMLIB_SRCS_STR - "${SYSTEMLIB_SRCS_STR} ${CMAKE_CURRENT_SOURCE_DIR}/../../${cls}" - ) + list(APPEND SYSTEMLIB_SRCS "${CMAKE_SOURCE_DIR}/${cls}") endif() endforeach() +set(CORE_SYSTEMLIB_FILE "${CMAKE_SOURCE_DIR}/hphp/runtime/ext/core/ext_core.php") + add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/systemlib.php + OUTPUT ${CORE_SYSTEMLIB_FILE} DEPENDS "php.txt" ${SYSTEMLIB_SRCS} - COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/make_systemlib.sh" - "${CMAKE_CURRENT_BINARY_DIR}/systemlib.php" - "${SYSTEMLIB_SRCS_STR}" - COMMENT "Generating systemlib.php") + COMMAND "${CMAKE_SOURCE_DIR}/hphp/runtime/ext/core/make_systemlib.sh" + "${CMAKE_SOURCE_DIR}/hphp/runtime/ext/core" + "ext_core.php" + ${SYSTEMLIB_SRCS} + COMMENT "Generating systemlib.php" + VERBATIM + ) add_custom_target( systemlib DEPENDS - ${CMAKE_CURRENT_BINARY_DIR}/systemlib.php + ${CORE_SYSTEMLIB_FILE} generated_systemlib ) diff --git a/hphp/system/php.txt b/hphp/system/php.txt new file mode 100644 index 00000000000000..0d52389ad6f45c --- /dev/null +++ b/hphp/system/php.txt @@ -0,0 +1 @@ +../runtime/ext/core/php.txt diff --git a/hphp/test/CMakeLists.txt b/hphp/test/CMakeLists.txt index 0cfdf3d3b2bcb6..42977136abe031 100644 --- a/hphp/test/CMakeLists.txt +++ b/hphp/test/CMakeLists.txt @@ -20,6 +20,3 @@ target_link_libraries(test ${HHVM_LINK_LIBRARIES}) link_object_libraries(test ${HHVM_WHOLE_ARCHIVE_LIBRARIES}) embed_all_systemlibs(test "${CMAKE_CURRENT_BINARY_DIR}/.." "${CMAKE_CURRENT_BINARY_DIR}/test") add_dependencies(test systemlib) -if (ENABLE_COTIRE) - cotire(test) -endif() diff --git a/hphp/tools/configs/Cargo.lock b/hphp/tools/configs/Cargo.lock index 0db6a6312cb135..d019fd47d7c05a 100644 --- a/hphp/tools/configs/Cargo.lock +++ b/hphp/tools/configs/Cargo.lock @@ -146,6 +146,7 @@ dependencies = [ "clap", "convert_case", "nom", + "nom-language", ] [[package]] @@ -179,19 +180,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "nom" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] [[package]] -name = "nom" -version = "7.1.3" +name = "nom-language" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29" dependencies = [ - "memchr", - "minimal-lexical", + "nom", ] [[package]] diff --git a/hphp/tools/configs/Cargo.toml b/hphp/tools/configs/Cargo.toml new file mode 100644 index 00000000000000..24ddedb1f96697 --- /dev/null +++ b/hphp/tools/configs/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "generate_configs_lib" +version = "0.0.0" +edition = "2021" +repository = "https://github.com/facebook/hhvm" +license = "MIT" + +[[bin]] +name = "generate_configs" +path = "generate_configs.rs" + +[lib] +path = "generate_configs_lib.rs" + +[dependencies] +clap = { version = "4.5.20", features = ["derive", "env", "string", "unicode", "wrap_help"] } +convert_case = "0.4.0" +nom = "8" +nom-language = "0.1" + +[build-dependencies] +anyhow = "1.0.86" +cc = "1.0.90" diff --git a/hphp/tools/tc-print/CMakeLists.txt b/hphp/tools/tc-print/CMakeLists.txt index 4a5c3438c08923..85c5fbbe66e213 100644 --- a/hphp/tools/tc-print/CMakeLists.txt +++ b/hphp/tools/tc-print/CMakeLists.txt @@ -29,7 +29,8 @@ else() endif() add_executable(tc-print ${TC_PRINT_CXX_SOURCES}) -link_object_libraries(tc-print ${HHVM_WHOLE_ARCHIVE_LIBRARIES}) +add_dependencies(tc-print hhvm) target_link_libraries(tc-print ${HHVM_LINK_LIBRARIES}) +link_object_libraries(tc-print ${HHVM_WHOLE_ARCHIVE_LIBRARIES}) embed_all_systemlibs(tc-print "${CMAKE_CURRENT_BINARY_DIR}/../.." "${CMAKE_CURRENT_BINARY_DIR}/tc-print") diff --git a/hphp/util/CMakeLists.txt b/hphp/util/CMakeLists.txt index 152b2c1be98762..cfe774b14f8eeb 100644 --- a/hphp/util/CMakeLists.txt +++ b/hphp/util/CMakeLists.txt @@ -15,28 +15,26 @@ list(APPEND HEADER_SOURCES ${files}) HHVM_REMOVE_MATCHES_FROM_LISTS(ASM_SOURCES CXX_SOURCES HEADER_SOURCES MATCHES "/test/" "channeled-json-") -if (NOT MSVC) - list(REMOVE_ITEM CXX_SOURCES +list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/portability/fnmatch.cpp ${CMAKE_CURRENT_SOURCE_DIR}/portability/glob.cpp ${CMAKE_CURRENT_SOURCE_DIR}/portability/rand_r.cpp ${CMAKE_CURRENT_SOURCE_DIR}/portability/strfmon.cpp ) - list(REMOVE_ITEM HEADER_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/portability/fnmatch.h - ${CMAKE_CURRENT_SOURCE_DIR}/portability/glob.h - ${CMAKE_CURRENT_SOURCE_DIR}/portability/rand_r.h - ${CMAKE_CURRENT_SOURCE_DIR}/portability/strfmon.h - ) -endif() +list(REMOVE_ITEM HEADER_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/portability/fnmatch.h + ${CMAKE_CURRENT_SOURCE_DIR}/portability/glob.h + ${CMAKE_CURRENT_SOURCE_DIR}/portability/rand_r.h + ${CMAKE_CURRENT_SOURCE_DIR}/portability/strfmon.h +) add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/low-ptr-def.h - COMMAND INSTALL_DIR=${CMAKE_CURRENT_BINARY_DIR} bash ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate-low-ptr.sh ignored - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate-low-ptr.sh + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ptr-def.h + COMMAND INSTALL_DIR=${CMAKE_CURRENT_BINARY_DIR} bash ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate-ptr-def.sh ignored + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/../tools/generate-ptr-def.sh ) -list(APPEND HEADER_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/low-ptr-def.h) +list(APPEND HEADER_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/ptr-def.h) HHVM_PUBLIC_HEADERS(util ${HEADER_SOURCES}) @@ -46,13 +44,6 @@ if (LIBNUMA_INCLUDE_DIRS) include_directories(${LIBNUMA_INCLUDE_DIRS}) endif() -if(MSVC) - list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/afdt-util.cpp") - list(REMOVE_ITEM HEADER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/afdt-util.h") - list(REMOVE_ITEM CXX_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/light-process.cpp") - list(REMOVE_ITEM HEADER_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/light-process.h") -endif() - get_target_property(CARGO_EXE cargo LOCATION) get_target_property(RUSTC_EXE rustc LOCATION) @@ -68,8 +59,9 @@ HHVM_RENDER_CONFIG_SPECIFICATION( auto_source_group("hphp_util" "${CMAKE_CURRENT_SOURCE_DIR}" ${ASM_SOURCES} ${CXX_SOURCES} ${HEADER_SOURCES}) -if (ENABLE_COTIRE) - cotire(hphp_util) + +if (ENABLE_PIE) + target_compile_definitions(hphp_util PUBLIC HHVM_PIE FULLPTR_FOR_BUILTINS) endif() target_link_libraries(hphp_util brotli folly zstd) diff --git a/hphp/util/alloc-defs.h b/hphp/util/alloc-defs.h index 145b32ff92b7d2..c2ddfe388ee435 100644 --- a/hphp/util/alloc-defs.h +++ b/hphp/util/alloc-defs.h @@ -48,11 +48,19 @@ constexpr bool use_jemalloc = #endif ; +constexpr bool use_position_dependent_jemalloc_arenas = +#if USE_JEMALLOC && !defined(HHVM_PIE) + true +#else + false +#endif +; + // When we have control over the virtual address space for the heap, all // static/uncounted strings/arrays have addresses lower than kUncountedMaxAddr, // and all counted HeapObjects have higher addresses. constexpr bool addr_encodes_persistency = -#if USE_JEMALLOC && defined(__x86_64__) && defined(__linux__) +#if USE_JEMALLOC && defined(__x86_64__) && defined(__linux__) && !defined(HHVM_PIE) true #else false diff --git a/hphp/util/alloc.cpp b/hphp/util/alloc.cpp index bebed3d6f25442..cf9d83ea225d2b 100644 --- a/hphp/util/alloc.cpp +++ b/hphp/util/alloc.cpp @@ -224,6 +224,10 @@ RangeMapper* getMapperChain(RangeState& range, unsigned n1GPages, // from the input, because some part of the range may have already been mapped // in. unsigned allocate2MPagesToRange(AddrRangeClass c, unsigned pages) { + if constexpr (!use_position_dependent_jemalloc_arenas) { + return 0; + } + auto& range = getRange(c); auto mapper = range.getLowMapper(); if (!mapper) return 0; @@ -370,6 +374,10 @@ static std::vector, std::atomic_uint*>> s_extra_arenas; static unsigned s_extra_arena_per_node; bool setup_extra_arenas(unsigned count) { + if constexpr (!use_position_dependent_jemalloc_arenas) { + return false; + } + if (count == 0) return false; // This may be called when we have many other threads running. So hold the // lock while making changes. @@ -470,6 +478,10 @@ void setup_local_arenas(PageSpec spec, unsigned slabs) { } } + if constexpr (!use_position_dependent_jemalloc_arenas) { + return; + } + #ifdef __x86_64__ spec.n1GPages = std::min(spec.n1GPages, get_huge1g_info().nr_hugepages); spec.n2MPages = std::min(spec.n2MPages, get_huge2m_info().nr_hugepages); @@ -583,101 +595,119 @@ struct JEMallocInitializer { init_numa(); #ifdef USE_JEMALLOC - unsigned low_1g_pages = 0; - if (char* buffer = getenv("HHVM_LOW_1G_PAGE")) { - if (!sscanf(buffer, "%u", &low_1g_pages)) { - fprintf(stderr, - "Bad environment variable HHVM_LOW_1G_PAGE: %s\n", buffer); - abort(); + if constexpr (use_position_dependent_jemalloc_arenas) { + unsigned low_1g_pages = 0; + if (char* buffer = getenv("HHVM_LOW_1G_PAGE")) { + if (!sscanf(buffer, "%u", &low_1g_pages)) { + fprintf(stderr, + "Bad environment variable HHVM_LOW_1G_PAGE: %s\n", buffer); + abort(); + } } - } - unsigned high_1g_pages = 0; - if (char* buffer = getenv("HHVM_HIGH_1G_PAGE")) { - if (!sscanf(buffer, "%u", &high_1g_pages)) { - fprintf(stderr, - "Bad environment variable HHVM_HIGH_1G_PAGE: %s\n", buffer); - abort(); + unsigned high_1g_pages = 0; + if (char* buffer = getenv("HHVM_HIGH_1G_PAGE")) { + if (!sscanf(buffer, "%u", &high_1g_pages)) { + fprintf(stderr, + "Bad environment variable HHVM_HIGH_1G_PAGE: %s\n", buffer); + abort(); + } } - } - unsigned low_2m_pages = 0; - if (char* buffer = getenv("HHVM_LOW_2M_PAGE")) { - if (!sscanf(buffer, "%u", &low_2m_pages)) { - fprintf(stderr, - "Bad environment variable HHVM_LOW_2M_PAGE: %s\n", buffer); - abort(); + unsigned low_2m_pages = 0; + if (char* buffer = getenv("HHVM_LOW_2M_PAGE")) { + if (!sscanf(buffer, "%u", &low_2m_pages)) { + fprintf(stderr, + "Bad environment variable HHVM_LOW_2M_PAGE: %s\n", buffer); + abort(); + } } - } - unsigned high_2m_pages = 0; - if (char* buffer = getenv("HHVM_HIGH_2M_PAGE")) { - if (!sscanf(buffer, "%u", &high_2m_pages)) { - fprintf(stderr, - "Bad environment variable HHVM_HIGH_2M_PAGE: %s\n", buffer); - abort(); + unsigned high_2m_pages = 0; + if (char* buffer = getenv("HHVM_HIGH_2M_PAGE")) { + if (!sscanf(buffer, "%u", &high_2m_pages)) { + fprintf(stderr, + "Bad environment variable HHVM_HIGH_2M_PAGE: %s\n", buffer); + abort(); + } } - } - // Do some reallocation between low and high 1G arenas based on the total - // number of pages reserved. - HugePageInfo info = get_huge1g_info(); - unsigned remaining = static_cast(info.nr_hugepages); - if (low_1g_pages > 2) low_1g_pages = 2; -#ifdef __x86_64__ - auto const origLow1G = low_1g_pages; - if (remaining == 0) { - low_1g_pages = high_1g_pages = 0; - } else if (low_1g_pages > 0 || high_1g_pages > 0) { - KernelVersion version; - if (version.m_major < 3 || - (version.m_major == 3 && version.m_minor < 9)) { - // Older kernels need an explicit hugetlbfs mount point. - find_hugetlbfs_path() || auto_mount_hugetlbfs(); + // Do some reallocation between low and high 1G arenas based on the total + // number of pages reserved. + HugePageInfo info = get_huge1g_info(); + unsigned remaining = static_cast(info.nr_hugepages); + if (low_1g_pages > 2) low_1g_pages = 2; + #ifdef __x86_64__ + auto const origLow1G = low_1g_pages; + if (remaining == 0) { + low_1g_pages = high_1g_pages = 0; + } else if (low_1g_pages > 0 || high_1g_pages > 0) { + KernelVersion version; + if (version.m_major < 3 || + (version.m_major == 3 && version.m_minor < 9)) { + // Older kernels need an explicit hugetlbfs mount point. + find_hugetlbfs_path() || auto_mount_hugetlbfs(); + } } - } - if (low_1g_pages > 0) { - if (low_1g_pages + high_1g_pages > remaining) { - low_1g_pages = 1; + if (low_1g_pages > 0) { + if (low_1g_pages + high_1g_pages > remaining) { + low_1g_pages = 1; + } + assert(remaining >= low_1g_pages); + remaining -= low_1g_pages; } - assert(remaining >= low_1g_pages); - remaining -= low_1g_pages; - } - if (origLow1G) { - fprintf(stderr, - "using %u (specified %u) 1G huge pages for low arena\n", - low_1g_pages, origLow1G); - } -#else - if (low_1g_pages && !remaining) { - fprintf(stderr, - "specified %u 1G huge pages for low arena but the host doesn't " - "have any, will try to use THP\n", - low_1g_pages); - } -#endif + if (origLow1G) { + fprintf(stderr, + "using %u (specified %u) 1G huge pages for low arena\n", + low_1g_pages, origLow1G); + } + #else + if (low_1g_pages && !remaining) { + fprintf(stderr, + "specified %u 1G huge pages for low arena but the host doesn't " + "have any, will try to use THP\n", + low_1g_pages); + } + #endif - setup_low_arena({low_1g_pages, low_2m_pages}); -#ifdef __x86_64__ - auto const origHigh1G = high_1g_pages; - if (high_1g_pages > remaining) { - high_1g_pages = remaining; - } - if (origHigh1G) { - fprintf(stderr, - "using %u (specified %u) 1G huge pages for high arena\n", - high_1g_pages, origHigh1G); - } -#else - if (high_1g_pages && !remaining) { - fprintf(stderr, - "specified %u 1G huge pages for high arena but the host doesn't " - "have any, will try to use THP\n", - high_1g_pages); + setup_low_arena({low_1g_pages, low_2m_pages}); + #ifdef __x86_64__ + auto const origHigh1G = high_1g_pages; + if (high_1g_pages > remaining) { + high_1g_pages = remaining; + } + if (origHigh1G) { + fprintf(stderr, + "using %u (specified %u) 1G huge pages for high arena\n", + high_1g_pages, origHigh1G); + } + #else + if (high_1g_pages && !remaining) { + fprintf(stderr, + "specified %u 1G huge pages for high arena but the host doesn't " + "have any, will try to use THP\n", + high_1g_pages); + } + #endif + setup_high_arena({high_1g_pages, high_2m_pages}); + // Make sure high/low arenas are available to the current thread. + arenas_thread_init(); + } else { + // Create the legacy low arena that uses brk() instead of mmap(). When + // using newer versions of jemalloc, we use extent hooks to get more + // control. If the mallctl fails, it will always_assert in mallctlHelper. + if (mallctlRead("arenas.create", &low_arena)) { + return; + } + char buf[32]; + snprintf(buf, sizeof(buf), "arena.%u.dss", low_arena); + if (mallctlWrite(buf, "primary") != 0) { + // Error; bail out. + return; + } + low_arena_flags = MALLOCX_ARENA(low_arena) | MALLOCX_TCACHE_NONE; + low_small_arena = low_arena; + low_small_arena_flags = low_arena_flags; } -#endif - setup_high_arena({high_1g_pages, high_2m_pages}); - // Make sure high/low arenas are available to the current thread. - arenas_thread_init(); // Initialize global mibs init_mallctl_mibs(); diff --git a/hphp/util/alloc.h b/hphp/util/alloc.h index 29b697cbb318fd..bbccbe9307d89b 100644 --- a/hphp/util/alloc.h +++ b/hphp/util/alloc.h @@ -321,7 +321,7 @@ struct WrapAllocator { // Helpers (malloc, free, sized_free) to allocate/deallocate on a specific arena // given flags. When not using jemalloc generic malloc/free will be used. #if USE_JEMALLOC -#define DEF_ALLOC_FUNCS(prefix, flag, upper_prefix) \ +#define DEF_JEMALLOC_ALLOC_FUNCS(prefix, flag, upper_prefix) \ inline void* prefix##_malloc(size_t size) { \ assert(size != 0); \ return mallocx(size, flag); \ @@ -339,9 +339,11 @@ struct WrapAllocator { assert(sallocx(ptr, flag) == nallocx(size, flag)); \ return sdallocx(ptr, size, flag); \ } \ - \ template using upper_prefix##Allocator = \ - WrapAllocator; + WrapAllocator; + +#define DEF_ALLOC_FUNCS(prefix, flag, upper_prefix) \ + DEF_JEMALLOC_ALLOC_FUNCS(prefix, flag, upper_prefix) #else #define DEF_ALLOC_FUNCS(prefix, flag, upper_prefix) \ inline void* prefix##_malloc(size_t size) { \ @@ -383,9 +385,29 @@ DEF_ALLOC_FUNCS(apc, HIGH_ARENA_FLAGS, APC) // Thread-local allocations that are not accessed outside the thread. DEF_ALLOC_FUNCS(local, local_arena_flags, Local) +#if USE_JEMALLOC && !defined(HHVM_PIE) DEF_ALLOC_FUNCS(low, low_arena_flags, Low) DEF_ALLOC_FUNCS(small, low_small_arena_flags, Small) +#else +DEF_JEMALLOC_ALLOC_FUNCS(low, low_arena_flags, Low) + +inline void* small_malloc(size_t size) { + return low_malloc(size); +} +inline void small_free(void* ptr) { + return low_free(ptr); +} +inline void* small_realloc(void* ptr, size_t size) { + return low_realloc(ptr, size); +} +inline void small_sized_free(void* ptr, size_t size) { + return low_free(ptr); +} + +template using SmallAllocator = WrapAllocator; +#endif +#undef DEF_JEMALLOC_ALLOC_FUNCS #undef DEF_ALLOC_FUNCS using SwappableReadonlyArena = ReadOnlyArena, false, 8>; diff --git a/hphp/util/eh-frame.h b/hphp/util/eh-frame.h index 8ec0c5da7a624e..278cac6e3c9e2f 100644 --- a/hphp/util/eh-frame.h +++ b/hphp/util/eh-frame.h @@ -30,6 +30,9 @@ #include #include +#ifdef LIBDWARF_USE_NEW_PRODUCER_API +#include +#endif namespace HPHP { diff --git a/hphp/util/hphp-config.h.in b/hphp/util/hphp-config.h.in index a63b1cc35f3202..393b3b586a052b 100644 --- a/hphp/util/hphp-config.h.in +++ b/hphp/util/hphp-config.h.in @@ -39,11 +39,9 @@ */ #ifdef USE_CMAKE -#cmakedefine ENABLE_AVX2 1 #cmakedefine ENABLE_AARCH64_CRC 1 #cmakedefine EXECUTION_PROFILER 1 #else -/* #undef ENABLE_AVX2 */ /* #undef ENABLE_AARCH64_CRC */ /* #undef EXECUTION_PROFILER */ #endif @@ -90,7 +88,7 @@ ${HHVM_COMPILES_DEFINE_STRING} #endif #ifdef USE_CMAKE -# if ${HHVM_EXTENSION_COUNT} != 99 +# if ${HHVM_EXTENSION_COUNT} != 100 # error You need to update the config file for the new builtin extension, and add the define to the FB section # endif ${HHVM_EXTENSIONS_ENABLED_DEFINE_STRING} diff --git a/hphp/util/memset-x64-avx2.S b/hphp/util/memset-x64-avx2.S index 2cbf543b465342..be5ee84314a94a 100644 --- a/hphp/util/memset-x64-avx2.S +++ b/hphp/util/memset-x64-avx2.S @@ -101,7 +101,7 @@ ETCH_LABEL(more_than_63bytes): addq %rax, %rcx subq %rax, %rdx je ETCH_LABEL(EXIT_MEMSET) - + ETCH_ALIGN8 ETCH_ALIGN4 ETCH_LABEL(128byte_loop_data_guzzler): diff --git a/hphp/util/process.cpp b/hphp/util/process.cpp index 8bdf320136de5a..d3cbf425d0a7b9 100644 --- a/hphp/util/process.cpp +++ b/hphp/util/process.cpp @@ -34,6 +34,7 @@ #include #include +#include "hphp/util/alloc-defs.h" #include "hphp/util/hugetlb.h" #include "hphp/util/managed-arena.h" #include "hphp/util/user-info.h" @@ -421,21 +422,24 @@ void ProcStatus::update() { } #ifdef USE_JEMALLOC mallctl_epoch(); - size_t unused = 0; - // Various arenas where range of hugetlb pages can be reserved but only - // partially used. - unused += alloc::getRange(alloc::AddrRangeClass::Low).retained(); -#ifdef USE_PACKEDPTR - unused += alloc::getRange(alloc::AddrRangeClass::Mid).retained(); -#endif - unused += alloc::getRange(alloc::AddrRangeClass::Uncounted).retained(); - for (auto const arena : alloc::g_auto_arenas) { - if (arena) unused += arena->retained(); - } - for (auto const arena : alloc::g_local_arenas) { - if (arena) unused += arena->retained(); + + if constexpr (use_position_dependent_jemalloc_arenas) { + size_t unused = 0; + // Various arenas where range of hugetlb pages can be reserved but only + // partially used. + unused += alloc::getRange(alloc::AddrRangeClass::Low).retained(); + #ifdef USE_PACKEDPTR + unused += alloc::getRange(alloc::AddrRangeClass::Mid).retained(); + #endif + unused += alloc::getRange(alloc::AddrRangeClass::Uncounted).retained(); + for (auto const arena : alloc::g_auto_arenas) { + if (arena) unused += arena->retained(); + } + for (auto const arena : alloc::g_local_arenas) { + if (arena) unused += arena->retained(); + } + updateUnused(unused >> 10); // convert to kB } - updateUnused(unused >> 10); // convert to kB #endif } } diff --git a/hphp/zend/CMakeLists.txt b/hphp/zend/CMakeLists.txt index 0eec537b30da3a..2f9dd291495152 100644 --- a/hphp/zend/CMakeLists.txt +++ b/hphp/zend/CMakeLists.txt @@ -10,7 +10,7 @@ set(HEADER_SOURCES) auto_sources(files "*.h" "RECURSE") list(APPEND HEADER_SOURCES ${files}) -if (NOT MSVC AND NOT APPLE) +if (NOT APPLE) list(REMOVE_ITEM CXX_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/crypt-freesec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/crypt-sha256.cpp diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 5642df2630c843..24e479868f52df 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -50,6 +50,7 @@ list(APPEND THIRD_PARTY_MODULES timelib) # Required by folly add_subdirectory(double-conversion) add_subdirectory(boost) +add_subdirectory(fast_float) add_subdirectory(fmt) add_subdirectory(jemalloc) add_subdirectory(libsodium) @@ -140,3 +141,5 @@ endif() ##### --- new style, but only depends on old style --- ##### add_subdirectory(watchman) + +add_subdirectory(usdt) diff --git a/third-party/fast_float/CMakeLists.txt b/third-party/fast_float/CMakeLists.txt new file mode 100644 index 00000000000000..88bc2f9b330ed8 --- /dev/null +++ b/third-party/fast_float/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(fast_float INTERFACE) +target_include_directories(fast_float INTERFACE "${CMAKE_CURRENT_LIST_DIR}") diff --git a/third-party/fast_float/fast_float/fast_float.h b/third-party/fast_float/fast_float/fast_float.h new file mode 100644 index 00000000000000..f1712168b59b7d --- /dev/null +++ b/third-party/fast_float/fast_float/fast_float.h @@ -0,0 +1,4025 @@ +// fast_float by Daniel Lemire +// fast_float by João Paulo Magalhaes +// +// +// with contributions from Eugene Golushkov +// with contributions from Maksim Kita +// with contributions from Marcin Wojdyr +// with contributions from Neal Richardson +// with contributions from Tim Paine +// with contributions from Fabio Pellacini +// with contributions from Lénárd Szolnoki +// with contributions from Jan Pharago +// with contributions from Maya Warrier +// with contributions from Taha Khokhar +// with contributions from Anders Dalvander +// +// +// Licensed under the Apache License, Version 2.0, or the +// MIT License or the Boost License. This file may not be copied, +// modified, or distributed except according to those terms. +// +// MIT License Notice +// +// MIT License +// +// Copyright (c) 2021 The fast_float authors +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Apache License (Version 2.0) Notice +// +// Copyright 2021 The fast_float authors +// 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 +// +// BOOST License Notice +// +// Boost Software License - Version 1.0 - August 17th, 2003 +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// + +#ifndef FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H +#define FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H + +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + +// Testing for https://wg21.link/N3652, adopted in C++14 +#if __cpp_constexpr >= 201304 +#define FASTFLOAT_CONSTEXPR14 constexpr +#else +#define FASTFLOAT_CONSTEXPR14 +#endif + +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#define FASTFLOAT_HAS_BIT_CAST 1 +#else +#define FASTFLOAT_HAS_BIT_CAST 0 +#endif + +#if defined(__cpp_lib_is_constant_evaluated) && \ + __cpp_lib_is_constant_evaluated >= 201811L +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1 +#else +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0 +#endif + +// Testing for relevant C++20 constexpr library features +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \ + __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/ +#define FASTFLOAT_CONSTEXPR20 constexpr +#define FASTFLOAT_IS_CONSTEXPR 1 +#else +#define FASTFLOAT_CONSTEXPR20 +#define FASTFLOAT_IS_CONSTEXPR 0 +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 0 +#else +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 1 +#endif + +#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H + +#ifndef FASTFLOAT_FLOAT_COMMON_H +#define FASTFLOAT_FLOAT_COMMON_H + +#include +#include +#include +#include +#include +#include +#ifdef __has_include +#if __has_include() && (__cplusplus > 202002L || _MSVC_LANG > 202002L) +#include +#endif +#endif + +namespace fast_float { + +enum class chars_format : uint64_t; + +namespace detail { +constexpr chars_format basic_json_fmt = chars_format(1 << 5); +constexpr chars_format basic_fortran_fmt = chars_format(1 << 6); +} // namespace detail + +enum class chars_format : uint64_t { + scientific = 1 << 0, + fixed = 1 << 2, + hex = 1 << 3, + no_infnan = 1 << 4, + // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6 + json = uint64_t(detail::basic_json_fmt) | fixed | scientific | no_infnan, + // Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed. + json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific, + fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific, + general = fixed | scientific, + allow_leading_plus = 1 << 7, + skip_white_space = 1 << 8, +}; + +template struct from_chars_result_t { + UC const *ptr; + std::errc ec; +}; +using from_chars_result = from_chars_result_t; + +template struct parse_options_t { + constexpr explicit parse_options_t(chars_format fmt = chars_format::general, + UC dot = UC('.'), int b = 10) + : format(fmt), decimal_point(dot), base(b) {} + + /** Which number formats are accepted */ + chars_format format; + /** The character used as decimal point */ + UC decimal_point; + /** The base used for integers */ + int base; +}; +using parse_options = parse_options_t; + +} // namespace fast_float + +#if FASTFLOAT_HAS_BIT_CAST +#include +#endif + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) || \ + defined(__MINGW64__) || defined(__s390x__) || \ + (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \ + defined(__PPC64LE__)) || \ + defined(__loongarch64)) +#define FASTFLOAT_64BIT 1 +#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \ + defined(__MINGW32__) || defined(__EMSCRIPTEN__)) +#define FASTFLOAT_32BIT 1 +#else + // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. +// We can never tell the register width, but the SIZE_MAX is a good +// approximation. UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max +// portability. +#if SIZE_MAX == 0xffff +#error Unknown platform (16-bit, unsupported) +#elif SIZE_MAX == 0xffffffff +#define FASTFLOAT_32BIT 1 +#elif SIZE_MAX == 0xffffffffffffffff +#define FASTFLOAT_64BIT 1 +#else +#error Unknown platform (not 32-bit, not 64-bit?) +#endif +#endif + +#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) || \ + (defined(_M_ARM64) && !defined(__MINGW32__)) +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define FASTFLOAT_VISUAL_STUDIO 1 +#endif + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(sun) || defined(__sun) +#include +#elif defined(__MVS__) +#include +#else +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#define FASTFLOAT_IS_BIG_ENDIAN 1 +#endif +#endif + +#if defined(__SSE2__) || (defined(FASTFLOAT_VISUAL_STUDIO) && \ + (defined(_M_AMD64) || defined(_M_X64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP == 2))) +#define FASTFLOAT_SSE2 1 +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +#define FASTFLOAT_NEON 1 +#endif + +#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON) +#define FASTFLOAT_HAS_SIMD 1 +#endif + +#if defined(__GNUC__) +// disable -Wcast-align=strict (GCC only) +#define FASTFLOAT_SIMD_DISABLE_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-align\"") +#else +#define FASTFLOAT_SIMD_DISABLE_WARNINGS +#endif + +#if defined(__GNUC__) +#define FASTFLOAT_SIMD_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") +#else +#define FASTFLOAT_SIMD_RESTORE_WARNINGS +#endif + +#ifdef FASTFLOAT_VISUAL_STUDIO +#define fastfloat_really_inline __forceinline +#else +#define fastfloat_really_inline inline __attribute__((always_inline)) +#endif + +#ifndef FASTFLOAT_ASSERT +#define FASTFLOAT_ASSERT(x) \ + { ((void)(x)); } +#endif + +#ifndef FASTFLOAT_DEBUG_ASSERT +#define FASTFLOAT_DEBUG_ASSERT(x) \ + { ((void)(x)); } +#endif + +// rust style `try!()` macro, or `?` operator +#define FASTFLOAT_TRY(x) \ + { \ + if (!(x)) \ + return false; \ + } + +#define FASTFLOAT_ENABLE_IF(...) \ + typename std::enable_if<(__VA_ARGS__), int>::type + +namespace fast_float { + +fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() { +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED + return std::is_constant_evaluated(); +#else + return false; +#endif +} + +template +fastfloat_really_inline constexpr bool is_supported_float_type() { + return std::is_same::value || std::is_same::value +#if __STDCPP_FLOAT32_T__ + || std::is_same::value +#endif +#if __STDCPP_FLOAT64_T__ + || std::is_same::value +#endif + ; +} + +template +fastfloat_really_inline constexpr bool is_supported_char_type() { + return std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value; +} + +// Compares two ASCII strings in a case insensitive manner. +template +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, + size_t length) { + for (size_t i = 0; i < length; ++i) { + UC const actual = actual_mixedcase[i]; + if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) { + return false; + } + } + return true; +} + +#ifndef FLT_EVAL_METHOD +#error "FLT_EVAL_METHOD should be defined, please include cfloat." +#endif + +// a pointer and a length to a contiguous block of memory +template struct span { + const T *ptr; + size_t length; + constexpr span(const T *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + constexpr span() : ptr(nullptr), length(0) {} + + constexpr size_t len() const noexcept { return length; } + + FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return ptr[index]; + } +}; + +struct value128 { + uint64_t low; + uint64_t high; + constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} + constexpr value128() : low(0), high(0) {} +}; + +/* Helper C++14 constexpr generic implementation of leading_zeroes */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int +leading_zeroes_generic(uint64_t input_num, int last_bit = 0) { + if (input_num & uint64_t(0xffffffff00000000)) { + input_num >>= 32; + last_bit |= 32; + } + if (input_num & uint64_t(0xffff0000)) { + input_num >>= 16; + last_bit |= 16; + } + if (input_num & uint64_t(0xff00)) { + input_num >>= 8; + last_bit |= 8; + } + if (input_num & uint64_t(0xf0)) { + input_num >>= 4; + last_bit |= 4; + } + if (input_num & uint64_t(0xc)) { + input_num >>= 2; + last_bit |= 2; + } + if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */ + last_bit |= 1; + } + return 63 - last_bit; +} + +/* result might be undefined when input_num is zero */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int +leading_zeroes(uint64_t input_num) { + assert(input_num > 0); + if (cpp20_and_in_constexpr()) { + return leading_zeroes_generic(input_num); + } +#ifdef FASTFLOAT_VISUAL_STUDIO +#if defined(_M_X64) || defined(_M_ARM64) + unsigned long leading_zero = 0; + // Search the mask data from most significant bit (MSB) + // to least significant bit (LSB) for a set bit (1). + _BitScanReverse64(&leading_zero, input_num); + return (int)(63 - leading_zero); +#else + return leading_zeroes_generic(input_num); +#endif +#else + return __builtin_clzll(input_num); +#endif +} + +// slow emulation routine for 32-bit +fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) { + return x * (uint64_t)y; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) { + uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); + uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); + uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); + uint64_t adbc_carry = (uint64_t)(adbc < ad); + uint64_t lo = bd + (adbc << 32); + *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + + (adbc_carry << 32) + (uint64_t)(lo < bd); + return lo; +} + +#ifdef FASTFLOAT_32BIT + +// slow emulation routine for 32-bit +#if !defined(__MINGW64__) +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t _umul128(uint64_t ab, + uint64_t cd, + uint64_t *hi) { + return umul128_generic(ab, cd, hi); +} +#endif // !__MINGW64__ + +#endif // FASTFLOAT_32BIT + +// compute 64-bit a*b +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +full_multiplication(uint64_t a, uint64_t b) { + if (cpp20_and_in_constexpr()) { + value128 answer; + answer.low = umul128_generic(a, b, &answer.high); + return answer; + } + value128 answer; +#if defined(_M_ARM64) && !defined(__MINGW32__) + // ARM64 has native support for 64-bit multiplications, no need to emulate + // But MinGW on ARM64 doesn't have native support for 64-bit multiplications + answer.high = __umulh(a, b); + answer.low = a * b; +#elif defined(FASTFLOAT_32BIT) || \ + (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64)) + answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 +#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) + __uint128_t r = ((__uint128_t)a) * b; + answer.low = uint64_t(r); + answer.high = uint64_t(r >> 64); +#else + answer.low = umul128_generic(a, b, &answer.high); +#endif + return answer; +} + +struct adjusted_mantissa { + uint64_t mantissa{0}; + int32_t power2{0}; // a negative value indicates an invalid result + adjusted_mantissa() = default; + constexpr bool operator==(const adjusted_mantissa &o) const { + return mantissa == o.mantissa && power2 == o.power2; + } + constexpr bool operator!=(const adjusted_mantissa &o) const { + return mantissa != o.mantissa || power2 != o.power2; + } +}; + +// Bias so we can get the real exponent with an invalid adjusted_mantissa. +constexpr static int32_t invalid_am_bias = -0x8000; + +// used for binary_format_lookup_tables::max_mantissa +constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; + +template struct binary_format_lookup_tables; + +template struct binary_format : binary_format_lookup_tables { + using equiv_uint = + typename std::conditional::type; + + static inline constexpr int mantissa_explicit_bits(); + static inline constexpr int minimum_exponent(); + static inline constexpr int infinite_power(); + static inline constexpr int sign_index(); + static inline constexpr int + min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST + static inline constexpr int max_exponent_fast_path(); + static inline constexpr int max_exponent_round_to_even(); + static inline constexpr int min_exponent_round_to_even(); + static inline constexpr uint64_t max_mantissa_fast_path(int64_t power); + static inline constexpr uint64_t + max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST + static inline constexpr int largest_power_of_ten(); + static inline constexpr int smallest_power_of_ten(); + static inline constexpr T exact_power_of_ten(int64_t power); + static inline constexpr size_t max_digits(); + static inline constexpr equiv_uint exponent_mask(); + static inline constexpr equiv_uint mantissa_mask(); + static inline constexpr equiv_uint hidden_bit_mask(); +}; + +template struct binary_format_lookup_tables { + static constexpr double powers_of_ten[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; + + // Largest integer value v so that (5**index * v) <= 1<<53. + // 0x20000000000000 == 1 << 53 + static constexpr uint64_t max_mantissa[] = { + 0x20000000000000, + 0x20000000000000 / 5, + 0x20000000000000 / (5 * 5), + 0x20000000000000 / (5 * 5 * 5), + 0x20000000000000 / (5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555), + 0x20000000000000 / (constant_55555 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr double binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template struct binary_format_lookup_tables { + static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, + 1e6f, 1e7f, 1e8f, 1e9f, 1e10f}; + + // Largest integer value v so that (5**index * v) <= 1<<24. + // 0x1000000 == 1<<24 + static constexpr uint64_t max_mantissa[] = { + 0x1000000, + 0x1000000 / 5, + 0x1000000 / (5 * 5), + 0x1000000 / (5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5), + 0x1000000 / (constant_55555), + 0x1000000 / (constant_55555 * 5), + 0x1000000 / (constant_55555 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * constant_55555), + 0x1000000 / (constant_55555 * constant_55555 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr float binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -22; +#endif +} + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -10; +#endif +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 52; +} +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 10; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -4; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -17; +} + +template <> inline constexpr int binary_format::minimum_exponent() { + return -1023; +} +template <> inline constexpr int binary_format::minimum_exponent() { + return -127; +} + +template <> inline constexpr int binary_format::infinite_power() { + return 0x7FF; +} +template <> inline constexpr int binary_format::infinite_power() { + return 0xFF; +} + +template <> inline constexpr int binary_format::sign_index() { + return 63; +} +template <> inline constexpr int binary_format::sign_index() { + return 31; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 22; +} +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 10; +} + +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 22 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 10 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr double +binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} +template <> +inline constexpr float binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 308; +} +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 38; +} + +template <> +inline constexpr int binary_format::smallest_power_of_ten() { + return -342; +} +template <> inline constexpr int binary_format::smallest_power_of_ten() { + return -64; +} + +template <> inline constexpr size_t binary_format::max_digits() { + return 769; +} +template <> inline constexpr size_t binary_format::max_digits() { + return 114; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7F800000; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7FF0000000000000; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x007FFFFF; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x000FFFFFFFFFFFFF; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x00800000; +} +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x0010000000000000; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +to_float(bool negative, adjusted_mantissa am, T &value) { + using fastfloat_uint = typename binary_format::equiv_uint; + fastfloat_uint word = (fastfloat_uint)am.mantissa; + word |= fastfloat_uint(am.power2) + << binary_format::mantissa_explicit_bits(); + word |= fastfloat_uint(negative) << binary_format::sign_index(); +#if FASTFLOAT_HAS_BIT_CAST + value = std::bit_cast(word); +#else + ::memcpy(&value, &word, sizeof(T)); +#endif +} + +template struct space_lut { + static constexpr bool value[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr bool space_lut::value[]; + +#endif + +template constexpr bool is_space(UC c) { + return c < 256 && space_lut<>::value[uint8_t(c)]; +} + +template static constexpr uint64_t int_cmp_zeros() { + static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), + "Unsupported character size"); + return (sizeof(UC) == 1) ? 0x3030303030303030 + : (sizeof(UC) == 2) + ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | + uint64_t(UC('0')) << 16 | UC('0')) + : (uint64_t(UC('0')) << 32 | UC('0')); +} +template static constexpr int int_cmp_len() { + return sizeof(uint64_t) / sizeof(UC); +} +template static constexpr UC const *str_const_nan() { + return nullptr; +} +template <> constexpr char const *str_const_nan() { return "nan"; } +template <> constexpr wchar_t const *str_const_nan() { return L"nan"; } +template <> constexpr char16_t const *str_const_nan() { + return u"nan"; +} +template <> constexpr char32_t const *str_const_nan() { + return U"nan"; +} +template static constexpr UC const *str_const_inf() { + return nullptr; +} +template <> constexpr char const *str_const_inf() { return "infinity"; } +template <> constexpr wchar_t const *str_const_inf() { + return L"infinity"; +} +template <> constexpr char16_t const *str_const_inf() { + return u"infinity"; +} +template <> constexpr char32_t const *str_const_inf() { + return U"infinity"; +} + +template struct int_luts { + static constexpr uint8_t chdigit[] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, + 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255}; + + static constexpr size_t maxdigits_u64[] = { + 64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13}; + + static constexpr uint64_t min_safe_u64[] = { + 9223372036854775808ull, 12157665459056928801ull, 4611686018427387904, + 7450580596923828125, 4738381338321616896, 3909821048582988049, + 9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull, + 5559917313492231481, 2218611106740436992, 8650415919381337933, + 2177953337809371136, 6568408355712890625, 1152921504606846976, + 2862423051509815793, 6746640616477458432, 15181127029874798299ull, + 1638400000000000000, 3243919932521508681, 6221821273427820544, + 11592836324538749809ull, 876488338465357824, 1490116119384765625, + 2481152873203736576, 4052555153018976267, 6502111422497947648, + 10260628712958602189ull, 15943230000000000000ull, 787662783788549761, + 1152921504606846976, 1667889514952984961, 2386420683693101056, + 3379220508056640625, 4738381338321616896}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint8_t int_luts::chdigit[]; + +template constexpr size_t int_luts::maxdigits_u64[]; + +template constexpr uint64_t int_luts::min_safe_u64[]; + +#endif + +template +fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) { + return int_luts<>::chdigit[static_cast(c)]; +} + +fastfloat_really_inline constexpr size_t max_digits_u64(int base) { + return int_luts<>::maxdigits_u64[base - 2]; +} + +// If a u64 is exactly max_digits_u64() in length, this is +// the value below which it has definitely overflowed. +fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) { + return int_luts<>::min_safe_u64[base - 2]; +} + +constexpr chars_format operator~(chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(~static_cast(rhs)); +} + +constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) & + static_cast(rhs)); +} + +constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} + +constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) ^ + static_cast(rhs)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator&=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs & rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator|=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs | rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator^=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs ^ rhs); +} + +namespace detail { +// adjust for deprecated feature macros +constexpr chars_format adjust_for_feature_macros(chars_format fmt) { + return fmt +#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS + | chars_format::allow_leading_plus +#endif +#ifdef FASTFLOAT_SKIP_WHITE_SPACE + | chars_format::skip_white_space +#endif + ; +} +} // namespace detail + +} // namespace fast_float + +#endif + + +#ifndef FASTFLOAT_FAST_FLOAT_H +#define FASTFLOAT_FAST_FLOAT_H + + +namespace fast_float { +/** + * This function parses the character sequence [first,last) for a number. It + * parses floating-point numbers expecting a locale-indepent format equivalent + * to what is used by std::strtod in the default ("C") locale. The resulting + * floating-point value is the closest floating-point values (using either float + * or double), using the "round to even" convention for values that would + * otherwise fall right in-between two values. That is, we provide exact parsing + * according to the IEEE standard. + * + * Given a successful parse, the pointer (`ptr`) in the returned value is set to + * point right after the parsed number, and the `value` referenced is set to the + * parsed value. In case of error, the returned `ec` contains a representative + * error, otherwise the default (`std::errc()`) value is stored. + * + * The implementation does not throw and does not allocate memory (e.g., with + * `new` or `malloc`). + * + * Like the C++17 standard, the `fast_float::from_chars` functions take an + * optional last argument of the type `fast_float::chars_format`. It is a bitset + * value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt & + * fast_float::chars_format::scientific` are set to determine whether we allow + * the fixed point and scientific notation respectively. The default is + * `fast_float::chars_format::general` which allows both `fixed` and + * `scientific`. + */ +template ())> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt = chars_format::general) noexcept; + +/** + * Like from_chars, but accepts an `options` argument to govern number parsing. + * Both for floating-point types and integer types. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept; + +/** + * from_chars for integer types. + */ +template ())> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept; + +} // namespace fast_float +#endif // FASTFLOAT_FAST_FLOAT_H + +#ifndef FASTFLOAT_ASCII_NUMBER_H +#define FASTFLOAT_ASCII_NUMBER_H + +#include +#include +#include +#include +#include +#include + + +#ifdef FASTFLOAT_SSE2 +#include +#endif + +#ifdef FASTFLOAT_NEON +#include +#endif + +namespace fast_float { + +template fastfloat_really_inline constexpr bool has_simd_opt() { +#ifdef FASTFLOAT_HAS_SIMD + return std::is_same::value; +#else + return false; +#endif +} + +// Next function can be micro-optimized, but compilers are entirely +// able to optimize it well. +template +fastfloat_really_inline constexpr bool is_integer(UC c) noexcept { + return !(c > UC('9') || c < UC('0')); +} + +fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { + return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 | + (val & 0x0000FF0000000000) >> 24 | (val & 0x000000FF00000000) >> 8 | + (val & 0x00000000FF000000) << 8 | (val & 0x0000000000FF0000) << 24 | + (val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56; +} + +// Read 8 UC into a u64. Truncates UC if not char. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +read8_to_u64(const UC *chars) { + if (cpp20_and_in_constexpr() || !std::is_same::value) { + uint64_t val = 0; + for (int i = 0; i < 8; ++i) { + val |= uint64_t(uint8_t(*chars)) << (i * 8); + ++chars; + } + return val; + } + uint64_t val; + ::memcpy(&val, chars, sizeof(uint64_t)); +#if FASTFLOAT_IS_BIG_ENDIAN == 1 + // Need to read as-if the number was in little-endian order. + val = byteswap(val); +#endif + return val; +} + +#ifdef FASTFLOAT_SSE2 + +fastfloat_really_inline uint64_t simd_read8_to_u64(const __m128i data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + const __m128i packed = _mm_packus_epi16(data, data); +#ifdef FASTFLOAT_64BIT + return uint64_t(_mm_cvtsi128_si64(packed)); +#else + uint64_t value; + // Visual Studio + older versions of GCC don't support _mm_storeu_si64 + _mm_storel_epi64(reinterpret_cast<__m128i *>(&value), packed); + return value; +#endif + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + _mm_loadu_si128(reinterpret_cast(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#elif defined(FASTFLOAT_NEON) + +fastfloat_really_inline uint64_t simd_read8_to_u64(const uint16x8_t data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + uint8x8_t utf8_packed = vmovn_u16(data); + return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(const char16_t *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + vld1q_u16(reinterpret_cast(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#endif // FASTFLOAT_SSE2 + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +uint64_t simd_read8_to_u64(UC const *) { + return 0; +} + +// credit @aqrit +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t +parse_eight_digits_unrolled(uint64_t val) { + const uint64_t mask = 0x000000FF000000FF; + const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) + const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) + val -= 0x3030303030303030; + val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; + val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; + return uint32_t(val); +} + +// Call this if chars are definitely 8 digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t +parse_eight_digits_unrolled(UC const *chars) noexcept { + if (cpp20_and_in_constexpr() || !has_simd_opt()) { + return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay + } + return parse_eight_digits_unrolled(simd_read8_to_u64(chars)); +} + +// credit @aqrit +fastfloat_really_inline constexpr bool +is_made_of_eight_digits_fast(uint64_t val) noexcept { + return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & + 0x8080808080808080)); +} + +#ifdef FASTFLOAT_HAS_SIMD + +// Call this if chars might not be 8 digits. +// Using this style (instead of is_made_of_eight_digits_fast() then +// parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +simd_parse_if_eight_digits_unrolled(const char16_t *chars, + uint64_t &i) noexcept { + if (cpp20_and_in_constexpr()) { + return false; + } +#ifdef FASTFLOAT_SSE2 + FASTFLOAT_SIMD_DISABLE_WARNINGS + const __m128i data = + _mm_loadu_si128(reinterpret_cast(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + const __m128i t0 = _mm_add_epi16(data, _mm_set1_epi16(32720)); + const __m128i t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759)); + + if (_mm_movemask_epi8(t1) == 0) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#elif defined(FASTFLOAT_NEON) + FASTFLOAT_SIMD_DISABLE_WARNINGS + const uint16x8_t data = vld1q_u16(reinterpret_cast(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + const uint16x8_t t0 = vsubq_u16(data, vmovq_n_u16('0')); + const uint16x8_t mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1)); + + if (vminvq_u16(mask) == 0xFFFF) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#else + (void)chars; + (void)i; + return false; +#endif // FASTFLOAT_SSE2 +} + +#endif // FASTFLOAT_HAS_SIMD + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) { + return 0; +} + +template ::value) = 0> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(const UC *&p, const UC *const pend, uint64_t &i) { + if (!has_simd_opt()) { + return; + } + while ((std::distance(p, pend) >= 8) && + simd_parse_if_eight_digits_unrolled( + p, i)) { // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(const char *&p, const char *const pend, + uint64_t &i) { + // optimizes better than parse_if_eight_digits_unrolled() for UC = char. + while ((std::distance(p, pend) >= 8) && + is_made_of_eight_digits_fast(read8_to_u64(p))) { + i = i * 100000000 + + parse_eight_digits_unrolled(read8_to_u64( + p)); // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +enum class parse_error { + no_error, + // [JSON-only] The minus sign must be followed by an integer. + missing_integer_after_sign, + // A sign must be followed by an integer or dot. + missing_integer_or_dot_after_sign, + // [JSON-only] The integer part must not have leading zeros. + leading_zeros_in_integer_part, + // [JSON-only] The integer part must have at least one digit. + no_digits_in_integer_part, + // [JSON-only] If there is a decimal point, there must be digits in the + // fractional part. + no_digits_in_fractional_part, + // The mantissa must have at least one digit. + no_digits_in_mantissa, + // Scientific notation requires an exponential part. + missing_exponential_part, +}; + +template struct parsed_number_string_t { + int64_t exponent{0}; + uint64_t mantissa{0}; + UC const *lastmatch{nullptr}; + bool negative{false}; + bool valid{false}; + bool too_many_digits{false}; + // contains the range of the significant digits + span integer{}; // non-nullable + span fraction{}; // nullable + parse_error error{parse_error::no_error}; +}; + +using byte_span = span; +using parsed_number_string = parsed_number_string_t; + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +report_parse_error(UC const *p, parse_error error) { + parsed_number_string_t answer; + answer.valid = false; + answer.lastmatch = p; + answer.error = error; + return answer; +} + +// Assuming that you use no more than 19 digits, this will +// parse an ASCII string. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +parse_number_string(UC const *p, UC const *pend, + parse_options_t options) noexcept { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + UC const decimal_point = options.decimal_point; + + parsed_number_string_t answer; + answer.valid = false; + answer.too_many_digits = false; + // assume p < pend, so dereference without checks; + answer.negative = (*p == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*p == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && + !uint64_t(fmt & detail::basic_json_fmt) && *p == UC('+'))) { + ++p; + if (p == pend) { + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + if (uint64_t(fmt & detail::basic_json_fmt)) { + if (!is_integer(*p)) { // a sign must be followed by an integer + return report_parse_error(p, + parse_error::missing_integer_after_sign); + } + } else { + if (!is_integer(*p) && + (*p != + decimal_point)) { // a sign must be followed by an integer or the dot + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + } + } + UC const *const start_digits = p; + + uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) + + while ((p != pend) && is_integer(*p)) { + // a multiplication by 10 is cheaper than an arbitrary integer + // multiplication + i = 10 * i + + uint64_t(*p - + UC('0')); // might overflow, we will handle the overflow later + ++p; + } + UC const *const end_of_integer_part = p; + int64_t digit_count = int64_t(end_of_integer_part - start_digits); + answer.integer = span(start_digits, size_t(digit_count)); + if (uint64_t(fmt & detail::basic_json_fmt)) { + // at least 1 digit in integer part, without leading zeros + if (digit_count == 0) { + return report_parse_error(p, parse_error::no_digits_in_integer_part); + } + if ((start_digits[0] == UC('0') && digit_count > 1)) { + return report_parse_error(start_digits, + parse_error::leading_zeros_in_integer_part); + } + } + + int64_t exponent = 0; + const bool has_decimal_point = (p != pend) && (*p == decimal_point); + if (has_decimal_point) { + ++p; + UC const *before = p; + // can occur at most twice without overflowing, but let it occur more, since + // for integers with many digits, digit parsing is the primary bottleneck. + loop_parse_if_eight_digits(p, pend, i); + + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + ++p; + i = i * 10 + digit; // in rare cases, this will overflow, but that's ok + } + exponent = before - p; + answer.fraction = span(before, size_t(p - before)); + digit_count -= exponent; + } + if (uint64_t(fmt & detail::basic_json_fmt)) { + // at least 1 digit in fractional part + if (has_decimal_point && exponent == 0) { + return report_parse_error(p, + parse_error::no_digits_in_fractional_part); + } + } else if (digit_count == + 0) { // we must have encountered at least one integer! + return report_parse_error(p, parse_error::no_digits_in_mantissa); + } + int64_t exp_number = 0; // explicit exponential part + if ((uint64_t(fmt & chars_format::scientific) && (p != pend) && + ((UC('e') == *p) || (UC('E') == *p))) || + (uint64_t(fmt & detail::basic_fortran_fmt) && (p != pend) && + ((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || + (UC('D') == *p)))) { + UC const *location_of_e = p; + if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || + (UC('D') == *p)) { + ++p; + } + bool neg_exp = false; + if ((p != pend) && (UC('-') == *p)) { + neg_exp = true; + ++p; + } else if ((p != pend) && + (UC('+') == + *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) + ++p; + } + if ((p == pend) || !is_integer(*p)) { + if (!uint64_t(fmt & chars_format::fixed)) { + // The exponential part is invalid for scientific notation, so it must + // be a trailing token for fixed notation. However, fixed notation is + // disabled, so report a scientific notation error. + return report_parse_error(p, parse_error::missing_exponential_part); + } + // Otherwise, we will be ignoring the 'e'. + p = location_of_e; + } else { + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + if (exp_number < 0x10000000) { + exp_number = 10 * exp_number + digit; + } + ++p; + } + if (neg_exp) { + exp_number = -exp_number; + } + exponent += exp_number; + } + } else { + // If it scientific and not fixed, we have to bail out. + if (uint64_t(fmt & chars_format::scientific) && + !uint64_t(fmt & chars_format::fixed)) { + return report_parse_error(p, parse_error::missing_exponential_part); + } + } + answer.lastmatch = p; + answer.valid = true; + + // If we frequently had to deal with long strings of digits, + // we could extend our code by using a 128-bit integer instead + // of a 64-bit integer. However, this is uncommon. + // + // We can deal with up to 19 digits. + if (digit_count > 19) { // this is uncommon + // It is possible that the integer had an overflow. + // We have to handle the case where we have 0.0000somenumber. + // We need to be mindful of the case where we only have zeroes... + // E.g., 0.000000000...000. + UC const *start = start_digits; + while ((start != pend) && (*start == UC('0') || *start == decimal_point)) { + if (*start == UC('0')) { + digit_count--; + } + start++; + } + + if (digit_count > 19) { + answer.too_many_digits = true; + // Let us start again, this time, avoiding overflows. + // We don't need to check if is_integer, since we use the + // pre-tokenized spans from above. + i = 0; + p = answer.integer.ptr; + UC const *int_end = p + answer.integer.len(); + const uint64_t minimal_nineteen_digit_integer{1000000000000000000}; + while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + if (i >= minimal_nineteen_digit_integer) { // We have a big integers + exponent = end_of_integer_part - p + exp_number; + } else { // We have a value with a fractional component. + p = answer.fraction.ptr; + UC const *frac_end = p + answer.fraction.len(); + while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + exponent = answer.fraction.ptr - p + exp_number; + } + // We have now corrected both exponent and i, to a truncated value + } + } + answer.exponent = exponent; + answer.mantissa = i; + return answer; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t +parse_int_string(UC const *p, UC const *pend, T &value, + parse_options_t options) { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + + UC const *const first = p; + + bool const negative = (*p == UC('-')); + if (!std::is_signed::value && negative) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + if ((*p == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && (*p == UC('+')))) { + ++p; + } + + UC const *const start_num = p; + + while (p != pend && *p == UC('0')) { + ++p; + } + + const bool has_leading_zeros = p > start_num; + + UC const *const start_digits = p; + + uint64_t i = 0; + if (base == 10) { + loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible + } + while (p != pend) { + uint8_t digit = ch_to_digit(*p); + if (digit >= base) { + break; + } + i = uint64_t(base) * i + digit; // might overflow, check this later + p++; + } + + size_t digit_count = size_t(p - start_digits); + + if (digit_count == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + answer.ptr = p; + + // check u64 overflow + size_t max_digits = max_digits_u64(base); + if (digit_count > max_digits) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + // this check can be eliminated for all other types, but they will all require + // a max_digits(base) equivalent + if (digit_count == max_digits && i < min_safe_u64(base)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + + // check other types overflow + if (!std::is_same::value) { + if (i > uint64_t(std::numeric_limits::max()) + uint64_t(negative)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + } + + if (negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + // this weird workaround is required because: + // - converting unsigned to signed when its value is greater than signed max + // is UB pre-C++23. + // - reinterpret_casting (~i + 1) would work, but it is not constexpr + // this is always optimized into a neg instruction (note: T is an integer + // type) + value = T(-std::numeric_limits::max() - + T(i - uint64_t(std::numeric_limits::max()))); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif + } else { + value = T(i); + } + + answer.ec = std::errc(); + return answer; +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_FAST_TABLE_H +#define FASTFLOAT_FAST_TABLE_H + +#include + +namespace fast_float { + +/** + * When mapping numbers from decimal to binary, + * we go from w * 10^q to m * 2^p but we have + * 10^q = 5^q * 2^q, so effectively + * we are trying to match + * w * 2^q * 5^q to m * 2^p. Thus the powers of two + * are not a concern since they can be represented + * exactly using the binary notation, only the powers of five + * affect the binary significand. + */ + +/** + * The smallest non-zero float (binary64) is 2^-1074. + * We take as input numbers of the form w x 10^q where w < 2^64. + * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. + * However, we have that + * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^-1074. + * Thus it is possible for a number of the form w * 10^-342 where + * w is a 64-bit value to be a non-zero floating-point number. + ********* + * Any number of form w * 10^309 where w>= 1 is going to be + * infinite in binary64 so we never need to worry about powers + * of 5 greater than 308. + */ +template struct powers_template { + + constexpr static int smallest_power_of_five = + binary_format::smallest_power_of_ten(); + constexpr static int largest_power_of_five = + binary_format::largest_power_of_ten(); + constexpr static int number_of_entries = + 2 * (largest_power_of_five - smallest_power_of_five + 1); + // Powers of five from 5^-342 all the way to 5^308 rounded toward one. + constexpr static uint64_t power_of_five_128[number_of_entries] = { + 0xeef453d6923bd65a, 0x113faa2906a13b3f, + 0x9558b4661b6565f8, 0x4ac7ca59a424c507, + 0xbaaee17fa23ebf76, 0x5d79bcf00d2df649, + 0xe95a99df8ace6f53, 0xf4d82c2c107973dc, + 0x91d8a02bb6c10594, 0x79071b9b8a4be869, + 0xb64ec836a47146f9, 0x9748e2826cdee284, + 0xe3e27a444d8d98b7, 0xfd1b1b2308169b25, + 0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7, + 0xb208ef855c969f4f, 0xbdbd2d335e51a935, + 0xde8b2b66b3bc4723, 0xad2c788035e61382, + 0x8b16fb203055ac76, 0x4c3bcb5021afcc31, + 0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d, + 0xd953e8624b85dd78, 0xd71d6dad34a2af0d, + 0x87d4713d6f33aa6b, 0x8672648c40e5ad68, + 0xa9c98d8ccb009506, 0x680efdaf511f18c2, + 0xd43bf0effdc0ba48, 0x212bd1b2566def2, + 0x84a57695fe98746d, 0x14bb630f7604b57, + 0xa5ced43b7e3e9188, 0x419ea3bd35385e2d, + 0xcf42894a5dce35ea, 0x52064cac828675b9, + 0x818995ce7aa0e1b2, 0x7343efebd1940993, + 0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8, + 0xca66fa129f9b60a6, 0xd41a26e077774ef6, + 0xfd00b897478238d0, 0x8920b098955522b4, + 0x9e20735e8cb16382, 0x55b46e5f5d5535b0, + 0xc5a890362fddbc62, 0xeb2189f734aa831d, + 0xf712b443bbd52b7b, 0xa5e9ec7501d523e4, + 0x9a6bb0aa55653b2d, 0x47b233c92125366e, + 0xc1069cd4eabe89f8, 0x999ec0bb696e840a, + 0xf148440a256e2c76, 0xc00670ea43ca250d, + 0x96cd2a865764dbca, 0x380406926a5e5728, + 0xbc807527ed3e12bc, 0xc605083704f5ecf2, + 0xeba09271e88d976b, 0xf7864a44c633682e, + 0x93445b8731587ea3, 0x7ab3ee6afbe0211d, + 0xb8157268fdae9e4c, 0x5960ea05bad82964, + 0xe61acf033d1a45df, 0x6fb92487298e33bd, + 0x8fd0c16206306bab, 0xa5d3b6d479f8e056, + 0xb3c4f1ba87bc8696, 0x8f48a4899877186c, + 0xe0b62e2929aba83c, 0x331acdabfe94de87, + 0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14, + 0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9, + 0xdb71e91432b1a24a, 0xc9e82cd9f69d6150, + 0x892731ac9faf056e, 0xbe311c083a225cd2, + 0xab70fe17c79ac6ca, 0x6dbd630a48aaf406, + 0xd64d3d9db981787d, 0x92cbbccdad5b108, + 0x85f0468293f0eb4e, 0x25bbf56008c58ea5, + 0xa76c582338ed2621, 0xaf2af2b80af6f24e, + 0xd1476e2c07286faa, 0x1af5af660db4aee1, + 0x82cca4db847945ca, 0x50d98d9fc890ed4d, + 0xa37fce126597973c, 0xe50ff107bab528a0, + 0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8, + 0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a, + 0x9faacf3df73609b1, 0x77b191618c54e9ac, + 0xc795830d75038c1d, 0xd59df5b9ef6a2417, + 0xf97ae3d0d2446f25, 0x4b0573286b44ad1d, + 0x9becce62836ac577, 0x4ee367f9430aec32, + 0xc2e801fb244576d5, 0x229c41f793cda73f, + 0xf3a20279ed56d48a, 0x6b43527578c1110f, + 0x9845418c345644d6, 0x830a13896b78aaa9, + 0xbe5691ef416bd60c, 0x23cc986bc656d553, + 0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8, + 0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9, + 0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53, + 0xe858ad248f5c22c9, 0xd1b3400f8f9cff68, + 0x91376c36d99995be, 0x23100809b9c21fa1, + 0xb58547448ffffb2d, 0xabd40a0c2832a78a, + 0xe2e69915b3fff9f9, 0x16c90c8f323f516c, + 0x8dd01fad907ffc3b, 0xae3da7d97f6792e3, + 0xb1442798f49ffb4a, 0x99cd11cfdf41779c, + 0xdd95317f31c7fa1d, 0x40405643d711d583, + 0x8a7d3eef7f1cfc52, 0x482835ea666b2572, + 0xad1c8eab5ee43b66, 0xda3243650005eecf, + 0xd863b256369d4a40, 0x90bed43e40076a82, + 0x873e4f75e2224e68, 0x5a7744a6e804a291, + 0xa90de3535aaae202, 0x711515d0a205cb36, + 0xd3515c2831559a83, 0xd5a5b44ca873e03, + 0x8412d9991ed58091, 0xe858790afe9486c2, + 0xa5178fff668ae0b6, 0x626e974dbe39a872, + 0xce5d73ff402d98e3, 0xfb0a3d212dc8128f, + 0x80fa687f881c7f8e, 0x7ce66634bc9d0b99, + 0xa139029f6a239f72, 0x1c1fffc1ebc44e80, + 0xc987434744ac874e, 0xa327ffb266b56220, + 0xfbe9141915d7a922, 0x4bf1ff9f0062baa8, + 0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9, + 0xc4ce17b399107c22, 0xcb550fb4384d21d3, + 0xf6019da07f549b2b, 0x7e2a53a146606a48, + 0x99c102844f94e0fb, 0x2eda7444cbfc426d, + 0xc0314325637a1939, 0xfa911155fefb5308, + 0xf03d93eebc589f88, 0x793555ab7eba27ca, + 0x96267c7535b763b5, 0x4bc1558b2f3458de, + 0xbbb01b9283253ca2, 0x9eb1aaedfb016f16, + 0xea9c227723ee8bcb, 0x465e15a979c1cadc, + 0x92a1958a7675175f, 0xbfacd89ec191ec9, + 0xb749faed14125d36, 0xcef980ec671f667b, + 0xe51c79a85916f484, 0x82b7e12780e7401a, + 0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810, + 0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15, + 0xdfbdcece67006ac9, 0x67a791e093e1d49a, + 0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0, + 0xaecc49914078536d, 0x58fae9f773886e18, + 0xda7f5bf590966848, 0xaf39a475506a899e, + 0x888f99797a5e012d, 0x6d8406c952429603, + 0xaab37fd7d8f58178, 0xc8e5087ba6d33b83, + 0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64, + 0x855c3be0a17fcd26, 0x5cf2eea09a55067f, + 0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e, + 0xd0601d8efc57b08b, 0xf13b94daf124da26, + 0x823c12795db6ce57, 0x76c53d08d6b70858, + 0xa2cb1717b52481ed, 0x54768c4b0c64ca6e, + 0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09, + 0xfe5d54150b090b02, 0xd3f93b35435d7c4c, + 0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf, + 0xc6b8e9b0709f109a, 0x359ab6419ca1091b, + 0xf867241c8cc6d4c0, 0xc30163d203c94b62, + 0x9b407691d7fc44f8, 0x79e0de63425dcf1d, + 0xc21094364dfb5636, 0x985915fc12f542e4, + 0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d, + 0x979cf3ca6cec5b5a, 0xa705992ceecf9c42, + 0xbd8430bd08277231, 0x50c6ff782a838353, + 0xece53cec4a314ebd, 0xa4f8bf5635246428, + 0x940f4613ae5ed136, 0x871b7795e136be99, + 0xb913179899f68584, 0x28e2557b59846e3f, + 0xe757dd7ec07426e5, 0x331aeada2fe589cf, + 0x9096ea6f3848984f, 0x3ff0d2c85def7621, + 0xb4bca50b065abe63, 0xfed077a756b53a9, + 0xe1ebce4dc7f16dfb, 0xd3e8495912c62894, + 0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c, + 0xb080392cc4349dec, 0xbd8d794d96aacfb3, + 0xdca04777f541c567, 0xecf0d7a0fc5583a0, + 0x89e42caaf9491b60, 0xf41686c49db57244, + 0xac5d37d5b79b6239, 0x311c2875c522ced5, + 0xd77485cb25823ac7, 0x7d633293366b828b, + 0x86a8d39ef77164bc, 0xae5dff9c02033197, + 0xa8530886b54dbdeb, 0xd9f57f830283fdfc, + 0xd267caa862a12d66, 0xd072df63c324fd7b, + 0x8380dea93da4bc60, 0x4247cb9e59f71e6d, + 0xa46116538d0deb78, 0x52d9be85f074e608, + 0xcd795be870516656, 0x67902e276c921f8b, + 0x806bd9714632dff6, 0xba1cd8a3db53b6, + 0xa086cfcd97bf97f3, 0x80e8a40eccd228a4, + 0xc8a883c0fdaf7df0, 0x6122cd128006b2cd, + 0xfad2a4b13d1b5d6c, 0x796b805720085f81, + 0x9cc3a6eec6311a63, 0xcbe3303674053bb0, + 0xc3f490aa77bd60fc, 0xbedbfc4411068a9c, + 0xf4f1b4d515acb93b, 0xee92fb5515482d44, + 0x991711052d8bf3c5, 0x751bdd152d4d1c4a, + 0xbf5cd54678eef0b6, 0xd262d45a78a0635d, + 0xef340a98172aace4, 0x86fb897116c87c34, + 0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0, + 0xbae0a846d2195712, 0x8974836059cca109, + 0xe998d258869facd7, 0x2bd1a438703fc94b, + 0x91ff83775423cc06, 0x7b6306a34627ddcf, + 0xb67f6455292cbf08, 0x1a3bc84c17b1d542, + 0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93, + 0x8e938662882af53e, 0x547eb47b7282ee9c, + 0xb23867fb2a35b28d, 0xe99e619a4f23aa43, + 0xdec681f9f4c31f31, 0x6405fa00e2ec94d4, + 0x8b3c113c38f9f37e, 0xde83bc408dd3dd04, + 0xae0b158b4738705e, 0x9624ab50b148d445, + 0xd98ddaee19068c76, 0x3badd624dd9b0957, + 0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6, + 0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c, + 0xd47487cc8470652b, 0x7647c3200069671f, + 0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073, + 0xa5fb0a17c777cf09, 0xf468107100525890, + 0xcf79cc9db955c2cc, 0x7182148d4066eeb4, + 0x81ac1fe293d599bf, 0xc6f14cd848405530, + 0xa21727db38cb002f, 0xb8ada00e5a506a7c, + 0xca9cf1d206fdc03b, 0xa6d90811f0e4851c, + 0xfd442e4688bd304a, 0x908f4a166d1da663, + 0x9e4a9cec15763e2e, 0x9a598e4e043287fe, + 0xc5dd44271ad3cdba, 0x40eff1e1853f29fd, + 0xf7549530e188c128, 0xd12bee59e68ef47c, + 0x9a94dd3e8cf578b9, 0x82bb74f8301958ce, + 0xc13a148e3032d6e7, 0xe36a52363c1faf01, + 0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1, + 0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9, + 0xbcb2b812db11a5de, 0x7415d448f6b6f0e7, + 0xebdf661791d60f56, 0x111b495b3464ad21, + 0x936b9fcebb25c995, 0xcab10dd900beec34, + 0xb84687c269ef3bfb, 0x3d5d514f40eea742, + 0xe65829b3046b0afa, 0xcb4a5a3112a5112, + 0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab, + 0xb3f4e093db73a093, 0x59ed216765690f56, + 0xe0f218b8d25088b8, 0x306869c13ec3532c, + 0x8c974f7383725573, 0x1e414218c73a13fb, + 0xafbd2350644eeacf, 0xe5d1929ef90898fa, + 0xdbac6c247d62a583, 0xdf45f746b74abf39, + 0x894bc396ce5da772, 0x6b8bba8c328eb783, + 0xab9eb47c81f5114f, 0x66ea92f3f326564, + 0xd686619ba27255a2, 0xc80a537b0efefebd, + 0x8613fd0145877585, 0xbd06742ce95f5f36, + 0xa798fc4196e952e7, 0x2c48113823b73704, + 0xd17f3b51fca3a7a0, 0xf75a15862ca504c5, + 0x82ef85133de648c4, 0x9a984d73dbe722fb, + 0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba, + 0xcc963fee10b7d1b3, 0x318df905079926a8, + 0xffbbcfe994e5c61f, 0xfdf17746497f7052, + 0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633, + 0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0, + 0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0, + 0x9c1661a651213e2d, 0x6bea10ca65c084e, + 0xc31bfa0fe5698db8, 0x486e494fcff30a62, + 0xf3e2f893dec3f126, 0x5a89dba3c3efccfa, + 0x986ddb5c6b3a76b7, 0xf89629465a75e01c, + 0xbe89523386091465, 0xf6bbb397f1135823, + 0xee2ba6c0678b597f, 0x746aa07ded582e2c, + 0x94db483840b717ef, 0xa8c2a44eb4571cdc, + 0xba121a4650e4ddeb, 0x92f34d62616ce413, + 0xe896a0d7e51e1566, 0x77b020baf9c81d17, + 0x915e2486ef32cd60, 0xace1474dc1d122e, + 0xb5b5ada8aaff80b8, 0xd819992132456ba, + 0xe3231912d5bf60e6, 0x10e1fff697ed6c69, + 0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1, + 0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2, + 0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde, + 0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b, + 0xad4ab7112eb3929d, 0x86c16c98d2c953c6, + 0xd89d64d57a607744, 0xe871c7bf077ba8b7, + 0x87625f056c7c4a8b, 0x11471cd764ad4972, + 0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf, + 0xd389b47879823479, 0x4aff1d108d4ec2c3, + 0x843610cb4bf160cb, 0xcedf722a585139ba, + 0xa54394fe1eedb8fe, 0xc2974eb4ee658828, + 0xce947a3da6a9273e, 0x733d226229feea32, + 0x811ccc668829b887, 0x806357d5a3f525f, + 0xa163ff802a3426a8, 0xca07c2dcb0cf26f7, + 0xc9bcff6034c13052, 0xfc89b393dd02f0b5, + 0xfc2c3f3841f17c67, 0xbbac2078d443ace2, + 0x9d9ba7832936edc0, 0xd54b944b84aa4c0d, + 0xc5029163f384a931, 0xa9e795e65d4df11, + 0xf64335bcf065d37d, 0x4d4617b5ff4a16d5, + 0x99ea0196163fa42e, 0x504bced1bf8e4e45, + 0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6, + 0xf07da27a82c37088, 0x5d767327bb4e5a4c, + 0x964e858c91ba2655, 0x3a6a07f8d510f86f, + 0xbbe226efb628afea, 0x890489f70a55368b, + 0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e, + 0x92c8ae6b464fc96f, 0x3b0b8bc90012929d, + 0xb77ada0617e3bbcb, 0x9ce6ebb40173744, + 0xe55990879ddcaabd, 0xcc420a6a101d0515, + 0x8f57fa54c2a9eab6, 0x9fa946824a12232d, + 0xb32df8e9f3546564, 0x47939822dc96abf9, + 0xdff9772470297ebd, 0x59787e2b93bc56f7, + 0x8bfbea76c619ef36, 0x57eb4edb3c55b65a, + 0xaefae51477a06b03, 0xede622920b6b23f1, + 0xdab99e59958885c4, 0xe95fab368e45eced, + 0x88b402f7fd75539b, 0x11dbcb0218ebb414, + 0xaae103b5fcd2a881, 0xd652bdc29f26a119, + 0xd59944a37c0752a2, 0x4be76d3346f0495f, + 0x857fcae62d8493a5, 0x6f70a4400c562ddb, + 0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952, + 0xd097ad07a71f26b2, 0x7e2000a41346a7a7, + 0x825ecc24c873782f, 0x8ed400668c0c28c8, + 0xa2f67f2dfa90563b, 0x728900802f0f32fa, + 0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9, + 0xfea126b7d78186bc, 0xe2f610c84987bfa8, + 0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9, + 0xc6ede63fa05d3143, 0x91503d1c79720dbb, + 0xf8a95fcf88747d94, 0x75a44c6397ce912a, + 0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba, + 0xc24452da229b021b, 0xfbe85badce996168, + 0xf2d56790ab41c2a2, 0xfae27299423fb9c3, + 0x97c560ba6b0919a5, 0xdccd879fc967d41a, + 0xbdb6b8e905cb600f, 0x5400e987bbc1c920, + 0xed246723473e3813, 0x290123e9aab23b68, + 0x9436c0760c86e30b, 0xf9a0b6720aaf6521, + 0xb94470938fa89bce, 0xf808e40e8d5b3e69, + 0xe7958cb87392c2c2, 0xb60b1d1230b20e04, + 0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2, + 0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3, + 0xe2280b6c20dd5232, 0x25c6da63c38de1b0, + 0x8d590723948a535f, 0x579c487e5a38ad0e, + 0xb0af48ec79ace837, 0x2d835a9df0c6d851, + 0xdcdb1b2798182244, 0xf8e431456cf88e65, + 0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff, + 0xac8b2d36eed2dac5, 0xe272467e3d222f3f, + 0xd7adf884aa879177, 0x5b0ed81dcc6abb0f, + 0x86ccbb52ea94baea, 0x98e947129fc2b4e9, + 0xa87fea27a539e9a5, 0x3f2398d747b36224, + 0xd29fe4b18e88640e, 0x8eec7f0d19a03aad, + 0x83a3eeeef9153e89, 0x1953cf68300424ac, + 0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7, + 0xcdb02555653131b6, 0x3792f412cb06794d, + 0x808e17555f3ebf11, 0xe2bbd88bbee40bd0, + 0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4, + 0xc8de047564d20a8b, 0xf245825a5a445275, + 0xfb158592be068d2e, 0xeed6e2f0f0d56712, + 0x9ced737bb6c4183d, 0x55464dd69685606b, + 0xc428d05aa4751e4c, 0xaa97e14c3c26b886, + 0xf53304714d9265df, 0xd53dd99f4b3066a8, + 0x993fe2c6d07b7fab, 0xe546a8038efe4029, + 0xbf8fdb78849a5f96, 0xde98520472bdd033, + 0xef73d256a5c0f77c, 0x963e66858f6d4440, + 0x95a8637627989aad, 0xdde7001379a44aa8, + 0xbb127c53b17ec159, 0x5560c018580d5d52, + 0xe9d71b689dde71af, 0xaab8f01e6e10b4a6, + 0x9226712162ab070d, 0xcab3961304ca70e8, + 0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22, + 0xe45c10c42a2b3b05, 0x8cb89a7db77c506a, + 0x8eb98a7a9a5b04e3, 0x77f3608e92adb242, + 0xb267ed1940f1c61c, 0x55f038b237591ed3, + 0xdf01e85f912e37a3, 0x6b6c46dec52f6688, + 0x8b61313bbabce2c6, 0x2323ac4b3b3da015, + 0xae397d8aa96c1b77, 0xabec975e0a0d081a, + 0xd9c7dced53c72255, 0x96e7bd358c904a21, + 0x881cea14545c7575, 0x7e50d64177da2e54, + 0xaa242499697392d2, 0xdde50bd1d5d0b9e9, + 0xd4ad2dbfc3d07787, 0x955e4ec64b44e864, + 0x84ec3c97da624ab4, 0xbd5af13bef0b113e, + 0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e, + 0xcfb11ead453994ba, 0x67de18eda5814af2, + 0x81ceb32c4b43fcf4, 0x80eacf948770ced7, + 0xa2425ff75e14fc31, 0xa1258379a94d028d, + 0xcad2f7f5359a3b3e, 0x96ee45813a04330, + 0xfd87b5f28300ca0d, 0x8bca9d6e188853fc, + 0x9e74d1b791e07e48, 0x775ea264cf55347e, + 0xc612062576589dda, 0x95364afe032a819e, + 0xf79687aed3eec551, 0x3a83ddbd83f52205, + 0x9abe14cd44753b52, 0xc4926a9672793543, + 0xc16d9a0095928a27, 0x75b7053c0f178294, + 0xf1c90080baf72cb1, 0x5324c68b12dd6339, + 0x971da05074da7bee, 0xd3f6fc16ebca5e04, + 0xbce5086492111aea, 0x88f4bb1ca6bcf585, + 0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6, + 0x9392ee8e921d5d07, 0x3aff322e62439fd0, + 0xb877aa3236a4b449, 0x9befeb9fad487c3, + 0xe69594bec44de15b, 0x4c2ebe687989a9b4, + 0x901d7cf73ab0acd9, 0xf9d37014bf60a11, + 0xb424dc35095cd80f, 0x538484c19ef38c95, + 0xe12e13424bb40e13, 0x2865a5f206b06fba, + 0x8cbccc096f5088cb, 0xf93f87b7442e45d4, + 0xafebff0bcb24aafe, 0xf78f69a51539d749, + 0xdbe6fecebdedd5be, 0xb573440e5a884d1c, + 0x89705f4136b4a597, 0x31680a88f8953031, + 0xabcc77118461cefc, 0xfdc20d2b36ba7c3e, + 0xd6bf94d5e57a42bc, 0x3d32907604691b4d, + 0x8637bd05af6c69b5, 0xa63f9a49c2c1b110, + 0xa7c5ac471b478423, 0xfcf80dc33721d54, + 0xd1b71758e219652b, 0xd3c36113404ea4a9, + 0x83126e978d4fdf3b, 0x645a1cac083126ea, + 0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4, + 0xcccccccccccccccc, 0xcccccccccccccccd, + 0x8000000000000000, 0x0, + 0xa000000000000000, 0x0, + 0xc800000000000000, 0x0, + 0xfa00000000000000, 0x0, + 0x9c40000000000000, 0x0, + 0xc350000000000000, 0x0, + 0xf424000000000000, 0x0, + 0x9896800000000000, 0x0, + 0xbebc200000000000, 0x0, + 0xee6b280000000000, 0x0, + 0x9502f90000000000, 0x0, + 0xba43b74000000000, 0x0, + 0xe8d4a51000000000, 0x0, + 0x9184e72a00000000, 0x0, + 0xb5e620f480000000, 0x0, + 0xe35fa931a0000000, 0x0, + 0x8e1bc9bf04000000, 0x0, + 0xb1a2bc2ec5000000, 0x0, + 0xde0b6b3a76400000, 0x0, + 0x8ac7230489e80000, 0x0, + 0xad78ebc5ac620000, 0x0, + 0xd8d726b7177a8000, 0x0, + 0x878678326eac9000, 0x0, + 0xa968163f0a57b400, 0x0, + 0xd3c21bcecceda100, 0x0, + 0x84595161401484a0, 0x0, + 0xa56fa5b99019a5c8, 0x0, + 0xcecb8f27f4200f3a, 0x0, + 0x813f3978f8940984, 0x4000000000000000, + 0xa18f07d736b90be5, 0x5000000000000000, + 0xc9f2c9cd04674ede, 0xa400000000000000, + 0xfc6f7c4045812296, 0x4d00000000000000, + 0x9dc5ada82b70b59d, 0xf020000000000000, + 0xc5371912364ce305, 0x6c28000000000000, + 0xf684df56c3e01bc6, 0xc732000000000000, + 0x9a130b963a6c115c, 0x3c7f400000000000, + 0xc097ce7bc90715b3, 0x4b9f100000000000, + 0xf0bdc21abb48db20, 0x1e86d40000000000, + 0x96769950b50d88f4, 0x1314448000000000, + 0xbc143fa4e250eb31, 0x17d955a000000000, + 0xeb194f8e1ae525fd, 0x5dcfab0800000000, + 0x92efd1b8d0cf37be, 0x5aa1cae500000000, + 0xb7abc627050305ad, 0xf14a3d9e40000000, + 0xe596b7b0c643c719, 0x6d9ccd05d0000000, + 0x8f7e32ce7bea5c6f, 0xe4820023a2000000, + 0xb35dbf821ae4f38b, 0xdda2802c8a800000, + 0xe0352f62a19e306e, 0xd50b2037ad200000, + 0x8c213d9da502de45, 0x4526f422cc340000, + 0xaf298d050e4395d6, 0x9670b12b7f410000, + 0xdaf3f04651d47b4c, 0x3c0cdd765f114000, + 0x88d8762bf324cd0f, 0xa5880a69fb6ac800, + 0xab0e93b6efee0053, 0x8eea0d047a457a00, + 0xd5d238a4abe98068, 0x72a4904598d6d880, + 0x85a36366eb71f041, 0x47a6da2b7f864750, + 0xa70c3c40a64e6c51, 0x999090b65f67d924, + 0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d, + 0x82818f1281ed449f, 0xbff8f10e7a8921a4, + 0xa321f2d7226895c7, 0xaff72d52192b6a0d, + 0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490, + 0xfee50b7025c36a08, 0x2f236d04753d5b4, + 0x9f4f2726179a2245, 0x1d762422c946590, + 0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5, + 0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2, + 0x9b934c3b330c8577, 0x63cc55f49f88eb2f, + 0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb, + 0xf316271c7fc3908a, 0x8bef464e3945ef7a, + 0x97edd871cfda3a56, 0x97758bf0e3cbb5ac, + 0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317, + 0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd, + 0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a, + 0xb975d6b6ee39e436, 0xb3e2fd538e122b44, + 0xe7d34c64a9c85d44, 0x60dbbca87196b616, + 0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd, + 0xb51d13aea4a488dd, 0x6babab6398bdbe41, + 0xe264589a4dcdab14, 0xc696963c7eed2dd1, + 0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2, + 0xb0de65388cc8ada8, 0x3b25a55f43294bcb, + 0xdd15fe86affad912, 0x49ef0eb713f39ebe, + 0x8a2dbf142dfcc7ab, 0x6e3569326c784337, + 0xacb92ed9397bf996, 0x49c2c37f07965404, + 0xd7e77a8f87daf7fb, 0xdc33745ec97be906, + 0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3, + 0xa8acd7c0222311bc, 0xc40832ea0d68ce0c, + 0xd2d80db02aabd62b, 0xf50a3fa490c30190, + 0x83c7088e1aab65db, 0x792667c6da79e0fa, + 0xa4b8cab1a1563f52, 0x577001b891185938, + 0xcde6fd5e09abcf26, 0xed4c0226b55e6f86, + 0x80b05e5ac60b6178, 0x544f8158315b05b4, + 0xa0dc75f1778e39d6, 0x696361ae3db1c721, + 0xc913936dd571c84c, 0x3bc3a19cd1e38e9, + 0xfb5878494ace3a5f, 0x4ab48a04065c723, + 0x9d174b2dcec0e47b, 0x62eb0d64283f9c76, + 0xc45d1df942711d9a, 0x3ba5d0bd324f8394, + 0xf5746577930d6500, 0xca8f44ec7ee36479, + 0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb, + 0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e, + 0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e, + 0x95d04aee3b80ece5, 0xbba1f1d158724a12, + 0xbb445da9ca61281f, 0x2a8a6e45ae8edc97, + 0xea1575143cf97226, 0xf52d09d71a3293bd, + 0x924d692ca61be758, 0x593c2626705f9c56, + 0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c, + 0xe498f455c38b997a, 0xb6dfb9c0f956447, + 0x8edf98b59a373fec, 0x4724bd4189bd5eac, + 0xb2977ee300c50fe7, 0x58edec91ec2cb657, + 0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed, + 0x8b865b215899f46c, 0xbd79e0d20082ee74, + 0xae67f1e9aec07187, 0xecd8590680a3aa11, + 0xda01ee641a708de9, 0xe80e6f4820cc9495, + 0x884134fe908658b2, 0x3109058d147fdcdd, + 0xaa51823e34a7eede, 0xbd4b46f0599fd415, + 0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a, + 0x850fadc09923329e, 0x3e2cf6bc604ddb0, + 0xa6539930bf6bff45, 0x84db8346b786151c, + 0xcfe87f7cef46ff16, 0xe612641865679a63, + 0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e, + 0xa26da3999aef7749, 0xe3be5e330f38f09d, + 0xcb090c8001ab551c, 0x5cadf5bfd3072cc5, + 0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6, + 0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa, + 0xc646d63501a1511d, 0xb281e1fd541501b8, + 0xf7d88bc24209a565, 0x1f225a7ca91a4226, + 0x9ae757596946075f, 0x3375788de9b06958, + 0xc1a12d2fc3978937, 0x52d6b1641c83ae, + 0xf209787bb47d6b84, 0xc0678c5dbd23a49a, + 0x9745eb4d50ce6332, 0xf840b7ba963646e0, + 0xbd176620a501fbff, 0xb650e5a93bc3d898, + 0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe, + 0x93ba47c980e98cdf, 0xc66f336c36b10137, + 0xb8a8d9bbe123f017, 0xb80b0047445d4184, + 0xe6d3102ad96cec1d, 0xa60dc059157491e5, + 0x9043ea1ac7e41392, 0x87c89837ad68db2f, + 0xb454e4a179dd1877, 0x29babe4598c311fb, + 0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a, + 0x8ce2529e2734bb1d, 0x1899e4a65f58660c, + 0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f, + 0xdc21a1171d42645d, 0x76707543f4fa1f73, + 0x899504ae72497eba, 0x6a06494a791c53a8, + 0xabfa45da0edbde69, 0x487db9d17636892, + 0xd6f8d7509292d603, 0x45a9d2845d3c42b6, + 0x865b86925b9bc5c2, 0xb8a2392ba45a9b2, + 0xa7f26836f282b732, 0x8e6cac7768d7141e, + 0xd1ef0244af2364ff, 0x3207d795430cd926, + 0x8335616aed761f1f, 0x7f44e6bd49e807b8, + 0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6, + 0xcd036837130890a1, 0x36dba887c37a8c0f, + 0x802221226be55a64, 0xc2494954da2c9789, + 0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c, + 0xc83553c5c8965d3d, 0x6f92829494e5acc7, + 0xfa42a8b73abbf48c, 0xcb772339ba1f17f9, + 0x9c69a97284b578d7, 0xff2a760414536efb, + 0xc38413cf25e2d70d, 0xfef5138519684aba, + 0xf46518c2ef5b8cd1, 0x7eb258665fc25d69, + 0x98bf2f79d5993802, 0xef2f773ffbd97a61, + 0xbeeefb584aff8603, 0xaafb550ffacfd8fa, + 0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38, + 0x952ab45cfa97a0b2, 0xdd945a747bf26183, + 0xba756174393d88df, 0x94f971119aeef9e4, + 0xe912b9d1478ceb17, 0x7a37cd5601aab85d, + 0x91abb422ccb812ee, 0xac62e055c10ab33a, + 0xb616a12b7fe617aa, 0x577b986b314d6009, + 0xe39c49765fdf9d94, 0xed5a7e85fda0b80b, + 0x8e41ade9fbebc27d, 0x14588f13be847307, + 0xb1d219647ae6b31c, 0x596eb2d8ae258fc8, + 0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb, + 0x8aec23d680043bee, 0x25de7bb9480d5854, + 0xada72ccc20054ae9, 0xaf561aa79a10ae6a, + 0xd910f7ff28069da4, 0x1b2ba1518094da04, + 0x87aa9aff79042286, 0x90fb44d2f05d0842, + 0xa99541bf57452b28, 0x353a1607ac744a53, + 0xd3fa922f2d1675f2, 0x42889b8997915ce8, + 0x847c9b5d7c2e09b7, 0x69956135febada11, + 0xa59bc234db398c25, 0x43fab9837e699095, + 0xcf02b2c21207ef2e, 0x94f967e45e03f4bb, + 0x8161afb94b44f57d, 0x1d1be0eebac278f5, + 0xa1ba1ba79e1632dc, 0x6462d92a69731732, + 0xca28a291859bbf93, 0x7d7b8f7503cfdcfe, + 0xfcb2cb35e702af78, 0x5cda735244c3d43e, + 0x9defbf01b061adab, 0x3a0888136afa64a7, + 0xc56baec21c7a1916, 0x88aaa1845b8fdd0, + 0xf6c69a72a3989f5b, 0x8aad549e57273d45, + 0x9a3c2087a63f6399, 0x36ac54e2f678864b, + 0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd, + 0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5, + 0x969eb7c47859e743, 0x9f644ae5a4b1b325, + 0xbc4665b596706114, 0x873d5d9f0dde1fee, + 0xeb57ff22fc0c7959, 0xa90cb506d155a7ea, + 0x9316ff75dd87cbd8, 0x9a7f12442d588f2, + 0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f, + 0xe5d3ef282a242e81, 0x8f1668c8a86da5fa, + 0x8fa475791a569d10, 0xf96e017d694487bc, + 0xb38d92d760ec4455, 0x37c981dcc395a9ac, + 0xe070f78d3927556a, 0x85bbe253f47b1417, + 0x8c469ab843b89562, 0x93956d7478ccec8e, + 0xaf58416654a6babb, 0x387ac8d1970027b2, + 0xdb2e51bfe9d0696a, 0x6997b05fcc0319e, + 0x88fcf317f22241e2, 0x441fece3bdf81f03, + 0xab3c2fddeeaad25a, 0xd527e81cad7626c3, + 0xd60b3bd56a5586f1, 0x8a71e223d8d3b074, + 0x85c7056562757456, 0xf6872d5667844e49, + 0xa738c6bebb12d16c, 0xb428f8ac016561db, + 0xd106f86e69d785c7, 0xe13336d701beba52, + 0x82a45b450226b39c, 0xecc0024661173473, + 0xa34d721642b06084, 0x27f002d7f95d0190, + 0xcc20ce9bd35c78a5, 0x31ec038df7b441f4, + 0xff290242c83396ce, 0x7e67047175a15271, + 0x9f79a169bd203e41, 0xf0062c6e984d386, + 0xc75809c42c684dd1, 0x52c07b78a3e60868, + 0xf92e0c3537826145, 0xa7709a56ccdf8a82, + 0x9bbcc7a142b17ccb, 0x88a66076400bb691, + 0xc2abf989935ddbfe, 0x6acff893d00ea435, + 0xf356f7ebf83552fe, 0x583f6b8c4124d43, + 0x98165af37b2153de, 0xc3727a337a8b704a, + 0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c, + 0xeda2ee1c7064130c, 0x1162def06f79df73, + 0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8, + 0xb9a74a0637ce2ee1, 0x6d953e2bd7173692, + 0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437, + 0x910ab1d4db9914a0, 0x1d9c9892400a22a2, + 0xb54d5e4a127f59c8, 0x2503beb6d00cab4b, + 0xe2a0b5dc971f303a, 0x2e44ae64840fd61d, + 0x8da471a9de737e24, 0x5ceaecfed289e5d2, + 0xb10d8e1456105dad, 0x7425a83e872c5f47, + 0xdd50f1996b947518, 0xd12f124e28f77719, + 0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f, + 0xace73cbfdc0bfb7b, 0x636cc64d1001550b, + 0xd8210befd30efa5a, 0x3c47f7e05401aa4e, + 0x8714a775e3e95c78, 0x65acfaec34810a71, + 0xa8d9d1535ce3b396, 0x7f1839a741a14d0d, + 0xd31045a8341ca07c, 0x1ede48111209a050, + 0x83ea2b892091e44d, 0x934aed0aab460432, + 0xa4e4b66b68b65d60, 0xf81da84d5617853f, + 0xce1de40642e3f4b9, 0x36251260ab9d668e, + 0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019, + 0xa1075a24e4421730, 0xb24cf65b8612f81f, + 0xc94930ae1d529cfc, 0xdee033f26797b627, + 0xfb9b7cd9a4a7443c, 0x169840ef017da3b1, + 0x9d412e0806e88aa5, 0x8e1f289560ee864e, + 0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2, + 0xf5b5d7ec8acb58a2, 0xae10af696774b1db, + 0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29, + 0xbff610b0cc6edd3f, 0x17fd090a58d32af3, + 0xeff394dcff8a948e, 0xddfc4b4cef07f5b0, + 0x95f83d0a1fb69cd9, 0x4abdaf101564f98e, + 0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1, + 0xea53df5fd18d5513, 0x84c86189216dc5ed, + 0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4, + 0xb7118682dbb66a77, 0x3fbc8c33221dc2a1, + 0xe4d5e82392a40515, 0xfabaf3feaa5334a, + 0x8f05b1163ba6832d, 0x29cb4d87f2a7400e, + 0xb2c71d5bca9023f8, 0x743e20e9ef511012, + 0xdf78e4b2bd342cf6, 0x914da9246b255416, + 0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e, + 0xae9672aba3d0c320, 0xa184ac2473b529b1, + 0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e, + 0x8865899617fb1871, 0x7e2fa67c7a658892, + 0xaa7eebfb9df9de8d, 0xddbb901b98feeab7, + 0xd51ea6fa85785631, 0x552a74227f3ea565, + 0x8533285c936b35de, 0xd53a88958f87275f, + 0xa67ff273b8460356, 0x8a892abaf368f137, + 0xd01fef10a657842c, 0x2d2b7569b0432d85, + 0x8213f56a67f6b29b, 0x9c3b29620e29fc73, + 0xa298f2c501f45f42, 0x8349f3ba91b47b8f, + 0xcb3f2f7642717713, 0x241c70a936219a73, + 0xfe0efb53d30dd4d7, 0xed238cd383aa0110, + 0x9ec95d1463e8a506, 0xf4363804324a40aa, + 0xc67bb4597ce2ce48, 0xb143c6053edcd0d5, + 0xf81aa16fdc1b81da, 0xdd94b7868e94050a, + 0x9b10a4e5e9913128, 0xca7cf2b4191c8326, + 0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0, + 0xf24a01a73cf2dccf, 0xbc633b39673c8cec, + 0x976e41088617ca01, 0xd5be0503e085d813, + 0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18, + 0xec9c459d51852ba2, 0xddf8e7d60ed1219e, + 0x93e1ab8252f33b45, 0xcabb90e5c942b503, + 0xb8da1662e7b00a17, 0x3d6a751f3b936243, + 0xe7109bfba19c0c9d, 0xcc512670a783ad4, + 0x906a617d450187e2, 0x27fb2b80668b24c5, + 0xb484f9dc9641e9da, 0xb1f9f660802dedf6, + 0xe1a63853bbd26451, 0x5e7873f8a0396973, + 0x8d07e33455637eb2, 0xdb0b487b6423e1e8, + 0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62, + 0xdc5c5301c56b75f7, 0x7641a140cc7810fb, + 0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d, + 0xac2820d9623bf429, 0x546345fa9fbdcd44, + 0xd732290fbacaf133, 0xa97c177947ad4095, + 0x867f59a9d4bed6c0, 0x49ed8eabcccc485d, + 0xa81f301449ee8c70, 0x5c68f256bfff5a74, + 0xd226fc195c6a2f8c, 0x73832eec6fff3111, + 0x83585d8fd9c25db7, 0xc831fd53c5ff7eab, + 0xa42e74f3d032f525, 0xba3e7ca8b77f5e55, + 0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb, + 0x80444b5e7aa7cf85, 0x7980d163cf5b81b3, + 0xa0555e361951c366, 0xd7e105bcc332621f, + 0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7, + 0xfa856334878fc150, 0xb14f98f6f0feb951, + 0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3, + 0xc3b8358109e84f07, 0xa862f80ec4700c8, + 0xf4a642e14c6262c8, 0xcd27bb612758c0fa, + 0x98e7e9cccfbd7dbd, 0x8038d51cb897789c, + 0xbf21e44003acdd2c, 0xe0470a63e6bd56c3, + 0xeeea5d5004981478, 0x1858ccfce06cac74, + 0x95527a5202df0ccb, 0xf37801e0c43ebc8, + 0xbaa718e68396cffd, 0xd30560258f54e6ba, + 0xe950df20247c83fd, 0x47c6b82ef32a2069, + 0x91d28b7416cdd27e, 0x4cdc331d57fa5441, + 0xb6472e511c81471d, 0xe0133fe4adf8e952, + 0xe3d8f9e563a198e5, 0x58180fddd97723a6, + 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648, + }; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr uint64_t + powers_template::power_of_five_128[number_of_entries]; + +#endif + +using powers = powers_template<>; + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H +#define FASTFLOAT_DECIMAL_TO_BINARY_H + +#include +#include +#include +#include +#include +#include + +namespace fast_float { + +// This will compute or rather approximate w * 5**q and return a pair of 64-bit +// words approximating the result, with the "high" part corresponding to the +// most significant bits and the low part corresponding to the least significant +// bits. +// +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +compute_product_approximation(int64_t q, uint64_t w) { + const int index = 2 * int(q - powers::smallest_power_of_five); + // For small values of q, e.g., q in [0,27], the answer is always exact + // because The line value128 firstproduct = full_multiplication(w, + // power_of_five_128[index]); gives the exact answer. + value128 firstproduct = + full_multiplication(w, powers::power_of_five_128[index]); + static_assert((bit_precision >= 0) && (bit_precision <= 64), + " precision should be in (0,64]"); + constexpr uint64_t precision_mask = + (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) + : uint64_t(0xFFFFFFFFFFFFFFFF); + if ((firstproduct.high & precision_mask) == + precision_mask) { // could further guard with (lower + w < lower) + // regarding the second product, we only need secondproduct.high, but our + // expectation is that the compiler will optimize this extra work away if + // needed. + value128 secondproduct = + full_multiplication(w, powers::power_of_five_128[index + 1]); + firstproduct.low += secondproduct.high; + if (secondproduct.high > firstproduct.low) { + firstproduct.high++; + } + } + return firstproduct; +} + +namespace detail { +/** + * For q in (0,350), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * floor(p) + q + * where + * p = log(5**q)/log(2) = q * log(5)/log(2) + * + * For negative values of q in (-400,0), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * -ceil(p) + q + * where + * p = log(5**-q)/log(2) = -q * log(5)/log(2) + */ +constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept { + return (((152170 + 65536) * q) >> 16) + 63; +} +} // namespace detail + +// create an adjusted mantissa, biased by the invalid power2 +// for significant digits already multiplied by 10 ** q. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa +compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { + int hilz = int(w >> 63) ^ 1; + adjusted_mantissa answer; + answer.mantissa = w << hilz; + int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent(); + answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + + invalid_am_bias); + return answer; +} + +// w * 10 ** q, without rounding the representation up. +// the power2 in the exponent will be adjusted by invalid_am_bias. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_error(int64_t q, uint64_t w) noexcept { + int lz = leading_zeroes(w); + w <<= lz; + value128 product = + compute_product_approximation(q, w); + return compute_error_scaled(q, product.high, lz); +} + +// w * 10 ** q +// The returned value should be a valid ieee64 number that simply need to be +// packed. However, in some very rare cases, the computation will fail. In such +// cases, we return an adjusted_mantissa with a negative power of 2: the caller +// should recompute in such cases. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_float(int64_t q, uint64_t w) noexcept { + adjusted_mantissa answer; + if ((w == 0) || (q < binary::smallest_power_of_ten())) { + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + if (q > binary::largest_power_of_ten()) { + // we want to get infinity: + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + return answer; + } + // At this point in time q is in [powers::smallest_power_of_five, + // powers::largest_power_of_five]. + + // We want the most significant bit of i to be 1. Shift if needed. + int lz = leading_zeroes(w); + w <<= lz; + + // The required precision is binary::mantissa_explicit_bits() + 3 because + // 1. We need the implicit bit + // 2. We need an extra bit for rounding purposes + // 3. We might lose a bit due to the "upperbit" routine (result too small, + // requiring a shift) + + value128 product = + compute_product_approximation(q, w); + // The computed 'product' is always sufficient. + // Mathematical proof: + // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to + // appear) See script/mushtak_lemire.py + + // The "compute_product_approximation" function can be slightly slower than a + // branchless approach: value128 product = compute_product(q, w); but in + // practice, we can win big with the compute_product_approximation if its + // additional branch is easily predicted. Which is best is data specific. + int upperbit = int(product.high >> 63); + int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3; + + answer.mantissa = product.high >> shift; + + answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - + binary::minimum_exponent()); + if (answer.power2 <= 0) { // we have a subnormal? + // Here have that answer.power2 <= 0 so -answer.power2 >= 0 + if (-answer.power2 + 1 >= + 64) { // if we have more than 64 bits below the minimum exponent, you + // have a zero for sure. + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + // next line is safe because -answer.power2 + 1 < 64 + answer.mantissa >>= -answer.power2 + 1; + // Thankfully, we can't have both "round-to-even" and subnormals because + // "round-to-even" only occurs for powers close to 0. + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + // There is a weird scenario where we don't have a subnormal but just. + // Suppose we start with 2.2250738585072013e-308, we end up + // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal + // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round + // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer + // subnormal, but we can only know this after rounding. + // So we only declare a subnormal if we are smaller than the threshold. + answer.power2 = + (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) + ? 0 + : 1; + return answer; + } + + // usually, we round *up*, but if we fall right in between and and we have an + // even basis, we need to round down + // We are only concerned with the cases where 5**q fits in single 64-bit word. + if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && + (q <= binary::max_exponent_round_to_even()) && + ((answer.mantissa & 3) == 1)) { // we may fall between two floats! + // To be in-between two floats we need that in doing + // answer.mantissa = product.high >> (upperbit + 64 - + // binary::mantissa_explicit_bits() - 3); + // ... we dropped out only zeroes. But if this happened, then we can go + // back!!! + if ((answer.mantissa << shift) == product.high) { + answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up + } + } + + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) { + answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits()); + answer.power2++; // undo previous addition + } + + answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits()); + if (answer.power2 >= binary::infinite_power()) { // infinity + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + } + return answer; +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_BIGINT_H +#define FASTFLOAT_BIGINT_H + +#include +#include +#include +#include + + +namespace fast_float { + +// the limb width: we want efficient multiplication of double the bits in +// limb, or for 64-bit limbs, at least 64-bit multiplication where we can +// extract the high and low parts efficiently. this is every 64-bit +// architecture except for sparc, which emulates 128-bit multiplication. +// we might have platforms where `CHAR_BIT` is not 8, so let's avoid +// doing `8 * sizeof(limb)`. +#if defined(FASTFLOAT_64BIT) && !defined(__sparc) +#define FASTFLOAT_64BIT_LIMB 1 +typedef uint64_t limb; +constexpr size_t limb_bits = 64; +#else +#define FASTFLOAT_32BIT_LIMB +typedef uint32_t limb; +constexpr size_t limb_bits = 32; +#endif + +typedef span limb_span; + +// number of bits in a bigint. this needs to be at least the number +// of bits required to store the largest bigint, which is +// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or +// ~3600 bits, so we round to 4000. +constexpr size_t bigint_bits = 4000; +constexpr size_t bigint_limbs = bigint_bits / limb_bits; + +// vector-like type that is allocated on the stack. the entire +// buffer is pre-allocated, and only the length changes. +template struct stackvec { + limb data[size]; + // we never need more than 150 limbs + uint16_t length{0}; + + stackvec() = default; + stackvec(const stackvec &) = delete; + stackvec &operator=(const stackvec &) = delete; + stackvec(stackvec &&) = delete; + stackvec &operator=(stackvec &&other) = delete; + + // create stack vector from existing limb span. + FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) { + FASTFLOAT_ASSERT(try_extend(s)); + } + + FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + // index from the end of the container + FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + size_t rindex = length - index - 1; + return data[rindex]; + } + + // set the length, without bounds checking. + FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { + length = uint16_t(len); + } + constexpr size_t len() const noexcept { return length; } + constexpr bool is_empty() const noexcept { return length == 0; } + constexpr size_t capacity() const noexcept { return size; } + // append item to vector, without bounds checking + FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { + data[length] = value; + length++; + } + // append item to vector, returning if item was added + FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept { + if (len() < capacity()) { + push_unchecked(value); + return true; + } else { + return false; + } + } + // add items to the vector, from a span, without bounds checking + FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept { + limb *ptr = data + length; + std::copy_n(s.ptr, s.len(), ptr); + set_len(len() + s.len()); + } + // try to add items to the vector, returning if items were added + FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept { + if (len() + s.len() <= capacity()) { + extend_unchecked(s); + return true; + } else { + return false; + } + } + // resize the vector, without bounds checking + // if the new size is longer than the vector, assign value to each + // appended item. + FASTFLOAT_CONSTEXPR20 + void resize_unchecked(size_t new_len, limb value) noexcept { + if (new_len > len()) { + size_t count = new_len - len(); + limb *first = data + len(); + limb *last = first + count; + ::std::fill(first, last, value); + set_len(new_len); + } else { + set_len(new_len); + } + } + // try to resize the vector, returning if the vector was resized. + FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept { + if (new_len > capacity()) { + return false; + } else { + resize_unchecked(new_len, value); + return true; + } + } + // check if any limbs are non-zero after the given index. + // this needs to be done in reverse order, since the index + // is relative to the most significant limbs. + FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept { + while (index < len()) { + if (rindex(index) != 0) { + return true; + } + index++; + } + return false; + } + // normalize the big integer, so most-significant zero limbs are removed. + FASTFLOAT_CONSTEXPR14 void normalize() noexcept { + while (len() > 0 && rindex(0) == 0) { + length--; + } + } +}; + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +empty_hi64(bool &truncated) noexcept { + truncated = false; + return 0; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, bool &truncated) noexcept { + truncated = false; + int shl = leading_zeroes(r0); + return r0 << shl; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, uint64_t r1, bool &truncated) noexcept { + int shl = leading_zeroes(r0); + if (shl == 0) { + truncated = r1 != 0; + return r0; + } else { + int shr = 64 - shl; + truncated = (r1 << shl) != 0; + return (r0 << shl) | (r1 >> shr); + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, bool &truncated) noexcept { + return uint64_hi64(r0, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + return uint64_hi64((x0 << 32) | x1, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + uint64_t x2 = r2; + return uint64_hi64(x0, (x1 << 32) | x2, truncated); +} + +// add two small integers, checking for overflow. +// we want an efficient operation. for msvc, where +// we don't have built-in intrinsics, this is still +// pretty fast. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_add(limb x, limb y, bool &overflow) noexcept { + limb z; +// gcc and clang +#if defined(__has_builtin) +#if __has_builtin(__builtin_add_overflow) + if (!cpp20_and_in_constexpr()) { + overflow = __builtin_add_overflow(x, y, &z); + return z; + } +#endif +#endif + + // generic, this still optimizes correctly on MSVC. + z = x + y; + overflow = z < x; + return z; +} + +// multiply two small integers, getting both the high and low bits. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_mul(limb x, limb y, limb &carry) noexcept { +#ifdef FASTFLOAT_64BIT_LIMB +#if defined(__SIZEOF_INT128__) + // GCC and clang both define it as an extension. + __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#else + // fallback, no native 128-bit integer multiplication with carry. + // on msvc, this optimizes identically, somehow. + value128 z = full_multiplication(x, y); + bool overflow; + z.low = scalar_add(z.low, carry, overflow); + z.high += uint64_t(overflow); // cannot overflow + carry = z.high; + return z.low; +#endif +#else + uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#endif +} + +// add scalar value to bigint starting from offset. +// used in grade school multiplication +template +inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, + size_t start) noexcept { + size_t index = start; + limb carry = y; + bool overflow; + while (carry != 0 && index < vec.len()) { + vec[index] = scalar_add(vec[index], carry, overflow); + carry = limb(overflow); + index += 1; + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add scalar value to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +small_add(stackvec &vec, limb y) noexcept { + return small_add_from(vec, y, 0); +} + +// multiply bigint by scalar value. +template +inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec &vec, + limb y) noexcept { + limb carry = 0; + for (size_t index = 0; index < vec.len(); index++) { + vec[index] = scalar_mul(vec[index], y, carry); + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add bigint to bigint starting from index. +// used in grade school multiplication +template +FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, + size_t start) noexcept { + // the effective x buffer is from `xstart..x.len()`, so exit early + // if we can't get that current range. + if (x.len() < start || y.len() > x.len() - start) { + FASTFLOAT_TRY(x.try_resize(y.len() + start, 0)); + } + + bool carry = false; + for (size_t index = 0; index < y.len(); index++) { + limb xi = x[index + start]; + limb yi = y[index]; + bool c1 = false; + bool c2 = false; + xi = scalar_add(xi, yi, c1); + if (carry) { + xi = scalar_add(xi, 1, c2); + } + x[index + start] = xi; + carry = c1 | c2; + } + + // handle overflow + if (carry) { + FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start)); + } + return true; +} + +// add bigint to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +large_add_from(stackvec &x, limb_span y) noexcept { + return large_add_from(x, y, 0); +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { + limb_span xs = limb_span(x.data, x.len()); + stackvec z(xs); + limb_span zs = limb_span(z.data, z.len()); + + if (y.len() != 0) { + limb y0 = y[0]; + FASTFLOAT_TRY(small_mul(x, y0)); + for (size_t index = 1; index < y.len(); index++) { + limb yi = y[index]; + stackvec zi; + if (yi != 0) { + // re-use the same buffer throughout + zi.set_len(0); + FASTFLOAT_TRY(zi.try_extend(zs)); + FASTFLOAT_TRY(small_mul(zi, yi)); + limb_span zis = limb_span(zi.data, zi.len()); + FASTFLOAT_TRY(large_add_from(x, zis, index)); + } + } + } + + x.normalize(); + return true; +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec &x, limb_span y) noexcept { + if (y.len() == 1) { + FASTFLOAT_TRY(small_mul(x, y[0])); + } else { + FASTFLOAT_TRY(long_mul(x, y)); + } + return true; +} + +template struct pow5_tables { + static constexpr uint32_t large_step = 135; + static constexpr uint64_t small_power_of_5[] = { + 1UL, + 5UL, + 25UL, + 125UL, + 625UL, + 3125UL, + 15625UL, + 78125UL, + 390625UL, + 1953125UL, + 9765625UL, + 48828125UL, + 244140625UL, + 1220703125UL, + 6103515625UL, + 30517578125UL, + 152587890625UL, + 762939453125UL, + 3814697265625UL, + 19073486328125UL, + 95367431640625UL, + 476837158203125UL, + 2384185791015625UL, + 11920928955078125UL, + 59604644775390625UL, + 298023223876953125UL, + 1490116119384765625UL, + 7450580596923828125UL, + }; +#ifdef FASTFLOAT_64BIT_LIMB + constexpr static limb large_power_of_5[] = { + 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL, + 10482974169319127550UL, 198276706040285095UL}; +#else + constexpr static limb large_power_of_5[] = { + 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U, + 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U}; +#endif +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint32_t pow5_tables::large_step; + +template constexpr uint64_t pow5_tables::small_power_of_5[]; + +template constexpr limb pow5_tables::large_power_of_5[]; + +#endif + +// big integer type. implements a small subset of big integer +// arithmetic, using simple algorithms since asymptotically +// faster algorithms are slower for a small number of limbs. +// all operations assume the big-integer is normalized. +struct bigint : pow5_tables<> { + // storage of the limbs, in little-endian order. + stackvec vec; + + FASTFLOAT_CONSTEXPR20 bigint() : vec() {} + bigint(const bigint &) = delete; + bigint &operator=(const bigint &) = delete; + bigint(bigint &&) = delete; + bigint &operator=(bigint &&other) = delete; + + FASTFLOAT_CONSTEXPR20 bigint(uint64_t value) : vec() { +#ifdef FASTFLOAT_64BIT_LIMB + vec.push_unchecked(value); +#else + vec.push_unchecked(uint32_t(value)); + vec.push_unchecked(uint32_t(value >> 32)); +#endif + vec.normalize(); + } + + // get the high 64 bits from the vector, and if bits were truncated. + // this is to get the significant digits for the float. + FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool &truncated) const noexcept { +#ifdef FASTFLOAT_64BIT_LIMB + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint64_hi64(vec.rindex(0), truncated); + } else { + uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated); + truncated |= vec.nonzero(2); + return result; + } +#else + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint32_hi64(vec.rindex(0), truncated); + } else if (vec.len() == 2) { + return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated); + } else { + uint64_t result = + uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated); + truncated |= vec.nonzero(3); + return result; + } +#endif + } + + // compare two big integers, returning the large value. + // assumes both are normalized. if the return value is + // negative, other is larger, if the return value is + // positive, this is larger, otherwise they are equal. + // the limbs are stored in little-endian order, so we + // must compare the limbs in ever order. + FASTFLOAT_CONSTEXPR20 int compare(const bigint &other) const noexcept { + if (vec.len() > other.vec.len()) { + return 1; + } else if (vec.len() < other.vec.len()) { + return -1; + } else { + for (size_t index = vec.len(); index > 0; index--) { + limb xi = vec[index - 1]; + limb yi = other.vec[index - 1]; + if (xi > yi) { + return 1; + } else if (xi < yi) { + return -1; + } + } + return 0; + } + } + + // shift left each limb n bits, carrying over to the new limb + // returns true if we were able to shift all the digits. + FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept { + // Internally, for each item, we shift left by n, and add the previous + // right shifted limb-bits. + // For example, we transform (for u8) shifted left 2, to: + // b10100100 b01000010 + // b10 b10010001 b00001000 + FASTFLOAT_DEBUG_ASSERT(n != 0); + FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); + + size_t shl = n; + size_t shr = limb_bits - shl; + limb prev = 0; + for (size_t index = 0; index < vec.len(); index++) { + limb xi = vec[index]; + vec[index] = (xi << shl) | (prev >> shr); + prev = xi; + } + + limb carry = prev >> shr; + if (carry != 0) { + return vec.try_push(carry); + } + return true; + } + + // move the limbs left by `n` limbs. + FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept { + FASTFLOAT_DEBUG_ASSERT(n != 0); + if (n + vec.len() > vec.capacity()) { + return false; + } else if (!vec.is_empty()) { + // move limbs + limb *dst = vec.data + n; + const limb *src = vec.data; + std::copy_backward(src, src + vec.len(), dst + vec.len()); + // fill in empty limbs + limb *first = vec.data; + limb *last = first + n; + ::std::fill(first, last, 0); + vec.set_len(n + vec.len()); + return true; + } else { + return true; + } + } + + // move the limbs left by `n` bits. + FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept { + size_t rem = n % limb_bits; + size_t div = n / limb_bits; + if (rem != 0) { + FASTFLOAT_TRY(shl_bits(rem)); + } + if (div != 0) { + FASTFLOAT_TRY(shl_limbs(div)); + } + return true; + } + + // get the number of leading zeros in the bigint. + FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept { + if (vec.is_empty()) { + return 0; + } else { +#ifdef FASTFLOAT_64BIT_LIMB + return leading_zeroes(vec.rindex(0)); +#else + // no use defining a specialized leading_zeroes for a 32-bit type. + uint64_t r0 = vec.rindex(0); + return leading_zeroes(r0 << 32); +#endif + } + } + + // get the number of bits in the bigint. + FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept { + int lz = ctlz(); + return int(limb_bits * vec.len()) - lz; + } + + FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); } + + FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept { return small_add(vec, y); } + + // multiply as if by 2 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept { return shl(exp); } + + // multiply as if by 5 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept { + // multiply by a power of 5 + size_t large_length = sizeof(large_power_of_5) / sizeof(limb); + limb_span large = limb_span(large_power_of_5, large_length); + while (exp >= large_step) { + FASTFLOAT_TRY(large_mul(vec, large)); + exp -= large_step; + } +#ifdef FASTFLOAT_64BIT_LIMB + uint32_t small_step = 27; + limb max_native = 7450580596923828125UL; +#else + uint32_t small_step = 13; + limb max_native = 1220703125U; +#endif + while (exp >= small_step) { + FASTFLOAT_TRY(small_mul(vec, max_native)); + exp -= small_step; + } + if (exp != 0) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + // This is similar to https://github.com/llvm/llvm-project/issues/47746, + // except the workaround described there don't work here + FASTFLOAT_TRY(small_mul( + vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))); + } + + return true; + } + + // multiply as if by 10 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept { + FASTFLOAT_TRY(pow5(exp)); + return pow2(exp); + } +}; + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_DIGIT_COMPARISON_H +#define FASTFLOAT_DIGIT_COMPARISON_H + +#include +#include +#include +#include + + +namespace fast_float { + +// 1e0 to 1e19 +constexpr static uint64_t powers_of_ten_uint64[] = {1UL, + 10UL, + 100UL, + 1000UL, + 10000UL, + 100000UL, + 1000000UL, + 10000000UL, + 100000000UL, + 1000000000UL, + 10000000000UL, + 100000000000UL, + 1000000000000UL, + 10000000000000UL, + 100000000000000UL, + 1000000000000000UL, + 10000000000000000UL, + 100000000000000000UL, + 1000000000000000000UL, + 10000000000000000000UL}; + +// calculate the exponent, in scientific notation, of the number. +// this algorithm is not even close to optimized, but it has no practical +// effect on performance: in order to have a faster algorithm, we'd need +// to slow down performance for faster algorithms, and this is still fast. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t +scientific_exponent(parsed_number_string_t &num) noexcept { + uint64_t mantissa = num.mantissa; + int32_t exponent = int32_t(num.exponent); + while (mantissa >= 10000) { + mantissa /= 10000; + exponent += 4; + } + while (mantissa >= 100) { + mantissa /= 100; + exponent += 2; + } + while (mantissa >= 10) { + mantissa /= 10; + exponent += 1; + } + return exponent; +} + +// this converts a native floating-point number to an extended-precision float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended(T value) noexcept { + using equiv_uint = typename binary_format::equiv_uint; + constexpr equiv_uint exponent_mask = binary_format::exponent_mask(); + constexpr equiv_uint mantissa_mask = binary_format::mantissa_mask(); + constexpr equiv_uint hidden_bit_mask = binary_format::hidden_bit_mask(); + + adjusted_mantissa am; + int32_t bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + equiv_uint bits; +#if FASTFLOAT_HAS_BIT_CAST + bits = std::bit_cast(value); +#else + ::memcpy(&bits, &value, sizeof(T)); +#endif + if ((bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = bits & mantissa_mask; + } else { + // normal + am.power2 = int32_t((bits & exponent_mask) >> + binary_format::mantissa_explicit_bits()); + am.power2 -= bias; + am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; + } + + return am; +} + +// get the extended precision value of the halfway point between b and b+u. +// we are given a native float that represents b, so we need to adjust it +// halfway between b and b+u. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended_halfway(T value) noexcept { + adjusted_mantissa am = to_extended(value); + am.mantissa <<= 1; + am.mantissa += 1; + am.power2 -= 1; + return am; +} + +// round an extended-precision float to the nearest machine float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am, + callback cb) noexcept { + int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; + if (-am.power2 >= mantissa_shift) { + // have a denormal float + int32_t shift = -am.power2 + 1; + cb(am, std::min(shift, 64)); + // check for round-up: if rounding-nearest carried us to the hidden bit. + am.power2 = (am.mantissa < + (uint64_t(1) << binary_format::mantissa_explicit_bits())) + ? 0 + : 1; + return; + } + + // have a normal float, use the default shift. + cb(am, mantissa_shift); + + // check for carry + if (am.mantissa >= + (uint64_t(2) << binary_format::mantissa_explicit_bits())) { + am.mantissa = (uint64_t(1) << binary_format::mantissa_explicit_bits()); + am.power2++; + } + + // check for infinite: we could have carried to an infinite power + am.mantissa &= ~(uint64_t(1) << binary_format::mantissa_explicit_bits()); + if (am.power2 >= binary_format::infinite_power()) { + am.power2 = binary_format::infinite_power(); + am.mantissa = 0; + } +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_nearest_tie_even(adjusted_mantissa &am, int32_t shift, + callback cb) noexcept { + const uint64_t mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; + const uint64_t halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); + uint64_t truncated_bits = am.mantissa & mask; + bool is_above = truncated_bits > halfway; + bool is_halfway = truncated_bits == halfway; + + // shift digits into position + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; + + bool is_odd = (am.mantissa & 1) == 1; + am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_down(adjusted_mantissa &am, int32_t shift) noexcept { + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; +} +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +skip_zeros(UC const *&first, UC const *last) noexcept { + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + break; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + break; + } + first++; + } +} + +// determine if any non-zero digits were truncated. +// all characters must be valid digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(UC const *first, UC const *last) noexcept { + // do 8-bit optimizations, can just compare to 8 literal 0s. + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + return true; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + return true; + } + ++first; + } + return false; +} +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(span s) noexcept { + return is_truncated(s.ptr, s.ptr + s.len()); +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +parse_eight_digits(const UC *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 100000000 + parse_eight_digits_unrolled(p); + p += 8; + counter += 8; + count += 8; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +parse_one_digit(UC const *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 10 + limb(*p - UC('0')); + p++; + counter++; + count++; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +add_native(bigint &big, limb power, limb value) noexcept { + big.mul(power); + big.add(value); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +round_up_bigint(bigint &big, size_t &count) noexcept { + // need to round-up the digits, but need to avoid rounding + // ....9999 to ...10000, which could cause a false halfway point. + add_native(big, 10, 1); + count++; +} + +// parse the significant digits into a big integer +template +inline FASTFLOAT_CONSTEXPR20 void +parse_mantissa(bigint &result, parsed_number_string_t &num, + size_t max_digits, size_t &digits) noexcept { + // try to minimize the number of big integer and scalar multiplication. + // therefore, try to parse 8 digits at a time, and multiply by the largest + // scalar value (9 or 19 digits) for each step. + size_t counter = 0; + digits = 0; + limb value = 0; +#ifdef FASTFLOAT_64BIT_LIMB + size_t step = 19; +#else + size_t step = 9; +#endif + + // process all integer digits. + UC const *p = num.integer.ptr; + UC const *pend = p + num.integer.len(); + skip_zeros(p, pend); + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (num.fraction.ptr != nullptr) { + truncated |= is_truncated(num.fraction); + } + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + + // add our fraction digits, if they're available. + if (num.fraction.ptr != nullptr) { + p = num.fraction.ptr; + pend = p + num.fraction.len(); + if (digits == 0) { + skip_zeros(p, pend); + } + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + } + + if (counter != 0) { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + } +} + +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept { + FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); + adjusted_mantissa answer; + bool truncated; + answer.mantissa = bigmant.hi64(truncated); + int bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + answer.power2 = bigmant.bit_length() - 64 + bias; + + round(answer, [truncated](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, + [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { + return is_above || (is_halfway && truncated) || + (is_odd && is_halfway); + }); + }); + + return answer; +} + +// the scaling here is quite simple: we have, for the real digits `m * 10^e`, +// and for the theoretical digits `n * 2^f`. Since `e` is always negative, +// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`. +// we then need to scale by `2^(f- e)`, and then the two significant digits +// are of the same magnitude. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp( + bigint &bigmant, adjusted_mantissa am, int32_t exponent) noexcept { + bigint &real_digits = bigmant; + int32_t real_exp = exponent; + + // get the value of `b`, rounded down, and get a bigint representation of b+h + adjusted_mantissa am_b = am; + // gcc7 buf: use a lambda to remove the noexcept qualifier bug with + // -Wnoexcept-type. + round(am_b, + [](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); }); + T b; + to_float(false, am_b, b); + adjusted_mantissa theor = to_extended_halfway(b); + bigint theor_digits(theor.mantissa); + int32_t theor_exp = theor.power2; + + // scale real digits and theor digits to be same power. + int32_t pow2_exp = theor_exp - real_exp; + uint32_t pow5_exp = uint32_t(-real_exp); + if (pow5_exp != 0) { + FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp)); + } + if (pow2_exp > 0) { + FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp))); + } else if (pow2_exp < 0) { + FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); + } + + // compare digits, and use it to director rounding + int ord = real_digits.compare(theor_digits); + adjusted_mantissa answer = am; + round(answer, [ord](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, [ord](bool is_odd, bool _, bool __) -> bool { + (void)_; // not needed, since we've done our comparison + (void)__; // not needed, since we've done our comparison + if (ord > 0) { + return true; + } else if (ord < 0) { + return false; + } else { + return is_odd; + } + }); + }); + + return answer; +} + +// parse the significant digits as a big integer to unambiguously round the +// the significant digits. here, we are trying to determine how to round +// an extended float representation close to `b+h`, halfway between `b` +// (the float rounded-down) and `b+u`, the next positive float. this +// algorithm is always correct, and uses one of two approaches. when +// the exponent is positive relative to the significant digits (such as +// 1234), we create a big-integer representation, get the high 64-bits, +// determine if any lower bits are truncated, and use that to direct +// rounding. in case of a negative exponent relative to the significant +// digits (such as 1.2345), we create a theoretical representation of +// `b` as a big-integer type, scaled to the same binary exponent as +// the actual digits. we then compare the big integer representations +// of both, and use that to direct rounding. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +digit_comp(parsed_number_string_t &num, adjusted_mantissa am) noexcept { + // remove the invalid exponent bias + am.power2 -= invalid_am_bias; + + int32_t sci_exp = scientific_exponent(num); + size_t max_digits = binary_format::max_digits(); + size_t digits = 0; + bigint bigmant; + parse_mantissa(bigmant, num, max_digits, digits); + // can't underflow, since digits is at most max_digits. + int32_t exponent = sci_exp + 1 - int32_t(digits); + if (exponent >= 0) { + return positive_digit_comp(bigmant, exponent); + } else { + return negative_digit_comp(bigmant, am, exponent); + } +} + +} // namespace fast_float + +#endif + +#ifndef FASTFLOAT_PARSE_NUMBER_H +#define FASTFLOAT_PARSE_NUMBER_H + + +#include +#include +#include +#include +namespace fast_float { + +namespace detail { +/** + * Special case +inf, -inf, nan, infinity, -infinity. + * The case comparisons could be made much faster given that we know that the + * strings a null-free and fixed. + **/ +template +from_chars_result_t + FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first, UC const *last, + T &value, chars_format fmt) noexcept { + from_chars_result_t answer{}; + answer.ptr = first; + answer.ec = std::errc(); // be optimistic + // assume first < last, so dereference without checks; + bool const minusSign = (*first == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*first == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && + (*first == UC('+')))) { + ++first; + } + if (last - first >= 3) { + if (fastfloat_strncasecmp(first, str_const_nan(), 3)) { + answer.ptr = (first += 3); + value = minusSign ? -std::numeric_limits::quiet_NaN() + : std::numeric_limits::quiet_NaN(); + // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, + // C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan). + if (first != last && *first == UC('(')) { + for (UC const *ptr = first + 1; ptr != last; ++ptr) { + if (*ptr == UC(')')) { + answer.ptr = ptr + 1; // valid nan(n-char-seq-opt) + break; + } else if (!((UC('a') <= *ptr && *ptr <= UC('z')) || + (UC('A') <= *ptr && *ptr <= UC('Z')) || + (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_'))) + break; // forbidden char, not nan(n-char-seq-opt) + } + } + return answer; + } + if (fastfloat_strncasecmp(first, str_const_inf(), 3)) { + if ((last - first >= 8) && + fastfloat_strncasecmp(first + 3, str_const_inf() + 3, 5)) { + answer.ptr = first + 8; + } else { + answer.ptr = first + 3; + } + value = minusSign ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + return answer; + } + } + answer.ec = std::errc::invalid_argument; + return answer; +} + +/** + * Returns true if the floating-pointing rounding mode is to 'nearest'. + * It is the default on most system. This function is meant to be inexpensive. + * Credit : @mwalcott3 + */ +fastfloat_really_inline bool rounds_to_nearest() noexcept { + // https://lemire.me/blog/2020/06/26/gcc-not-nearest/ +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return false; +#endif + // See + // A fast function to check your floating-point rounding mode + // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/ + // + // This function is meant to be equivalent to : + // prior: #include + // return fegetround() == FE_TONEAREST; + // However, it is expected to be much faster than the fegetround() + // function call. + // + // The volatile keyword prevents the compiler from computing the function + // at compile-time. + // There might be other ways to prevent compile-time optimizations (e.g., + // asm). The value does not need to be std::numeric_limits::min(), any + // small value so that 1 + x should round to 1 would do (after accounting for + // excess precision, as in 387 instructions). + static volatile float fmin = std::numeric_limits::min(); + float fmini = fmin; // we copy it so that it gets loaded at most once. +// +// Explanation: +// Only when fegetround() == FE_TONEAREST do we have that +// fmin + 1.0f == 1.0f - fmin. +// +// FE_UPWARD: +// fmin + 1.0f > 1 +// 1.0f - fmin == 1 +// +// FE_DOWNWARD or FE_TOWARDZERO: +// fmin + 1.0f == 1 +// 1.0f - fmin < 1 +// +// Note: This may fail to be accurate if fast-math has been +// enabled, as rounding conventions may not apply. +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +// todo: is there a VS warning? +// see +// https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013 +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + return (fmini + 1.0f == 1.0f - fmini); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#elif defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif +} + +} // namespace detail + +template struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced(first, last, value, options); + } +}; + +#if __STDCPP_FLOAT32_T__ == 1 +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float32_t &value, + parse_options_t options) noexcept { + // if std::float32_t is defined, and we are in C++23 mode; macro set for + // float32; set value to float due to equivalence between float and + // float32_t + float val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +#if __STDCPP_FLOAT64_T__ == 1 +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float64_t &value, + parse_options_t options) noexcept { + // if std::float64_t is defined, and we are in C++23 mode; macro set for + // float64; set value as double due to equivalence between double and + // float64_t + double val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt /*= chars_format::general*/) noexcept { + return from_chars_caller::call(first, last, value, + parse_options_t(fmt)); +} + +/** + * This function overload takes parsed_number_string_t structure that is created + * and populated either by from_chars_advanced function taking chars range and + * parsing options or other parsing custom function implemented by user. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(parsed_number_string_t &pns, T &value) noexcept { + + static_assert(is_supported_float_type(), + "only some floating-point types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + from_chars_result_t answer; + + answer.ec = std::errc(); // be optimistic + answer.ptr = pns.lastmatch; + // The implementation of the Clinger's fast path is convoluted because + // we want round-to-nearest in all cases, irrespective of the rounding mode + // selected on the thread. + // We proceed optimistically, assuming that detail::rounds_to_nearest() + // returns true. + if (binary_format::min_exponent_fast_path() <= pns.exponent && + pns.exponent <= binary_format::max_exponent_fast_path() && + !pns.too_many_digits) { + // Unfortunately, the conventional Clinger's fast path is only possible + // when the system rounds to the nearest float. + // + // We expect the next branch to almost always be selected. + // We could check it first (before the previous branch), but + // there might be performance advantages at having the check + // be last. + if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) { + // We have that fegetround() == FE_TONEAREST. + // Next is Clinger's fast path. + if (pns.mantissa <= binary_format::max_mantissa_fast_path()) { + value = T(pns.mantissa); + if (pns.exponent < 0) { + value = value / binary_format::exact_power_of_ten(-pns.exponent); + } else { + value = value * binary_format::exact_power_of_ten(pns.exponent); + } + if (pns.negative) { + value = -value; + } + return answer; + } + } else { + // We do not have that fegetround() == FE_TONEAREST. + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's + // proposal + if (pns.exponent >= 0 && + pns.mantissa <= + binary_format::max_mantissa_fast_path(pns.exponent)) { +#if defined(__clang__) || defined(FASTFLOAT_32BIT) + // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD + if (pns.mantissa == 0) { + value = pns.negative ? T(-0.) : T(0.); + return answer; + } +#endif + value = T(pns.mantissa) * + binary_format::exact_power_of_ten(pns.exponent); + if (pns.negative) { + value = -value; + } + return answer; + } + } + } + adjusted_mantissa am = + compute_float>(pns.exponent, pns.mantissa); + if (pns.too_many_digits && am.power2 >= 0) { + if (am != compute_float>(pns.exponent, pns.mantissa + 1)) { + am = compute_error>(pns.exponent, pns.mantissa); + } + } + // If we called compute_float>(pns.exponent, pns.mantissa) + // and we have an invalid power (am.power2 < 0), then we need to go the long + // way around again. This is very uncommon. + if (am.power2 < 0) { + am = digit_comp(pns, am); + } + to_float(pns.negative, am, value); + // Test for over/underflow. + if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || + am.power2 == binary_format::infinite_power()) { + answer.ec = std::errc::result_out_of_range; + } + return answer; +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_float_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(is_supported_float_type(), + "only some floating-point types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + parsed_number_string_t pns = + parse_number_string(first, last, options); + if (!pns.valid) { + if (uint64_t(fmt & chars_format::no_infnan)) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } else { + return detail::parse_infnan(first, last, value, fmt); + } + } + + // call overload that takes parsed_number_string_t directly. + return from_chars_advanced(pns, value); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base) noexcept { + + static_assert(std::is_integral::value, "only integer types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + parse_options_t options; + options.base = base; + return from_chars_advanced(first, last, value, options); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_int_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(std::is_integral::value, "only integer types are supported"); + static_assert(is_supported_char_type(), + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last || base < 2 || base > 36) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + + return parse_int_string(first, last, value, options); +} + +template struct from_chars_advanced_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_float_advanced(first, last, value, options); + } +}; + +template <> struct from_chars_advanced_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_int_advanced(first, last, value, options); + } +}; + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced_caller()>::call( + first, last, value, options); +} + +} // namespace fast_float + +#endif + diff --git a/third-party/fizz/CMakeLists.txt b/third-party/fizz/CMakeLists.txt index 29358173c3598b..23329861fd4cb8 100644 --- a/third-party/fizz/CMakeLists.txt +++ b/third-party/fizz/CMakeLists.txt @@ -68,8 +68,8 @@ ExternalProject_Add( "-DBOOST_LIBRARYDIR=${BOOST_LIBRARY_DIR}" -DDOUBLE_CONVERSION_INCLUDE_DIR=${DOUBLE_CONVERSION_INCLUDE_DIR} -DDOUBLE_CONVERSION_LIBRARY=${DOUBLE_CONVERSION_LIBRARY} - -DGLOG_INCLUDE_DIR=${GLOG_INCLUDE_DIR} - -DGLOG_LIBRARY=${GLOG_LIBRARY} + -DGLOG_INCLUDEDIR=${GLOG_INCLUDE_DIR} + -DGLOG_LIBRARYDIR=${GLOG_INSTALL_DIR}/lib -DLIBSODIUM_INCLUDEDIR=${LIBSODIUM_INCLUDE_DIR} -DLIBSODIUM_LIBRARIES=${LIBSODIUM_LIBRARY} -DZSTD_INCLUDE_DIR=${ZSTD_INCLUDE_DIR} @@ -94,4 +94,9 @@ target_link_libraries( fizz_deps ) +find_package(liboqs CONFIG) +if (liboqs_FOUND) + target_link_libraries(fizz INTERFACE OQS::oqs) +endif() + set(FIZZ_INSTALL_DIR "${INSTALL_DIR}" PARENT_SCOPE) diff --git a/third-party/fizz/patches/do-not-build-testsupport.patch b/third-party/fizz/patches/do-not-build-testsupport.patch index 29c0627838294b..2ceae641b973bb 100644 --- a/third-party/fizz/patches/do-not-build-testsupport.patch +++ b/third-party/fizz/patches/do-not-build-testsupport.patch @@ -1,78 +1,21 @@ diff --git a/fizz/CMakeLists.txt b/fizz/CMakeLists.txt -index 85b78981..5422ba9b 100644 +index c60177c2..2c41ae84 100644 --- a/fizz/CMakeLists.txt +++ b/fizz/CMakeLists.txt -@@ -314,42 +314,42 @@ SET(FIZZ_TEST_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) +@@ -281,7 +281,6 @@ SET(FIZZ_TEST_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) if(BUILD_TESTS) find_package(GMock 1.8.0 MODULE REQUIRED) find_package(GTest 1.8.0 MODULE REQUIRED) -endif() --add_library(fizz_test_support -- crypto/aead/test/TestUtil.cpp -- crypto/test/TestUtil.cpp -- protocol/ech/test/TestUtil.cpp -- ${FIZZ_TEST_HEADERS} --) -+ add_library(fizz_test_support -+ crypto/aead/test/TestUtil.cpp -+ crypto/test/TestUtil.cpp -+ protocol/ech/test/TestUtil.cpp -+ ${FIZZ_TEST_HEADERS} -+ ) + add_library(fizz_test_support + crypto/aead/test/TestUtil.cpp +@@ -304,6 +303,8 @@ install( + LIBRARY DESTINATION ${LIB_INSTALL_DIR} + ) --target_link_libraries(fizz_test_support -- PUBLIC -- fizz -- ${LIBGMOCK_LIBRARIES} -- ${GLOG_LIBRARY} --) -+ target_link_libraries(fizz_test_support -+ PUBLIC -+ fizz -+ ${LIBGMOCK_LIBRARIES} -+ ${GLOG_LIBRARY} -+ ) - --target_compile_definitions(fizz_test_support -- PUBLIC -- ${LIBGMOCK_DEFINES} --) -+ target_compile_definitions(fizz_test_support -+ PUBLIC -+ ${LIBGMOCK_DEFINES} -+ ) - --target_include_directories(fizz_test_support -- SYSTEM -- PUBLIC -- ${LIBGMOCK_INCLUDE_DIR} -- ${LIBGTEST_INCLUDE_DIRS} --) -+ target_include_directories(fizz_test_support -+ SYSTEM -+ PUBLIC -+ ${LIBGMOCK_INCLUDE_DIR} -+ ${LIBGTEST_INCLUDE_DIRS} -+ ) - --# export fizz headers and targets for unit tests utils --# since other projects such as mvfst and proxygen use them --install( -- TARGETS fizz_test_support -- EXPORT fizz-exports -- ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -- LIBRARY DESTINATION ${LIB_INSTALL_DIR} --) -+ # export fizz headers and targets for unit tests utils -+ # since other projects such as mvfst and proxygen use them -+ install( -+ TARGETS fizz_test_support -+ EXPORT fizz-exports -+ ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -+ LIBRARY DESTINATION ${LIB_INSTALL_DIR} -+ ) +endif() - ++ foreach(dir ${FIZZ_TEST_HEADER_DIRS}) get_filename_component(PARENT_DIR "/${dir}" DIRECTORY) + install( diff --git a/third-party/fizz/patches/fizz-config-libsodium.patch b/third-party/fizz/patches/fizz-config-libsodium.patch index 16b2eaa5c39c74..28925b25149af3 100644 --- a/third-party/fizz/patches/fizz-config-libsodium.patch +++ b/third-party/fizz/patches/fizz-config-libsodium.patch @@ -2,10 +2,11 @@ diff --git a/fizz/cmake/fizz-config.cmake.in b/fizz/cmake/fizz-config.cmake.in index 679b0e61..6415688b 100644 --- a/fizz/cmake/fizz-config.cmake.in +++ b/fizz/cmake/fizz-config.cmake.in -@@ -26,7 +26,6 @@ endif() +@@ -30,8 +30,7 @@ endif() set(FIZZ_LIBRARIES fizz::fizz) include(CMakeFindDependencyMacro) + -find_dependency(Sodium) find_dependency(folly CONFIG) find_dependency(ZLIB) diff --git a/third-party/fizz/patches/use-hhvm-libsodium-cmake.patch b/third-party/fizz/patches/use-hhvm-libsodium-cmake.patch index 1cdaefd1fd0657..83a6c019ef1da0 100644 --- a/third-party/fizz/patches/use-hhvm-libsodium-cmake.patch +++ b/third-party/fizz/patches/use-hhvm-libsodium-cmake.patch @@ -2,16 +2,18 @@ Index: fizz/fizz/CMakeLists.txt =================================================================== --- fizz.orig/fizz/CMakeLists.txt +++ fizz/fizz/CMakeLists.txt -@@ -64,7 +64,7 @@ endif() +@@ -62,8 +62,8 @@ endif() include(CheckAtomic) -find_package(Sodium REQUIRED) +-set(FIZZ_HAVE_SODIUM ${Sodium_FOUND}) +find_package(LibSodium REQUIRED) ++set(FIZZ_HAVE_SODIUM ${LibSodium_FOUND}) SET(FIZZ_SHINY_DEPENDENCIES "") SET(FIZZ_LINK_LIBRARIES "") -@@ -237,7 +237,7 @@ target_include_directories( +@@ -201,7 +201,7 @@ target_include_directories( $ ${FOLLY_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} @@ -20,7 +22,7 @@ Index: fizz/fizz/CMakeLists.txt ${ZSTD_INCLUDE_DIR} PRIVATE ${GLOG_INCLUDE_DIRS} -@@ -250,7 +250,7 @@ target_link_libraries(fizz +@@ -213,7 +213,7 @@ target_link_libraries(fizz PUBLIC ${FOLLY_LIBRARIES} ${OPENSSL_LIBRARIES} @@ -29,3 +31,4 @@ Index: fizz/fizz/CMakeLists.txt Threads::Threads ZLIB::ZLIB ${ZSTD_LIBRARY} + diff --git a/third-party/fmt/CMakeLists.txt b/third-party/fmt/CMakeLists.txt index b6f6cacc859bfc..a9801ee812daab 100644 --- a/third-party/fmt/CMakeLists.txt +++ b/third-party/fmt/CMakeLists.txt @@ -14,9 +14,9 @@ else() SET_HHVM_THIRD_PARTY_SOURCE_ARGS( FMT_SOURCE_ARGS SOURCE_URL - "https://github.com/fmtlib/fmt/releases/download/11.1.1/fmt-11.1.1.zip" + "https://github.com/fmtlib/fmt/releases/download/12.1.0/fmt-12.1.0.zip" SOURCE_HASH - "SHA512=6321f29b4ddabfcd92362883ca54039f5f2f90d85d95af1410ba98607acdde02c8c02b61c4fad212337aa2938681e038cd4533013b4e1f500c6839f77a74aeca" + "SHA512=405645141c93dcde2225976328a4b373e5ca3b0bc1c1759249ce3cee2ec86dc6080bec5d4adafb9d6b5f5501e5f8e8fe8bcdba9107047b54f8ef46a4a8f5971e" ) set(INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/fmt-prefix") diff --git a/third-party/folly/CMakeLists.txt b/third-party/folly/CMakeLists.txt index e72203e7677ce6..74e4688176989a 100644 --- a/third-party/folly/CMakeLists.txt +++ b/third-party/folly/CMakeLists.txt @@ -9,6 +9,7 @@ get_target_property(LIBSODIUM_LIBRARY libsodium INTERFACE_LINK_LIBRARIES) get_target_property(ZSTD_INCLUDE_DIR zstd INTERFACE_INCLUDE_DIRECTORIES) get_target_property(ZSTD_LIBRARY zstd INTERFACE_LINK_LIBRARIES) get_target_property(JEMALLOC_INCLUDE_DIR jemalloc INTERFACE_INCLUDE_DIRECTORIES) +get_target_property(FAST_FLOAT_INCLUDE_DIR fast_float INTERFACE_INCLUDE_DIRECTORIES) get_target_property(GFLAGS_INCLUDE_DIR gflags INTERFACE_INCLUDE_DIRECTORIES) get_target_property(GFLAGS_LIBRARY gflags INTERFACE_LINK_LIBRARIES) get_target_property(GLOG_INCLUDE_DIR glog INTERFACE_INCLUDE_DIRECTORIES) @@ -26,13 +27,6 @@ get_filename_component(BOOST_LIBRARY_DIR "${FIRST_LIB}" DIRECTORY) set(FOLLY_CXXFLAGS "-I${JEMALLOC_INCLUDE_DIR} -I${CMAKE_CURRENT_LIST_DIR}/include") message(STATUS "FOLLY_CXXFLAGS: ${FOLLY_CXXFLAGS}") -if(ENABLE_SSE4_2 OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "AppleClang") - if(IS_X64) - message(STATUS "Enabling SSE 4.2 for bundled folly") - set(FOLLY_CXXFLAGS "${FOLLY_CXXFLAGS} -msse4.2") - endif() -endif() - ExternalProject_add( bundled_folly SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/ @@ -62,8 +56,8 @@ ExternalProject_add( -DOPENSSL_CRYPTO_LIBRARY=${OPENSSL_CRYPTO_LIBRARY} -DGFLAGS_INCLUDE_DIR=${GFLAGS_INCLUDE_DIR} -DGFLAGS_LIBRARY=${GFLAGS_LIBRARY} - -DGLOG_INCLUDE_DIR=${GLOG_INCLUDE_DIR} - -DGLOG_LIBRARY=glog + -DGLOG_INCLUDEDIR=${GLOG_INCLUDE_DIR} + -DGLOG_LIBRARYDIR=${GLOG_INSTALL_DIR}/lib -DBoost_NO_SYSTEM_PATHS=ON -DBoost_NO_BOOST_CMAKE=ON -DBoost_USE_STATIC_LIBS=${Boost_USE_STATIC_LIBS} @@ -72,9 +66,9 @@ ExternalProject_add( -DBoost_DEBUG=1 -DDOUBLE_CONVERSION_INCLUDE_DIR=${DOUBLE_CONVERSION_INCLUDE_DIR} -DDOUBLE_CONVERSION_LIBRARY=${DOUBLE_CONVERSION_LIBRARY} + -DFASTFLOAT_INCLUDE_DIR=${FAST_FLOAT_INCLUDE_DIR} "-Dfmt_DIR=${fmt_DIR}" - -DLIBSODIUM_INCLUDE_DIR=${LIBSODIUM_INCLUDE_DIR} - -DLIBSODIUM_LIBRARY=${LIBSODIUM_LIBRARY} + -DZSTD_INCLUDE_DIR=${ZSTD_INCLUDE_DIR} -DZSTD_LIBRARY_RELEASE=${ZSTD_LIBRARY} BUILD_COMMAND @@ -92,6 +86,7 @@ set( FOLLY_DEPS boost double-conversion + fast_float fmt libsodium jemalloc diff --git a/third-party/folly/patches/do-not-export-unbuilt-targets.patch b/third-party/folly/patches/do-not-export-unbuilt-targets.patch index ce13f6a46572b1..a07fa830ae158f 100644 --- a/third-party/folly/patches/do-not-export-unbuilt-targets.patch +++ b/third-party/folly/patches/do-not-export-unbuilt-targets.patch @@ -10,10 +10,10 @@ Index: folly/folly/CMakeLists.txt RUNTIME DESTINATION ${BIN_INSTALL_DIR} LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} -Index: folly/folly/experimental/exception_tracer/CMakeLists.txt +Index: folly/folly/debugging/exception_tracer/CMakeLists.txt =================================================================== ---- folly.orig/folly/experimental/exception_tracer/CMakeLists.txt -+++ folly/folly/experimental/exception_tracer/CMakeLists.txt +--- folly.orig/folly/debugging/exception_tracer/CMakeLists.txt ++++ folly/folly/debugging/exception_tracer/CMakeLists.txt @@ -63,7 +63,6 @@ if (FOLLY_HAVE_ELF AND FOLLY_HAVE_DWARF) folly_exception_tracer_base folly_exception_tracer diff --git a/third-party/folly/patches/folly-install-component.patch b/third-party/folly/patches/folly-install-component.patch index 773b84cd1c3a0c..35ccc928fc9add 100644 --- a/third-party/folly/patches/folly-install-component.patch +++ b/third-party/folly/patches/folly-install-component.patch @@ -2,7 +2,7 @@ Index: folly/CMakeLists.txt =================================================================== --- folly.orig/CMakeLists.txt +++ folly/CMakeLists.txt -@@ -385,8 +385,6 @@ target_compile_definitions(folly_base +@@ -460,8 +460,6 @@ target_compile_definitions(folly_base $ ) @@ -11,7 +11,7 @@ Index: folly/CMakeLists.txt option(PYTHON_EXTENSIONS "Build Python Bindings for Folly, requires Cython and (BUILD_SHARED_LIBS=ON)" OFF -@@ -414,21 +412,31 @@ target_link_libraries(folly_test_util +@@ -492,21 +490,31 @@ target_link_libraries(folly_test_util ${LIBGMOCK_LIBRARIES} ) apply_folly_compile_options_to_target(folly_test_util) diff --git a/third-party/folly/src/folly/Subprocess.cpp b/third-party/folly/src/folly/Subprocess.cpp index 6ce056ed06b6fb..11121a56ddfb6c 100644 --- a/third-party/folly/src/folly/Subprocess.cpp +++ b/third-party/folly/src/folly/Subprocess.cpp @@ -145,6 +145,10 @@ static Ret subprocess_libc_load( #define FOLLY_DETAIL_SUBPROCESS_LIBC_X_OPEN(X) \ X(open, __open_real) \ X(openat, __openat_real) +#elif defined(_FORTIFY_SOURCE) && defined(__clang__) && (__GLIBC__ > 2 || __GLIBC__ == 2 && __GLIBC_MINOR__ >= 40) +#define FOLLY_DETAIL_SUBPROCESS_LIBC_X_OPEN(X) \ + X(open, open) \ + X(openat, __openat_2) #else #define FOLLY_DETAIL_SUBPROCESS_LIBC_X_OPEN(X) \ X(open, open) \ diff --git a/third-party/folly/src/folly/Traits.h b/third-party/folly/src/folly/Traits.h index 2c03fd70ae378b..9be444ecc4a7dc 100644 --- a/third-party/folly/src/folly/Traits.h +++ b/third-party/folly/src/folly/Traits.h @@ -1490,14 +1490,15 @@ using value_list_concat_t = namespace detail { template -constexpr std::size_t type_pack_find_() { - bool eq[] = {std::is_same_v..., true}; - for (size_t i = 0; i < sizeof...(T); ++i) { - if (eq[i]) { - return i; - } +constexpr bool type_pack_find_a_[sizeof...(T) + 1] = { + std::is_same_v..., true}; + +constexpr std::size_t type_pack_find_(bool const* eq) { + size_t i = 0; + while (!eq[i]) { + ++i; } - return sizeof...(T); + return i; } template @@ -1505,7 +1506,8 @@ struct type_list_find_; template