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