xref: /netbsd-src/external/bsd/libfido2/dist/CMakeLists.txt (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1# Copyright (c) 2018 Yubico AB. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file.
4
5# detect AppleClang; needs to come before project()
6cmake_policy(SET CMP0025 NEW)
7
8project(libfido2 C)
9cmake_minimum_required(VERSION 3.0)
10
11include(CheckCCompilerFlag)
12include(CheckFunctionExists)
13include(CheckIncludeFiles)
14include(CheckTypeSize)
15include(GNUInstallDirs)
16
17set(CMAKE_COLOR_MAKEFILE off)
18set(CMAKE_VERBOSE_MAKEFILE on)
19set(CMAKE_POSITION_INDEPENDENT_CODE ON)
20
21set(FIDO_MAJOR "1")
22set(FIDO_MINOR "3")
23set(FIDO_PATCH "1")
24set(FIDO_VERSION ${FIDO_MAJOR}.${FIDO_MINOR}.${FIDO_PATCH})
25
26add_definitions(-D_FIDO_MAJOR=${FIDO_MAJOR})
27add_definitions(-D_FIDO_MINOR=${FIDO_MINOR})
28add_definitions(-D_FIDO_PATCH=${FIDO_PATCH})
29
30if(CYGWIN OR MSYS)
31	set(WIN32 1)
32	add_definitions(-DWINVER=0x0a00)
33endif()
34
35if(WIN32)
36	add_definitions(-DWIN32_LEAN_AND_MEAN)
37endif()
38
39if(APPLE)
40	set(CMAKE_INSTALL_NAME_DIR
41		"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
42endif()
43
44# Observe OpenBSD's library versioning scheme.
45if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
46	set(LIB_VERSION ${FIDO_MAJOR}.${FIDO_MINOR})
47	set(LIB_SOVERSION ${LIB_VERSION})
48else()
49	set(LIB_VERSION ${FIDO_VERSION})
50	set(LIB_SOVERSION ${FIDO_MAJOR})
51endif()
52
53if(MSVC)
54	if((NOT CBOR_INCLUDE_DIRS) OR (NOT CBOR_LIBRARY_DIRS) OR
55	   (NOT CRYPTO_INCLUDE_DIRS) OR (NOT CRYPTO_LIBRARY_DIRS))
56		message(FATAL_ERROR "please provide definitions for "
57		    "{CBOR,CRYPTO}_{INCLUDE,LIBRARY}_DIRS when building "
58		    "under msvc")
59	endif()
60	set(CBOR_LIBRARIES cbor)
61	set(CRYPTO_LIBRARIES crypto-45)
62	set(MSVC_DISABLED_WARNINGS_LIST
63		"C4200" # nonstandard extension used: zero-sized array in
64			# struct/union;
65		"C4204" # nonstandard extension used: non-constant aggregate
66			# initializer;
67		"C4706" # assignment within conditional expression;
68		"C4996" # The POSIX name for this item is deprecated. Instead,
69			# use the ISO C and C++ conformant name
70		)
71	# The construction in the following 3 lines was taken from LibreSSL's
72	# CMakeLists.txt.
73	string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
74		${MSVC_DISABLED_WARNINGS_LIST})
75	string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
76	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 ${MSVC_DISABLED_WARNINGS_STR}")
77	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /Z7")
78	set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Zi")
79else()
80	include(FindPkgConfig)
81	pkg_search_module(CBOR libcbor)
82	pkg_search_module(CRYPTO libcrypto)
83
84	# XXX workaround libcbor's missing .pc file
85	if(NOT CBOR_FOUND)
86		check_include_files(cbor.h HAVE_CBOR_H)
87		if(NOT HAVE_CBOR_H)
88			message(FATAL_ERROR "could not find cbor header files")
89		endif()
90		set(CBOR_LIBRARIES "cbor")
91	endif()
92
93	# XXX workaround libcrypto's missing .pc file
94	if(NOT CRYPTO_FOUND)
95		check_include_files(openssl/opensslv.h HAVE_OPENSSLV_H)
96		if(NOT HAVE_OPENSSLV_H)
97			message(FATAL_ERROR "could not find crypto header files")
98		endif()
99		set(CRYPTO_LIBRARIES "crypto")
100	endif()
101
102	if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
103		pkg_search_module(UDEV libudev REQUIRED)
104		set(UDEV_NAME "udev")
105		# Define be32toh().
106		add_definitions(-D_GNU_SOURCE)
107		# If using hidapi, use hidapi-hidraw.
108		set(HIDAPI_SUFFIX -hidraw)
109	elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR
110	       CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
111		set(BASE_LIBRARIES usbhid)
112	endif()
113
114	if(MINGW)
115		# MinGW is stuck with a flavour of C89.
116		add_definitions(-DFIDO_NO_DIAGNOSTIC)
117		add_definitions(-DWC_ERR_INVALID_CHARS=0x80)
118		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-parameter")
119	endif()
120
121	if(USE_HIDAPI)
122		add_definitions(-DUSE_HIDAPI)
123		pkg_search_module(HIDAPI hidapi${HIDAPI_SUFFIX} REQUIRED)
124		if(HIDAPI_FOUND)
125			set(HIDAPI_LIBRARIES hidapi${HIDAPI_SUFFIX})
126		endif()
127	endif()
128
129	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
130	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wextra")
131	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
132	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshadow")
133	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wwrite-strings")
134	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes")
135	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wbad-function-cast")
136	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic")
137	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors")
138	check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
139	if(HAVE_STACK_PROTECTOR_ALL)
140		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-all")
141	endif()
142
143	add_definitions(-D_DEFAULT_SOURCE)
144	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
145
146	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g2")
147	set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer")
148
149	if(FUZZ)
150		if(LIBFUZZER)
151			set(FUZZ_LDFLAGS "-fsanitize=fuzzer")
152			set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
153		endif()
154		add_definitions(-DFIDO_FUZZ)
155	endif()
156
157	if(ASAN)
158		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,leak")
159	endif()
160
161	if(MSAN)
162		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory")
163		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-memory-track-origins")
164	endif()
165
166	if(UBSAN)
167		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
168		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize-trap=undefined")
169	endif()
170
171	if(COVERAGE)
172		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-instr-generate -fcoverage-mapping")
173	endif()
174endif()
175
176# Use -Wshorten-64-to-32 if available.
177check_c_compiler_flag("-Wshorten-64-to-32" HAVE_SHORTEN_64_TO_32)
178if(HAVE_SHORTEN_64_TO_32)
179	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wshorten-64-to-32")
180endif()
181
182# Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
183if(CMAKE_COMPILER_IS_GNUCC)
184	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-result")
185endif()
186
187# Decide which keyword to use for thread-local storage.
188if(CMAKE_COMPILER_IS_GNUCC OR
189   CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
190   CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
191	set(TLS "__thread")
192elseif(WIN32)
193	set(TLS "__declspec(thread)")
194endif()
195
196add_definitions(-DTLS=${TLS})
197
198# endian.h
199check_include_files(endian.h HAVE_ENDIAN_H)
200if(HAVE_ENDIAN_H)
201	add_definitions(-DHAVE_ENDIAN_H)
202endif()
203
204# err.h
205check_include_files(err.h HAVE_ERR_H)
206if(HAVE_ERR_H)
207	add_definitions(-DHAVE_ERR_H)
208endif()
209
210# unistd.h
211check_include_files(unistd.h HAVE_UNISTD_H)
212if(HAVE_UNISTD_H)
213	add_definitions(-DHAVE_UNISTD_H)
214endif()
215
216# signal.h
217check_include_files(signal.h HAVE_SIGNAL_H)
218if(HAVE_SIGNAL_H)
219	add_definitions(-DHAVE_SIGNAL_H)
220endif()
221
222# sys/random.h
223check_include_files(sys/random.h HAVE_SYS_RANDOM_H)
224if(HAVE_SYS_RANDOM_H)
225	add_definitions(-DHAVE_SYS_RANDOM_H)
226endif()
227
228# strlcpy
229check_function_exists(strlcpy HAVE_STRLCPY)
230if(HAVE_STRLCPY)
231	add_definitions(-DHAVE_STRLCPY)
232endif()
233
234# strlcat
235check_function_exists(strlcpy HAVE_STRLCAT)
236if(HAVE_STRLCAT)
237	add_definitions(-DHAVE_STRLCAT)
238endif()
239
240# recallocarray
241check_function_exists(recallocarray HAVE_RECALLOCARRAY)
242if(HAVE_RECALLOCARRAY)
243	add_definitions(-DHAVE_RECALLOCARRAY)
244endif()
245
246# XXX getpagesize is incorrectly detected when cross-compiling
247# with mingw on Linux. Avoid.
248if(NOT WIN32)
249	check_function_exists(getpagesize HAVE_GETPAGESIZE)
250endif()
251if(HAVE_GETPAGESIZE)
252	add_definitions(-DHAVE_GETPAGESIZE)
253endif()
254
255# sysconf
256check_function_exists(sysconf HAVE_SYSCONF)
257if(HAVE_SYSCONF)
258	add_definitions(-DHAVE_SYSCONF)
259endif()
260
261# memset_s
262if(APPLE)
263	add_definitions(-D__STDC_WANT_LIB_EXT1__=1)
264endif()
265check_function_exists(memset_s HAVE_MEMSET_S)
266if(HAVE_MEMSET_S)
267	add_definitions(-DHAVE_MEMSET_S)
268endif()
269
270# explicit_bzero
271if(NOT LIBFUZZER)
272	check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
273	if(HAVE_EXPLICIT_BZERO)
274		add_definitions(-DHAVE_EXPLICIT_BZERO)
275	endif()
276endif()
277
278# timingsafe_bcmp
279check_function_exists(timingsafe_bcmp HAVE_TIMINGSAFE_BCMP)
280if(HAVE_TIMINGSAFE_BCMP)
281	add_definitions(-DHAVE_TIMINGSAFE_BCMP)
282endif()
283
284# readpassphrase
285check_function_exists(readpassphrase HAVE_READPASSPHRASE)
286if(HAVE_READPASSPHRASE)
287	add_definitions(-DHAVE_READPASSPHRASE)
288endif()
289
290# getline
291check_function_exists(getline HAVE_GETLINE)
292if(HAVE_GETLINE)
293	add_definitions(-DHAVE_GETLINE)
294endif()
295
296# getopt
297check_function_exists(getopt HAVE_GETOPT)
298if(HAVE_GETOPT)
299	add_definitions(-DHAVE_GETOPT)
300	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wcast-qual")
301else()
302	if(CMAKE_COMPILER_IS_GNUCC)
303		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-discarded-qualifiers")
304	endif()
305	if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
306		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-incompatible-pointer-types-discards-qualifiers")
307	endif()
308endif()
309
310# usable sigaction
311set(CMAKE_EXTRA_INCLUDE_FILES signal.h)
312check_function_exists(sigaction HAVE_SIGACTION)
313check_type_size("sig_atomic_t" HAVE_SIG_ATOMIC_T)
314if(HAVE_SIGACTION AND (NOT HAVE_SIG_ATOMIC_T STREQUAL ""))
315	add_definitions(-DSIGNAL_EXAMPLE)
316endif()
317set(CMAKE_EXTRA_INCLUDE_FILES)
318
319# arc4random_buf
320check_function_exists(arc4random_buf HAVE_ARC4RANDOM_BUF)
321if(HAVE_ARC4RANDOM_BUF)
322	add_definitions(-DHAVE_ARC4RANDOM_BUF)
323endif()
324
325# getrandom
326check_function_exists(getrandom HAVE_GETRANDOM)
327if(HAVE_GETRANDOM)
328	add_definitions(-DHAVE_GETRANDOM)
329endif()
330
331# /dev/urandom
332if(UNIX)
333	add_definitions(-DHAVE_DEV_URANDOM)
334endif()
335
336# export list
337if(APPLE AND (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
338   CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
339	# clang + lld
340	string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
341	    " -exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/src/export.llvm")
342elseif(NOT MSVC)
343	# clang/gcc + gnu ld
344	if(FUZZ)
345		string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
346                    " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/fuzz/export.gnu")
347	else()
348		string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
349                    " -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/src/export.gnu")
350	endif()
351	if(NOT WIN32)
352		string(CONCAT CMAKE_SHARED_LINKER_FLAGS
353		    ${CMAKE_SHARED_LINKER_FLAGS}
354		    " -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
355		string(CONCAT CMAKE_EXE_LINKER_FLAGS
356		    ${CMAKE_EXE_LINKER_FLAGS}
357		    " -Wl,-z,noexecstack -Wl,-z,relro,-z,now")
358		if(FUZZ)
359			file(STRINGS fuzz/wrapped.sym WRAPPED_SYMBOLS)
360			foreach(s ${WRAPPED_SYMBOLS})
361				string(CONCAT CMAKE_SHARED_LINKER_FLAGS
362				    ${CMAKE_SHARED_LINKER_FLAGS}
363				    " -Wl,--wrap=${s}")
364			endforeach()
365		endif()
366	endif()
367else()
368	string(CONCAT CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}
369		" /def:\"${CMAKE_CURRENT_SOURCE_DIR}/src/export.msvc\"")
370endif()
371
372include_directories(${CMAKE_SOURCE_DIR}/src)
373include_directories(${CBOR_INCLUDE_DIRS})
374include_directories(${CRYPTO_INCLUDE_DIRS})
375
376link_directories(${CBOR_LIBRARY_DIRS})
377link_directories(${CRYPTO_LIBRARY_DIRS})
378
379message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
380message(STATUS "CMAKE_C_COMPILER_ID: ${CMAKE_C_COMPILER_ID}")
381message(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
382message(STATUS "CMAKE_INSTALL_LIBDIR: ${CMAKE_INSTALL_LIBDIR}")
383message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
384message(STATUS "CBOR_INCLUDE_DIRS: ${CBOR_INCLUDE_DIRS}")
385message(STATUS "CBOR_LIBRARY_DIRS: ${CBOR_LIBRARY_DIRS}")
386message(STATUS "CBOR_LIBRARIES: ${CBOR_LIBRARIES}")
387message(STATUS "CRYPTO_INCLUDE_DIRS: ${CRYPTO_INCLUDE_DIRS}")
388message(STATUS "CRYPTO_LIBRARY_DIRS: ${CRYPTO_LIBRARY_DIRS}")
389message(STATUS "CRYPTO_LIBRARIES: ${CRYPTO_LIBRARIES}")
390message(STATUS "BASE_LIBRARIES: ${BASE_LIBRARIES}")
391message(STATUS "HIDAPI_LIBRARIES: ${HIDAPI_LIBRARIES}")
392message(STATUS "VERSION: ${FIDO_VERSION}")
393message(STATUS "LIB_VERSION: ${LIB_VERSION}")
394message(STATUS "LIB_SOVERSION: ${LIB_SOVERSION}")
395message(STATUS "FUZZ: ${FUZZ}")
396message(STATUS "AFL: ${AFL}")
397message(STATUS "LIBFUZZER: ${LIBFUZZER}")
398message(STATUS "ASAN: ${ASAN}")
399message(STATUS "MSAN: ${MSAN}")
400message(STATUS "COVERAGE: ${COVERAGE}")
401message(STATUS "TLS: ${TLS}")
402message(STATUS "USE_HIDAPI: ${USE_HIDAPI}")
403
404if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
405	message(STATUS "UDEV_INCLUDE_DIRS: ${UDEV_INCLUDE_DIRS}")
406	message(STATUS "UDEV_LIBRARY_DIRS: ${UDEV_LIBRARY_DIRS}")
407	message(STATUS "UDEV_LIBRARIES: ${UDEV_LIBRARIES}")
408	message(STATUS "UDEV_RULES_DIR: ${UDEV_RULES_DIR}")
409endif()
410
411subdirs(src)
412subdirs(examples)
413subdirs(tools)
414subdirs(man)
415
416if(NOT WIN32)
417	if(CMAKE_BUILD_TYPE STREQUAL "Debug")
418		if(NOT MSAN AND NOT LIBFUZZER)
419			subdirs(regress)
420		endif()
421	endif()
422	if(FUZZ)
423		subdirs(fuzz)
424	endif()
425
426	if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
427		subdirs(udev)
428	endif()
429endif()
430