Properly check for functions in Win32 shared libs
[openal-soft.git] / CMakeLists.txt
blob97723be9a3a132ffebafd630e1253f3794b975aa
1 # CMake build file list for OpenAL
3 CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
5 IF(COMMAND CMAKE_POLICY)
6   CMAKE_POLICY(SET CMP0003 NEW)
7 ENDIF(COMMAND CMAKE_POLICY)
9 SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
11 INCLUDE(CheckFunctionExists)
12 INCLUDE(CheckLibraryExists)
13 INCLUDE(CheckSharedLibraryExists)
14 INCLUDE(CheckIncludeFile)
15 INCLUDE(CheckIncludeFiles)
16 INCLUDE(CheckSymbolExists)
17 INCLUDE(CheckCCompilerFlag)
18 INCLUDE(CheckCSourceCompiles)
19 INCLUDE(CheckTypeSize)
22 PROJECT(OpenAL C)
25 SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
28 OPTION(ALSA    "Check for ALSA backend"                ON)
29 OPTION(OSS     "Check for OSS backend"                 ON)
30 OPTION(SOLARIS "Check for Solaris backend"             ON)
31 OPTION(DSOUND  "Check for DirectSound backend"         ON)
32 OPTION(WINMM   "Check for Windows Multimedia backend"  ON)
33 OPTION(PORTAUDIO  "Check for PortAudio backend"        ON)
34 OPTION(PULSEAUDIO "Check for PulseAudio backend"       ON)
36 OPTION(DLOPEN  "Check for the dlopen API for loading optional libs"  ON)
38 OPTION(WERROR  "Treat compile warnings as errors"      OFF)
40 OPTION(EXAMPLES  "Build example programs"              ON)
42 OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF)
45 IF(WIN32)
46     SET(LIBNAME OpenAL32)
47     ADD_DEFINITIONS("-D_WIN32")
48 ELSE()
49     SET(LIBNAME openal)
50 ENDIF()
52 SET(LIB_MAJOR_VERSION "1")
53 SET(LIB_MINOR_VERSION "11")
54 SET(LIB_BUILD_VERSION "753")
55 SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_BUILD_VERSION}")
56 IF(NOT DEFINED LIB_INSTALL_DIR)
57   SET(LIB_INSTALL_DIR "lib${LIB_SUFFIX}")
58 ENDIF(NOT DEFINED LIB_INSTALL_DIR)
61 CHECK_TYPE_SIZE("long" SIZEOF_LONG)
62 CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
63 CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT)
64 CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP)
67 # Add definitions, compiler switches, etc.
68 INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}")
70 IF(NOT CMAKE_BUILD_TYPE)
71     SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
72         "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
73         FORCE)
74 ENDIF()
75 IF(NOT CMAKE_DEBUG_POSTFIX)
76     SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING
77         "Library postfix for debug builds. Normally left blank."
78         FORCE)
79 ENDIF()
81 IF(NOT DXSDK_DIR)
82     STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}")
83 ELSE()
84     STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "${DXSDK_DIR}")
85 ENDIF()
86 IF(DXSDK_DIR)
87     MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}")
88     SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${DXSDK_DIR}/Include")
89     INCLUDE_DIRECTORIES("${DXSDK_DIR}/Include")
90     LINK_DIRECTORIES("${DXSDK_DIR}/Lib")
91 ENDIF()
93 IF(MSVC)
94     # ???
95     SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEBUG")
96     SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
97     SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
98     SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
99     ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
100 ELSE()
101     ADD_DEFINITIONS(-Wall)
102     CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA)
103     IF(HAVE_W_EXTRA)
104         ADD_DEFINITIONS(-Wextra)
105     ENDIF()
107     IF(WERROR)
108         ADD_DEFINITIONS(-Werror)
109     ENDIF()
111     SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -funroll-loops -D_DEBUG" CACHE STRING
112         "Flags used by the compiler during Release with Debug Info builds."
113         FORCE)
114     SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING
115         "Flags used by the compiler during release minsize builds."
116         FORCE)
117     SET(CMAKE_C_FLAGS_RELEASE "-O2 -funroll-loops -fomit-frame-pointer -DNDEBUG" CACHE STRING
118         "Flags used by the compiler during release builds"
119         FORCE)
120     SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING
121         "Flags used by the compiler during debug builds."
122         FORCE)
124     # Set visibility options if available
125     IF(NOT WIN32)
126         CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
127                                  int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
129         CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_SWITCH)
130         IF(HAVE_VISIBILITY_SWITCH)
131             CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\")));
132                                      int main() {return 0;}" HAVE_GCC_VISIBILITY)
133             IF(HAVE_GCC_VISIBILITY)
134                 ADD_DEFINITIONS(-fvisibility=hidden -DHAVE_GCC_VISIBILITY)
135             ENDIF()
136         ENDIF()
137     ENDIF()
138 ENDIF()
140 CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2)));
141                          int main() {return 0;}" HAVE_GCC_FORMAT)
143 CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H)
144 CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H)
146 CHECK_LIBRARY_EXISTS(m  sqrtf  "" HAVE_SQRTF)
147 CHECK_LIBRARY_EXISTS(m  acosf  "" HAVE_ACOSF)
148 CHECK_LIBRARY_EXISTS(m  atanf  "" HAVE_ATANF)
149 CHECK_LIBRARY_EXISTS(m  fabsf  "" HAVE_FABSF)
150 IF(HAVE_FENV_H)
151     CHECK_LIBRARY_EXISTS(m  fesetround  "" HAVE_FESETROUND)
152 ENDIF()
153 IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND)
154     SET(EXTRA_LIBS m ${EXTRA_LIBS})
155 ENDIF()
156 CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
157 CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP)
159 CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
160 CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP)
161 IF(NOT HAVE_STRCASECMP)
162     CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP)
163     IF(NOT HAVE__STRICMP)
164         MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!")
165     ENDIF()
167     ADD_DEFINITIONS(-Dstrcasecmp=_stricmp)
168 ENDIF()
170 CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP)
171 IF(NOT HAVE_STRNCASECMP)
172     CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP)
173     IF(NOT HAVE__STRNICMP)
174         MESSAGE(FATAL_ERROR "No case-insensitive size-limitted compare function found, please report!")
175     ENDIF()
177     ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp)
178 ENDIF()
180 CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF)
181 IF(NOT HAVE_SNPRINTF)
182     CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF)
183     IF(NOT HAVE__SNPRINTF)
184         MESSAGE(FATAL_ERROR "No snprintf function found, please report!")
185     ENDIF()
187     ADD_DEFINITIONS(-Dsnprintf=_snprintf)
188 ENDIF()
190 CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF)
191 IF(NOT HAVE_VSNPRINTF)
192     CHECK_FUNCTION_EXISTS(_vsnprintf HAVE__VSNPRINTF)
193     IF(NOT HAVE__VSNPRINTF)
194         MESSAGE(FATAL_ERROR "No vsnprintf function found, please report!")
195     ENDIF()
197     ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf)
198 ENDIF()
200 CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN)
201 IF(NOT HAVE_ISNAN)
202     CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN)
203     IF(NOT HAVE__ISNAN)
204         MESSAGE(FATAL_ERROR "No isnan function found, please report!")
205     ENDIF()
207     ADD_DEFINITIONS(-Disnan=_isnan)
208 ENDIF()
211 # Check for the dlopen API (for dynamicly loading backend libs)
212 IF(DLOPEN)
213     CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H)
214     IF(HAVE_DLFCN_H)
215         CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL)
216         IF(HAVE_LIBDL)
217             SET(EXTRA_LIBS dl ${EXTRA_LIBS})
218         ENDIF()
219     ENDIF()
220 ENDIF()
222 # Check if we have Windows headers
223 CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500)
224 IF(NOT HAVE_WINDOWS_H)
225     CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY)
226     IF(NOT HAVE_GETTIMEOFDAY)
227         MESSAGE(FATAL_ERROR "No timing function found!")
228     ENDIF()
230     CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP)
231     IF(NOT HAVE_NANOSLEEP)
232         MESSAGE(FATAL_ERROR "No sleep function found!")
233     ENDIF()
235     CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD)
236     IF(HAVE_PTHREAD)
237         ADD_DEFINITIONS(-pthread)
238         SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread)
239     ENDIF()
241     # We need pthreads outside of Windows
242     CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H)
243     IF(NOT HAVE_PTHREAD_H)
244         MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!")
245     ENDIF()
246     # Some systems need pthread_np.h to get recursive mutexes
247     CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H)
249     # _GNU_SOURCE is needed on some systems for extra attributes, and
250     # _REENTRANT is needed for libc thread-safety
251     ADD_DEFINITIONS(-D_GNU_SOURCE=1)
252     CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD)
253     IF(HAVE_LIBPTHREAD)
254         SET(EXTRA_LIBS pthread ${EXTRA_LIBS})
255     ENDIF()
257     CHECK_LIBRARY_EXISTS(pthread pthread_setschedparam "" HAVE_PTHREAD_SETSCHEDPARAM)
259     CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT)
260     IF(HAVE_LIBRT)
261         SET(EXTRA_LIBS rt ${EXTRA_LIBS})
262     ENDIF()
263 ENDIF()
265 # Check for a 64-bit type
266 CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H)
267 IF(NOT HAVE_STDINT_H)
268     IF(HAVE_WINDOWS_H)
269         CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500
270                                  \#include <windows.h>
271                                  __int64 foo;
272                                  int main() {return 0;}" HAVE___INT64)
273     ENDIF()
274     IF(NOT HAVE___INT64)
275         IF(NOT SIZEOF_LONG MATCHES "8")
276             IF(NOT SIZEOF_LONG_LONG MATCHES "8")
277                 MESSAGE(FATAL_ERROR "No 64-bit types found, please report!")
278             ENDIF()
279         ENDIF()
280     ENDIF()
281 ENDIF()
284 SET(OPENAL_OBJS  OpenAL32/alAuxEffectSlot.c
285                  OpenAL32/alBuffer.c
286                  OpenAL32/alDatabuffer.c
287                  OpenAL32/alEffect.c
288                  OpenAL32/alError.c
289                  OpenAL32/alExtension.c
290                  OpenAL32/alFilter.c
291                  OpenAL32/alListener.c
292                  OpenAL32/alSource.c
293                  OpenAL32/alState.c
294                  OpenAL32/alThunk.c
296 SET(ALC_OBJS  Alc/ALc.c
297               Alc/ALu.c
298               Alc/alcConfig.c
299               Alc/alcEcho.c
300               Alc/alcReverb.c
301               Alc/alcRing.c
302               Alc/alcThread.c
303               Alc/bs2b.c
304               Alc/wave.c
307 SET(BACKENDS "")
309 # Check ALSA backend
310 IF(ALSA)
311     CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H)
312     IF(HAVE_ALSA_ASOUNDLIB_H)
313         CHECK_SHARED_LIBRARY_EXISTS(asound snd_pcm_open 4 "" HAVE_LIBASOUND)
314         IF(HAVE_DLFCN_H OR HAVE_LIBASOUND)
315             SET(HAVE_ALSA 1)
316             SET(ALC_OBJS  ${ALC_OBJS} Alc/alsa.c)
317             IF(HAVE_DLFCN_H)
318                 SET(BACKENDS  "${BACKENDS} ALSA,")
319             ELSE()
320                 SET(BACKENDS  "${BACKENDS} ALSA \(linked\),")
321                 SET(EXTRA_LIBS asound ${EXTRA_LIBS})
322             ENDIF()
323         ENDIF()
324     ENDIF()
325 ENDIF()
327 # Check OSS backend
328 IF(OSS)
329     CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H)
330     IF(HAVE_SYS_SOUNDCARD_H)
331         SET(HAVE_OSS 1)
332         SET(ALC_OBJS  ${ALC_OBJS} Alc/oss.c)
333         SET(BACKENDS  "${BACKENDS} OSS,")
334     ENDIF()
335 ENDIF()
337 # Check Solaris backend
338 IF(SOLARIS)
339     CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H)
340     IF(HAVE_SYS_AUDIOIO_H)
341         SET(HAVE_SOLARIS 1)
342         SET(ALC_OBJS  ${ALC_OBJS} Alc/solaris.c)
343         SET(BACKENDS  "${BACKENDS} Solaris,")
344     ENDIF()
345 ENDIF()
347 # Check DSound/MMSystem backend
348 IF(DSOUND)
349     CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H)
350     IF(HAVE_DSOUND_H)
351         CHECK_SHARED_LIBRARY_EXISTS(dsound DirectSoundCreate 3 "" HAVE_LIBDSOUND)
352         IF(HAVE_LIBDSOUND OR WIN32)
353             SET(HAVE_DSOUND 1)
354             SET(ALC_OBJS  ${ALC_OBJS} Alc/dsound.c)
356             IF(WIN32)
357                 SET(BACKENDS  "${BACKENDS} DirectSound,")
358             ELSE()
359                 SET(BACKENDS  "${BACKENDS} DirectSound \(linked\),")
360                 SET(EXTRA_LIBS dsound ${EXTRA_LIBS})
361             ENDIF()
362         ENDIF()
363     ENDIF()
364 ENDIF()
365 IF(HAVE_WINDOWS_H)
366     IF(WINMM)
367         CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500)
368         IF(HAVE_MMSYSTEM_H)
369             CHECK_SHARED_LIBRARY_EXISTS(winmm waveInOpen 6 "" HAVE_LIBWINMM)
370             IF(HAVE_LIBWINMM)
371                 SET(HAVE_WINMM 1)
372                 SET(ALC_OBJS  ${ALC_OBJS} Alc/winmm.c)
373                 SET(BACKENDS  "${BACKENDS} WinMM,")
375                 SET(EXTRA_LIBS winmm ${EXTRA_LIBS})
376             ENDIF()
377         ENDIF()
378     ENDIF()
379 ENDIF()
381 # Check PortAudio backend
382 IF(PORTAUDIO)
383     CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H)
384     IF(HAVE_PORTAUDIO_H)
385         CHECK_SHARED_LIBRARY_EXISTS(portaudio Pa_Initialize 0 "" HAVE_LIBPORTAUDIO)
386         IF(HAVE_LIBPORTAUDIO)
387             SET(HAVE_PORTAUDIO 1)
388             SET(ALC_OBJS  ${ALC_OBJS} Alc/portaudio.c)
389             IF(HAVE_DLFCN_H)
390                 SET(BACKENDS  "${BACKENDS} PortAudio,")
391             ELSE()
392                 SET(BACKENDS  "${BACKENDS} PortAudio \(linked\),")
393                 SET(EXTRA_LIBS portaudio ${EXTRA_LIBS})
394             ENDIF()
395         ENDIF()
396     ENDIF()
397 ENDIF()
399 # Check PortAudio backend
400 IF(PULSEAUDIO)
401     CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H)
402     IF(HAVE_PULSE_PULSEAUDIO_H)
403         CHECK_SHARED_LIBRARY_EXISTS(pulse pa_context_new 2 "" HAVE_LIBPULSE)
404         IF(HAVE_LIBPULSE)
405             SET(HAVE_PULSEAUDIO 1)
406             SET(ALC_OBJS  ${ALC_OBJS} Alc/pulseaudio.c)
407             IF(HAVE_DLFCN_H)
408                 SET(BACKENDS  "${BACKENDS} PulseAudio,")
409             ELSE()
410                 SET(BACKENDS  "${BACKENDS} PulseAudio \(linked\),")
411                 SET(EXTRA_LIBS pulse ${EXTRA_LIBS})
412             ENDIF()
413         ENDIF()
414     ENDIF()
415 ENDIF()
417 # This is always available
418 SET(BACKENDS  "${BACKENDS} WaveFile")
420 # Needed for openal.pc.in
421 SET(prefix ${CMAKE_INSTALL_PREFIX})
422 SET(exec_prefix "\${prefix}")
423 SET(libdir "\${exec_prefix}/${LIB_INSTALL_DIR}")
424 SET(bindir "\${exec_prefix}/bin")
425 SET(includedir "\${prefix}/include")
426 SET(PACKAGE_VERSION "${LIB_VERSION}")
428 # End configuration
429 CONFIGURE_FILE(
430     "${OpenAL_SOURCE_DIR}/config.h.in"
431     "${OpenAL_BINARY_DIR}/config.h")
432 CONFIGURE_FILE(
433     "${OpenAL_SOURCE_DIR}/openal.pc.in"
434     "${OpenAL_BINARY_DIR}/openal.pc"
435     @ONLY)
437 ADD_DEFINITIONS(-DAL_BUILD_LIBRARY)
439 # Build a library
440 IF(NOT LIBTYPE)
441     SET(LIBTYPE SHARED)
442 ENDIF()
443 ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS})
444 SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
445                                             SOVERSION ${LIB_MAJOR_VERSION})
446 IF(WIN32)
447     SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "")
448 ENDIF()
450 TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS})
452 # Add an install target here
453 INSTALL(TARGETS ${LIBNAME}
454         RUNTIME DESTINATION bin
455         LIBRARY DESTINATION ${LIB_INSTALL_DIR}
456         ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
458 INSTALL(FILES include/AL/al.h
459               include/AL/alc.h
460               include/AL/alext.h
461         DESTINATION include/AL
463 INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
464         DESTINATION "${LIB_INSTALL_DIR}/pkgconfig")
466 # Install alsoft.conf configuration file
467 IF(ALSOFT_CONFIG)
468     INSTALL(FILES alsoftrc.sample
469             DESTINATION /etc/openal
470             RENAME alsoft.conf
471     )
472 ENDIF()
474 IF(EXAMPLES)
475     ADD_EXECUTABLE(openal-info examples/openal-info.c)
476     TARGET_LINK_LIBRARIES(openal-info ${LIBNAME})
477     INSTALL(TARGETS openal-info
478             RUNTIME DESTINATION bin
479             LIBRARY DESTINATION ${LIB_INSTALL_DIR}
480             ARCHIVE DESTINATION ${LIB_INSTALL_DIR}
481     )
482 ENDIF()
484 MESSAGE(STATUS "")
485 MESSAGE(STATUS "Building OpenAL with support for the following backends:")
486 MESSAGE(STATUS "    ${BACKENDS}")
487 MESSAGE(STATUS "")
489 IF(WIN32)
490     IF(NOT HAVE_DSOUND)
491         MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output")
492         MESSAGE(STATUS "         This is probably NOT what you want!")
493         MESSAGE(STATUS "")
494     ENDIF()
495 ENDIF()