From af87b7b7e4654bd5d9ccf00593d60428da07abf5 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Tue, 7 Dec 2021 20:21:42 +0100 Subject: [PATCH] cmake: replace LFS check with scripts from wireshark Testing on 32bit arm have weird issues where the build failed if run/continued without configuring again. With these scripts we also require less files, no .c files in cmake/. One downside is that we now require at least Visual Studio 2005 (MSVCR80) for compiling on windows (and there's no check for this currently). --- cmake/FindFseeko.cmake | 85 +++++++++++++++++ cmake/FindLFS.cmake | 153 +++++++++++++++++++++++++++++++ cmake/LargeFiles.c | 15 --- cmake/LargeFiles.cmake | 107 --------------------- cmake/LargeFiles64.c | 16 ---- cmake/LargeFilesWindows.c | 8 -- heimdall-frontend/CMakeLists.txt | 32 ++++++- heimdall/CMakeLists.txt | 33 ++++++- 8 files changed, 299 insertions(+), 150 deletions(-) create mode 100644 cmake/FindFseeko.cmake create mode 100644 cmake/FindLFS.cmake delete mode 100644 cmake/LargeFiles.c delete mode 100644 cmake/LargeFiles.cmake delete mode 100644 cmake/LargeFiles64.c delete mode 100644 cmake/LargeFilesWindows.c diff --git a/cmake/FindFseeko.cmake b/cmake/FindFseeko.cmake new file mode 100644 index 0000000..ca53a5a --- /dev/null +++ b/cmake/FindFseeko.cmake @@ -0,0 +1,85 @@ +# CMake support for fseeko +# +# Based on FindLFS.cmake by +# Copyright (C) 2016 Julian Andres Klode . +# +# 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. +# +# This defines the following variables +# +# FSEEKO_DEFINITIONS - List of definitions to pass to add_definitions() +# FSEEKO_COMPILE_OPTIONS - List of definitions to pass to add_compile_options() +# FSEEKO_LIBRARIES - List of libraries and linker flags +# FSEEKO_FOUND - If there is Large files support +# + +include(CheckCSourceCompiles) +include(FindPackageHandleStandardArgs) +include(CMakePushCheckState) + +# Check for the availability of fseeko() +# The cases handled are: +# +# * Native fseeko() +# * Preprocessor flag -D_LARGEFILE_SOURCE +# +function(_fseeko_check) + set(_fseeko_cppflags) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS}) + message(STATUS "Looking for native fseeko support") + check_symbol_exists(fseeko stdio.h fseeko_native) + cmake_pop_check_state() + if (fseeko_native) + message(STATUS "Looking for native fseeko support - found") + set(FSEEKO_FOUND TRUE) + else() + message(STATUS "Looking for native fseeko support - not found") + endif() + + if (NOT FSEEKO_FOUND) + # See if it's available with _LARGEFILE_SOURCE. + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS} "-D_LARGEFILE_SOURCE") + check_symbol_exists(fseeko stdio.h fseeko_need_largefile_source) + cmake_pop_check_state() + if (fseeko_need_largefile_source) + message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - found") + set(FSEEKO_FOUND TRUE) + set(_fseeko_cppflags "-D_LARGEFILE_SOURCE") + else() + message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - not found") + endif() + endif() + + set(FSEEKO_DEFINITIONS ${_fseeko_cppflags} CACHE STRING "Extra definitions for fseeko support") + set(FSEEKO_COMPILE_OPTIONS "" CACHE STRING "Extra compiler options for fseeko support") + set(FSEEKO_LIBRARIES "" CACHE STRING "Extra definitions for fseeko support") + set(FSEEKO_FOUND ${FSEEKO_FOUND} CACHE INTERNAL "Found fseeko") +endfunction() + +if (NOT FSEEKO_FOUND) + _fseeko_check() +endif() + +find_package_handle_standard_args(FSEEKO "Could not find fseeko. Set FSEEKO_DEFINITIONS, FSEEKO_COMPILE_OPTIONS, FSEEKO_LIBRARIES." FSEEKO_FOUND) diff --git a/cmake/FindLFS.cmake b/cmake/FindLFS.cmake new file mode 100644 index 0000000..be5f0d4 --- /dev/null +++ b/cmake/FindLFS.cmake @@ -0,0 +1,153 @@ +# CMake support for large files +# +# Copyright (C) 2016 Julian Andres Klode . +# +# 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. +# +# This defines the following variables +# +# LFS_DEFINITIONS - List of definitions to pass to add_definitions() +# LFS_COMPILE_OPTIONS - List of definitions to pass to add_compile_options() +# LFS_LIBRARIES - List of libraries and linker flags +# LFS_FOUND - If there is Large files support +# + +include(CheckCSourceCompiles) +include(FindPackageHandleStandardArgs) +include(CMakePushCheckState) + +# Test program to check for LFS. Requires that off_t has at least 8 byte large +set(_lfs_test_source + " + #include + typedef char my_static_assert[sizeof(off_t) >= 8 ? 1 : -1]; + int main(void) { return 0; } + " +) + +# Check if the given options are needed +# +# This appends to the variables _lfs_cppflags, _lfs_cflags, and _lfs_ldflags, +# it also sets LFS_FOUND to 1 if it works. +function(_lfs_check_compiler_option var options definitions libraries) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${options}) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${definitions}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_DEFINITIONS} ${libraries}) + + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries}") + check_c_source_compiles("${_lfs_test_source}" ${var}) + cmake_pop_check_state() + + if(${var}) + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - found") + set(_lfs_cppflags ${_lfs_cppflags} ${definitions} PARENT_SCOPE) + set(_lfs_cflags ${_lfs_cflags} ${options} PARENT_SCOPE) + set(_lfs_ldflags ${_lfs_ldflags} ${libraries} PARENT_SCOPE) + set(LFS_FOUND TRUE PARENT_SCOPE) + else() + message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - not found") + endif() +endfunction() + +# Check for the availability of LFS. +# The cases handled are: +# +# * Native LFS +# * Output of getconf LFS_CFLAGS; getconf LFS_LIBS; getconf LFS_LDFLAGS +# * Preprocessor flag -D_FILE_OFFSET_BITS=64 +# * Preprocessor flag -D_LARGE_FILES +# +function(_lfs_check) + set(_lfs_cflags) + set(_lfs_cppflags) + set(_lfs_ldflags) + set(_lfs_libs) + cmake_push_check_state() + set(CMAKE_REQUIRED_QUIET 1) + message(STATUS "Looking for native LFS support") + check_c_source_compiles("${_lfs_test_source}" lfs_native) + cmake_pop_check_state() + if (lfs_native) + message(STATUS "Looking for native LFS support - found") + set(LFS_FOUND TRUE) + else() + message(STATUS "Looking for native LFS support - not found") + endif() + + if (NOT LFS_FOUND) + # Check using getconf. If getconf fails, don't worry, the check in + # _lfs_check_compiler_option will fail as well. + execute_process(COMMAND getconf LFS_CFLAGS + OUTPUT_VARIABLE _lfs_cflags_raw + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + execute_process(COMMAND getconf LFS_LIBS + OUTPUT_VARIABLE _lfs_libs_tmp + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + execute_process(COMMAND getconf LFS_LDFLAGS + OUTPUT_VARIABLE _lfs_ldflags_tmp + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + + separate_arguments(_lfs_cflags_raw) + separate_arguments(_lfs_ldflags_tmp) + separate_arguments(_lfs_libs_tmp) + + # Move -D flags to the place they are supposed to be + foreach(flag ${_lfs_cflags_raw}) + if (flag MATCHES "-D.*") + list(APPEND _lfs_cppflags_tmp ${flag}) + else() + list(APPEND _lfs_cflags_tmp ${flag}) + endif() + endforeach() + + # Check if the flags we received (if any) produce working LFS support + _lfs_check_compiler_option(lfs_getconf_works + "${_lfs_cflags_tmp}" + "${_lfs_cppflags_tmp}" + "${_lfs_libs_tmp};${_lfs_ldflags_tmp}") + endif() + + if(NOT LFS_FOUND) # IRIX stuff + _lfs_check_compiler_option(lfs_need_n32 "-n32" "" "") + endif() + if(NOT LFS_FOUND) # Linux and friends + _lfs_check_compiler_option(lfs_need_file_offset_bits "" "-D_FILE_OFFSET_BITS=64" "") + endif() + if(NOT LFS_FOUND) # AIX + _lfs_check_compiler_option(lfs_need_large_files "" "-D_LARGE_FILES=1" "") + endif() + + set(LFS_DEFINITIONS ${_lfs_cppflags} CACHE STRING "Extra definitions for large file support") + set(LFS_COMPILE_OPTIONS ${_lfs_cflags} CACHE STRING "Extra definitions for large file support") + set(LFS_LIBRARIES ${_lfs_libs} ${_lfs_ldflags} CACHE STRING "Extra definitions for large file support") + set(LFS_FOUND ${LFS_FOUND} CACHE INTERNAL "Found LFS") +endfunction() + +if (NOT LFS_FOUND) + _lfs_check() +endif() + +find_package_handle_standard_args(LFS "Could not find LFS. Set LFS_DEFINITIONS, LFS_COMPILE_OPTIONS, LFS_LIBRARIES." LFS_FOUND) diff --git a/cmake/LargeFiles.c b/cmake/LargeFiles.c deleted file mode 100644 index d11ea97..0000000 --- a/cmake/LargeFiles.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) -#define VALID_ARRAY_LENGTH 1 -#define INVALID_ARRAY_LENGTH -1 - -int main(int argc, const char **argv) -{ - int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH]; - off_t offset = ftello(NULL); - fseeko(NULL, offset, SEEK_SET); - return 0; -} diff --git a/cmake/LargeFiles.cmake b/cmake/LargeFiles.cmake deleted file mode 100644 index 6e60a8d..0000000 --- a/cmake/LargeFiles.cmake +++ /dev/null @@ -1,107 +0,0 @@ -macro(test_large_files VARIABLE USE_64_SUFFIX) - if(NOT DEFINED ${VARIABLE}) - message(STATUS "Checking if large (64-bit) file support is available...") - - if(USE_64_SUFFIX) - set(SUFFIX_64 "64") - else(USE_64_SUFFIX) - set(SUFFIX_64 "") - endif(USE_64_SUFFIX) - - # First try without any macros defined - try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}" - "${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c" - OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT) - - if(VERBOSE_LARGE_FILES) - message(STATUS "Large file output (no special flags):\n${TRY_LARGE_FILES_OUTPUT}") - endif(VERBOSE_LARGE_FILES) - - if(NOT LARGE_FILES_SUPPORTED) - # Try with C macro _FILE_OFFSET_BITS=64 - try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}" - "${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c" - COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" - OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT) - - if(VERBOSE_LARGE_FILES) - message(STATUS "Large file output (_FILE_OFFSET_BITS=64):\n${TRY_LARGE_FILES_OUTPUT}") - endif(VERBOSE_LARGE_FILES) - - if(LARGE_FILES_SUPPORTED) - set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support") - endif(LARGE_FILES_SUPPORTED) - endif(NOT LARGE_FILES_SUPPORTED) - - if(NOT LARGE_FILES_SUPPORTED) - # Try with C macro _LARGEFILE_SOURCE - - try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}" - "${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c" - COMPILE_DEFINITIONS "-D_LARGEFILE${SUFFIX_64}_SOURCE" - OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT) - - if(VERBOSE_LARGE_FILES) - message(STATUS "Large file output (_LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}") - endif(VERBOSE_LARGE_FILES) - - if(LARGE_FILES_SUPPORTED) - set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support") - endif(LARGE_FILES_SUPPORTED) - endif(NOT LARGE_FILES_SUPPORTED) - - if(NOT LARGE_FILES_SUPPORTED) - # Try with both C macro _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE - try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}" - "${CMAKE_MODULE_PATH}/LargeFiles${SUFFIX_64}.c" - COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" "-D_LARGEFILE${SUFFIX_64}_SOURCE" - OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT) - - if(VERBOSE_LARGE_FILES) - message(STATUS "Large file output (_FILE_OFFSET_BITS=64 and _LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}") - endif(VERBOSE_LARGE_FILES) - - if(LARGE_FILES_SUPPORTED) - set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support") - set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support") - endif(LARGE_FILES_SUPPORTED) - endif(NOT LARGE_FILES_SUPPORTED) - - if(NOT LARGE_FILES_SUPPORTED) - # Maybe we are using the Windows C standard library - try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}" - "${CMAKE_MODULE_PATH}/LargeFilesWindows.c") - endif(NOT LARGE_FILES_SUPPORTED) - - if(LARGE_FILES_SUPPORTED) - message(STATUS "Checking if large (64-bit) file support is available - yes") - set(${VARIABLE} 1 CACHE INTERNAL "Is large file support available?") - else(LARGE_FILES_SUPPORTED) - message(STATUS "Checking if large (64-bit) file support is available - no") - set(${VARIABLE} 0 CACHE INTERNAL "Is large file support available?") - endif(LARGE_FILES_SUPPORTED) - endif(NOT DEFINED ${VARIABLE}) -endmacro(test_large_files VARIABLE USE_64_SUFFIX) - -macro(use_large_files TARGET USE_64_SUFFIX) - test_large_files(USING_LARGE_FILES ${USE_64_SUFFIX}) - - if(USING_LARGE_FILES) - if(DEFINED _FILE_OFFSET_BITS) - set_property(TARGET ${TARGET} - APPEND PROPERTY COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}") - endif(DEFINED _FILE_OFFSET_BITS) - - if(DEFINED _LARGEFILE_SOURCE) - set_property(TARGET ${TARGET} - APPEND PROPERTY COMPILE_DEFINITIONS "-D_LARGEFILE_SOURCE") - endif(DEFINED _LARGEFILE_SOURCE) - - if(DEFINED _LARGEFILE64_SOURCE) - set_property(TARGET ${TARGET} - APPEND PROPERTY COMPILE_DEFINITIONS "-D_LARGEFILE64_SOURCE") - endif(DEFINED _LARGEFILE64_SOURCE) - else(USING_LARGE_FILES) - message(FATAL_ERROR "Large file support not available") - endif(USING_LARGE_FILES) -endmacro(use_large_files TARGET USE_64_SUFFIX) diff --git a/cmake/LargeFiles64.c b/cmake/LargeFiles64.c deleted file mode 100644 index 4953392..0000000 --- a/cmake/LargeFiles64.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) -#define VALID_ARRAY_LENGTH 1 -#define INVALID_ARRAY_LENGTH -1 - -int main(int argc, const char **argv) -{ - int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH]; - off64_t offset = ftello64(NULL); - fseeko64(NULL, offset, SEEK_SET); - return 0; -} diff --git a/cmake/LargeFilesWindows.c b/cmake/LargeFilesWindows.c deleted file mode 100644 index 85fadd8..0000000 --- a/cmake/LargeFilesWindows.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main() -{ - __int64 off = 0; - _fseeki64(NULL, off, SEEK_SET); - return 0; -} diff --git a/heimdall-frontend/CMakeLists.txt b/heimdall-frontend/CMakeLists.txt index 2488cad..d0270c5 100644 --- a/heimdall-frontend/CMakeLists.txt +++ b/heimdall-frontend/CMakeLists.txt @@ -46,8 +46,36 @@ add_executable(heimdall-frontend WIN32 target_compile_features(heimdall-frontend PRIVATE cxx_std_11) -include(LargeFiles) -use_large_files(heimdall-frontend YES) +include(CheckSymbolExists) + +# +# Large file support on UN*X, a/k/a LFS. +# +# On Windows, we require _fseeki64() and _ftelli64(). Visual Studio +# has had supported them since Visual Studio 2005/MSVCR80. +# +if(NOT WIN32) + include(FindLFS) + if(LFS_FOUND) + # + # Add the required #defines. + # + add_definitions(${LFS_DEFINITIONS}) + endif() + + # + # Check for fseeko as well. + # + include(FindFseeko) + if(FSEEKO_FOUND) + set(HAVE_FSEEKO ON) + + # + # Add the required #defines. + # + add_definitions(${FSEEKO_DEFINITIONS}) + endif() +endif() set_property(TARGET heimdall-frontend APPEND PROPERTY COMPILE_DEFINITIONS "QT_LARGEFILE_SUPPORT") diff --git a/heimdall/CMakeLists.txt b/heimdall/CMakeLists.txt index bafb2cb..e5bc63a 100644 --- a/heimdall/CMakeLists.txt +++ b/heimdall/CMakeLists.txt @@ -39,8 +39,37 @@ set(HEIMDALL_SOURCE_FILES source/Utility.cpp source/VersionAction.cpp) -include(LargeFiles) -use_large_files(heimdall YES) +include(CheckSymbolExists) + +# +# Large file support on UN*X, a/k/a LFS. +# +# On Windows, we require _fseeki64() and _ftelli64(). Visual Studio +# has had supported them since Visual Studio 2005/MSVCR80. +# +if(NOT WIN32) + include(FindLFS) + if(LFS_FOUND) + # + # Add the required #defines. + # + add_definitions(${LFS_DEFINITIONS}) + endif() + + # + # Check for fseeko as well. + # + include(FindFseeko) + if(FSEEKO_FOUND) + set(HAVE_FSEEKO ON) + + # + # Add the required #defines. + # + add_definitions(${FSEEKO_DEFINITIONS}) + endif() +endif() + add_executable(heimdall ${HEIMDALL_SOURCE_FILES}) target_compile_features(heimdall PRIVATE cxx_std_11)