src: use LIBC_SO and LIBNSL_SO from GNU libc, if available
[nss_wrapper.git] / ConfigureChecks.cmake
1 include(CheckIncludeFile)
2 include(CheckSymbolExists)
3 include(CheckFunctionExists)
4 include(CheckLibraryExists)
5 include(CheckTypeSize)
6 include(CheckStructHasMember)
7 include(CheckPrototypeDefinition)
8 include(TestBigEndian)
9 include(CheckCSourceRuns)
10
11 set(PACKAGE ${PROJECT_NAME})
12 set(VERSION ${PROJECT_VERSION})
13 set(DATADIR ${DATA_INSTALL_DIR})
14 set(LIBDIR ${LIB_INSTALL_DIR})
15 set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
16 set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
17
18 set(BINARYDIR ${CMAKE_BINARY_DIR})
19 set(SOURCEDIR ${CMAKE_SOURCE_DIR})
20
21 function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
22     # Remove whitespaces from the argument.
23     # This is needed for CC="ccache gcc" cmake ..
24     string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
25
26     execute_process(
27         COMMAND
28             ${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
29         OUTPUT_VARIABLE _COMPILER_VERSION
30     )
31
32     string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
33            _COMPILER_VERSION "${_COMPILER_VERSION}")
34
35     set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
36 endfunction()
37
38 if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
39     compiler_dumpversion(GNUCC_VERSION)
40     if (NOT GNUCC_VERSION EQUAL 34)
41         set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
42         check_c_source_compiles(
43 "void __attribute__((visibility(\"default\"))) test() {}
44 int main(void){ return 0; }
45 " WITH_VISIBILITY_HIDDEN)
46         set(CMAKE_REQUIRED_FLAGS "")
47     endif (NOT GNUCC_VERSION EQUAL 34)
48 endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
49
50 # HEADERS
51 check_include_file(sys/types.h HAVE_SYS_TYPES_H)
52 check_include_file(pwd.h HAVE_PWD_H)
53 check_include_file(shadow.h HAVE_SHADOW_H)
54 check_include_file(grp.h HAVE_GRP_H)
55 check_include_file(nss.h HAVE_NSS_H)
56 check_include_file(nss_common.h HAVE_NSS_COMMON_H)
57 check_include_file(gnu/lib-names.h HAVE_GNU_LIB_NAMES_H)
58
59 # FUNCTIONS
60 check_function_exists(strncpy HAVE_STRNCPY)
61 check_function_exists(vsnprintf HAVE_VSNPRINTF)
62 check_function_exists(snprintf HAVE_SNPRINTF)
63
64 check_function_exists(getpwnam_r HAVE_GETPWNAM_R)
65 check_function_exists(getpwuid_r HAVE_GETPWUID_R)
66 check_function_exists(getpwent_r HAVE_GETPWENT_R)
67
68 check_function_exists(setspent HAVE_SETSPENT)
69 check_function_exists(getspnam HAVE_GETSPNAM)
70
71 check_function_exists(getgrnam_r HAVE_GETGRNAM_R)
72 check_function_exists(getgrgid_r HAVE_GETGRGID_R)
73 check_function_exists(getgrent_r HAVE_GETGRENT_R)
74
75 check_function_exists(getgrouplist HAVE_GETGROUPLIST)
76
77 check_function_exists(gethostbyaddr_r HAVE_GETHOSTBYADDR_R)
78 check_function_exists(gethostbyname_r HAVE_GETHOSTBYNAME_R)
79
80 check_function_exists(gethostbyname2 HAVE_GETHOSTBYNAME2)
81 check_function_exists(gethostbyname2_r HAVE_GETHOSTBYNAME2_R)
82
83 check_function_exists(getprogname HAVE_GETPROGNAME)
84 check_function_exists(getexecname HAVE_GETEXECNAME)
85
86 if (WIN32)
87     check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
88     check_function_exists(_vsnprintf HAVE__VSNPRINTF)
89     check_function_exists(_snprintf HAVE__SNPRINTF)
90     check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
91 endif (WIN32)
92
93 if (UNIX)
94     if (NOT LINUX)
95         # libsocket (Solaris)
96         check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
97         if (HAVE_LIBSOCKET)
98             list(APPEND _REQUIRED_LIBRARIES socket)
99         endif (HAVE_LIBSOCKET)
100
101         # libnsl/inet_pton (Solaris)
102         check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
103         if (HAVE_LIBNSL)
104             list(APPEND _REQUIRED_LIBRARIES nsl)
105         endif (HAVE_LIBNSL)
106     endif (NOT LINUX)
107
108     check_function_exists(getaddrinfo HAVE_GETADDRINFO)
109 endif (UNIX)
110
111 if (SOLARIS)
112     check_function_exists(__posix_getpwnam_r HAVE___POSIX_GETPWNAM_R)
113     check_function_exists(__posix_getpwuid_r HAVE___POSIX_GETPWUID_R)
114
115     check_function_exists(__posix_getgrgid_r HAVE___POSIX_GETGRGID_R)
116     check_function_exists(__posix_getgrnam_r HAVE___POSIX_GETGRNAM_R)
117 endif (SOLARIS)
118
119 check_function_exists(asprintf HAVE_ASPRINTF)
120 if (UNIX AND HAVE_ASPRINTF)
121     add_definitions(-D_GNU_SOURCE)
122 endif (UNIX AND HAVE_ASPRINTF)
123
124 set(CMAKE_REQUIRED_DEFINITIONS -D_POSIX_PTHREAD_SEMANTICS)
125 check_prototype_definition(getpwent_r
126     "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
127     "NULL"
128     "unistd.h;pwd.h"
129     HAVE_SOLARIS_GETPWENT_R)
130
131 check_prototype_definition(getpwnam_r
132     "int getpwnam_r(const char *name, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)"
133     "-1"
134     "unistd.h;pwd.h"
135     HAVE_SOLARIS_GETPWNAM_R)
136
137 check_prototype_definition(getpwuid_r
138     "int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, int buflen, struct passwd **ppwd)"
139     "-1"
140     "unistd.h;pwd.h"
141     HAVE_SOLARIS_GETPWUID_R)
142
143 check_prototype_definition(getgrent_r
144     "struct group *getgrent_r(struct group *src, char *buf, int buflen)"
145     "NULL"
146     "unistd.h;grp.h"
147     HAVE_SOLARIS_GETGRENT_R)
148
149 check_prototype_definition(getgrnam_r
150     "int getgrnam_r(const char *name, struct group *grp, char *buf, int buflen, struct group **pgrp)"
151     "-1"
152     "unistd.h;grp.h"
153     HAVE_SOLARIS_GETGRNAM_R)
154
155 check_prototype_definition(getgrgid_r
156     "int getgrgid_r(gid_t gid, struct group *grp, char *buf, int buflen, struct group **pgrp)"
157     "-1"
158     "unistd.h;grp.h"
159     HAVE_SOLARIS_GETGRGID_R)
160
161 check_prototype_definition(sethostent
162     "int sethostent(int stayopen)"
163     "-1"
164     "unistd.h;netdb.h"
165     HAVE_SOLARIS_SETHOSTENT)
166
167 check_prototype_definition(endhostent
168     "int endhostent(void)"
169     "-1"
170     "unistd.h;netdb.h"
171     HAVE_SOLARIS_ENDHOSTENT)
172
173 check_prototype_definition(gethostname
174     "int gethostname(char *name, int len)"
175     "-1"
176     "unistd.h;netdb.h"
177     HAVE_SOLARIS_GETHOSTNAME)
178 set(CMAKE_REQUIRED_DEFINITIONS)
179
180 check_prototype_definition(setgrent
181     "int setgrent(void)"
182     "-1"
183     "unistd.h;grp.h"
184     HAVE_BSD_SETGRENT)
185
186 check_prototype_definition(getnameinfo
187     "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, int flags)"
188     "-1"
189     "unistd.h;netdb.h"
190     HAVE_LINUX_GETNAMEINFO)
191
192 check_prototype_definition(getnameinfo
193     "int getnameinfo (const struct sockaddr *sa, socklen_t salen, char *host, socklen_t __hostlen, char *serv, socklen_t servlen, unsigned int flags)"
194     "-1"
195     "unistd.h;netdb.h"
196     HAVE_LINUX_GETNAMEINFO_UNSIGNED)
197
198 # STRUCT MEMBERS
199 check_struct_has_member("struct sockaddr" sa_len "sys/socket.h netinet/in.h" HAVE_STRUCT_SOCKADDR_SA_LEN)
200 check_struct_has_member("struct passwd" pw_class "pwd.h" HAVE_STRUCT_PASSWD_PW_CLASS)
201 check_struct_has_member("struct passwd" pw_change "pwd.h" HAVE_STRUCT_PASSWD_PW_CHANGE)
202 check_struct_has_member("struct passwd" pw_expire "pwd.h" HAVE_STRUCT_PASSWD_PW_EXPIRE)
203
204 # IPV6
205 check_c_source_compiles("
206     #include <stdlib.h>
207     #include <sys/socket.h>
208     #include <netdb.h>
209     #include <netinet/in.h>
210     #include <net/if.h>
211
212 int main(void) {
213     struct sockaddr_storage sa_store;
214     struct addrinfo *ai = NULL;
215     struct in6_addr in6addr;
216     int idx = if_nametoindex(\"iface1\");
217     int s = socket(AF_INET6, SOCK_STREAM, 0);
218     int ret = getaddrinfo(NULL, NULL, NULL, &ai);
219     if (ret != 0) {
220         const char *es = gai_strerror(ret);
221     }
222
223     freeaddrinfo(ai);
224     {
225         int val = 1;
226 #ifdef HAVE_LINUX_IPV6_V6ONLY_26
227 #define IPV6_V6ONLY 26
228 #endif
229         ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
230                          (const void *)&val, sizeof(val));
231     }
232
233     return 0;
234 }" HAVE_IPV6)
235
236 check_c_source_compiles("
237 void log_fn(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
238
239 int main(void) {
240     return 0;
241 }" HAVE_ATTRIBUTE_PRINTF_FORMAT)
242
243 check_c_source_compiles("
244 void test_constructor_attribute(void) __attribute__ ((constructor));
245
246 void test_constructor_attribute(void)
247 {
248      return;
249 }
250
251 int main(void) {
252      return 0;
253 }" HAVE_CONSTRUCTOR_ATTRIBUTE)
254
255 check_c_source_compiles("
256 void test_destructor_attribute(void) __attribute__ ((destructor));
257
258 void test_destructor_attribute(void)
259 {
260     return;
261 }
262
263 int main(void) {
264     return 0;
265 }" HAVE_DESTRUCTOR_ATTRIBUTE)
266
267 check_c_source_compiles("
268 #pragma init (test_constructor)
269 void test_constructor(void);
270
271 void test_constructor(void)
272 {
273      return;
274 }
275
276 int main(void) {
277      return 0;
278 }" HAVE_PRAGMA_INIT)
279
280 check_c_source_compiles("
281 #pragma fini (test_destructor)
282 void test_destructor(void);
283
284 void test_destructor(void)
285 {
286     return;
287 }
288
289 int main(void) {
290     return 0;
291 }" HAVE_PRAGMA_FINI)
292
293 find_library(DLFCN_LIBRARY dl)
294 if (DLFCN_LIBRARY)
295     list(APPEND _REQUIRED_LIBRARIES ${DLFCN_LIBRARY})
296 else()
297     check_function_exists(dlopen HAVE_DLOPEN)
298     if (NOT HAVE_DLOPEN)
299         message(FATAL_ERROR "FATAL: No dlopen() function detected")
300     endif()
301 endif()
302
303 # ENDIAN
304 if (NOT WIN32)
305     test_big_endian(WORDS_BIGENDIAN)
306 endif (NOT WIN32)
307
308 if (NOT CMAKE_CROSSCOMPILING)
309     # check whether getaddrinfo() returns "node" in "ai_canonname" for IP-addresses
310     check_c_source_runs("#include <stddef.h>
311     #include <string.h>
312     #include <sys/types.h>
313     #include <sys/socket.h>
314     #include <netdb.h>
315
316     int main(void) {
317         struct addrinfo hints;
318         struct addrinfo *res = NULL;
319
320         memset(&hints, 0, sizeof(struct addrinfo));
321         hints.ai_family = AF_INET;
322         hints.ai_socktype = SOCK_STREAM;
323         hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
324
325         if (getaddrinfo(\"0.0.0.0\", \"389\", &hints, &res) != 0) {
326             return 2;
327         }
328
329         if (res == NULL) {
330             return 3;
331         }
332
333         return strncmp(res->ai_canonname, \"0.0.0.0\", sizeof(\"0.0.0.0\")) != 0;
334     }" HAVE_GETADDRINFO_SETS_CANONNAME_FOR_IPADDRESSES)
335
336     # Check whether getaddrinfo() returns EAI_SERVICE when the requested
337     # service is not available for the requested socket type.
338     check_c_source_runs("#include <stddef.h>
339     #include <string.h>
340     #include <sys/types.h>
341     #include <sys/socket.h>
342     #include <netdb.h>
343
344     int main(void) {
345         struct addrinfo hints;
346         struct addrinfo *res = NULL;
347         int rc;
348
349         memset(&hints, 0, sizeof(struct addrinfo));
350         hints.ai_family = AF_UNSPEC;    /* Allow IPv4 or IPv6 */
351         hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
352         hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV;    /* For wildcard IP address */
353         hints.ai_protocol = 0;          /* Any protocol */
354         hints.ai_canonname = NULL;
355
356         rc = getaddrinfo(NULL, \"echo\", &hints, &res);
357         return rc != EAI_SERVICE;
358     }" HAVE_GETADDRINFO_USES_EAI_SERVICE)
359
360     # Check for non-NULL gethostent()
361     check_c_source_runs("#include <stddef.h>
362     #include <netdb.h>
363     int main(void) {
364         struct hostent *hostent = NULL;
365         sethostent(0);
366         hostent = gethostent();
367         endhostent();
368         return hostent == NULL;
369     }" HAVE_NONNULL_GETHOSTENT)
370 endif (NOT CMAKE_CROSSCOMPILING)
371
372 set(NWRAP_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "nss_wrapper required system libraries")