1# 2# Compiler/stdlib feature checks for ctwm 3# 4 5 6# Expect and try to enforce a C99 capable compiler. There doesn't seem 7# an obvious way to be sure in a fully portable way, but we probably 8# don't work well in places that compile with something other than a 9# program called like 'cc', and a cc that supports C99 should accept -std 10# calls, so that's good enough. Lacking it is not (yet) a fatal error, 11# but is a sign that it's a compiler or platform we're moving further 12# away from. 13# 14# cmake 3.1+ has C_STANDARD and related vars that seem like they'd help 15# with this, but it's unclear that they actually solve the whole 16# problem... 17# 18# Known alternate spellings: 19# -xc99 (Sun C 5.10 SunOS_i386, sunstudio12.1, OpenIndiana) 20include(CheckCCompilerFlag) 21set(MANUAL_C_STD_FLAG true) 22if(NOT MANUAL_C_STD_FLAG) 23 # This is the Better Way(tm), but is disabled by default because, as 24 # with the manual one below, the added arg doesn't apply in 25 # check_symbol_exists(), so it screws up the tests below. I'm unable 26 # to find a way to get info from cmake about what arg it would add 27 # for the specified standard, so we can't pull it out manually to add 28 # like we do our found C99_FLAG below, so... 29 if(NOT "c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES) 30 message(WARNING "cmake doesn't know about c99 support for this " 31 "compiler, trying manual search...") 32 set(MANUAL_C_STD_FLAG true) 33 else() 34 message(STATUS "Enabling C99 mode") 35 set(CMAKE_C_EXTENSIONS false) 36 set(CMAKE_C_STANDARD 99) 37 endif() 38endif() 39if(MANUAL_C_STD_FLAG) 40 set(c99_flag_options -std=c99 -xc99) 41 foreach(_C99_FLAG ${c99_flag_options}) 42 # CheckCCompilerFlag calls into CheckCSourceCompiles, which won't do 43 # anything if the result var is already set in the cache, so we have 44 # to unset it. Otherwise, the second and later invocations don't 45 # actually do anything, and it'll never check any flag after the 46 # first. 47 unset(COMPILER_C99_FLAG CACHE) 48 check_c_compiler_flag(${_C99_FLAG} COMPILER_C99_FLAG) 49 if(COMPILER_C99_FLAG) 50 set(C99_FLAG ${_C99_FLAG}) 51 break() 52 endif(COMPILER_C99_FLAG) 53 endforeach(_C99_FLAG) 54 if(C99_FLAG) 55 message(STATUS "Enabling C99 flag: ${C99_FLAG}") 56 add_definitions(${C99_FLAG}) 57 else() 58 message(WARNING "Compiler doesn't support known C99 flag, " 59 "building without it.") 60 endif(C99_FLAG) 61endif() 62 63 64 65# With -std=c99, some systems/compilers/etc enable ANSI strictness, and 66# so don't export symbols from headers for e.g. a lot of POSIX etc stuff. 67# So we may need some extra -D's. 68# Some refs: 69# https://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html 70# https://illumos.org/man/5/standards 71 72# Somewhat irritatingly, check_symbol_exists() doesn't use the extra 73# flags we set above for the C standard. So we have to add it manually, 74# and stash up the old C_R_D. x-ref above. 75set(OLD_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) 76list(APPEND CMAKE_REQUIRED_DEFINITIONS ${C99_FLAG}) 77 78# What might and will we add? 79set(AVAIL_SYM_FLAGS -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 80 -D_GNU_SOURCE -D__EXTENSIONS__) 81set(EXTRA_SYM_FLAGS "") 82 83# Abstract 84macro(_check_func_flag FUNC HEADER) 85 unset(_HAS_FUNC CACHE) 86 check_symbol_exists(${FUNC} ${HEADER} _HAS_FUNC) 87 if(NOT _HAS_FUNC) 88 foreach(_SFLAG ${AVAIL_SYM_FLAGS}) 89 unset(_HAS_FUNC CACHE) 90 list(APPEND CMAKE_REQUIRED_DEFINITIONS ${_SFLAG}) 91 check_symbol_exists(${FUNC} ${HEADER} _HAS_FUNC) 92 list(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS ${_SFLAG}) 93 if(_HAS_FUNC) 94 message(STATUS "${FUNC}() needs ${_SFLAG}") 95 list(APPEND EXTRA_SYM_FLAGS ${_SFLAG}) 96 break() 97 endif() 98 endforeach() 99 if(NOT _HAS_FUNC) 100 message(WARNING "Couldn't find def for ${FUNC}, not good...") 101 endif() 102 endif() 103 unset(_HAS_FUNC CACHE) 104endmacro(_check_func_flag) 105 106# strdup is POSIX, so see if we have to ask for that. Probably 107# _POSIX_C_SOURCE. 108_check_func_flag(strdup string.h) 109 110# isascii falls into XOPEN on glibc, POSIX on Illumos. 111_check_func_flag(isascii ctype.h) 112 113# asprintf() is even weirder. glibc apparently usually uses _GNU_SOURCE, 114# Illumos has a pure __EXTENSIONS__ 115_check_func_flag(asprintf stdio.h) 116 117if(EXTRA_SYM_FLAGS) 118 list(REMOVE_DUPLICATES EXTRA_SYM_FLAGS) 119 message(STATUS "Adding extra visibility flags: ${EXTRA_SYM_FLAGS}") 120 add_definitions(${EXTRA_SYM_FLAGS}) 121endif() 122 123# And restore 124set(CMAKE_REQUIRED_DEFINITIONS ${OLD_CMAKE_REQUIRED_DEFINITIONS}) 125 126 127 128 129# Some compilers (like Sun's) don't take -W flags for warnings. Do a 130# quick check with -Wall. They're mostly for devs, so we don't care THAT 131# much, I guess... maybe we should be more thorough about checking the 132# flags we use too, but worry about what when it becomes an issue. 133check_c_compiler_flag("-Wall" COMPILER_TAKES_WALL) 134if(NOT COMPILER_TAKES_WALL) 135 message(STATUS "Compiler doesn't like -Wall, disabling warnings.") 136 set(NO_WARNS 1) 137endif(NOT COMPILER_TAKES_WALL) 138 139if(NOT NO_WARNS) 140 add_definitions(${STD_WARNS}) 141 message(STATUS "Enabling standard warnings.") 142endif(NOT NO_WARNS) 143