1 2add_library(glfw ${GLFW_LIBRARY_TYPE} 3 "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h" 4 "${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h" 5 internal.h platform.h mappings.h 6 context.c init.c input.c monitor.c platform.c vulkan.c window.c 7 egl_context.c osmesa_context.c null_platform.h null_joystick.h 8 null_init.c null_monitor.c null_window.c null_joystick.c) 9 10# The time, thread and module code is shared between all backends on a given OS, 11# including the null backend, which still needs those bits to be functional 12if (APPLE) 13 target_sources(glfw PRIVATE cocoa_time.h cocoa_time.c posix_thread.h 14 posix_module.c posix_thread.c) 15elseif (WIN32) 16 target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c 17 win32_time.c win32_thread.c) 18else() 19 target_sources(glfw PRIVATE posix_time.h posix_thread.h posix_module.c 20 posix_time.c posix_thread.c) 21endif() 22 23add_custom_target(update_mappings 24 COMMAND "${CMAKE_COMMAND}" -P "${GLFW_SOURCE_DIR}/CMake/GenerateMappings.cmake" mappings.h.in mappings.h 25 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 26 COMMENT "Updating gamepad mappings from upstream repository" 27 SOURCES mappings.h.in "${GLFW_SOURCE_DIR}/CMake/GenerateMappings.cmake" 28 VERBATIM) 29 30set_target_properties(update_mappings PROPERTIES FOLDER "GLFW3") 31 32if (GLFW_BUILD_COCOA) 33 target_compile_definitions(glfw PRIVATE _GLFW_COCOA) 34 target_sources(glfw PRIVATE cocoa_platform.h cocoa_joystick.h cocoa_init.m 35 cocoa_joystick.m cocoa_monitor.m cocoa_window.m 36 nsgl_context.m) 37endif() 38 39if (GLFW_BUILD_WIN32) 40 target_compile_definitions(glfw PRIVATE _GLFW_WIN32) 41 target_sources(glfw PRIVATE win32_platform.h win32_joystick.h win32_init.c 42 win32_joystick.c win32_monitor.c win32_window.c 43 wgl_context.c) 44endif() 45 46if (GLFW_BUILD_X11) 47 target_compile_definitions(glfw PRIVATE _GLFW_X11) 48 target_sources(glfw PRIVATE x11_platform.h xkb_unicode.h x11_init.c 49 x11_monitor.c x11_window.c xkb_unicode.c 50 glx_context.c) 51endif() 52 53if (GLFW_BUILD_WAYLAND) 54 target_compile_definitions(glfw PRIVATE _GLFW_WAYLAND) 55 target_sources(glfw PRIVATE wl_platform.h xkb_unicode.h wl_init.c 56 wl_monitor.c wl_window.c xkb_unicode.c) 57endif() 58 59if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND) 60 if (CMAKE_SYSTEM_NAME STREQUAL "Linux") 61 target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c) 62 endif() 63 target_sources(glfw PRIVATE posix_poll.h posix_poll.c) 64endif() 65 66if (GLFW_BUILD_WAYLAND) 67 include(CheckIncludeFiles) 68 include(CheckFunctionExists) 69 check_function_exists(memfd_create HAVE_MEMFD_CREATE) 70 if (HAVE_MEMFD_CREATE) 71 target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) 72 endif() 73 74 find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) 75 if (NOT WAYLAND_SCANNER_EXECUTABLE) 76 message(FATAL_ERROR "Failed to find wayland-scanner") 77 endif() 78 79 macro(generate_wayland_protocol protocol_file) 80 set(protocol_path "${GLFW_SOURCE_DIR}/deps/wayland/${protocol_file}") 81 82 string(REGEX REPLACE "\\.xml$" "-client-protocol.h" header_file ${protocol_file}) 83 string(REGEX REPLACE "\\.xml$" "-client-protocol-code.h" code_file ${protocol_file}) 84 85 add_custom_command(OUTPUT ${header_file} 86 COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" client-header "${protocol_path}" ${header_file} 87 DEPENDS "${protocol_path}" 88 VERBATIM) 89 90 add_custom_command(OUTPUT ${code_file} 91 COMMAND "${WAYLAND_SCANNER_EXECUTABLE}" private-code "${protocol_path}" ${code_file} 92 DEPENDS "${protocol_path}" 93 VERBATIM) 94 95 target_sources(glfw PRIVATE ${header_file} ${code_file}) 96 endmacro() 97 98 generate_wayland_protocol("wayland.xml") 99 generate_wayland_protocol("viewporter.xml") 100 generate_wayland_protocol("xdg-shell.xml") 101 generate_wayland_protocol("idle-inhibit-unstable-v1.xml") 102 generate_wayland_protocol("pointer-constraints-unstable-v1.xml") 103 generate_wayland_protocol("relative-pointer-unstable-v1.xml") 104 generate_wayland_protocol("fractional-scale-v1.xml") 105 generate_wayland_protocol("xdg-activation-v1.xml") 106 generate_wayland_protocol("xdg-decoration-unstable-v1.xml") 107endif() 108 109if (WIN32 AND GLFW_BUILD_SHARED_LIBRARY) 110 configure_file(glfw.rc.in glfw.rc @ONLY) 111 target_sources(glfw PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/glfw.rc") 112endif() 113 114if (UNIX AND GLFW_BUILD_SHARED_LIBRARY) 115 # On Unix-like systems, shared libraries can use the soname system. 116 set(GLFW_LIB_NAME glfw) 117else() 118 set(GLFW_LIB_NAME glfw3) 119endif() 120set(GLFW_LIB_NAME_SUFFIX "") 121 122set_target_properties(glfw PROPERTIES 123 OUTPUT_NAME ${GLFW_LIB_NAME} 124 VERSION ${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR} 125 SOVERSION ${GLFW_VERSION_MAJOR} 126 POSITION_INDEPENDENT_CODE ON 127 C_STANDARD 99 128 C_EXTENSIONS OFF 129 DEFINE_SYMBOL _GLFW_BUILD_DLL 130 FOLDER "GLFW3") 131 132target_include_directories(glfw PUBLIC 133 "$<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>" 134 "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>") 135target_include_directories(glfw PRIVATE 136 "${GLFW_SOURCE_DIR}/src" 137 "${GLFW_BINARY_DIR}/src") 138target_link_libraries(glfw PRIVATE Threads::Threads) 139 140# Workaround for CMake not knowing about .m files before version 3.16 141if (CMAKE_VERSION VERSION_LESS "3.16" AND APPLE) 142 set_source_files_properties(cocoa_init.m cocoa_joystick.m cocoa_monitor.m 143 cocoa_window.m nsgl_context.m PROPERTIES 144 LANGUAGE C) 145endif() 146 147if (GLFW_BUILD_WIN32) 148 list(APPEND glfw_PKG_LIBS "-lgdi32") 149endif() 150 151if (GLFW_BUILD_COCOA) 152 target_link_libraries(glfw PRIVATE "-framework Cocoa" 153 "-framework IOKit" 154 "-framework CoreFoundation" 155 "-framework QuartzCore") 156 157 set(glfw_PKG_DEPS "") 158 set(glfw_PKG_LIBS "-framework Cocoa -framework IOKit -framework CoreFoundation -framework QuartzCore") 159endif() 160 161if (GLFW_BUILD_WAYLAND) 162 include(FindPkgConfig) 163 164 pkg_check_modules(Wayland REQUIRED 165 wayland-client>=0.2.7 166 wayland-cursor>=0.2.7 167 wayland-egl>=0.2.7 168 xkbcommon>=0.5.0) 169 170 target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) 171 172 if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") 173 find_package(EpollShim) 174 if (EPOLLSHIM_FOUND) 175 target_include_directories(glfw PRIVATE ${EPOLLSHIM_INCLUDE_DIRS}) 176 target_link_libraries(glfw PRIVATE ${EPOLLSHIM_LIBRARIES}) 177 endif() 178 endif() 179endif() 180 181if (GLFW_BUILD_X11) 182 find_package(X11 REQUIRED) 183 target_include_directories(glfw PRIVATE "${X11_X11_INCLUDE_PATH}") 184 185 # Check for XRandR (modern resolution switching and gamma control) 186 if (NOT X11_Xrandr_INCLUDE_PATH) 187 message(FATAL_ERROR "RandR headers not found; install libxrandr development package") 188 endif() 189 target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}") 190 191 # Check for Xinerama (legacy multi-monitor support) 192 if (NOT X11_Xinerama_INCLUDE_PATH) 193 message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") 194 endif() 195 target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}") 196 197 # Check for Xkb (X keyboard extension) 198 if (NOT X11_Xkb_INCLUDE_PATH) 199 message(FATAL_ERROR "XKB headers not found; install X11 development package") 200 endif() 201 target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}") 202 203 # Check for Xcursor (cursor creation from RGBA images) 204 if (NOT X11_Xcursor_INCLUDE_PATH) 205 message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") 206 endif() 207 target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}") 208 209 # Check for XInput (modern HID input) 210 if (NOT X11_Xi_INCLUDE_PATH) 211 message(FATAL_ERROR "XInput headers not found; install libxi development package") 212 endif() 213 target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}") 214 215 # Check for X Shape (custom window input shape) 216 if (NOT X11_Xshape_INCLUDE_PATH) 217 message(FATAL_ERROR "X Shape headers not found; install libxext development package") 218 endif() 219 target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}") 220endif() 221 222if (UNIX AND NOT APPLE) 223 find_library(RT_LIBRARY rt) 224 mark_as_advanced(RT_LIBRARY) 225 if (RT_LIBRARY) 226 target_link_libraries(glfw PRIVATE "${RT_LIBRARY}") 227 list(APPEND glfw_PKG_LIBS "-lrt") 228 endif() 229 230 find_library(MATH_LIBRARY m) 231 mark_as_advanced(MATH_LIBRARY) 232 if (MATH_LIBRARY) 233 target_link_libraries(glfw PRIVATE "${MATH_LIBRARY}") 234 list(APPEND glfw_PKG_LIBS "-lm") 235 endif() 236 237 if (CMAKE_DL_LIBS) 238 target_link_libraries(glfw PRIVATE "${CMAKE_DL_LIBS}") 239 list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}") 240 endif() 241endif() 242 243if (WIN32) 244 if (GLFW_USE_HYBRID_HPG) 245 target_compile_definitions(glfw PRIVATE _GLFW_USE_HYBRID_HPG) 246 endif() 247endif() 248 249# Enable a reasonable set of warnings 250# NOTE: The order matters here, Clang-CL matches both MSVC and Clang 251if (MSVC) 252 target_compile_options(glfw PRIVATE "/W3") 253elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU" OR 254 CMAKE_C_COMPILER_ID STREQUAL "Clang" OR 255 CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 256 257 target_compile_options(glfw PRIVATE "-Wall") 258endif() 259 260if (GLFW_BUILD_WIN32) 261 target_compile_definitions(glfw PRIVATE UNICODE _UNICODE) 262endif() 263 264# HACK: When building on MinGW, WINVER and UNICODE need to be defined before 265# the inclusion of stddef.h (by glfw3.h), which is itself included before 266# win32_platform.h. We define them here until a saner solution can be found 267# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack. 268if (MINGW) 269 target_compile_definitions(glfw PRIVATE WINVER=0x0501) 270endif() 271 272# Workaround for legacy MinGW not providing XInput and DirectInput 273if (MINGW) 274 include(CheckIncludeFile) 275 check_include_file(dinput.h DINPUT_H_FOUND) 276 check_include_file(xinput.h XINPUT_H_FOUND) 277 if (NOT DINPUT_H_FOUND OR NOT XINPUT_H_FOUND) 278 target_include_directories(glfw PRIVATE "${GLFW_SOURCE_DIR}/deps/mingw") 279 endif() 280endif() 281 282# Workaround for the MS CRT deprecating parts of the standard library 283if (MSVC OR CMAKE_C_SIMULATE_ID STREQUAL "MSVC") 284 target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS) 285endif() 286 287# Workaround for -std=c99 on Linux disabling _DEFAULT_SOURCE (POSIX 2008 and more) 288if (CMAKE_SYSTEM_NAME STREQUAL "Linux") 289 target_compile_definitions(glfw PRIVATE _DEFAULT_SOURCE) 290endif() 291 292if (GLFW_BUILD_SHARED_LIBRARY) 293 if (WIN32) 294 if (MINGW) 295 # Remove the dependency on the shared version of libgcc 296 # NOTE: MinGW-w64 has the correct default but MinGW needs this 297 target_link_libraries(glfw PRIVATE "-static-libgcc") 298 299 # Remove the lib prefix on the DLL (but not the import library) 300 set_target_properties(glfw PROPERTIES PREFIX "") 301 302 # Add a suffix to the import library to avoid naming conflicts 303 set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.a") 304 else() 305 # Add a suffix to the import library to avoid naming conflicts 306 set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib") 307 endif() 308 set (GLFW_LIB_NAME_SUFFIX "dll") 309 310 target_compile_definitions(glfw INTERFACE GLFW_DLL) 311 endif() 312 313 if (MINGW) 314 # Enable link-time exploit mitigation features enabled by default on MSVC 315 include(CheckCCompilerFlag) 316 317 # Compatibility with data execution prevention (DEP) 318 set(CMAKE_REQUIRED_FLAGS "-Wl,--nxcompat") 319 check_c_compiler_flag("" _GLFW_HAS_DEP) 320 if (_GLFW_HAS_DEP) 321 target_link_libraries(glfw PRIVATE "-Wl,--nxcompat") 322 endif() 323 324 # Compatibility with address space layout randomization (ASLR) 325 set(CMAKE_REQUIRED_FLAGS "-Wl,--dynamicbase") 326 check_c_compiler_flag("" _GLFW_HAS_ASLR) 327 if (_GLFW_HAS_ASLR) 328 target_link_libraries(glfw PRIVATE "-Wl,--dynamicbase") 329 endif() 330 331 # Compatibility with 64-bit address space layout randomization (ASLR) 332 set(CMAKE_REQUIRED_FLAGS "-Wl,--high-entropy-va") 333 check_c_compiler_flag("" _GLFW_HAS_64ASLR) 334 if (_GLFW_HAS_64ASLR) 335 target_link_libraries(glfw PRIVATE "-Wl,--high-entropy-va") 336 endif() 337 338 # Clear flags again to avoid breaking later tests 339 set(CMAKE_REQUIRED_FLAGS) 340 endif() 341 342 if (UNIX) 343 # Hide symbols not explicitly tagged for export from the shared library 344 target_compile_options(glfw PRIVATE "-fvisibility=hidden") 345 endif() 346endif() 347 348foreach(arg ${glfw_PKG_DEPS}) 349 string(APPEND deps " ${arg}") 350endforeach() 351foreach(arg ${glfw_PKG_LIBS}) 352 string(APPEND libs " ${arg}") 353endforeach() 354 355set(GLFW_PKG_CONFIG_REQUIRES_PRIVATE "${deps}" CACHE INTERNAL 356 "GLFW pkg-config Requires.private") 357set(GLFW_PKG_CONFIG_LIBS_PRIVATE "${libs}" CACHE INTERNAL 358 "GLFW pkg-config Libs.private") 359 360configure_file("${GLFW_SOURCE_DIR}/CMake/glfw3.pc.in" glfw3.pc @ONLY) 361 362if (GLFW_INSTALL) 363 install(TARGETS glfw 364 EXPORT glfwTargets 365 RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 366 ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" 367 LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}") 368endif() 369 370