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