From d9d08fb479ad5d431049ca162c0d52e6dd9ed82b Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 27 Sep 2023 00:58:17 +0300 Subject: [PATCH] CMake: Use -D_FILE_OFFSET_BITS=64 if (and only if) needed. A CMake option LARGE_FILE_SUPPORT is created if and only if -D_FILE_OFFSET_BITS=64 affects sizeof(off_t). This is needed on many 32-bit platforms and even with 64-bit builds with MinGW-w64 to get support for files larger than 2 GiB. (cherry picked from commit 36fabdbe67c8a8fbdc3ac695a91fc443a1328cc4) --- CMakeLists.txt | 7 +++- cmake/tuklib_large_file_support.cmake | 52 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 cmake/tuklib_large_file_support.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 27580d03..00de16b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,6 @@ # # On some platforms this builds also xz and xzdec, but these are # highly experimental and meant for testing only: -# - No large file support on those 32-bit platforms that need it # - No replacement getopt_long(), libc must have it # - No sandboxing support # - No translations @@ -50,6 +49,7 @@ cmake_minimum_required(VERSION 3.13...3.27 FATAL_ERROR) include(CheckSymbolExists) include(CheckStructHasMember) +include(cmake/tuklib_large_file_support.cmake) include(cmake/tuklib_integer.cmake) include(cmake/tuklib_cpucores.cmake) include(cmake/tuklib_physmem.cmake) @@ -164,6 +164,11 @@ add_compile_definitions( # it also adds the definitions to CMAKE_REQUIRED_DEFINITIONS. tuklib_use_system_extensions(ALL) +# Check for large file support. It's required on some 32-bit platforms and +# even on 64-bit MinGW-w64 to get 64-bit off_t. This can be forced off on +# the CMake command line if needed: -DLARGE_FILE_SUPPORT=OFF +tuklib_large_file_support(ALL) + # This is needed by liblzma and xz. tuklib_integer(ALL) diff --git a/cmake/tuklib_large_file_support.cmake b/cmake/tuklib_large_file_support.cmake new file mode 100644 index 00000000..0800faa2 --- /dev/null +++ b/cmake/tuklib_large_file_support.cmake @@ -0,0 +1,52 @@ +# +# tuklib_large_file_support.cmake +# +# If off_t is less than 64 bits by default and -D_FILE_OFFSET_BITS=64 +# makes off_t become 64-bit, the CMake option LARGE_FILE_SUPPORT is +# provided (ON by default) and -D_FILE_OFFSET_BITS=64 is added to +# the compile definitions if LARGE_FILE_SUPPORT is ON. +# +# Author: Lasse Collin +# +# This file has been put into the public domain. +# You can do whatever you want with this file. +# + +include("${CMAKE_CURRENT_LIST_DIR}/tuklib_common.cmake") +include(CheckCSourceCompiles) + +function(tuklib_large_file_support TARGET_OR_ALL) + # MSVC must be handled specially in the C code. + if(MSVC) + return() + endif() + + set(TUKLIB_LARGE_FILE_SUPPORT_TEST + "#include + int foo[sizeof(off_t) >= 8 ? 1 : -1]; + int main(void) { return 0; }") + + check_c_source_compiles("${TUKLIB_LARGE_FILE_SUPPORT_TEST}" + TUKLIB_LARGE_FILE_SUPPORT_BY_DEFAULT) + + if(NOT TUKLIB_LARGE_FILE_SUPPORT_BY_DEFAULT) + cmake_push_check_state() + # This needs -D. + list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64") + check_c_source_compiles("${TUKLIB_LARGE_FILE_SUPPORT_TEST}" + TUKLIB_LARGE_FILE_SUPPORT_WITH_FOB64) + cmake_pop_check_state() + endif() + + if(TUKLIB_LARGE_FILE_SUPPORT_WITH_FOB64) + # Show the option only when _FILE_OFFSET_BITS=64 affects sizeof(off_t). + option(LARGE_FILE_SUPPORT + "Use -D_FILE_OFFSET_BITS=64 to support files larger than 2 GiB." + ON) + + if(LARGE_FILE_SUPPORT) + # This must not use -D. + tuklib_add_definitions("${TARGET_OR_ALL}" "_FILE_OFFSET_BITS=64") + endif() + endif() +endfunction()