• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) The c-ares project and its contributors
2# SPDX-License-Identifier: MIT
3CMAKE_MINIMUM_REQUIRED (VERSION 3.5.0...3.10.0)
4
5list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
6
7INCLUDE (CheckIncludeFiles)
8INCLUDE (CheckTypeSize)
9INCLUDE (CheckFunctionExists)
10INCLUDE (CheckSymbolExists)
11INCLUDE (CheckCSourceCompiles)
12INCLUDE (CheckStructHasMember)
13INCLUDE (CheckLibraryExists)
14
15PROJECT (c-ares LANGUAGES C VERSION "1.34.5" )
16
17# Set this version before release
18SET (CARES_VERSION "${PROJECT_VERSION}")
19
20INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are wrong.
21
22# This is for libtool compatibility, and specified in a form that is easily
23# translatable from libtool (even if the actual form doesn't make sense).
24# For instance, in an autotools project, in Makefile.am there is a line that
25# contains something like:
26#     -version-info 4:0:2
27# This breaks down into sections of current:revision:age
28# This then generates a version of  "(current-age).age.revision"  with an
29# interface version of "(current-age)"
30# For example, a version of 4:0:2 would generate output such as:
31#    libname.so   -> libname.so.2
32#    libname.so.2 -> libname.so.2.2.0
33SET (CARES_LIB_VERSIONINFO "21:4:19")
34
35
36OPTION (CARES_STATIC        "Build as a static library"                                             OFF)
37OPTION (CARES_SHARED        "Build as a shared library"                                             ON)
38OPTION (CARES_INSTALL       "Create installation targets (chain builders may want to disable this)" ON)
39OPTION (CARES_STATIC_PIC    "Build the static library as PIC (position independent)"                OFF)
40OPTION (CARES_BUILD_TESTS   "Build and run tests"                                                   OFF)
41OPTION (CARES_BUILD_CONTAINER_TESTS "Build and run container tests (implies CARES_BUILD_TESTS, Linux only)" OFF)
42OPTION (CARES_BUILD_TOOLS   "Build tools"                                                           ON)
43OPTION (CARES_SYMBOL_HIDING "Hide private symbols in shared libraries"                              OFF)
44OPTION (CARES_THREADS       "Build with thread-safety support"                                      ON)
45OPTION (CARES_COVERAGE      "Build for code coverage"                                               OFF)
46SET    (CARES_RANDOM_FILE "/dev/urandom" CACHE STRING "Suitable File / Device Path for entropy, such as /dev/urandom")
47
48
49# Tests require a C++14 compiler
50IF (CARES_BUILD_TESTS OR CARES_BUILD_CONTAINER_TESTS)
51	set(CMAKE_CXX_STANDARD 14)
52	set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
53	set(CMAKE_CXX_EXTENSIONS FALSE)
54	enable_language(CXX)
55ENDIF ()
56
57# Tests require static to be enabled on Windows to be able to access otherwise hidden symbols
58IF ((CARES_BUILD_TESTS OR CARES_BUILD_CONTAINER_TESTS) AND (NOT CARES_STATIC) AND WIN32)
59	SET (CARES_STATIC ON)
60	SET (CARES_STATIC_PIC ON)
61	MESSAGE (WARNING "Static building was requested be disabled, but re-enabled to support tests")
62ENDIF ()
63
64INCLUDE (EnableWarnings)
65
66IF (MSVC)
67	# allow linking against the static runtime library in msvc
68	OPTION (CARES_MSVC_STATIC_RUNTIME "Link against the static runtime library" OFF)
69	IF (CARES_MSVC_STATIC_RUNTIME)
70		# CMAKE_CONFIGURATION_TYPES is empty on non-IDE generators (Ninja, NMake)
71		# and that's why we also use CMAKE_BUILD_TYPE to cover for those generators.
72		# For IDE generators, CMAKE_BUILD_TYPE is usually empty
73		FOREACH (config_type ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE})
74			STRING (TOUPPER ${config_type} upper_config_type)
75			SET (flag_var "CMAKE_C_FLAGS_${upper_config_type}")
76			IF (${flag_var} MATCHES "/MD")
77				STRING (REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
78			ENDIF ()
79		ENDFOREACH ()
80
81		# clean up
82		SET (upper_config_type)
83		SET (config_type)
84		SET (flag_var)
85	ENDIF ()
86ENDIF ()
87
88IF (CARES_SYMBOL_HIDING)
89	IF (CMAKE_VERSION VERSION_LESS 3.12)
90		MESSAGE (FATAL_ERROR "Hiding symbols requires CMake 3.12")
91	ENDIF ()
92	CMAKE_POLICY (SET CMP0063 NEW)
93ENDIF ()
94
95# Keep build organized, but only if it is the top-level project.
96# CMake 3.21 or later has PROJECT_IS_TOP_LEVEL, but we aren't yet depending on
97# that version.
98IF (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
99	SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
100	SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
101	SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
102	SET (CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
103ENDIF ()
104
105# Destinations for installing different kinds of targets (pass to install command).
106SET (TARGETS_INST_DEST
107	RUNTIME DESTINATION  ${CMAKE_INSTALL_BINDIR}
108	BUNDLE DESTINATION   ${CMAKE_INSTALL_BINDIR}
109	LIBRARY DESTINATION  ${CMAKE_INSTALL_LIBDIR}
110	ARCHIVE DESTINATION  ${CMAKE_INSTALL_LIBDIR}
111)
112
113# Function in Library
114# CHECK_LIBRARY_EXISTS can't be used as it will return true if the function
115# is found in a different required/dependent library.
116MACRO (CARES_FUNCTION_IN_LIBRARY func lib var)
117	SET (_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
118	SET (CMAKE_REQUIRED_LIBRARIES )
119	CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}")
120	SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_FIL_CMAKE_REQUIRED_LIBRARIES}")
121
122	IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}")
123		SET (${var} FALSE)
124	ELSE ()
125		CHECK_LIBRARY_EXISTS ("${lib}" "${func}" "" ${var})
126	ENDIF ()
127ENDMACRO ()
128
129# Look for dependent/required libraries
130CARES_FUNCTION_IN_LIBRARY (res_servicename resolv HAVE_RES_SERVICENAME_IN_LIBRESOLV)
131IF (HAVE_RES_SERVICENAME_IN_LIBRESOLV)
132	SET (HAVE_LIBRESOLV 1)
133ENDIF ()
134
135IF (APPLE)
136	CHECK_C_SOURCE_COMPILES ("
137	#include <stdio.h>
138	#include <TargetConditionals.h>
139	int main() {
140#if TARGET_OS_IPHONE == 0
141#error Not an iPhone target
142#endif
143return 0;
144	}
145	"
146	IOS)
147
148	CHECK_C_SOURCE_COMPILES ("
149#include <stdio.h>
150#include <TargetConditionals.h>
151	int main() {
152#if TARGET_OS_IPHONE == 0 || __IPHONE_OS_VERSION_MIN_REQUIRED < 100000
153#  error Not iOS v10
154#endif
155return 0;
156	}
157	"
158	IOS_V10)
159
160	CHECK_C_SOURCE_COMPILES ("
161#include <stdio.h>
162#include <AvailabilityMacros.h>
163#ifndef MAC_OS_X_VERSION_10_12
164#  define MAC_OS_X_VERSION_10_12 101200
165#endif
166	int main() {
167#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12
168#  error Not MacOSX 10.12 or higher
169#endif
170return 0;
171	}
172	"
173	MACOS_V1012)
174ENDIF ()
175
176IF (ZOS AND HAVE_LIBRESOLV)
177	SET (CARES_USE_LIBRESOLV 1)
178ENDIF()
179
180
181CARES_FUNCTION_IN_LIBRARY (gethostbyname nsl HAVE_LIBNSL)
182CARES_FUNCTION_IN_LIBRARY (gethostbyname socket HAVE_GHBN_LIBSOCKET)
183CARES_FUNCTION_IN_LIBRARY (gethostbyname network HAVE_LIBNETWORK)
184CARES_FUNCTION_IN_LIBRARY (socket socket HAVE_SOCKET_LIBSOCKET)
185IF (HAVE_GHBN_LIBSOCKET OR HAVE_SOCKET_LIBSOCKET)
186	SET(HAVE_LIBSOCKET TRUE)
187ENDIF ()
188CARES_FUNCTION_IN_LIBRARY (socket network HAVE_LIBNETWORK)
189CARES_FUNCTION_IN_LIBRARY (clock_gettime rt HAVE_LIBRT)
190
191
192# Look for necessary includes
193CHECK_INCLUDE_FILES (AvailabilityMacros.h  HAVE_AVAILABILITYMACROS_H)
194CHECK_INCLUDE_FILES (sys/types.h           HAVE_SYS_TYPES_H)
195CHECK_INCLUDE_FILES (sys/random.h          HAVE_SYS_RANDOM_H)
196CHECK_INCLUDE_FILES (sys/socket.h          HAVE_SYS_SOCKET_H)
197CHECK_INCLUDE_FILES (sys/sockio.h          HAVE_SYS_SOCKIO_H)
198CHECK_INCLUDE_FILES (arpa/inet.h           HAVE_ARPA_INET_H)
199CHECK_INCLUDE_FILES (arpa/nameser_compat.h HAVE_ARPA_NAMESER_COMPAT_H)
200CHECK_INCLUDE_FILES (arpa/nameser.h        HAVE_ARPA_NAMESER_H)
201CHECK_INCLUDE_FILES (assert.h              HAVE_ASSERT_H)
202CHECK_INCLUDE_FILES (errno.h               HAVE_ERRNO_H)
203CHECK_INCLUDE_FILES (fcntl.h               HAVE_FCNTL_H)
204CHECK_INCLUDE_FILES (inttypes.h            HAVE_INTTYPES_H)
205CHECK_INCLUDE_FILES (limits.h              HAVE_LIMITS_H)
206CHECK_INCLUDE_FILES (malloc.h              HAVE_MALLOC_H)
207CHECK_INCLUDE_FILES (memory.h              HAVE_MEMORY_H)
208CHECK_INCLUDE_FILES (netdb.h               HAVE_NETDB_H)
209CHECK_INCLUDE_FILES (netinet/in.h          HAVE_NETINET_IN_H)
210CHECK_INCLUDE_FILES (netinet6/in6.h        HAVE_NETINET6_IN6_H)
211# On old MacOS SDK versions, you must include sys/socket.h before net/if.h
212IF (HAVE_SYS_SOCKET_H)
213  CHECK_INCLUDE_FILES ("sys/socket.h;net/if.h"  HAVE_NET_IF_H)
214ELSE ()
215  CHECK_INCLUDE_FILES (net/if.h                 HAVE_NET_IF_H)
216ENDIF ()
217CHECK_INCLUDE_FILES (signal.h              HAVE_SIGNAL_H)
218CHECK_INCLUDE_FILES (socket.h              HAVE_SOCKET_H)
219CHECK_INCLUDE_FILES (stdbool.h             HAVE_STDBOOL_H)
220CHECK_INCLUDE_FILES (stdint.h              HAVE_STDINT_H)
221CHECK_INCLUDE_FILES (stdlib.h              HAVE_STDLIB_H)
222CHECK_INCLUDE_FILES (strings.h             HAVE_STRINGS_H)
223CHECK_INCLUDE_FILES (string.h              HAVE_STRING_H)
224CHECK_INCLUDE_FILES (stropts.h             HAVE_STROPTS_H)
225CHECK_INCLUDE_FILES (sys/ioctl.h           HAVE_SYS_IOCTL_H)
226CHECK_INCLUDE_FILES (sys/param.h           HAVE_SYS_PARAM_H)
227CHECK_INCLUDE_FILES (sys/select.h          HAVE_SYS_SELECT_H)
228CHECK_INCLUDE_FILES (sys/stat.h            HAVE_SYS_STAT_H)
229CHECK_INCLUDE_FILES (sys/time.h            HAVE_SYS_TIME_H)
230CHECK_INCLUDE_FILES (sys/uio.h             HAVE_SYS_UIO_H)
231CHECK_INCLUDE_FILES (sys/event.h           HAVE_SYS_EVENT_H)
232CHECK_INCLUDE_FILES (sys/epoll.h           HAVE_SYS_EPOLL_H)
233CHECK_INCLUDE_FILES (ifaddrs.h             HAVE_IFADDRS_H)
234CHECK_INCLUDE_FILES (time.h                HAVE_TIME_H)
235CHECK_INCLUDE_FILES (poll.h                HAVE_POLL_H)
236CHECK_INCLUDE_FILES (dlfcn.h               HAVE_DLFCN_H)
237CHECK_INCLUDE_FILES (unistd.h              HAVE_UNISTD_H)
238# On OpenBSD, you must include sys/types.h before netinet/tcp.h
239IF (HAVE_SYS_TYPES_H)
240  CHECK_INCLUDE_FILES ("sys/types.h;netinet/tcp.h"         HAVE_NETINET_TCP_H)
241ELSE ()
242  CHECK_INCLUDE_FILES (netinet/tcp.h                       HAVE_NETINET_TCP_H)
243ENDIF ()
244
245# Include order matters for these windows files.
246# As cygwin environment has both socket.h and winsock2.h
247# headers check WIN32 not to include the later one here
248IF (WIN32)
249CHECK_INCLUDE_FILES ("winsock2.h;windows.h"            HAVE_WINSOCK2_H)
250CHECK_INCLUDE_FILES ("winsock2.h;ws2tcpip.h;windows.h" HAVE_WS2TCPIP_H)
251CHECK_INCLUDE_FILES ("winsock2.h;iphlpapi.h;windows.h" HAVE_IPHLPAPI_H)
252CHECK_INCLUDE_FILES ("winsock2.h;netioapi.h;windows.h" HAVE_NETIOAPI_H)
253CHECK_INCLUDE_FILES ("winsock2.h;mswsock.h;windows.h"  HAVE_MSWSOCK_H)
254CHECK_INCLUDE_FILES ("winsock.h;windows.h"             HAVE_WINSOCK_H)
255CHECK_INCLUDE_FILES (windows.h                         HAVE_WINDOWS_H)
256CHECK_INCLUDE_FILES ("windows.h;winternl.h"            HAVE_WINTERNL_H)
257CHECK_INCLUDE_FILES ("windows.h;ntdef.h"               HAVE_NTDEF_H)
258CHECK_INCLUDE_FILES ("windows.h;ntdef.h;ntstatus.h"    HAVE_NTSTATUS_H)
259
260
261ENDIF ()
262
263# Set system-specific compiler flags
264IF (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
265	LIST (APPEND SYSFLAGS -D_DARWIN_C_SOURCE)
266ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR CMAKE_SYSTEM_NAME STREQUAL "Android")
267	LIST (APPEND SYSFLAGS -D_GNU_SOURCE -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700)
268ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
269	LIST (APPEND SYSFLAGS -D__EXTENSIONS__ -D_REENTRANT -D_XOPEN_SOURCE=600)
270ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "AIX")
271	LIST (APPEND SYSFLAGS -D_ALL_SOURCE -D_XOPEN_SOURCE=700 -D_USE_IRS)
272ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
273	# Don't define _XOPEN_SOURCE on FreeBSD, it actually reduces visibility instead of increasing it
274ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "QNX")
275	LIST (APPEND SYSFLAGS -D_QNX_SOURCE)
276ELSEIF (WIN32)
277	LIST (APPEND SYSFLAGS -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
278	IF (NOT CMAKE_C_FLAGS MATCHES ".*-D_WIN32_WINNT=.*")
279		LIST (APPEND SYSFLAGS -D_WIN32_WINNT=0x0602)
280	ENDIF ()
281ENDIF ()
282ADD_DEFINITIONS(${SYSFLAGS})
283
284
285# Tell C-Ares about libraries to depend on
286IF (HAVE_LIBRESOLV)
287	LIST (APPEND CARES_DEPENDENT_LIBS resolv)
288ENDIF ()
289IF (HAVE_LIBNSL)
290	LIST (APPEND CARES_DEPENDENT_LIBS nsl)
291ENDIF ()
292IF (HAVE_LIBSOCKET)
293	LIST (APPEND CARES_DEPENDENT_LIBS socket)
294ENDIF ()
295IF (HAVE_LIBNETWORK)
296	LIST (APPEND CARES_DEPENDENT_LIBS network)
297ENDIF ()
298IF (HAVE_LIBRT)
299	LIST (APPEND CARES_DEPENDENT_LIBS rt)
300ENDIF ()
301IF (WIN32)
302	LIST (APPEND CARES_DEPENDENT_LIBS ws2_32 advapi32 iphlpapi)
303ENDIF ()
304
305
306# When checking for symbols, we need to make sure we set the proper
307# headers, libraries, and definitions for the detection to work properly
308# CMAKE_REQUIRED_DEFINITIONS, CMAKE_REQUIRED_LIBRARIES, and
309# CMAKE_EXTRA_INCLUDE_FILES.  When we're done with the detection, we'll
310# restore them to their original values (otherwise a parent project
311# that tries to set these won't be maintained, see Issue #729)
312SET (ORIG_CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEEFINITIONS})
313SET (ORIG_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
314SET (ORIG_CMAKE_EXTRA_INCLUDE_FILES ${CMAKE_EXTRA_INCLUDE_FILES})
315
316SET (CMAKE_REQUIRED_DEFINITIONS ${SYSFLAGS})
317LIST (APPEND CMAKE_REQUIRED_LIBRARIES ${CARES_DEPENDENT_LIBS})
318
319MACRO (CARES_EXTRAINCLUDE_IFSET var include)
320	IF (${var})
321		LIST (APPEND CMAKE_EXTRA_INCLUDE_FILES ${include})
322	ENDIF ()
323ENDMACRO ()
324
325CARES_EXTRAINCLUDE_IFSET (HAVE_AVAILABILITYMACROS_H AvailabilityMacros.h)
326CARES_EXTRAINCLUDE_IFSET (HAVE_STDBOOL_H      stdbool.h)
327CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_TYPES_H    sys/types.h)
328CARES_EXTRAINCLUDE_IFSET (HAVE_ARPA_INET_H    arpa/inet.h)
329CARES_EXTRAINCLUDE_IFSET (HAVE_ARPA_NAMESER_H arpa/nameser.h)
330CARES_EXTRAINCLUDE_IFSET (HAVE_NETDB_H        netdb.h)
331CARES_EXTRAINCLUDE_IFSET (HAVE_NET_IF_H       net/if.h)
332CARES_EXTRAINCLUDE_IFSET (HAVE_IFADDRS_H      ifaddrs.h)
333CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_IN_H   netinet/in.h)
334CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET6_IN6_H netinet6/in6.h)
335CARES_EXTRAINCLUDE_IFSET (HAVE_NETINET_TCP_H  netinet/tcp.h)
336CARES_EXTRAINCLUDE_IFSET (HAVE_SIGNAL_H       signal.h)
337CARES_EXTRAINCLUDE_IFSET (HAVE_STDLIB_H       stdlib.h)
338CARES_EXTRAINCLUDE_IFSET (HAVE_STRING_H       string.h)
339CARES_EXTRAINCLUDE_IFSET (HAVE_STRINGS_H      strings.h)
340CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_IOCTL_H    sys/ioctl.h)
341CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_RANDOM_H   sys/random.h)
342CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SELECT_H   sys/select.h)
343CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SOCKET_H   sys/socket.h)
344CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_SOCKIO_H	sys/sockio.h)
345CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_TIME_H     sys/time.h)
346CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_STAT_H     sys/stat.h)
347CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_UIO_H      sys/uio.h)
348CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_EVENT_H    sys/event.h)
349CARES_EXTRAINCLUDE_IFSET (HAVE_SYS_EPOLL_H    sys/epoll.h)
350CARES_EXTRAINCLUDE_IFSET (HAVE_TIME_H         time.h)
351CARES_EXTRAINCLUDE_IFSET (HAVE_POLL_H         poll.h)
352CARES_EXTRAINCLUDE_IFSET (HAVE_FCNTL_H        fcntl.h)
353CARES_EXTRAINCLUDE_IFSET (HAVE_UNISTD_H       unistd.h)
354CARES_EXTRAINCLUDE_IFSET (HAVE_WINSOCK2_H     winsock2.h)
355CARES_EXTRAINCLUDE_IFSET (HAVE_WS2TCPIP_H     ws2tcpip.h)
356CARES_EXTRAINCLUDE_IFSET (HAVE_IPHLPAPI_H     iphlpapi.h)
357CARES_EXTRAINCLUDE_IFSET (HAVE_WINDOWS_H      windows.h)
358
359# Check Types
360# CHECK_TYPE_SIZE can't be used to see if a type exists because on Apple when
361# building multi-arch, it will throw an error.  So we need to wrap
362# CHECK_C_SOURCE_COMPILES for our tests.
363MACRO (CARES_TYPE_EXISTS type var)
364	SET(_CARES_C_SOURCE "
365		#include <stdio.h>
366		#include <stdlib.h>
367	")
368	FOREACH(_C_HEADER ${CMAKE_EXTRA_INCLUDE_FILES})
369		SET(_CARES_C_SOURCE "${_CARES_C_SOURCE}
370		#include <${_C_HEADER}>")
371	ENDFOREACH(_C_HEADER)
372
373	SET(_CARES_C_SOURCE "${_CARES_C_SOURCE}
374		int main() {
375			${type} var_exists;
376			(void)var_exists;
377			return 0;
378		}
379	")
380	CHECK_C_SOURCE_COMPILES ("${_CARES_C_SOURCE}" ${var})
381ENDMACRO ()
382
383CARES_TYPE_EXISTS (socklen_t                 HAVE_SOCKLEN_T)
384CARES_TYPE_EXISTS (SOCKET                    HAVE_TYPE_SOCKET)
385CARES_TYPE_EXISTS (ssize_t                   HAVE_SSIZE_T)
386CARES_TYPE_EXISTS ("long long"               HAVE_LONGLONG)
387CARES_TYPE_EXISTS ("struct addrinfo"         HAVE_STRUCT_ADDRINFO)
388CARES_TYPE_EXISTS ("struct in6_addr"         HAVE_STRUCT_IN6_ADDR)
389CARES_TYPE_EXISTS ("struct sockaddr_in6"     HAVE_STRUCT_SOCKADDR_IN6)
390CARES_TYPE_EXISTS ("struct sockaddr_storage" HAVE_STRUCT_SOCKADDR_STORAGE)
391CARES_TYPE_EXISTS ("struct timeval"          HAVE_STRUCT_TIMEVAL)
392
393
394# Check for preprocessor defines
395CHECK_SYMBOL_EXISTS (AF_INET6        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_AF_INET6)
396CHECK_SYMBOL_EXISTS (O_NONBLOCK      "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_O_NONBLOCK)
397CHECK_SYMBOL_EXISTS (FIONBIO         "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FIONBIO)
398CHECK_SYMBOL_EXISTS (SIOCGIFADDR     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IOCTL_SIOCGIFADDR)
399CHECK_SYMBOL_EXISTS (MSG_NOSIGNAL    "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_MSG_NOSIGNAL)
400CHECK_SYMBOL_EXISTS (PF_INET6        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_PF_INET6)
401CHECK_SYMBOL_EXISTS (SO_NONBLOCK     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SO_NONBLOCK)
402
403# XCode v8 bug: iOS when targeting less than v10, or MacOS when targeting less than v10.12 will
404# say clock_gettime exists, it is a weak symbol that only exists in iOS10/MacOS10.12 and will
405# cause a crash at runtime when running on older versions.  Skip finding CLOCK_MONOTONIC on older
406# OS's.
407IF ((NOT APPLE) OR IOS_V10 OR MACOS_V1012)
408	CHECK_SYMBOL_EXISTS (CLOCK_MONOTONIC "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOCK_GETTIME_MONOTONIC)
409ENDIF ()
410
411CHECK_STRUCT_HAS_MEMBER("struct sockaddr_in6" sin6_scope_id "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID LANGUAGE C)
412
413CHECK_SYMBOL_EXISTS (strnlen         "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRNLEN)
414CHECK_SYMBOL_EXISTS (memmem          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_MEMMEM)
415CHECK_SYMBOL_EXISTS (closesocket     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET)
416CHECK_SYMBOL_EXISTS (CloseSocket     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CLOSESOCKET_CAMEL)
417CHECK_SYMBOL_EXISTS (connect         "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONNECT)
418CHECK_SYMBOL_EXISTS (connectx        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONNECTX)
419CHECK_SYMBOL_EXISTS (fcntl           "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FCNTL)
420CHECK_SYMBOL_EXISTS (freeaddrinfo    "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_FREEADDRINFO)
421CHECK_SYMBOL_EXISTS (getaddrinfo     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETADDRINFO)
422CHECK_SYMBOL_EXISTS (getenv          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETENV)
423CHECK_SYMBOL_EXISTS (gethostname     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETHOSTNAME)
424CHECK_SYMBOL_EXISTS (getnameinfo     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETNAMEINFO)
425CHECK_SYMBOL_EXISTS (getrandom       "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETRANDOM)
426CHECK_SYMBOL_EXISTS (getservbyport_r "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETSERVBYPORT_R)
427CHECK_SYMBOL_EXISTS (getservbyname_r "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETSERVBYNAME_R)
428CHECK_SYMBOL_EXISTS (gettimeofday    "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETTIMEOFDAY)
429CHECK_SYMBOL_EXISTS (if_indextoname  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IF_INDEXTONAME)
430CHECK_SYMBOL_EXISTS (if_nametoindex  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IF_NAMETOINDEX)
431CHECK_SYMBOL_EXISTS (GetBestRoute2   "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETBESTROUTE2)
432CHECK_SYMBOL_EXISTS (ConvertInterfaceIndexToLuid  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACEINDEXTOLUID)
433CHECK_SYMBOL_EXISTS (ConvertInterfaceLuidToNameA  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_CONVERTINTERFACELUIDTONAMEA)
434CHECK_SYMBOL_EXISTS (NotifyIpInterfaceChange      "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_NOTIFYIPINTERFACECHANGE)
435CHECK_SYMBOL_EXISTS (RegisterWaitForSingleObject  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_REGISTERWAITFORSINGLEOBJECT)
436
437
438CHECK_SYMBOL_EXISTS (inet_net_pton   "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_INET_NET_PTON)
439IF (NOT WIN32)
440	# Disabled on Windows, because these functions are only really supported on Windows
441	# Vista or newer (_WIN32_WINNT >= 0x0600). Older versions of Windows may provide
442	# them as experimental non-working features, so we have to disable them manually.
443	CHECK_SYMBOL_EXISTS (inet_ntop       "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_INET_NTOP)
444	CHECK_SYMBOL_EXISTS (inet_pton       "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_INET_PTON)
445ENDIF ()
446CHECK_SYMBOL_EXISTS (ioctl           "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IOCTL)
447CHECK_SYMBOL_EXISTS (ioctlsocket     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IOCTLSOCKET)
448CHECK_SYMBOL_EXISTS (IoctlSocket     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_IOCTLSOCKET_CAMEL)
449CHECK_SYMBOL_EXISTS (recv            "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_RECV)
450CHECK_SYMBOL_EXISTS (recvfrom        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_RECVFROM)
451CHECK_SYMBOL_EXISTS (send            "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SEND)
452CHECK_SYMBOL_EXISTS (sendto          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SENDTO)
453CHECK_SYMBOL_EXISTS (setsockopt      "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SETSOCKOPT)
454CHECK_SYMBOL_EXISTS (socket          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_SOCKET)
455CHECK_SYMBOL_EXISTS (strcasecmp      "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRCASECMP)
456CHECK_SYMBOL_EXISTS (strcmpi         "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRCMPI)
457CHECK_SYMBOL_EXISTS (strdup          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRDUP)
458CHECK_SYMBOL_EXISTS (stricmp         "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRICMP)
459CHECK_SYMBOL_EXISTS (strncasecmp     "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRNCASECMP)
460CHECK_SYMBOL_EXISTS (strncmpi        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRNCMPI)
461CHECK_SYMBOL_EXISTS (strnicmp        "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STRNICMP)
462CHECK_SYMBOL_EXISTS (writev          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_WRITEV)
463CHECK_SYMBOL_EXISTS (arc4random_buf  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_ARC4RANDOM_BUF)
464CHECK_SYMBOL_EXISTS (stat            "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_STAT)
465CHECK_SYMBOL_EXISTS (getifaddrs      "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_GETIFADDRS)
466CHECK_SYMBOL_EXISTS (poll            "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_POLL)
467CHECK_SYMBOL_EXISTS (pipe            "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_PIPE)
468CHECK_SYMBOL_EXISTS (pipe2           "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_PIPE2)
469CHECK_SYMBOL_EXISTS (kqueue          "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_KQUEUE)
470CHECK_SYMBOL_EXISTS (epoll_create1   "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_EPOLL)
471
472
473# On Android, the system headers may define __system_property_get(), but excluded
474# from libc.  We need to perform a link test instead of a header/symbol test.
475CHECK_FUNCTION_EXISTS (__system_property_get HAVE___SYSTEM_PROPERTY_GET)
476
477# Restore original values (as per Issue #729)
478SET (CMAKE_REQUIRED_DEFINITIONS ${ORIG_CMAKE_REQUIRED_DEEFINITIONS})
479SET (CMAKE_REQUIRED_LIBRARIES ${ORIG_CMAKE_REQUIRED_LIBRARIES})
480SET (CMAKE_EXTRA_INCLUDE_FILES ${ORIG_CMAKE_EXTRA_INCLUDE_FILES})
481
482
483################################################################################
484# Threading Support
485#
486IF (CARES_THREADS)
487	IF (WIN32)
488		# Do nothing, always has threads
489	ELSE ()
490		# Need to prefer pthreads on platforms that may have more threading choices
491		# (e.g. Solaris)
492		SET (CMAKE_THREAD_PREFER_PTHREAD TRUE)
493		FIND_PACKAGE (Threads)
494
495		IF (Threads_FOUND)
496			# Fix solaris9 bug due to libc having pthread_create() stubs that always fail.  CMake
497			# doesn't realize that the real pthread functions aren't in libc, so sets the pthread
498			# library CAKE_THREAD_LIBS_INIT variable to blank instead of to the correct "-lpthread".
499			IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND NOT CMAKE_THREAD_LIBS_INIT)
500				SET (CMAKE_THREAD_LIBS_INIT "-lpthread")
501			ENDIF ()
502
503			# PThread functions.
504			CHECK_INCLUDE_FILES (pthread.h                                 HAVE_PTHREAD_H)
505			CHECK_INCLUDE_FILES (pthread_np.h                              HAVE_PTHREAD_NP_H)
506			CARES_EXTRAINCLUDE_IFSET (HAVE_PTHREAD_H                       pthread.h)
507			CARES_EXTRAINCLUDE_IFSET (HAVE_PTHREAD_NP_H                    pthread_np.h)
508			CHECK_SYMBOL_EXISTS (pthread_init  "${CMAKE_EXTRA_INCLUDE_FILES}" HAVE_PTHREAD_INIT)
509			LIST (APPEND CARES_DEPENDENT_LIBS ${CMAKE_THREAD_LIBS_INIT})
510		ELSE ()
511			MESSAGE (WARNING "Threading support not found, disabling...")
512			SET (CARES_THREADS OFF)
513		ENDIF ()
514	ENDIF ()
515ENDIF ()
516
517
518
519################################################################################
520# recv, recvfrom, send, getnameinfo, gethostname
521# ARGUMENTS AND RETURN VALUES
522#
523# The AutoTools build tries to be really thorough here.  So much so that it
524# takes forever.  We really don't want to do that.  Lets make some educated
525# guesses based on datatypes we have available, and for others, use some 'sane'
526# defaults.  This should be much quicker and nearly as accurate ... and even
527# if not, it probably won't matter in the least.
528
529IF (HAVE_SSIZE_T AND HAVE_SOCKLEN_T AND NOT WIN32)
530	# If we have ssize_t and socklen_t, the API is usually sane and uses ssize_t and size_t for lengths
531	SET (RECVFROM_TYPE_RETV ssize_t)
532	SET (RECVFROM_TYPE_ARG3 size_t)
533ELSE ()
534	SET (RECVFROM_TYPE_RETV int)
535	SET (RECVFROM_TYPE_ARG3 int)
536ENDIF ()
537
538IF (HAVE_TYPE_SOCKET)
539	# If the SOCKET type is defined, it uses socket ... should be windows only
540	SET (RECVFROM_TYPE_ARG1 SOCKET)
541ELSE ()
542	SET (RECVFROM_TYPE_ARG1 int)
543ENDIF()
544
545IF (HAVE_SOCKLEN_T)
546	# If we have socklen_t the APIs pretty much always actually use it
547	SET (RECVFROM_TYPE_ARG6 "socklen_t *")
548	SET (GETNAMEINFO_TYPE_ARG2 socklen_t)
549	SET (GETNAMEINFO_TYPE_ARG46 socklen_t)
550ELSE ()
551	SET (RECVFROM_TYPE_ARG6 "int *")
552	SET (GETNAMEINFO_TYPE_ARG2 int)
553	SET (GETNAMEINFO_TYPE_ARG46 int)
554ENDIF ()
555
556IF (WIN32)
557	SET (RECV_TYPE_ARG2 "char *")
558ELSE ()
559	SET (RECV_TYPE_ARG2 "void *")
560ENDIF ()
561
562# Functions are typically consistent so the equivalent fields map ... equivalently
563SET (RECV_TYPE_RETV ${RECVFROM_TYPE_RETV})
564SET (SEND_TYPE_RETV ${RECVFROM_TYPE_RETV})
565SET (RECV_TYPE_ARG1 ${RECVFROM_TYPE_ARG1})
566SET (RECVFROM_TYPE_ARG2 ${RECV_TYPE_ARG2})
567SET (SEND_TYPE_ARG1 ${RECVFROM_TYPE_ARG1})
568SET (RECV_TYPE_ARG3 ${RECVFROM_TYPE_ARG3})
569SET (SEND_TYPE_ARG3 ${RECVFROM_TYPE_ARG3})
570SET (GETHOSTNAME_TYPE_ARG2 ${RECVFROM_TYPE_ARG3})
571
572# These should always be "sane" values to use always
573SET (RECVFROM_QUAL_ARG5 )
574SET (RECVFROM_TYPE_ARG4 int)
575SET (RECVFROM_TYPE_ARG5 "struct sockaddr *")
576SET (RECV_TYPE_ARG4 int)
577SET (GETNAMEINFO_TYPE_ARG1 "struct sockaddr *")
578SET (GETNAMEINFO_TYPE_ARG7 int)
579SET (SEND_TYPE_ARG2 "const void *")
580SET (SEND_TYPE_ARG4 int)
581################################################################################
582
583
584# HAVE_CXX11  ??
585# HAVE_SIG_ATOMIC_T_VOLATILE  ??
586
587
588# Set a few variables by hand that C-Ares wants, logically, based on detection
589# data.
590
591IF (HAVE_SOCKLEN_T)
592	Set (CARES_TYPEOF_ARES_SOCKLEN_T "socklen_t")
593ELSE ()
594	Set (CARES_TYPEOF_ARES_SOCKLEN_T "int")
595ENDIF ()
596
597IF (HAVE_SSIZE_T)
598	Set (CARES_TYPEOF_ARES_SSIZE_T "ssize_t")
599ELSE ()
600	IF (WIN32)
601		IF ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
602			Set (CARES_TYPEOF_ARES_SSIZE_T "__int64")
603		ELSE ()
604			Set (CARES_TYPEOF_ARES_SSIZE_T "int")
605		ENDIF ()
606	ELSE ()
607		Set (CARES_TYPEOF_ARES_SSIZE_T "long")
608	ENDIF ()
609ENDIF ()
610
611IF (HAVE_FCNTL AND HAVE_O_NONBLOCK)
612	SET (HAVE_FCNTL_O_NONBLOCK 1)
613ENDIF ()
614
615IF (HAVE_IOCTL AND HAVE_FIONBIO)
616	SET (HAVE_IOCTL_FIONBIO 1)
617ENDIF ()
618
619IF (HAVE_IOCTLSOCKET AND HAVE_FIONBIO)
620	SET (HAVE_IOCTLSOCKET_FIONBIO 1)
621ENDIF ()
622
623IF (HAVE_IOCTLSOCKET_CAMEL AND HAVE_FIONBIO)
624	SET (HAVE_IOCTLSOCKET_CAMEL_FIONBIO 1)
625ENDIF ()
626
627IF (HAVE_GETADDRINFO)
628	IF (CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR
629		CMAKE_SYSTEM_NAME STREQUAL "HPUX" OR
630		CMAKE_SYSTEM_NAME STREQUAL "NetBSD" OR
631		CMAKE_SYSTEM_NAME STREQUAL "SunOS" OR
632		CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
633		CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
634		WIN32)
635			SET (HAVE_GETADDRINFO_THREADSAFE 1)
636	ENDIF ()
637ENDIF ()
638
639IF (HAVE_TIME_H AND HAVE_SYS_TIME_H)
640	SET (TIME_WITH_SYS_TIME 1)
641ENDIF ()
642
643IF (HAVE_GETSERVBYPORT_R)
644	# TODO : Should probably autodetect
645	IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
646		SET (GETSERVBYPORT_R_ARGS 5)
647	ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
648		CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
649		HAIKU)
650		SET (GETSERVBYPORT_R_ARGS 4)
651	ELSE ()
652		# Probably linux
653		SET (GETSERVBYPORT_R_ARGS 6)
654	ENDIF ()
655ENDIF ()
656
657IF (HAVE_GETSERVBYNAME_R)
658	# TODO : Should probably autodetect
659	IF (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
660		SET (GETSERVBYNAME_R_ARGS 5)
661	ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "AIX" OR
662		CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR
663		HAIKU)
664		SET (GETSERVBYNAME_R_ARGS 4)
665	ELSE ()
666		# Probably linux
667		SET (GETSERVBYNAME_R_ARGS 6)
668	ENDIF ()
669ENDIF ()
670
671# Set some aliases used for ares_build.h
672IF (HAVE_SYS_TYPES_H)
673	SET (CARES_HAVE_SYS_TYPES_H 1)
674ENDIF ()
675IF (HAVE_SYS_SOCKET_H)
676	SET (CARES_HAVE_SYS_SOCKET_H 1)
677ENDIF()
678IF (HAVE_SYS_SELECT_H)
679	SET (CARES_HAVE_SYS_SELECT_H 1)
680ENDIF()
681IF (HAVE_WS2TCPIP_H)
682	SET (CARES_HAVE_WS2TCPIP_H 1)
683ENDIF()
684IF (HAVE_WINSOCK2_H)
685	SET (CARES_HAVE_WINSOCK2_H 1)
686ENDIF()
687IF (HAVE_WINDOWS_H)
688	SET (CARES_HAVE_WINDOWS_H 1)
689ENDIF()
690IF (HAVE_ARPA_NAMESER_H)
691	SET (CARES_HAVE_ARPA_NAMESER_H 1)
692ENDIF()
693IF (HAVE_ARPA_NAMESER_COMPAT_H)
694	SET (CARES_HAVE_ARPA_NAMESER_COMPAT_H 1)
695ENDIF()
696
697# Coverage
698IF (CARES_COVERAGE)
699	# set compiler flags
700	SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftest-coverage -fprofile-arcs")
701	SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftest-coverage -fprofile-arcs")
702
703	# find required tools
704	FIND_PROGRAM(LCOV lcov REQUIRED)
705	FIND_PROGRAM(GENHTML genhtml REQUIRED)
706
707	# add coverage target
708	ADD_CUSTOM_TARGET(coverage
709		# gather data
710		COMMAND ${LCOV} --directory . --capture --output-file coverage.info
711		# generate report
712		COMMAND ${GENHTML} --demangle-cpp -o coverage coverage.info
713		WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
714	)
715ENDIF()
716
717# TRANSFORM_MAKEFILE_INC
718#
719# This function consumes the "Makefile.inc" autotools file, and converts it into
720#  "Makefile.inc.cmake", a cmake include file; transforming this:
721#
722# CSOURCES = ares__close_sockets.c	\
723#   ares__get_hostent.c			\
724#   ares__read_line.c			\
725#   ...
726#
727#   into this:
728#
729# SET (CSOURCES
730# 	ares__close_sockets.c
731# 	ares__get_hostent.c
732# 	ares__read_line.c
733#	...
734function(TRANSFORM_MAKEFILE_INC INPUT_FILE OUTPUT_FILE)
735	file(READ ${INPUT_FILE} MAKEFILE_INC_TEXT)
736	string(REPLACE "$(top_srcdir)"   "\${PROJECT_SOURCE_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
737	string(REPLACE "$(top_builddir)" "\${PROJECT_BINARY_DIR}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
738
739	string(REGEX REPLACE "\\\\\n" "ß!ß" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
740	string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "SET(\\1 \\2)" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
741	string(REPLACE "ß!ß" "\n" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})
742
743	string(REGEX REPLACE "\\$\\(([a-zA-Z_][a-zA-Z0-9_]*)\\)" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace $() with ${}
744	string(REGEX REPLACE "@([a-zA-Z_][a-zA-Z0-9_]*)@" "\${\\1}" MAKEFILE_INC_TEXT ${MAKEFILE_INC_TEXT})    # Replace @@ with ${}, even if that may not be read by CMake scripts.
745	file(WRITE ${OUTPUT_FILE} ${MAKEFILE_INC_TEXT})
746endfunction()
747
748# Directory for includes
749ADD_SUBDIRECTORY (include)
750
751# Directory for lib and tools
752ADD_SUBDIRECTORY (src)
753
754# Docs
755ADD_SUBDIRECTORY (docs)
756
757# Tests
758IF (CARES_BUILD_TESTS OR CARES_BUILD_CONTAINER_TESTS)
759	ENABLE_TESTING ()
760	ADD_SUBDIRECTORY (test)
761ENDIF ()
762
763# Export targets
764IF (CARES_INSTALL)
765	SET (CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
766	INCLUDE (CMakePackageConfigHelpers)
767	CONFIGURE_PACKAGE_CONFIG_FILE (${PROJECT_NAME}-config.cmake.in ${PROJECT_NAME}-config.cmake
768		INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
769		PATH_VARS CMAKE_INSTALL_INCLUDEDIR
770		NO_CHECK_REQUIRED_COMPONENTS_MACRO
771	)
772
773	WRITE_BASIC_PACKAGE_VERSION_FILE(${PROJECT_NAME}-config-version.cmake VERSION "${CARES_VERSION}" COMPATIBILITY SameMajorVersion)
774	INSTALL (EXPORT ${PROJECT_NAME}-targets COMPONENT Devel DESTINATION ${CMAKECONFIG_INSTALL_DIR} NAMESPACE ${PROJECT_NAME}::)
775	INSTALL (FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake" COMPONENT Devel DESTINATION ${CMAKECONFIG_INSTALL_DIR})
776
777	# pkgconfig support for static builds
778	FOREACH (LIB ${CARES_DEPENDENT_LIBS})
779		IF (NOT LIB MATCHES "^-")
780			SET (LIB "-l${LIB}")
781		ENDIF ()
782		SET (CARES_PRIVATE_LIBS "${CARES_PRIVATE_LIBS} ${LIB}")
783	ENDFOREACH ()
784
785	CONFIGURE_FILE("libcares.pc.cmake" "libcares.pc" @ONLY)
786	INSTALL (FILES "${CMAKE_CURRENT_BINARY_DIR}/libcares.pc" COMPONENT Devel DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
787ENDIF ()
788
789# Legacy chain-building variables (provided for compatibility with old code).
790# Don't use these, external code should be updated to refer to the aliases directly (e.g., Cares::cares).
791SET (CARES_FOUND 1 CACHE INTERNAL "CARES LIBRARY FOUND")
792SET (CARES_LIBRARIES ${PROJECT_NAME}::cares CACHE INTERNAL "CARES LIBRARIES")
793
794
795IF (CARES_INSTALL)
796    # Package creation
797    set( CPACK_PACKAGE_NAME ${PROJECT_NAME} )
798    set( CPACK_PACKAGE_VENDOR "Daniel Stenberg" ) # Github project owner
799    set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "A C library for asynchronous DNS requests" )
800    set( CPACK_PACKAGE_HOMEPAGE_URL "https://c-ares.org/" )
801    set( CPACK_PACKAGE_CONTACT      "https://c-ares.org/" )
802    set( CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} )
803    set( CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR} )
804    set( CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH} )
805    set( CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} )
806    set( CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME} )
807    set( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md" )
808    set( CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md" )
809
810    set( CPACK_COMPONENT_Library_DISPLAY_NAME "c-ares Library" )
811    set( CPACK_COMPONENT_Library_DESCRIPTION "The c-ares binary library." )
812    set( CPACK_COMPONENT_Library_REQUIRED 1 )
813    set( CPACK_COMPONENT_Devel_DISPLAY_NAME "c-ares Development Files" )
814    set( CPACK_COMPONENT_Devel_DESCRIPTION "Development files for compiling against c-ares." )
815    set( CPACK_COMPONENT_Devel_REQUIRED 0 )
816    IF (CARES_BUILD_TOOLS)
817        set( CPACK_COMPONENT_Tools_DISPLAY_NAME "c-ares Tools" )
818        set( CPACK_COMPONENT_Tools_DESCRIPTION "Tools for using c-ares." )
819        set( CPACK_COMPONENT_Tools_REQUIRED 0 )
820    ENDIF ()
821
822    if( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )
823
824        if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
825            set( CPACK_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}" )
826        endif()
827        if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
828            if ( "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows" )
829                message( FATAL_ERROR "Failed to determine CPACK_PACKAGE_ARCHITECTURE. Is CMAKE_SYSTEM_PROCESSOR set?" )
830            endif()
831            # Note: the architecture should default to the local architecture, but it
832            # in fact comes up empty.  We call `uname -m` to ask the kernel instead.
833            EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE )
834        endif()
835
836        set( CPACK_INCLUDE_TOPLEVEL_DIRECTORY 1 )
837        set( CPACK_PACKAGE_RELEASE 1 )
838
839
840        # RPM - https://cmake.org/cmake/help/latest/cpack_gen/rpm.html
841        set( CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE} )
842        set( CPACK_RPM_PACKAGE_ARCHITECTURE ${CPACK_PACKAGE_ARCHITECTURE} )
843        set( CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION_SUMMARY} )
844        set( CPACK_RPM_PACKAGE_URL ${CPACK_PACKAGE_HOMEPAGE_URL} )
845        set( CPACK_RPM_PACKAGE_LICENSE "MIT" )
846        set( CPACK_RPM_COMPONENT_INSTALL 1 )
847        set( CPACK_RPM_COMPRESSION_TYPE "xz" )
848        set( CPACK_RPM_PACKAGE_AUTOPROV 1 )
849
850        set( CPACK_RPM_Library_PACKAGE_SUMMARY ${CPACK_COMPONENT_Library_DESCRIPTION} )
851        set( CPACK_RPM_Library_PACKAGE_ARCHITECTURE ${CPACK_RPM_PACKAGE_ARCHITECTURE} )
852        set( CPACK_RPM_Library_PACKAGE_NAME "libcares${CARES_LIB_VERSION_MAJOR}" )
853        set( CPACK_RPM_Library_FILE_NAME "RPM-DEFAULT" )
854
855        set( CPACK_RPM_Devel_PACKAGE_REQUIRES "cmake >= ${CMAKE_MINIMUM_REQUIRED_VERSION}, ${CPACK_RPM_Library_PACKAGE_NAME} >= ${CPACK_PACKAGE_VERSION}" )
856        set( CPACK_RPM_Devel_PACKAGE_SUMMARY ${CPACK_COMPONENT_Devel_DESCRIPTION} )
857        set( CPACK_RPM_Devel_PACKAGE_ARCHITECTURE ${CPACK_RPM_PACKAGE_ARCHITECTURE} )
858        set( CPACK_RPM_Devel_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-devel" )
859        set( CPACK_RPM_Devel_FILE_NAME "RPM-DEFAULT" )
860
861        IF (CARES_BUILD_TOOLS)
862            set( CPACK_RPM_Tools_PACKAGE_REQUIRES "${CPACK_RPM_Library_PACKAGE_NAME} >= ${CPACK_PACKAGE_VERSION}" )
863            set( CPACK_RPM_Tools_PACKAGE_SUMMARY ${CPACK_COMPONENT_Tools_DESCRIPTION} )
864            set( CPACK_RPM_Tools_PACKAGE_ARCHITECTURE ${CPACK_RPM_PACKAGE_ARCHITECTURE} )
865            set( CPACK_RPM_Tools_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-tools" )
866            set( CPACK_RPM_Tools_FILE_NAME "RPM-DEFAULT" )
867        ENDIF ()
868
869
870        # DEB - https://cmake.org/cmake/help/latest/cpack_gen/deb.html
871        set( CPACK_DEBIAN_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE} )
872        set( CPACK_DEBIAN_PACKAGE_HOMEPAGE ${CPACK_PACKAGE_HOMEPAGE_URL} )
873        set( CPACK_DEB_COMPONENT_INSTALL 1 )
874        set( CPACK_DEBIAN_COMPRESSION_TYPE "xz")
875        set( CPACK_DEBIAN_PACKAGE_SHLIBDEPS 1 )
876
877        if ( ${CPACK_PACKAGE_ARCHITECTURE} STREQUAL "x86_64" )
878            set( CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64" )  # DEB doesn't always use the kernel's arch name
879        else()
880            set( CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CPACK_PACKAGE_ARCHITECTURE} )
881        endif()
882
883        set( CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT" ) # Use default naming scheme
884
885        set( CPACK_DEBIAN_LIBRARY_PACKAGE_NAME ${CPACK_RPM_Library_PACKAGE_NAME} )
886
887        set( CPACK_DEBIAN_DEVEL_PACKAGE_DEPENDS "cmake (>= ${CMAKE_MINIMUM_REQUIRED_VERSION}), ${CPACK_DEBIAN_LIBRARY_PACKAGE_NAME} (>= ${CPACK_PACKAGE_VERSION})" )
888        set( CPACK_DEBIAN_DEVEL_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-dev" )
889
890        IF (CARES_BUILD_TOOLS)
891            set( CPACK_DEBIAN_TOOLS_PACKAGE_NAME "${CPACK_PACKAGE_NAME}-tools" )
892            set( CPACK_DEBIAN_TOOLS_PACKAGE_SHLIBDEPS OFF ) # dpkg-shlibdeps can't find the libs we built
893            set( CPACK_DEBIAN_TOOLS_PACKAGE_DEPENDS "${CPACK_DEBIAN_LIBRARY_PACKAGE_NAME} (>= ${CPACK_PACKAGE_VERSION})" )
894        ENDIF ()
895
896    elseif( ${CMAKE_HOST_WIN32} )
897        set( CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON )
898        set( CPACK_NSIS_DISPLAY_NAME ${PROJECT_NAME} )
899        set( CPACK_NSIS_PACKAGE_NAME ${PROJECT_NAME} )
900        set( CPACK_NSIS_URL_INFO_ABOUT ${CPACK_PACKAGE_HOMEPAGE_URL} )
901    endif()
902
903    # This must always be last!
904    include( CPack )
905ENDIF ()
906