mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-30 06:03:49 +08:00
e04785604a
static_assert without a message is C++17. Which we can't use 5 years later.
291 lines
10 KiB
CMake
291 lines
10 KiB
CMake
# The following defines affect the environment configuration tests are run in:
|
|
# CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_FLAGS, CMAKE_REQUIRED_LIBRARIES,
|
|
# and CMAKE_REQUIRED_INCLUDES
|
|
# `wcstod_l` is a GNU-extension, sometimes hidden behind GNU-related defines.
|
|
# This is the case for at least Cygwin and Newlib.
|
|
list(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE=1)
|
|
include(CheckCXXCompilerFlag)
|
|
|
|
if(APPLE)
|
|
check_cxx_compiler_flag("-Werror=unguarded-availability" REQUIRES_UNGUARDED_AVAILABILITY)
|
|
if(REQUIRES_UNGUARDED_AVAILABILITY)
|
|
list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Werror=unguarded-availability")
|
|
endif()
|
|
endif()
|
|
|
|
# An unrecognized flag is usually a warning and not an error, which CMake apparently does
|
|
# not pick up on. Combine it with -Werror to determine if it's actually supported.
|
|
# This is not bulletproof; old versions of GCC only emit a warning about unrecognized warning
|
|
# options when there are other warnings to emit :rolleyes:
|
|
# See https://github.com/fish-shell/fish-shell/commit/fe2da0a9#commitcomment-47431659
|
|
|
|
# GCC supports -Wno-redundant-move from GCC9 onwards
|
|
check_cxx_compiler_flag("-Werror=no-redundant-move" HAS_NO_REDUNDANT_MOVE)
|
|
if (HAS_NO_REDUNDANT_MOVE)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-redundant-move")
|
|
endif()
|
|
# Clang once supported -Wno-redundant-move but replaced it with a Wredundant-move option instead
|
|
# (and it is functionally different from its older version of GCC's Wno-redundant-move).
|
|
check_cxx_compiler_flag("-Werror=redundant-move" HAS_REDUNDANT_MOVE)
|
|
if (HAS_REDUNDANT_MOVE)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wredundant-move")
|
|
endif()
|
|
|
|
# Disable static destructors if we can.
|
|
check_cxx_compiler_flag("-fno-c++-static-destructors" DISABLE_STATIC_DESTRUCTORS)
|
|
if (DISABLE_STATIC_DESTRUCTORS)
|
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-c++-static-destructors")
|
|
endif()
|
|
|
|
|
|
# Try using CMake's own logic to locate curses/ncurses
|
|
find_package(Curses)
|
|
if(NOT ${CURSES_FOUND})
|
|
# CMake has trouble finding platform-specific system libraries
|
|
# installed to multiarch paths (e.g. /usr/lib/x86_64-linux-gnu)
|
|
# if not symlinked or passed in as a manual define.
|
|
message("Falling back to pkg-config for (n)curses detection")
|
|
include(FindPkgConfig)
|
|
pkg_search_module(CURSES REQUIRED ncurses curses)
|
|
set(CURSES_CURSES_LIBRARY ${CURSES_LIBRARIES})
|
|
set(CURSES_LIBRARY ${CURSES_LIBRARIES})
|
|
endif()
|
|
# Set up extra include directories for CheckIncludeFile
|
|
list(APPEND CMAKE_REQUIRED_INCLUDES ${CURSES_INCLUDE_DIRS})
|
|
|
|
# Fix undefined reference to tparm on RHEL 6 and potentially others
|
|
# If curses is found via CMake, it also links against tinfo if it exists. But if we use our
|
|
# fallback pkg-config logic above, we need to do this manually.
|
|
find_library(CURSES_TINFO tinfo)
|
|
if (CURSES_TINFO)
|
|
set(CURSES_LIBRARY ${CURSES_LIBRARY} ${CURSES_TINFO})
|
|
endif()
|
|
|
|
# Get threads.
|
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
|
find_package(Threads REQUIRED)
|
|
|
|
# Detect WSL. Does not match against native Windows/WIN32.
|
|
if (CMAKE_HOST_SYSTEM_VERSION MATCHES ".*-Microsoft")
|
|
set(WSL 1)
|
|
endif()
|
|
|
|
# Set up the config.h file.
|
|
set(PACKAGE_NAME "fish")
|
|
set(PACKAGE_TARNAME "fish")
|
|
include(CheckCXXSymbolExists)
|
|
include(CheckIncludeFileCXX)
|
|
include(CheckIncludeFiles)
|
|
include(CheckStructHasMember)
|
|
include(CheckCXXSourceCompiles)
|
|
include(CheckTypeSize)
|
|
include(CMakePushCheckState)
|
|
check_cxx_symbol_exists(backtrace_symbols execinfo.h HAVE_BACKTRACE_SYMBOLS)
|
|
|
|
# workaround for lousy mtime precision on a Linux kernel
|
|
if (CMAKE_SYSTEM_NAME MATCHES "Linux|Android")
|
|
check_cxx_symbol_exists(clock_gettime time.h HAVE_CLOCK_GETTIME)
|
|
check_cxx_symbol_exists(futimens sys/stat.h HAVE_FUTIMENS)
|
|
if ((HAVE_CLOCK_GETTIME) AND (HAVE_FUTIMENS))
|
|
set(UVAR_FILE_SET_MTIME_HACK 1)
|
|
endif()
|
|
endif()
|
|
|
|
check_cxx_symbol_exists(ctermid_r stdio.h HAVE_CTERMID_R)
|
|
check_struct_has_member("struct dirent" d_type dirent.h HAVE_STRUCT_DIRENT_D_TYPE LANGUAGE CXX)
|
|
check_cxx_symbol_exists(dirfd "sys/types.h;dirent.h" HAVE_DIRFD)
|
|
check_include_file_cxx(execinfo.h HAVE_EXECINFO_H)
|
|
check_cxx_symbol_exists(flock sys/file.h HAVE_FLOCK)
|
|
check_cxx_symbol_exists(getpwent pwd.h HAVE_GETPWENT)
|
|
check_cxx_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
|
|
check_cxx_symbol_exists(gettext libintl.h HAVE_GETTEXT)
|
|
check_cxx_symbol_exists(killpg "sys/types.h;signal.h" HAVE_KILLPG)
|
|
# mkostemp is in stdlib in glibc and FreeBSD, but unistd on macOS
|
|
check_cxx_symbol_exists(mkostemp "stdlib.h;unistd.h" HAVE_MKOSTEMP)
|
|
set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H})
|
|
set(HAVE_NCURSES_CURSES_H ${CURSES_HAVE_NCURSES_CURSES_H})
|
|
set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H})
|
|
if(HAVE_CURSES_H)
|
|
check_include_files("curses.h;term.h" HAVE_TERM_H)
|
|
endif()
|
|
if(NOT HAVE_TERM_H)
|
|
check_include_file_cxx("ncurses/term.h" HAVE_NCURSES_TERM_H)
|
|
endif()
|
|
check_include_file_cxx(siginfo.h HAVE_SIGINFO_H)
|
|
check_include_file_cxx(spawn.h HAVE_SPAWN_H)
|
|
check_struct_has_member("struct stat" st_ctime_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_CTIME_NSEC
|
|
LANGUAGE CXX)
|
|
check_struct_has_member("struct stat" st_mtimespec.tv_nsec "sys/stat.h"
|
|
HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC LANGUAGE CXX)
|
|
check_struct_has_member("struct stat" st_mtim.tv_nsec "sys/stat.h" HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
|
LANGUAGE CXX)
|
|
check_include_file_cxx(sys/ioctl.h HAVE_SYS_IOCTL_H)
|
|
check_include_file_cxx(sys/select.h HAVE_SYS_SELECT_H)
|
|
|
|
# glibc 2.30 deprecated <sys/sysctl.h> because that's what glibc does.
|
|
# Checking for that here rather than hardcoding a check on the glibc
|
|
# version in the C++ sources at point of use makes more sense.
|
|
SET(OLD_CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
|
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
|
|
check_include_files("sys/types.h;sys/sysctl.h" HAVE_SYS_SYSCTL_H)
|
|
SET(CMAKE_C_FLAGS "${OLD_CMAKE_C_FLAGS}")
|
|
|
|
check_cxx_symbol_exists(eventfd sys/eventfd.h HAVE_EVENTFD)
|
|
check_cxx_symbol_exists(pipe2 unistd.h HAVE_PIPE2)
|
|
check_cxx_symbol_exists(wcscasecmp wchar.h HAVE_WCSCASECMP)
|
|
check_cxx_symbol_exists(wcsdup wchar.h HAVE_WCSDUP)
|
|
check_cxx_symbol_exists(wcsncasecmp wchar.h HAVE_WCSNCASECMP)
|
|
|
|
# These are for compatibility with Solaris 10, which places the following
|
|
# in the std namespace.
|
|
if(NOT HAVE_WCSNCASECMP)
|
|
check_cxx_symbol_exists(std::wcscasecmp wchar.h HAVE_STD__WCSCASECMP)
|
|
endif()
|
|
if(NOT HAVE_WCSDUP)
|
|
check_cxx_symbol_exists(std::wcsdup wchar.h HAVE_STD__WCSDUP)
|
|
endif()
|
|
if(NOT HAVE_WCSNCASECMP)
|
|
check_cxx_symbol_exists(std::wcsncasecmp wchar.h HAVE_STD__WCSNCASECMP)
|
|
endif()
|
|
|
|
# `xlocale.h` is required to find `wcstod_l` in `wchar.h` under FreeBSD,
|
|
# but it's not present under Linux.
|
|
check_include_files("xlocale.h" HAVE_XLOCALE_H)
|
|
if(HAVE_XLOCALE_H)
|
|
list(APPEND WCSTOD_L_INCLUDES "xlocale.h")
|
|
endif()
|
|
list(APPEND WCSTOD_L_INCLUDES "wchar.h")
|
|
check_cxx_symbol_exists(wcstod_l "${WCSTOD_L_INCLUDES}" HAVE_WCSTOD_L)
|
|
|
|
check_cxx_symbol_exists(uselocale "locale.h;xlocale.h" HAVE_USELOCALE)
|
|
|
|
cmake_push_check_state()
|
|
set(CMAKE_EXTRA_INCLUDE_FILES termios.h sys/ioctl.h)
|
|
check_type_size("struct winsize" STRUCT_WINSIZE LANGUAGE CXX)
|
|
check_cxx_symbol_exists("TIOCGWINSZ" "termios.h;sys/ioctl.h" HAVE_TIOCGWINSZ)
|
|
if(STRUCT_WINSIZE GREATER -1 AND HAVE_TIOCGWINSZ EQUAL 1)
|
|
set(HAVE_WINSIZE 1)
|
|
endif()
|
|
cmake_pop_check_state()
|
|
|
|
check_type_size("wchar_t[8]" WCHAR_T_BITS LANGUAGE CXX)
|
|
|
|
set(TPARM_INCLUDES)
|
|
if(HAVE_NCURSES_H)
|
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses.h>\n")
|
|
elseif(HAVE_NCURSES_CURSES_H)
|
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/curses.h>\n")
|
|
else()
|
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <curses.h>\n")
|
|
endif()
|
|
|
|
if(HAVE_TERM_H)
|
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <term.h>\n")
|
|
elseif(HAVE_NCURSES_TERM_H)
|
|
set(TPARM_INCLUDES "${TPARM_INCLUDES}#include <ncurses/term.h>\n")
|
|
endif()
|
|
|
|
cmake_push_check_state()
|
|
list(APPEND CMAKE_REQUIRED_LIBRARIES ${CURSES_LIBRARY})
|
|
# Solaris and X/Open-conforming systems have a fixed-args tparm
|
|
check_cxx_source_compiles("
|
|
#define TPARM_VARARGS
|
|
${TPARM_INCLUDES}
|
|
|
|
int main () {
|
|
tparm( \"\" );
|
|
}
|
|
"
|
|
TPARM_TAKES_VARARGS
|
|
)
|
|
|
|
|
|
# Check if tputs needs a function reading an int or char.
|
|
# The only curses I can find that needs a char is OpenIndiana.
|
|
check_cxx_source_compiles("
|
|
#include <curses.h>
|
|
#include <term.h>
|
|
|
|
static int writer(int b) {
|
|
return b;
|
|
}
|
|
|
|
int main() {
|
|
return tputs(\"foo\", 5, writer);
|
|
}"
|
|
TPUTS_USES_INT_ARG
|
|
)
|
|
|
|
if(TPARM_TAKES_VARARGS)
|
|
set(TPARM_VARARGS 1)
|
|
else()
|
|
set(TPARM_SOLARIS_KLUDGE 1)
|
|
endif()
|
|
cmake_pop_check_state()
|
|
|
|
# Work around the fact that cmake does not propagate the language standard flag into
|
|
# the CHECK_CXX_SOURCE_COMPILES function. See CMake issue #16456.
|
|
# Ensure we do this after the FIND_PACKAGE calls which use C, and will error on a C++
|
|
# standards flag.
|
|
# Also see https://github.com/fish-shell/fish-shell/issues/5865
|
|
if(NOT POLICY CMP0067)
|
|
list(APPEND CMAKE_REQUIRED_FLAGS "${CMAKE_CXX${CMAKE_CXX_STANDARD}_EXTENSION_COMPILE_OPTION}")
|
|
endif()
|
|
|
|
check_cxx_source_compiles("
|
|
#include <memory>
|
|
|
|
int main () {
|
|
std::unique_ptr<int> foo = std::make_unique<int>();
|
|
}
|
|
"
|
|
HAVE_STD__MAKE_UNIQUE
|
|
)
|
|
|
|
# Detect support for thread_local.
|
|
check_cxx_source_compiles("
|
|
int main () {
|
|
static thread_local int x = 3;
|
|
(void)x;
|
|
}
|
|
"
|
|
HAVE_CX11_THREAD_LOCAL
|
|
)
|
|
|
|
check_cxx_source_compiles("
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
std::atomic<uint8_t> n8 (0);
|
|
std::atomic<uint64_t> n64 (0);
|
|
int main() {
|
|
uint8_t i = n8.load(std::memory_order_relaxed);
|
|
uint64_t j = n64.load(std::memory_order_relaxed);
|
|
return std::atomic_is_lock_free(&n8)
|
|
& std::atomic_is_lock_free(&n64);
|
|
}"
|
|
LIBATOMIC_NOT_NEEDED)
|
|
IF (NOT LIBATOMIC_NOT_NEEDED)
|
|
set(ATOMIC_LIBRARY "atomic")
|
|
endif()
|
|
|
|
check_cxx_source_compiles("
|
|
#include <sys/wait.h>
|
|
|
|
int main() {
|
|
static_assert(WEXITSTATUS(0x007f) == 0x7f, \"This is our message we need to add because C++ is terrible\");
|
|
return 0;
|
|
}
|
|
"
|
|
HAVE_WAITSTATUS_SIGNAL_RET)
|
|
|
|
IF (APPLE)
|
|
# Check if mbrtowc implementation attempts to encode invalid UTF-8 sequences
|
|
# Known culprits: at least some versions of macOS (confirmed Snow Leopard and Yosemite)
|
|
try_run(mbrtowc_invalid_utf8_exit mbrtowc_invalid_utf8_compiles ${CMAKE_CURRENT_BINARY_DIR}
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/checks/mbrtowc_invalid_utf8.cpp")
|
|
IF ("${mbrtowc_invalid_utf8_compiles}" AND ("${mbrtowc_invalid_utf8_exit}" EQUAL 1))
|
|
SET(HAVE_BROKEN_MBRTOWC_UTF8 1)
|
|
ENDIF()
|
|
ENDIF()
|
|
|