From 6ca6180f43a56ed8365cbe73bb565037fdd2056c Mon Sep 17 00:00:00 2001 From: David Korth Date: Sat, 20 Jun 2020 14:01:52 -0400 Subject: [PATCH] Copied various CMake module updates from rom-properties. - Changed several macros to functions, e.g. C/C++ language version checks. - Improved CPU architecture detection. - Improved LFS detection on some *BSD platforms. - Preliminary support for Windows on ARM. - Added toolchain files for i686 and x86_64 MinGW-w64. --- cmake/macros/CheckC11C99CompilerFlag.cmake | 130 +++++++++--------- cmake/macros/CheckCXX11CompilerFlag.cmake | 80 ++++++----- cmake/macros/CheckLargeFileSupport.cmake | 32 ++++- .../CheckStackProtectorCompilerFlag.cmake | 37 ++--- cmake/platform.cmake | 68 +++++---- cmake/platform/gcc.cmake | 13 +- cmake/platform/win32-gcc.cmake | 32 +++-- cmake/platform/win32-msvc.cmake | 31 ++--- cmake/toolchain/i686-w64-mingw32.cmake | 20 +++ cmake/toolchain/x86_64-w64-mingw32.cmake | 20 +++ 10 files changed, 280 insertions(+), 183 deletions(-) create mode 100644 cmake/toolchain/i686-w64-mingw32.cmake create mode 100644 cmake/toolchain/x86_64-w64-mingw32.cmake diff --git a/cmake/macros/CheckC11C99CompilerFlag.cmake b/cmake/macros/CheckC11C99CompilerFlag.cmake index d7fe4aa..a143c3c 100644 --- a/cmake/macros/CheckC11C99CompilerFlag.cmake +++ b/cmake/macros/CheckC11C99CompilerFlag.cmake @@ -16,82 +16,80 @@ INCLUDE(CheckCSourceCompiles) -MACRO(CHECK_C11_C99_COMPILER_FLAG _RESULT) +FUNCTION(CHECK_C11_C99_COMPILER_FLAG _result) # Flag listing borrowed from GNU autoconf's AC_PROG_CC_C99 macro. - UNSET(${_RESULT}) + UNSET(${_result} PARENT_SCOPE) # MSVC doesn't allow setting the C standard. - IF(NOT MSVC) - # Check if C11 is present without any flags. - # gcc-5.1 uses C11 mode by default. - MESSAGE(STATUS "Checking if C11 is enabled by default:") - CHECK_C_SOURCE_COMPILES(" + IF(NOT DEFINED _SYS_C11_C99_CFLAG AND NOT MSVC) + # Check if C11 is present without any flags. + # gcc-5.1 uses C11 mode by default. + MESSAGE(STATUS "Checking if C11 is enabled by default:") + CHECK_C_SOURCE_COMPILES(" #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L -#error C11 is not enabled +# error C11 is not enabled #endif int main() { return 0; }" CHECK_C11_ENABLED_DEFAULT) - IF (${CHECK_C11_ENABLED_DEFAULT}) - UNSET(${_RESULT}) - MESSAGE(STATUS "Checking if C11 is enabled by default: yes") - ELSE() - MESSAGE(STATUS "Checking if C11 is enabled by default: no") - MESSAGE(STATUS "Checking what CFLAG is required for C11:") - FOREACH(CHECK_C11_CFLAG "-std=gnu11" "-std=c11" "-c99" "-AC99" "-xc99=all" "-qlanglvl=extc1x" "-qlanglvl=stdc11") - SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_C11_CFLAG}") - CHECK_C_SOURCE_COMPILES("int main() { return 0; }" CFLAG_${CHECK_C11_CFLAG}) - SET(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") - IF(CFLAG_${CHECK_C11_CFLAG}) - SET(${_RESULT} ${CHECK_C11_CFLAG}) - BREAK() - ENDIF(CFLAG_${CHECK_C11_CFLAG}) - UNSET(CFLAG_${CHECK_C11_CFLAG}) - ENDFOREACH() - - IF(${_RESULT}) - MESSAGE(STATUS "Checking what CFLAG is required for C11: ${${_RESULT}}") - ELSE(${_RESULT}) - MESSAGE(STATUS "Checking what CFLAG is required for C11: unavailable") - ENDIF(${_RESULT}) - ENDIF() - - IF(NOT CHECK_C11_ENABLED_DEFAULT AND NOT ${_RESULT}) - # Could not enable C11. Try C99 instead. - MESSAGE(STATUS "Checking if C99 is enabled by default:") - CHECK_C_SOURCE_COMPILES(" - #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L - #error C99 is not enabled - #endif - - int main() { return 0; }" CHECK_C99_ENABLED_DEFAULT) - IF (${CHECK_C99_ENABLED_DEFAULT}) - UNSET(${_RESULT}) - MESSAGE(STATUS "Checking if C99 is enabled by default: yes") - ELSE() - MESSAGE(STATUS "Checking if C99 is enabled by default: no") - MESSAGE(STATUS "Checking what CFLAG is required for C99:") - FOREACH(CHECK_C99_CFLAG "-std=gnu99" "-std=c99" "-c99" "-AC99" "-xc99=all" "-qlanglvl=extc99") + IF (CHECK_C11_ENABLED_DEFAULT) + SET(_SYS_C11_C99_CFLAG "" CACHE INTERNAL "CFLAG required for C11 or C99 mode.") + MESSAGE(STATUS "Checking if C11 is enabled by default: yes") + ELSE(CHECK_C11_ENABLED_DEFAULT) + MESSAGE(STATUS "Checking if C11 is enabled by default: no") + MESSAGE(STATUS "Checking what CFLAG is required for C11:") + FOREACH(CHECK_C11_CFLAG "-std=gnu11" "-std=c11" "-c99" "-AC99" "-xc99=all" "-qlanglvl=extc1x" "-qlanglvl=stdc11") SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_C99_CFLAG}") - CHECK_C_SOURCE_COMPILES("int main() { return 0; }" CFLAG_${CHECK_C99_CFLAG}) + SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_C11_CFLAG}") + CHECK_C_SOURCE_COMPILES("int main() { return 0; }" CFLAG_${CHECK_C11_CFLAG}) SET(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") - IF(CFLAG_${CHECK_C99_CFLAG}) - SET(${_RESULT} ${CHECK_C99_CFLAG}) + IF(CFLAG_${CHECK_C11_CFLAG}) + SET(_SYS_C11_C99_CFLAG "${CHECK_C11_CFLAG}" CACHE INTERNAL "CFLAG required for C11 or C99 mode.") BREAK() - ENDIF(CFLAG_${CHECK_C99_CFLAG}) - UNSET(CFLAG_${CHECK_C99_CFLAG}) + ENDIF(CFLAG_${CHECK_C11_CFLAG}) ENDFOREACH() - IF(${_RESULT}) - MESSAGE(STATUS "Checking what CFLAG is required for C99: ${${_RESULT}}") - ELSE(${_RESULT}) - MESSAGE(STATUS "Checking what CFLAG is required for C99: unavailable") - ENDIF(${_RESULT}) - ENDIF() - ENDIF(NOT CHECK_C11_ENABLED_DEFAULT AND NOT ${_RESULT}) + IF(_SYS_C11_C99_CFLAG) + MESSAGE(STATUS "Checking what CFLAG is required for C11: ${_SYS_C11_C99_CFLAG}") + ELSE(_SYS_C11_C99_CFLAG) + MESSAGE(STATUS "Checking what CFLAG is required for C11: unavailable") + ENDIF(_SYS_C11_C99_CFLAG) + ENDIF(CHECK_C11_ENABLED_DEFAULT) - UNSET(CHECK_C11_ENABLED_DEFAULT) - UNSET(CHECK_C99_ENABLED_DEFAULT) - ENDIF(NOT MSVC) -ENDMACRO(CHECK_C11_C99_COMPILER_FLAG) + IF(NOT CHECK_C11_ENABLED_DEFAULT AND NOT _SYS_C11_C99_CFLAG) + # Could not enable C11. Try C99 instead. + MESSAGE(STATUS "Checking if C99 is enabled by default:") + CHECK_C_SOURCE_COMPILES(" +#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L +# error C99 is not enabled +#endif + +int main() { return 0; }" CHECK_C99_ENABLED_DEFAULT) + IF (CHECK_C99_ENABLED_DEFAULT) + SET(_SYS_C11_C99_CFLAG "" CACHE INTERNAL "CFLAG required for C11 or C99 mode.") + MESSAGE(STATUS "Checking if C99 is enabled by default: yes") + ELSE(CHECK_C99_ENABLED_DEFAULT) + MESSAGE(STATUS "Checking if C99 is enabled by default: no") + MESSAGE(STATUS "Checking what CFLAG is required for C99:") + FOREACH(CHECK_C99_CFLAG "-std=gnu99" "-std=c99" "-c99" "-AC99" "-xc99=all" "-qlanglvl=extc99") + SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_C99_CFLAG}") + CHECK_C_SOURCE_COMPILES("int main() { return 0; }" CFLAG_${CHECK_C99_CFLAG}) + SET(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") + IF(CFLAG_${CHECK_C99_CFLAG}) + SET(_SYS_C11_C99_CFLAG "${CHECK_C99_CFLAG}" CACHE INTERNAL "CFLAG required for C11 or C99 mode.") + BREAK() + ENDIF(CFLAG_${CHECK_C99_CFLAG}) + ENDFOREACH() + + IF(_SYS_C11_C99_CFLAG) + MESSAGE(STATUS "Checking what CFLAG is required for C99: ${_SYS_C11_C99_CFLAG}") + ELSE(_SYS_C11_C99_CFLAG) + SET(${_SYS_C11_C99_CFLAG} "" CACHE INTERNAL "CFLAG required for C11 or C99 mode.") + MESSAGE(STATUS "Checking what CFLAG is required for C99: unavailable") + ENDIF(_SYS_C11_C99_CFLAG) + ENDIF(CHECK_C99_ENABLED_DEFAULT) + ENDIF(NOT CHECK_C11_ENABLED_DEFAULT AND NOT _SYS_C11_C99_CFLAG) + ENDIF(NOT DEFINED _SYS_C11_C99_CFLAG AND NOT MSVC) + + SET(${_result} "${_SYS_C11_C99_CFLAG}" PARENT_SCOPE) +ENDFUNCTION(CHECK_C11_C99_COMPILER_FLAG) diff --git a/cmake/macros/CheckCXX11CompilerFlag.cmake b/cmake/macros/CheckCXX11CompilerFlag.cmake index 6f02872..0416fc4 100644 --- a/cmake/macros/CheckCXX11CompilerFlag.cmake +++ b/cmake/macros/CheckCXX11CompilerFlag.cmake @@ -17,51 +17,49 @@ INCLUDE(CheckCXXSourceCompiles) -MACRO(CHECK_CXX11_COMPILER_FLAG _RESULT) - UNSET(${_RESULT}) - +FUNCTION(CHECK_CXX11_COMPILER_FLAG _result) + UNSET(${_result} PARENT_SCOPE) + # MSVC doesn't allow setting the C standard. - IF(NOT MSVC) - # Check if C++ 2011 is present without any flags. - # g++-5.1 uses C++ 1998 by default, but this may change - # in future versions of gcc. - MESSAGE(STATUS "Checking if C++ 2011 is enabled by default:") - CHECK_CXX_SOURCE_COMPILES(" + IF(NOT DEFINED _SYS_CXX11_CXXFLAG AND NOT MSVC) + # Check if C++ 2011 is present without any flags. + # g++-5.1 uses C++ 1998 by default, but this may change + # in future versions of gcc. + MESSAGE(STATUS "Checking if C++ 2011 is enabled by default:") + CHECK_CXX_SOURCE_COMPILES(" #if !defined(__cplusplus) || __cplusplus < 201103L -#error C++ 2011 is not enabled +# error C++ 2011 is not enabled #endif int main() { return 0; }" CHECK_CXX11_ENABLED_DEFAULT) - IF (${CHECK_CXX11_ENABLED_DEFAULT}) - UNSET(${_RESULT}) - MESSAGE(STATUS "Checking if C++ 2011 is enabled by default: yes") - ELSE() - MESSAGE(STATUS "Checking if C++ 2011 is enabled by default: no") - MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011:") - FOREACH(CHECK_CXX11_CXXFLAG "-std=gnu++11" "-std=gnu++0x" "-std=c++11" "-std=c++0x") - # CMake doesn't like "+" characters in variable names. - STRING(REPLACE "+" "_" CHECK_CXX11_CXXFLAG_VARNAME "CHECK_CXXFLAG_${CHECK_CXX11_CXXFLAG}") + IF (CHECK_CXX11_ENABLED_DEFAULT) + SET(_SYS_CXX11_CXXFLAG "" CACHE INTERNAL "CXXFLAG required for C++11 mode.") + MESSAGE(STATUS "Checking if C++ 2011 is enabled by default: yes") + ELSE(CHECK_CXX11_ENABLED_DEFAULT) + MESSAGE(STATUS "Checking if C++ 2011 is enabled by default: no") + MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011:") + FOREACH(CHECK_CXX11_CXXFLAG "-std=gnu++11" "-std=gnu++0x" "-std=c++11" "-std=c++0x") + # CMake doesn't like "+" characters in variable names. + STRING(REPLACE "+" "_" CHECK_CXX11_CXXFLAG_VARNAME "CHECK_CXXFLAG_${CHECK_CXX11_CXXFLAG}") - SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") - SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_CXX11_CXXFLAG}") - CHECK_CXX_SOURCE_COMPILES("int main() { static_assert(0 == 0, \"test assertion\"); return 0; }" ${CHECK_CXX11_CXXFLAG_VARNAME}) - SET(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") + SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + SET(CMAKE_REQUIRED_DEFINITIONS "${CHECK_CXX11_CXXFLAG}") + CHECK_CXX_SOURCE_COMPILES("int main() { static_assert(0 == 0, \"test assertion\"); return 0; }" ${CHECK_CXX11_CXXFLAG_VARNAME}) + SET(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}") - IF(${${CHECK_CXX11_CXXFLAG_VARNAME}}) - SET(${_RESULT} ${CHECK_CXX11_CXXFLAG}) - UNSET(${CHECK_CXX11_CXXFLAG_VARNAME}) - UNSET(CHECK_CXX11_CXXFLAG_VARNAME) - BREAK() - ENDIF(${${CHECK_CXX11_CXXFLAG_VARNAME}}) - UNSET(${CHECK_CXX11_CXXFLAG_VARNAME}) - UNSET(CHECK_CXX11_CXXFLAG_VARNAME) - ENDFOREACH() - IF(${_RESULT}) - MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011: ${${_RESULT}}") - ELSE(${_RESULT}) - MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011: none") - ENDIF(${_RESULT}) - ENDIF() - UNSET(CHECK_CXX11_ENABLED_DEFAULT) - ENDIF(NOT MSVC) -ENDMACRO(CHECK_CXX11_COMPILER_FLAG) + IF(${${CHECK_CXX11_CXXFLAG_VARNAME}}) + SET(_SYS_CXX11_CXXFLAG ${CHECK_CXX11_CXXFLAG} CACHE INTERNAL "CXXFLAG required for C++11 mode.") + BREAK() + ENDIF(${${CHECK_CXX11_CXXFLAG_VARNAME}}) + ENDFOREACH() + IF(_SYS_CXX11_CXXFLAG) + MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011: ${_SYS_CXX11_CXXFLAG}") + ELSE(_SYS_CXX11_CXXFLAG) + SET(${_SYS_CXX11_CXXFLAG} "" CACHE INTERNAL "CXXFLAG required for C++11 mode.") + MESSAGE(STATUS "Checking what CXXFLAG is required for C++ 2011: unavailable") + ENDIF(_SYS_CXX11_CXXFLAG) + ENDIF(CHECK_CXX11_ENABLED_DEFAULT) + ENDIF(NOT DEFINED _SYS_CXX11_CXXFLAG AND NOT MSVC) + + SET(${_result} "${_SYS_CXX11_CXXFLAG}" PARENT_SCOPE) +ENDFUNCTION(CHECK_CXX11_COMPILER_FLAG) diff --git a/cmake/macros/CheckLargeFileSupport.cmake b/cmake/macros/CheckLargeFileSupport.cmake index e475912..1724405 100644 --- a/cmake/macros/CheckLargeFileSupport.cmake +++ b/cmake/macros/CheckLargeFileSupport.cmake @@ -18,11 +18,15 @@ # - LFS_FOUND_FSEEKI64: Set to 1 if LFS is supported using _fseeki64(). # - LFS_DEFINITIONS: Preprocessor macros required for large file support, if any. +# Additional variables are set based on the existance of types: +# - SIZEOF_OFF_T: sizeof(off_t), if available. +# - SIZEOF_OFF64_T: sizeof(off64_t), if available. + # TODO: Use _fseeki64() and _ftelli64() on MinGW to avoid # the use of wrapper functions? FUNCTION(CHECK_LARGE_FILE_SUPPORT) - IF(NOT DEFINED LFS_FOUND) + IF(NOT DEFINED LFS_FOUND OR NOT DEFINED CHECKED_OFF_T) # NOTE: ${CMAKE_MODULE_PATH} has two directories, macros/ and libs/, # so we have to configure this manually. SET(LFS_SOURCE_PATH "${CMAKE_SOURCE_DIR}/cmake/macros") @@ -51,21 +55,18 @@ FUNCTION(CHECK_LARGE_FILE_SUPPORT) MESSAGE(STATUS "Checking if Large File Support is available - yes") ELSE() # Try adding LFS macros. - SET(TMP_LFS_DEFINITIONS -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64) + SET(TMP_LFS_DEFINITIONS_BITS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) TRY_COMPILE(TMP_LFS_FOUND "${CMAKE_BINARY_DIR}" "${LFS_SOURCE_PATH}/LargeFileSupport_fseeko.c" - COMPILE_DEFINITIONS ${TMP_LFS_DEFINITIONS}) + COMPILE_DEFINITIONS ${TMP_LFS_DEFINITIONS_BITS}) IF(TMP_LFS_FOUND) # LFS macros work. MESSAGE(STATUS "Checking if Large File Support is available - yes, using LFS macros") SET(TMP_LFS_FOUND_FSEEKO 1) - # NOTE: COMPILE_DEFINITIONS requires a semicolon-separated list; - # CFLAGS reqiures space-separated. - STRING(REPLACE ";" " " TMP_LFS_DEFINITIONS "${TMP_LFS_DEFINITIONS}") + SET(TMP_LFS_DEFINITIONS "${TMP_LFS_DEFINITIONS_BITS}") ELSE() # LFS macros failed. MESSAGE(STATUS "Checking if Large File Support is available - no") - UNSET(TMP_LFS_DEFINITIONS) ENDIF() ENDIF() ENDIF() @@ -73,6 +74,23 @@ FUNCTION(CHECK_LARGE_FILE_SUPPORT) SET(LFS_FOUND ${TMP_LFS_FOUND} CACHE INTERNAL "Is Large File Support available?") SET(LFS_FOUND_FSEEKO ${TMP_LFS_FOUND_FSEEKO} CACHE INTERNAL "Large File Support is available using LFS macros") SET(LFS_FOUND_FSEEKI64 ${TMP_LFS_FOUND_FSEEKI64} CACHE INTERNAL "Large File Support is available using MSVC non-standard functions") + + # Check for off_t and off64_t. + INCLUDE(CheckTypeSize) + SET(CMAKE_REQUIRED_INCLUDES "unistd.h") + SET(CMAKE_REQUIRED_DEFINITIONS ${TMP_LFS_DEFINITIONS}) + CHECK_TYPE_SIZE("off_t" OFF_T) + # off64_t requires -D_LARGEFILE64_SOURCE. + SET(CMAKE_REQUIRED_DEFINITIONS "${TMP_LFS_DEFINITIONS};-D_LARGEFILE64_SOURCE") + CHECK_TYPE_SIZE("off64_t" OFF64_T) + IF(HAVE_OFF64_T) + SET(TMP_LFS_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}") + ENDIF(HAVE_OFF64_T) + SET(CHECKED_OFF_T "1" CACHE INTERNAL "off_t/off64_t were checked") + + # NOTE: COMPILE_DEFINITIONS requires a semicolon-separated list; + # CFLAGS reqiures space-separated. + STRING(REPLACE ";" " " TMP_LFS_DEFINITIONS "${TMP_LFS_DEFINITIONS}") SET(LFS_DEFINITIONS "${TMP_LFS_DEFINITIONS}" CACHE INTERNAL "Definitions required for Large File Support") ENDIF() ENDFUNCTION(CHECK_LARGE_FILE_SUPPORT) diff --git a/cmake/macros/CheckStackProtectorCompilerFlag.cmake b/cmake/macros/CheckStackProtectorCompilerFlag.cmake index f08db85..fb2beaf 100644 --- a/cmake/macros/CheckStackProtectorCompilerFlag.cmake +++ b/cmake/macros/CheckStackProtectorCompilerFlag.cmake @@ -17,21 +17,24 @@ INCLUDE(CheckCSourceCompiles) -MACRO(CHECK_STACK_PROTECTOR_COMPILER_FLAG _RESULT) - UNSET(${_RESULT}) - +FUNCTION(CHECK_STACK_PROTECTOR_COMPILER_FLAG _result) + UNSET(${_result} PARENT_SCOPE) + + IF(NOT DEFINED _SYS_STACK_PROTECTOR_COMPILER_FLAG) IF(MSVC) # MSVC 2002 introduced the /GS option. # MSVC 2005+ enables it by default. IF(MSVC_VERSION GREATER 1399) # MSVC 2005+. - MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: none") + SET(_SYS_STACK_PROTECTOR_COMPILER_FLAG "" CACHE INTERNAL "CFLAG required for stack smashing protection.") + MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: none, enabled by default") ELSEIF(MSVC_VERSION GREATER 1299) # MSVC 2002 or 2003. - SET(${_RESULT} "/GS") - MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: ${${_RESULT}}") + SET(_SYS_STACK_PROTECTOR_COMPILER_FLAG "/GS" CACHE INTERNAL "CFLAG required for stack smashing protection.") + MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: ${_SYS_STACK_PROTECTOR_COMPILER_FLAG}") ELSE() # MSVC 2002 or earlier. + SET(_SYS_STACK_PROTECTOR_COMPILER_FLAG "" CACHE INTERNAL "CFLAG required for stack smashing protection.") MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: not available") ENDIF() ELSE(MSVC) @@ -96,21 +99,19 @@ int main(int argc, char *argv[]) SET(CMAKE_REQUIRED_LIBRARIES "${SAFE_CMAKE_REQUIRED_LIBRARIES}") IF(${${CHECK_STACK_CFLAG_VARNAME}}) - SET(${_RESULT} ${CHECK_STACK_CFLAG}) - UNSET(${CHECK_STACK_CFLAG_VARNAME}) - UNSET(CHECK_STACK_CFLAG_VARNAME) + SET(_SYS_STACK_PROTECTOR_COMPILER_FLAG "${CHECK_STACK_CFLAG}" CACHE INTERNAL "CFLAG required for stack smashing protection.") BREAK() ENDIF(${${CHECK_STACK_CFLAG_VARNAME}}) - UNSET(${CHECK_STACK_CFLAG_VARNAME}) - UNSET(CHECK_STACK_CFLAG_VARNAME) - UNSET(SAFE_CMAKE_REQUIRED_DEFINITIONS) - UNSET(SAFE_CMAKE_REQUIRED_LIBRARIES) ENDFOREACH() - IF(${_RESULT}) - MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: ${${_RESULT}}") - ELSE(${_RESULT}) + IF(_SYS_STACK_PROTECTOR_COMPILER_FLAG) + MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: ${_SYS_STACK_PROTECTOR_COMPILER_FLAG}") + ELSE(_SYS_STACK_PROTECTOR_COMPILER_FLAG) + SET(_SYS_STACK_PROTECTOR_COMPILER_FLAG "" CACHE INTERNAL "CFLAG required for stack smashing protection.") MESSAGE(STATUS "Checking what CFLAG is required for stack smashing protection: not available") MESSAGE(WARNING "Stack smashing protection is not available.\nPlease check your toolchain installation.") - ENDIF(${_RESULT}) + ENDIF(_SYS_STACK_PROTECTOR_COMPILER_FLAG) ENDIF(MSVC) -ENDMACRO(CHECK_STACK_PROTECTOR_COMPILER_FLAG) + ENDIF(NOT DEFINED _SYS_STACK_PROTECTOR_COMPILER_FLAG) + + SET(${_result} "${_SYS_STACK_PROTECTOR_COMPILER_FLAG}" PARENT_SCOPE) +ENDFUNCTION(CHECK_STACK_PROTECTOR_COMPILER_FLAG) diff --git a/cmake/platform.cmake b/cmake/platform.cmake index 5013922..38da10e 100644 --- a/cmake/platform.cmake +++ b/cmake/platform.cmake @@ -18,23 +18,50 @@ IF(NOT HAVE_STDINT_H) ENDIF(NOT HAVE_STDINT_H) # CPU architecture. -# TODO: Verify cross-compile functionality. -# TODO: ARM/ARM64 is untested. -STRING(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" arch) -IF(arch MATCHES "^(i.|x)86$|^x86_64$|^amd64$") - IF(CMAKE_CL_64 OR ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)) - SET(CPU_amd64 1) - ELSE() +IF(MSVC AND _MSVC_C_ARCHITECTURE_FAMILY) + # Check the MSVC architecture. + # Set CMAKE_SYSTEM_PROCESSOR to match, since it doesn't get + # set to the target architecture correctly. + # TODO: Verify 32-bit. + IF(_MSVC_C_ARCHITECTURE_FAMILY MATCHES "^[iI]?[xX3]86$") SET(CPU_i386 1) + SET(CMAKE_SYSTEM_PROCESSOR "x86") + ELSEIF(_MSVC_C_ARCHITECTURE_FAMILY MATCHES "^[xX]64$") + SET(CPU_amd64 1) + SET(CMAKE_SYSTEM_PROCESSOR "AMD64") + ELSEIF(_MSVC_C_ARCHITECTURE_FAMILY MATCHES "[iI][aA]64") + SET(CPU_ia64 1) + SET(CMAKE_SYSTEM_PROCESSOR "IA64") + ELSEIF(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM") + SET(CPU_arm 1) + SET(CMAKE_SYSTEM_PROCESSOR "ARM") + ELSEIF(_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64") + SET(CPU_arm64 1) + SET(CMAKE_SYSTEM_PROCESSOR "ARM64") + ELSE() + MESSAGE(FATAL_ERROR "Unsupported value for _MSVC_C_ARCHITECTURE_FAMILY: ${_MSVC_C_ARCHITECTURE_FAMILY}") ENDIF() -ELSEIF(arch STREQUAL "ia64") - SET(CPU_ia64 1) -ELSEIF(arch STREQUAL "arm") - SET(CPU_arm 1) -ELSEIF(arch STREQUAL "aarch64") - SET(CPU_arm64 1) +ELSE() + # TODO: Verify cross-compile functionality. + # TODO: ARM/ARM64 is untested. + STRING(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" arch) + IF(arch MATCHES "^(i.|x)86$|^x86_64$|^amd64$") + IF(CMAKE_CL_64 OR ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)) + SET(CPU_amd64 1) + ELSE() + SET(CPU_i386 1) + ENDIF() + ELSEIF(arch STREQUAL "ia64") + SET(CPU_ia64 1) + ELSEIF(arch STREQUAL "arm" OR arch STREQUAL "aarch64") + IF(CMAKE_CL_64 OR ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)) + SET(CPU_arm64 1) + ELSE() + SET(CPU_arm 1) + ENDIF() + ENDIF() + UNSET(arch) ENDIF() -UNSET(arch) # Common flag variables: # [common] @@ -186,7 +213,6 @@ IF(WIN32) UNSET(UNICODE_FLAG) ELSE(MSVC) # MinGW does not automatically prepend an underscore. - # TODO: Does ARM Windows have a leading underscore? # TODO: _setargv for MinGW. # NOTE: MinGW uses separate crt*.o files for Unicode @@ -196,15 +222,11 @@ IF(WIN32) STRING(SUBSTRING "${_entrypoint}" 1 -1 _entrypoint) ENDIF() - IF(CPU_i386 OR CPU_amd64) - IF(CMAKE_SIZEOF_VOID_P EQUAL 4) - SET(ENTRY_POINT "_${_entrypoint}CRTStartup") - ELSE() - SET(ENTRY_POINT "${_entrypoint}CRTStartup") - ENDIF() - ELSE() + IF(CPU_i386) + SET(ENTRY_POINT "_${_entrypoint}CRTStartup") + ELSE(CPU_i386) SET(ENTRY_POINT "${_entrypoint}CRTStartup") - ENDIF(CPU_i386 OR CPU_amd64) + ENDIF(CPU_i386) SET(ENTRY_POINT_FLAG "-Wl,-e,${ENTRY_POINT}") UNSET(SETARGV_FLAG) ENDIF(MSVC) diff --git a/cmake/platform/gcc.cmake b/cmake/platform/gcc.cmake index 9b3ccaf..2c5f3e5 100644 --- a/cmake/platform/gcc.cmake +++ b/cmake/platform/gcc.cmake @@ -10,6 +10,12 @@ ELSEIF(CMAKE_COMPILER_IS_GNUCXX) ENDIF() ENDIF() +# gcc-5.4 and earlier have issues with LTO. +IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0) + SET(GCC_5xx_LTO_ISSUES ON) +ENDIF() + # Compiler flag modules. INCLUDE(CheckCCompilerFlag) INCLUDE(CheckCXXCompilerFlag) @@ -22,10 +28,13 @@ CHECK_C11_C99_COMPILER_FLAG(RP_C11_CFLAG) INCLUDE(CheckCXX11CompilerFlag) CHECK_CXX11_COMPILER_FLAG(RP_CXX11_CXXFLAG) -SET(RP_C_FLAGS_COMMON "-D_GNU_SOURCE=1 ${RP_C11_CFLAG}") -SET(RP_CXX_FLAGS_COMMON "-D_GNU_SOURCE=1 ${RP_CXX11_CXXFLAG}") +SET(RP_C_FLAGS_COMMON "${RP_C11_CFLAG}") +SET(RP_CXX_FLAGS_COMMON "${RP_CXX11_CXXFLAG}") SET(RP_EXE_LINKER_FLAGS_COMMON "") +# _GNU_SOURCE is needed for memmem() and statx(). +ADD_DEFINITIONS(-D_GNU_SOURCE=1) + UNSET(RP_C11_CFLAG) UNSET(RP_CXX11_CXXFLAG) diff --git a/cmake/platform/win32-gcc.cmake b/cmake/platform/win32-gcc.cmake index f7bf082..87d8355 100644 --- a/cmake/platform/win32-gcc.cmake +++ b/cmake/platform/win32-gcc.cmake @@ -5,21 +5,33 @@ SET(RP_C_FLAGS_WIN32 "${RP_C_FLAGS_WIN32} -DMINGW_HAS_SECURE_API") # Subsystem and minimum Windows version: -# - If 32-bit: 5.01 -# - If 64-bit: 5.02 +# - If i386: 5.01 +# - If amd64: 5.02 +# - If arm or arm64: 6.02 # NOTE: MS_ENH_RSA_AES_PROV is only available starting with # Windows XP. Because we're actually using some XP-specific # functionality now, the minimum version is now Windows XP. -IF(CMAKE_SIZEOF_VOID_P EQUAL 8) - # 64-bit, Unicode Windows only. - # (There is no 64-bit ANSI Windows.) - SET(CMAKE_CREATE_WIN32_EXE "-Wl,--subsystem,windows:5.02") - SET(CMAKE_CREATE_CONSOLE_EXE "-Wl,--subsystem,console:5.02") -ELSE() +IF(CPU_amd64) + # amd64 (64-bit), Unicode Windows only. + # (There is no amd64 ANSI Windows.) + # Minimum target version is Windows Server 2003 / XP 64-bit. + SET(RP_WIN32_SUBSYSTEM_VERSION "5.02") +ELSEIF(CPU_arm OR CPU_arm64) + # ARM (32-bit or 64-bit), Unicode windows only. (MSVC) + # (There is no ARM ANSI Windows.) + # Minimum target version is Windows 8. + SET(RP_WIN32_SUBSYSTEM_VERSION "6.02") +ELSEIF(CPU_i386) # 32-bit, Unicode Windows only. - SET(CMAKE_CREATE_WIN32_EXE "-Wl,--subsystem,windows:5.01") - SET(CMAKE_CREATE_CONSOLE_EXE "-Wl,--subsystem,console:5.01") + # Minimum target version is Windows XP. + SET(RP_WIN32_SUBSYSTEM_VERSION "5.01") +ELSE() + MESSAGE(FATAL_ERROR "Unsupported CPU.") ENDIF() +# FIXME: Maybe we should use RP_LINKER_FLAGS_WIN32_EXE and RP_LINKER_FLAGS_CONSOLE_EXE. +# This is what's used in win32-msvc.cmake. +SET(CMAKE_CREATE_WIN32_EXE "-Wl,--subsystem,windows:${RP_WIN32_SUBSYSTEM_VERSION}") +SET(CMAKE_CREATE_CONSOLE_EXE "-Wl,--subsystem,console:${RP_WIN32_SUBSYSTEM_VERSION}") SET(RP_EXE_LINKER_FLAGS_WIN32 "") SET(RP_SHARED_LINKER_FLAGS_WIN32 "") diff --git a/cmake/platform/win32-msvc.cmake b/cmake/platform/win32-msvc.cmake index 508841c..2732683 100644 --- a/cmake/platform/win32-msvc.cmake +++ b/cmake/platform/win32-msvc.cmake @@ -11,8 +11,9 @@ ENDIF() # No ANSI support. # Subsystem and minimum Windows version: -# - If 32-bit: 5.01 -# - If 64-bit: 5.02 +# - If i386: 5.01 +# - If amd64: 5.02 +# - If arm or arm64: 6.02 # ROM Properties does NOT support ANSI Windows. # MSVC 2010's minimum supported target OS is XP SP2. # MSVC 2012 and later has a minimum subsystem value of 5.01. @@ -25,20 +26,22 @@ ENDIF() # NOTE: MS_ENH_RSA_AES_PROV is only available starting with # Windows XP. Because we're actually using some XP-specific # functionality now, the minimum version is now Windows XP. -IF(MSVC AND CMAKE_CL_64) - # 64-bit, Unicode Windows only. (MSVC) - # (There is no 64-bit ANSI Windows.) +IF(CPU_amd64) + # amd64 (64-bit), Unicode Windows only. (MSVC) + # (There is no amd64 ANSI Windows.) # Minimum target version is Windows Server 2003 / XP 64-bit. SET(RP_WIN32_SUBSYSTEM_VERSION "5.02") -ELSEIF(NOT MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8) - # 64-bit, Unicode Windows only. (MinGW) - # (There is no 64-bit ANSI Windows.) - # Minimum target version is Windows Server 2003 / XP 64-bit. - SET(RP_WIN32_SUBSYSTEM_VERSION "5.02") -ELSE() - # 32-bit, Unicode Windows only. +ELSEIF(CPU_arm OR CPU_arm64) + # ARM (32-bit or 64-bit), Unicode windows only. (MSVC) + # (There is no ARM ANSI Windows.) + # Minimum target version is Windows 8. + SET(RP_WIN32_SUBSYSTEM_VERSION "6.02") +ELSEIF(CPU_i386) + # i386 (32-bit), Unicode Windows only. # Minimum target version is Windows XP. SET(RP_WIN32_SUBSYSTEM_VERSION "5.01") +ELSE() + MESSAGE(FATAL_ERROR "Unsupported CPU.") ENDIF() SET(RP_LINKER_FLAGS_WIN32_EXE "/SUBSYSTEM:WINDOWS,${RP_WIN32_SUBSYSTEM_VERSION}") SET(RP_LINKER_FLAGS_CONSOLE_EXE "/SUBSYSTEM:CONSOLE,${RP_WIN32_SUBSYSTEM_VERSION}") @@ -47,10 +50,6 @@ UNSET(RP_WIN32_SUBSYSTEM_VERSION) # Append the CFLAGS and LDFLAGS. SET(RP_C_FLAGS_COMMON "${RP_C_FLAGS_COMMON} ${RP_C_FLAGS_WIN32}") SET(RP_CXX_FLAGS_COMMON "${RP_CXX_FLAGS_COMMON} ${RP_C_FLAGS_WIN32} ${RP_CXX_FLAGS_WIN32}") -SET(RP_EXE_LINKER_FLAGS_COMMON "${RP_EXE_LINKER_FLAGS_COMMON} ${RP_EXE_LINKER_FLAGS_WIN32}") -SET(RP_SHARED_LINKER_FLAGS_COMMON "${RP_SHARED_LINKER_FLAGS_COMMON} ${RP_EXE_LINKER_FLAGS_WIN32}") -SET(RP_MODULE_LINKER_FLAGS_COMMON "${RP_MODULE_LINKER_FLAGS_COMMON} ${RP_EXE_LINKER_FLAGS_WIN32}") # Unset temporary variables. UNSET(RP_C_FLAGS_WIN32) -UNSET(RP_EXE_LINKER_FLAGS_WIN32) diff --git a/cmake/toolchain/i686-w64-mingw32.cmake b/cmake/toolchain/i686-w64-mingw32.cmake new file mode 100644 index 0000000..6ef640e --- /dev/null +++ b/cmake/toolchain/i686-w64-mingw32.cmake @@ -0,0 +1,20 @@ +SET(HOST_SYSTEM i686-w64-mingw32) + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) +SET(CMAKE_SYSTEM_PROCESSOR i686) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER ${HOST_SYSTEM}-gcc) +SET(CMAKE_CXX_COMPILER ${HOST_SYSTEM}-g++) +SET(CMAKE_RC_COMPILER ${HOST_SYSTEM}-windres) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/${HOST_SYSTEM}) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/toolchain/x86_64-w64-mingw32.cmake b/cmake/toolchain/x86_64-w64-mingw32.cmake new file mode 100644 index 0000000..b80deb2 --- /dev/null +++ b/cmake/toolchain/x86_64-w64-mingw32.cmake @@ -0,0 +1,20 @@ +SET(HOST_SYSTEM x86_64-w64-mingw32) + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) +SET(CMAKE_SYSTEM_PROCESSOR x86_64) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER ${HOST_SYSTEM}-gcc) +SET(CMAKE_CXX_COMPILER ${HOST_SYSTEM}-g++) +SET(CMAKE_RC_COMPILER ${HOST_SYSTEM}-windres) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/${HOST_SYSTEM}) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) +SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)