CMakeLists.txt 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. # CMAKE REFERENCE
  2. # intro: https://codingnest.com/basic-cmake/
  3. # best practices (3.0+): https://gist.github.com/mbinna/c61dbb39bca0e4fb7d1f73b0d66a4fd1
  4. # Version should match the tested CMAKE_URL in .github/workflows/ci.yml.
  5. cmake_minimum_required(VERSION 3.10)
  6. project(nvim C)
  7. if(POLICY CMP0065)
  8. cmake_policy(SET CMP0065 NEW)
  9. endif()
  10. if(POLICY CMP0060)
  11. cmake_policy(SET CMP0060 NEW)
  12. endif()
  13. if(POLICY CMP0075)
  14. cmake_policy(SET CMP0075 NEW)
  15. endif()
  16. # Point CMake at any custom modules we may ship
  17. list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
  18. # We don't support building in-tree.
  19. include(PreventInTreeBuilds)
  20. set_property(GLOBAL PROPERTY USE_FOLDERS ON)
  21. # Prefer our bundled versions of dependencies.
  22. if(DEFINED ENV{DEPS_BUILD_DIR})
  23. if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
  24. # pkg-config 29.2 has a bug on OpenBSD which causes it to drop any paths that
  25. # *contain* system include paths. To avoid this, we prefix what would be
  26. # "/usr/include" as "/_usr/include".
  27. # This check is also performed in the third-party/CMakeLists.txt and in the
  28. # else clause following here.
  29. # https://github.com/neovim/neovim/pull/14745#issuecomment-860201794
  30. set(DEPS_PREFIX "$ENV{DEPS_BUILD_DIR}/_usr" CACHE PATH "Path prefix for finding dependencies")
  31. else()
  32. set(DEPS_PREFIX "$ENV{DEPS_BUILD_DIR}/usr" CACHE PATH "Path prefix for finding dependencies")
  33. endif()
  34. else()
  35. if(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
  36. set(DEPS_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/.deps/_usr" CACHE PATH "Path prefix for finding dependencies")
  37. else()
  38. set(DEPS_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/.deps/usr" CACHE PATH "Path prefix for finding dependencies")
  39. endif()
  40. # When running from within CLion or Visual Studio,
  41. # build bundled dependencies automatically.
  42. if(NOT EXISTS ${DEPS_PREFIX}
  43. AND (DEFINED ENV{CLION_IDE}
  44. OR DEFINED ENV{VisualStudioEdition}))
  45. message(STATUS "Building dependencies...")
  46. set(DEPS_BUILD_DIR ${PROJECT_BINARY_DIR}/.deps)
  47. file(MAKE_DIRECTORY ${DEPS_BUILD_DIR})
  48. execute_process(
  49. COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR}
  50. -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}
  51. -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
  52. -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
  53. -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
  54. -DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
  55. -DCMAKE_C_FLAGS_MINSIZEREL=${CMAKE_C_FLAGS_MINSIZEREL}
  56. -DCMAKE_C_FLAGS_RELWITHDEBINFO=${CMAKE_C_FLAGS_RELWITHDEBINFO}
  57. -DCMAKE_C_FLAGS_RELEASE=${CMAKE_C_FLAGS_RELEASE}
  58. -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
  59. ${PROJECT_SOURCE_DIR}/third-party
  60. WORKING_DIRECTORY ${DEPS_BUILD_DIR})
  61. execute_process(
  62. COMMAND ${CMAKE_COMMAND} --build ${DEPS_BUILD_DIR}
  63. --config ${CMAKE_BUILD_TYPE})
  64. set(DEPS_PREFIX ${DEPS_BUILD_DIR}/usr)
  65. endif()
  66. endif()
  67. list(INSERT CMAKE_PREFIX_PATH 0 ${DEPS_PREFIX})
  68. set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${DEPS_PREFIX}/lib/pkgconfig")
  69. # used for check_c_compiler_flag
  70. include(CheckCCompilerFlag)
  71. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  72. # CMake tries to treat /sw and /opt/local as extension of the system path, but
  73. # that doesn't really work out very well. Once you have a dependency that
  74. # resides there and have to add it as an include directory, then any other
  75. # dependency that could be satisfied from there must be--otherwise you can end
  76. # up with conflicting versions. So, let's make them more of a priority having
  77. # them be included as one of the first places to look for dependencies.
  78. list(APPEND CMAKE_PREFIX_PATH /sw /opt/local)
  79. # If the macOS deployment target is not set manually (via $MACOSX_DEPLOYMENT_TARGET),
  80. # fall back to local system version. Needs to be done both here and in cmake.deps.
  81. if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
  82. execute_process(COMMAND sw_vers -productVersion
  83. OUTPUT_VARIABLE MACOS_VERSION
  84. OUTPUT_STRIP_TRAILING_WHITESPACE)
  85. set(CMAKE_OSX_DEPLOYMENT_TARGET "${MACOS_VERSION}")
  86. endif()
  87. message("Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}")
  88. # Work around some old, broken detection by CMake for knowing when to use the
  89. # isystem flag. Apple's compilers have supported this for quite some time
  90. # now.
  91. if(CMAKE_COMPILER_IS_GNUCC)
  92. set(CMAKE_INCLUDE_SYSTEM_FLAG_C "-isystem ")
  93. endif()
  94. endif()
  95. if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  96. # Ignore case when comparing filenames on Windows and Mac.
  97. set(CASE_INSENSITIVE_FILENAME TRUE)
  98. # Enable fixing case-insensitive filenames for Windows and Mac.
  99. set(USE_FNAME_CASE TRUE)
  100. endif()
  101. option(ENABLE_LIBINTL "enable libintl" ON)
  102. option(ENABLE_LIBICONV "enable libiconv" ON)
  103. if (MINGW)
  104. # Disable LTO by default as it may not compile
  105. # See https://github.com/Alexpux/MINGW-packages/issues/3516
  106. # and https://github.com/neovim/neovim/pull/8654#issuecomment-402316672
  107. option(ENABLE_LTO "enable link time optimization" OFF)
  108. else()
  109. option(ENABLE_LTO "enable link time optimization" ON)
  110. endif()
  111. message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
  112. # Build type.
  113. if(NOT CMAKE_BUILD_TYPE)
  114. message(STATUS "CMAKE_BUILD_TYPE not specified, default is 'Debug'")
  115. set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build" FORCE)
  116. else()
  117. message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
  118. endif()
  119. if(CMAKE_BUILD_TYPE MATCHES Debug)
  120. set(DEBUG 1)
  121. else()
  122. set(DEBUG 0)
  123. endif()
  124. # Set available build types for CMake GUIs.
  125. # Other build types can still be set by -DCMAKE_BUILD_TYPE=...
  126. set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
  127. STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
  128. # If not in a git repo (e.g., a tarball) these tokens define the complete
  129. # version string, else they are combined with the result of `git describe`.
  130. set(NVIM_VERSION_MAJOR 0)
  131. set(NVIM_VERSION_MINOR 7)
  132. set(NVIM_VERSION_PATCH 3)
  133. set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
  134. # API level
  135. set(NVIM_API_LEVEL 9) # Bump this after any API change.
  136. set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
  137. set(NVIM_API_PRERELEASE false)
  138. set(NVIM_VERSION_BUILD_TYPE "${CMAKE_BUILD_TYPE}")
  139. # NVIM_VERSION_CFLAGS set further below.
  140. set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
  141. # Log level (MIN_LOG_LEVEL in log.h)
  142. if("${MIN_LOG_LEVEL}" MATCHES "^$")
  143. # Minimize logging for release-type builds.
  144. if(CMAKE_BUILD_TYPE STREQUAL "Release"
  145. OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo"
  146. OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")
  147. message(STATUS "MIN_LOG_LEVEL not specified, default is 3 (ERROR) for release builds")
  148. set(MIN_LOG_LEVEL 3)
  149. else()
  150. message(STATUS "MIN_LOG_LEVEL not specified, default is 1 (INFO)")
  151. set(MIN_LOG_LEVEL 1)
  152. endif()
  153. else()
  154. if(NOT MIN_LOG_LEVEL MATCHES "^[0-3]$")
  155. message(FATAL_ERROR "invalid MIN_LOG_LEVEL: " ${MIN_LOG_LEVEL})
  156. endif()
  157. message(STATUS "MIN_LOG_LEVEL=${MIN_LOG_LEVEL}")
  158. endif()
  159. # Default to -O2 on release builds.
  160. if(CMAKE_C_FLAGS_RELEASE MATCHES "-O3")
  161. message(STATUS "Replacing -O3 in CMAKE_C_FLAGS_RELEASE with -O2")
  162. string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
  163. endif()
  164. if(CMAKE_COMPILER_IS_GNUCC)
  165. check_c_compiler_flag(-Og HAS_OG_FLAG)
  166. else()
  167. set(HAS_OG_FLAG 0)
  168. endif()
  169. #
  170. # Build-type: RelWithDebInfo
  171. #
  172. if(HAS_OG_FLAG)
  173. set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -Og -g")
  174. endif()
  175. # We _want_ assertions in RelWithDebInfo build-type.
  176. if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG)
  177. string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
  178. endif()
  179. # gcc 4.0+ sets _FORTIFY_SOURCE=2 automatically. This currently
  180. # does not work with Neovim due to some uses of dynamically-sized structures.
  181. # https://github.com/neovim/neovim/issues/223
  182. include(CheckCSourceCompiles)
  183. # Include the build type's default flags in the check for _FORTIFY_SOURCE,
  184. # otherwise we may incorrectly identify the level as acceptable and find out
  185. # later that it was not when optimizations were enabled. CFLAGS is applied
  186. # even though you don't see it in CMAKE_REQUIRED_FLAGS.
  187. set(INIT_FLAGS_NAME CMAKE_C_FLAGS_${CMAKE_BUILD_TYPE})
  188. string(TOUPPER ${INIT_FLAGS_NAME} INIT_FLAGS_NAME)
  189. if(${INIT_FLAGS_NAME})
  190. set(CMAKE_REQUIRED_FLAGS "${${INIT_FLAGS_NAME}}")
  191. endif()
  192. # Include <string.h> because some toolchains define _FORTIFY_SOURCE=2 in
  193. # internal header files, which should in turn be #included by <string.h>.
  194. check_c_source_compiles("
  195. #include <string.h>
  196. #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1
  197. #error \"_FORTIFY_SOURCE > 1\"
  198. #endif
  199. int
  200. main(void)
  201. {
  202. return 0;
  203. }
  204. " HAS_ACCEPTABLE_FORTIFY)
  205. if(NOT HAS_ACCEPTABLE_FORTIFY)
  206. message(STATUS "Unsupported _FORTIFY_SOURCE found, forcing _FORTIFY_SOURCE=1")
  207. # Extract possible prefix to _FORTIFY_SOURCE (e.g. -Wp,-D_FORTIFY_SOURCE).
  208. STRING(REGEX MATCH "[^\ ]+-D_FORTIFY_SOURCE" _FORTIFY_SOURCE_PREFIX "${CMAKE_C_FLAGS}")
  209. STRING(REPLACE "-D_FORTIFY_SOURCE" "" _FORTIFY_SOURCE_PREFIX "${_FORTIFY_SOURCE_PREFIX}" )
  210. if(NOT _FORTIFY_SOURCE_PREFIX STREQUAL "")
  211. message(STATUS "Detected _FORTIFY_SOURCE Prefix=${_FORTIFY_SOURCE_PREFIX}")
  212. endif()
  213. # -U in add_definitions doesn't end up in the correct spot, so we add it to
  214. # the flags variable instead.
  215. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FORTIFY_SOURCE_PREFIX}-U_FORTIFY_SOURCE ${_FORTIFY_SOURCE_PREFIX}-D_FORTIFY_SOURCE=1")
  216. endif()
  217. # Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374).
  218. # TODO: Figure out the root cause.
  219. if(CMAKE_EXE_LINKER_FLAGS MATCHES "--sort-common" OR
  220. CMAKE_SHARED_LINKER_FLAGS MATCHES "--sort-common" OR
  221. CMAKE_MODULE_LINKER_FLAGS MATCHES "--sort-common")
  222. message(STATUS "Removing --sort-common from linker flags")
  223. string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
  224. string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
  225. string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
  226. # If no linker flags remain for a -Wl argument, remove it.
  227. # '-Wl$' will match LDFLAGS="-Wl,--sort-common",
  228. # '-Wl ' will match LDFLAGS="-Wl,--sort-common -Wl,..."
  229. string(REGEX REPLACE "-Wl($| )" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
  230. string(REGEX REPLACE "-Wl($| )" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
  231. string(REGEX REPLACE "-Wl($| )" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
  232. endif()
  233. check_c_source_compiles("
  234. #include <execinfo.h>
  235. int main(void)
  236. {
  237. void *trace[1];
  238. backtrace(trace, 1);
  239. return 0;
  240. }
  241. " HAVE_EXECINFO_BACKTRACE)
  242. check_c_source_compiles("
  243. int main(void)
  244. {
  245. int a = 42;
  246. __builtin_add_overflow(a, a, &a);
  247. __builtin_sub_overflow(a, a, &a);
  248. return 0;
  249. }
  250. " HAVE_BUILTIN_ADD_OVERFLOW)
  251. option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF)
  252. if(MSVC)
  253. # XXX: /W4 gives too many warnings. #3241
  254. add_compile_options(/W3)
  255. add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
  256. add_definitions(-DWIN32)
  257. else()
  258. add_compile_options(-Wall -Wextra -pedantic -Wno-unused-parameter
  259. -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion
  260. -Wdouble-promotion
  261. -Wmissing-noreturn
  262. -Wmissing-format-attribute
  263. -Wmissing-prototypes)
  264. check_c_compiler_flag(-Wimplicit-fallthrough HAVE_WIMPLICIT_FALLTHROUGH_FLAG)
  265. if(HAVE_WIMPLICIT_FALLTHROUGH_FLAG)
  266. add_compile_options(-Wimplicit-fallthrough)
  267. endif()
  268. if(ENABLE_COMPILER_SUGGESTIONS)
  269. # Clang doesn't have -Wsuggest-attribute so check for each one.
  270. check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE)
  271. if(HAVE_WSUGGEST_ATTRIBUTE_PURE)
  272. add_compile_options(-Wsuggest-attribute=pure)
  273. endif()
  274. check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST)
  275. if(HAVE_WSUGGEST_ATTRIBUTE_CONST)
  276. add_compile_options(-Wsuggest-attribute=const)
  277. endif()
  278. check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC)
  279. if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC)
  280. add_compile_options(-Wsuggest-attribute=malloc)
  281. endif()
  282. check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD)
  283. if(HAVE_WSUGGEST_ATTRIBUTE_COLD)
  284. add_compile_options(-Wsuggest-attribute=cold)
  285. endif()
  286. endif()
  287. # On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang
  288. # 3.4.1 used there.
  289. if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND CMAKE_C_COMPILER_ID MATCHES "Clang")
  290. add_compile_options(-Wno-c11-extensions)
  291. endif()
  292. endif()
  293. if(MINGW)
  294. # Use POSIX compatible stdio in Mingw
  295. add_definitions(-D__USE_MINGW_ANSI_STDIO)
  296. endif()
  297. if(WIN32)
  298. # Windows Vista is the minimum supported version
  299. add_definitions(-D_WIN32_WINNT=0x0600)
  300. endif()
  301. # OpenBSD's GCC (4.2.1) doesn't have -Wvla
  302. check_c_compiler_flag(-Wvla HAS_WVLA_FLAG)
  303. if(HAS_WVLA_FLAG)
  304. add_compile_options(-Wvla)
  305. endif()
  306. if(UNIX)
  307. # -fstack-protector breaks non Unix builds even in Mingw-w64
  308. check_c_compiler_flag(-fstack-protector-strong HAS_FSTACK_PROTECTOR_STRONG_FLAG)
  309. check_c_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR_FLAG)
  310. if(HAS_FSTACK_PROTECTOR_STRONG_FLAG)
  311. add_compile_options(-fstack-protector-strong)
  312. link_libraries(-fstack-protector-strong)
  313. elseif(HAS_FSTACK_PROTECTOR_FLAG)
  314. add_compile_options(-fstack-protector --param ssp-buffer-size=4)
  315. link_libraries(-fstack-protector --param ssp-buffer-size=4)
  316. endif()
  317. endif()
  318. check_c_compiler_flag(-fno-common HAVE_FNO_COMMON)
  319. if (HAVE_FNO_COMMON)
  320. add_compile_options(-fno-common)
  321. endif()
  322. check_c_compiler_flag(-fdiagnostics-color=auto HAS_DIAG_COLOR_FLAG)
  323. if(HAS_DIAG_COLOR_FLAG)
  324. if(CMAKE_GENERATOR MATCHES "Ninja")
  325. add_compile_options(-fdiagnostics-color=always)
  326. else()
  327. add_compile_options(-fdiagnostics-color=auto)
  328. endif()
  329. endif()
  330. option(CI_BUILD "CI, extra flags will be set" OFF)
  331. if(CI_BUILD)
  332. message(STATUS "CI build enabled")
  333. add_compile_options(-Werror)
  334. if(DEFINED ENV{BUILD_32BIT})
  335. # Get some test coverage for unsigned char
  336. add_compile_options(-funsigned-char)
  337. endif()
  338. endif()
  339. option(LOG_LIST_ACTIONS "Add list actions logging" OFF)
  340. add_definitions(-DINCLUDE_GENERATED_DECLARATIONS)
  341. if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
  342. if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
  343. set(NO_UNDEFINED "-Wl,--no-undefined -lsocket")
  344. elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin")
  345. set(NO_UNDEFINED "-Wl,--no-undefined")
  346. endif()
  347. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${NO_UNDEFINED}")
  348. set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${NO_UNDEFINED}")
  349. # For O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags on older systems
  350. # (pre POSIX.1-2008: glibc 2.11 and earlier). #4042
  351. # For ptsname(). #6743
  352. add_definitions(-D_GNU_SOURCE)
  353. endif()
  354. if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT PREFER_LUA AND LUAJIT_VERSION LESS "2.1.0-beta3")
  355. # Required for luajit < 2.1.0-beta3.
  356. set(CMAKE_EXE_LINKER_FLAGS
  357. "${CMAKE_EXE_LINKER_FLAGS} -pagezero_size 10000 -image_base 100000000")
  358. set(CMAKE_SHARED_LINKER_FLAGS
  359. "${CMAKE_SHARED_LINKER_FLAGS} -image_base 100000000")
  360. set(CMAKE_MODULE_LINKER_FLAGS
  361. "${CMAKE_MODULE_LINKER_FLAGS} -image_base 100000000")
  362. endif()
  363. include_directories("${PROJECT_BINARY_DIR}/config")
  364. include_directories("${PROJECT_SOURCE_DIR}/src")
  365. find_package(LibUV 1.28.0 REQUIRED)
  366. include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
  367. find_package(Msgpack 1.0.0 REQUIRED)
  368. include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
  369. find_package(LibLUV 1.43.0 REQUIRED)
  370. include_directories(SYSTEM ${LIBLUV_INCLUDE_DIRS})
  371. find_package(TreeSitter REQUIRED)
  372. include_directories(SYSTEM ${TreeSitter_INCLUDE_DIRS})
  373. list(APPEND CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}")
  374. list(APPEND CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}")
  375. check_c_source_compiles("
  376. #include <tree_sitter/api.h>
  377. int
  378. main(void)
  379. {
  380. TSQueryCursor *cursor = ts_query_cursor_new();
  381. ts_query_cursor_set_match_limit(cursor, 32);
  382. return 0;
  383. }
  384. " TS_HAS_SET_MATCH_LIMIT)
  385. if(TS_HAS_SET_MATCH_LIMIT)
  386. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_MATCH_LIMIT")
  387. endif()
  388. check_c_source_compiles("
  389. #include <stdlib.h>
  390. #include <tree_sitter/api.h>
  391. int
  392. main(void)
  393. {
  394. ts_set_allocator(malloc, calloc, realloc, free);
  395. return 0;
  396. }
  397. " TS_HAS_SET_ALLOCATOR)
  398. if(TS_HAS_SET_ALLOCATOR)
  399. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_ALLOCATOR")
  400. endif()
  401. # Note: The test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
  402. option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
  403. if(PREFER_LUA)
  404. find_package(Lua 5.1 REQUIRED)
  405. set(LUA_PREFERRED_INCLUDE_DIRS ${LUA_INCLUDE_DIR})
  406. set(LUA_PREFERRED_LIBRARIES ${LUA_LIBRARIES})
  407. # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped.
  408. find_package(LuaJit)
  409. else()
  410. find_package(LuaJit REQUIRED)
  411. set(LUA_PREFERRED_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIRS})
  412. set(LUA_PREFERRED_LIBRARIES ${LUAJIT_LIBRARIES})
  413. endif()
  414. list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}")
  415. check_c_source_compiles("
  416. #include <msgpack.h>
  417. int
  418. main(void)
  419. {
  420. return MSGPACK_OBJECT_FLOAT32;
  421. }
  422. " MSGPACK_HAS_FLOAT32)
  423. list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}")
  424. if(MSGPACK_HAS_FLOAT32)
  425. add_definitions(-DNVIM_MSGPACK_HAS_FLOAT32)
  426. endif()
  427. option(FEAT_TUI "Enable the Terminal UI" ON)
  428. if(FEAT_TUI)
  429. find_package(UNIBILIUM 2.0 REQUIRED)
  430. include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
  431. list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
  432. list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
  433. check_c_source_compiles("
  434. #include <unibilium.h>
  435. int
  436. main(void)
  437. {
  438. return unibi_num_from_var(unibi_var_from_num(0));
  439. }
  440. " UNIBI_HAS_VAR_FROM)
  441. list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}")
  442. list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}")
  443. if(UNIBI_HAS_VAR_FROM)
  444. add_definitions(-DNVIM_UNIBI_HAS_VAR_FROM)
  445. endif()
  446. find_package(LibTermkey 0.18 REQUIRED)
  447. include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS})
  448. endif()
  449. find_package(LIBVTERM 0.1 REQUIRED)
  450. include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS})
  451. if(WIN32)
  452. find_package(Winpty 0.4.3 REQUIRED)
  453. include_directories(SYSTEM ${WINPTY_INCLUDE_DIRS})
  454. endif()
  455. option(CLANG_ASAN_UBSAN "Enable Clang address & undefined behavior sanitizer for nvim binary." OFF)
  456. option(CLANG_MSAN "Enable Clang memory sanitizer for nvim binary." OFF)
  457. option(CLANG_TSAN "Enable Clang thread sanitizer for nvim binary." OFF)
  458. if((CLANG_ASAN_UBSAN AND CLANG_MSAN)
  459. OR (CLANG_ASAN_UBSAN AND CLANG_TSAN)
  460. OR (CLANG_MSAN AND CLANG_TSAN))
  461. message(FATAL_ERROR "Sanitizers cannot be enabled simultaneously")
  462. endif()
  463. if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
  464. message(FATAL_ERROR "Sanitizers are only supported for Clang")
  465. endif()
  466. if(ENABLE_LIBICONV)
  467. find_package(Iconv REQUIRED)
  468. include_directories(SYSTEM ${Iconv_INCLUDE_DIRS})
  469. endif()
  470. if(ENABLE_LIBINTL)
  471. # LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464
  472. find_package(LibIntl REQUIRED)
  473. include_directories(SYSTEM ${LibIntl_INCLUDE_DIRS})
  474. endif()
  475. # Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD
  476. # explicitly to indicate a strong preference for pthread.
  477. set(CMAKE_THREAD_PREFER_PTHREAD ON)
  478. find_package(Threads REQUIRED)
  479. # Place targets in bin/ or lib/ for all build configurations
  480. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
  481. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  482. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
  483. foreach(CFGNAME ${CMAKE_CONFIGURATION_TYPES})
  484. string(TOUPPER ${CFGNAME} CFGNAME)
  485. set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_${CFGNAME} ${CMAKE_BINARY_DIR}/bin)
  486. set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_${CFGNAME} ${CMAKE_BINARY_DIR}/lib)
  487. set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CFGNAME} ${CMAKE_BINARY_DIR}/lib)
  488. endforeach()
  489. # Find Lua interpreter
  490. include(LuaHelpers)
  491. set(LUA_DEPENDENCIES lpeg mpack bit)
  492. if(NOT LUA_PRG)
  493. foreach(CURRENT_LUA_PRG luajit lua5.1 lua5.2 lua)
  494. unset(_CHECK_LUA_PRG CACHE)
  495. unset(LUA_PRG_WORKS)
  496. find_program(_CHECK_LUA_PRG ${CURRENT_LUA_PRG})
  497. if(_CHECK_LUA_PRG)
  498. check_lua_deps(${_CHECK_LUA_PRG} "${LUA_DEPENDENCIES}" LUA_PRG_WORKS)
  499. if(LUA_PRG_WORKS)
  500. set(LUA_PRG "${_CHECK_LUA_PRG}" CACHE FILEPATH "Path to a program.")
  501. break()
  502. endif()
  503. endif()
  504. endforeach()
  505. unset(_CHECK_LUA_PRG CACHE)
  506. else()
  507. check_lua_deps(${LUA_PRG} "${LUA_DEPENDENCIES}" LUA_PRG_WORKS)
  508. endif()
  509. if(NOT LUA_PRG_WORKS)
  510. message(FATAL_ERROR "Failed to find a Lua 5.1-compatible interpreter")
  511. endif()
  512. message(STATUS "Using Lua interpreter: ${LUA_PRG}")
  513. if(DEBUG)
  514. option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" OFF)
  515. else()
  516. option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON)
  517. endif()
  518. if(COMPILE_LUA AND NOT WIN32)
  519. if(PREFER_LUA)
  520. foreach(CURRENT_LUAC_PRG luac5.1 luac)
  521. find_program(_CHECK_LUAC_PRG ${CURRENT_LUAC_PRG})
  522. if(_CHECK_LUAC_PRG)
  523. set(LUAC_PRG "${_CHECK_LUAC_PRG} -s -o - %s" CACHE STRING "Format for compiling to Lua bytecode")
  524. break()
  525. endif()
  526. endforeach()
  527. elseif(LUA_PRG MATCHES "luajit")
  528. check_lua_module(${LUA_PRG} "jit.bcsave" LUAJIT_HAS_JIT_BCSAVE)
  529. if(LUAJIT_HAS_JIT_BCSAVE)
  530. set(LUAC_PRG "${LUA_PRG} -b -s %s -" CACHE STRING "Format for compiling to Lua bytecode")
  531. endif()
  532. endif()
  533. endif()
  534. if(LUAC_PRG)
  535. message(STATUS "Using Lua compiler: ${LUAC_PRG}")
  536. endif()
  537. # Setup busted.
  538. find_program(BUSTED_PRG NAMES busted busted.bat)
  539. find_program(BUSTED_LUA_PRG busted-lua)
  540. if(NOT BUSTED_OUTPUT_TYPE)
  541. set(BUSTED_OUTPUT_TYPE "nvim")
  542. endif()
  543. find_program(LUACHECK_PRG luacheck)
  544. find_program(FLAKE8_PRG flake8)
  545. find_program(GPERF_PRG gperf)
  546. include(InstallHelpers)
  547. file(GLOB MANPAGES
  548. RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  549. man/nvim.1)
  550. install_helper(
  551. FILES ${MANPAGES}
  552. DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
  553. #
  554. # Go down the tree.
  555. #
  556. add_subdirectory(src/nvim)
  557. get_directory_property(NVIM_VERSION_CFLAGS DIRECTORY src/nvim DEFINITION NVIM_VERSION_CFLAGS)
  558. add_subdirectory(test/includes)
  559. add_subdirectory(config)
  560. add_subdirectory(test/functional/fixtures) # compile test programs
  561. add_subdirectory(runtime)
  562. get_directory_property(GENERATED_HELP_TAGS DIRECTORY runtime DEFINITION GENERATED_HELP_TAGS)
  563. if(WIN32)
  564. install_helper(
  565. FILES ${DEPS_PREFIX}/share/nvim-qt/runtime/plugin/nvim_gui_shim.vim
  566. DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim-qt/runtime/plugin)
  567. endif()
  568. # Setup some test-related bits. We do this after going down the tree because we
  569. # need some of the targets.
  570. if(BUSTED_PRG)
  571. get_property(TEST_INCLUDE_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  572. PROPERTY INCLUDE_DIRECTORIES)
  573. # When running tests from 'ninja' we need to use the
  574. # console pool: to do so we need to use the USES_TERMINAL
  575. # option, but this is only available in CMake 3.2
  576. set(TEST_TARGET_ARGS)
  577. list(APPEND TEST_TARGET_ARGS "USES_TERMINAL")
  578. set(UNITTEST_PREREQS nvim-test unittest-headers)
  579. set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test pwsh-test streams-test tty-test ${GENERATED_HELP_TAGS})
  580. set(BENCHMARK_PREREQS nvim tty-test)
  581. # Useful for automated build systems, if they want to manually run the tests.
  582. add_custom_target(unittest-prereqs
  583. DEPENDS ${UNITTEST_PREREQS})
  584. set_target_properties(unittest-prereqs PROPERTIES FOLDER test)
  585. add_custom_target(functionaltest-prereqs
  586. DEPENDS ${FUNCTIONALTEST_PREREQS})
  587. add_custom_target(benchmark-prereqs
  588. DEPENDS ${BENCHMARK_PREREQS})
  589. check_lua_module(${LUA_PRG} "ffi" LUA_HAS_FFI)
  590. if(LUA_HAS_FFI)
  591. add_custom_target(unittest
  592. COMMAND ${CMAKE_COMMAND}
  593. -DBUSTED_PRG=${BUSTED_PRG}
  594. -DLUA_PRG=${LUA_PRG}
  595. -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
  596. -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
  597. -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
  598. -DBUILD_DIR=${CMAKE_BINARY_DIR}
  599. -DTEST_TYPE=unit
  600. -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
  601. DEPENDS ${UNITTEST_PREREQS}
  602. ${TEST_TARGET_ARGS})
  603. set_target_properties(unittest PROPERTIES FOLDER test)
  604. else()
  605. message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}")
  606. endif()
  607. if(LUA_HAS_FFI)
  608. set(TEST_LIBNVIM_PATH $<TARGET_FILE:nvim-test>)
  609. else()
  610. set(TEST_LIBNVIM_PATH "")
  611. endif()
  612. configure_file(
  613. ${CMAKE_SOURCE_DIR}/test/config/paths.lua.in
  614. ${CMAKE_BINARY_DIR}/test/config/paths.lua.gen)
  615. file(GENERATE
  616. OUTPUT ${CMAKE_BINARY_DIR}/test/config/paths.lua
  617. INPUT ${CMAKE_BINARY_DIR}/test/config/paths.lua.gen)
  618. add_custom_target(functionaltest
  619. COMMAND ${CMAKE_COMMAND}
  620. -DBUSTED_PRG=${BUSTED_PRG}
  621. -DLUA_PRG=${LUA_PRG}
  622. -DNVIM_PRG=$<TARGET_FILE:nvim>
  623. -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
  624. -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
  625. -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
  626. -DBUILD_DIR=${CMAKE_BINARY_DIR}
  627. -DTEST_TYPE=functional
  628. -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
  629. DEPENDS ${FUNCTIONALTEST_PREREQS}
  630. ${TEST_TARGET_ARGS})
  631. set_target_properties(functionaltest functionaltest-prereqs
  632. PROPERTIES FOLDER test)
  633. add_custom_target(benchmark
  634. COMMAND ${CMAKE_COMMAND}
  635. -DBUSTED_PRG=${BUSTED_PRG}
  636. -DLUA_PRG=${LUA_PRG}
  637. -DNVIM_PRG=$<TARGET_FILE:nvim>
  638. -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
  639. -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
  640. -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
  641. -DBUILD_DIR=${CMAKE_BINARY_DIR}
  642. -DTEST_TYPE=benchmark
  643. -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
  644. DEPENDS ${BENCHMARK_PREREQS}
  645. ${TEST_TARGET_ARGS})
  646. set_target_properties(benchmark benchmark-prereqs PROPERTIES FOLDER test)
  647. endif()
  648. if(BUSTED_LUA_PRG)
  649. add_custom_target(functionaltest-lua
  650. COMMAND ${CMAKE_COMMAND}
  651. -DBUSTED_PRG=${BUSTED_LUA_PRG}
  652. -DLUA_PRG=${LUA_PRG}
  653. -DNVIM_PRG=$<TARGET_FILE:nvim>
  654. -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
  655. -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
  656. -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
  657. -DBUILD_DIR=${CMAKE_BINARY_DIR}
  658. -DTEST_TYPE=functional
  659. -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
  660. DEPENDS ${FUNCTIONALTEST_PREREQS}
  661. ${TEST_TARGET_ARGS})
  662. set_target_properties(functionaltest-lua PROPERTIES FOLDER test)
  663. endif()
  664. if(LUACHECK_PRG)
  665. add_custom_target(lualint
  666. COMMAND ${LUACHECK_PRG} -q runtime/ scripts/ src/ test/
  667. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
  668. else()
  669. add_custom_target(lualint false
  670. COMMENT "lualint: LUACHECK_PRG not defined")
  671. endif()
  672. #add uninstall target
  673. if(NOT TARGET uninstall)
  674. configure_file(
  675. "cmake/UninstallHelper.cmake.in"
  676. "${CMAKE_CURRENT_BINARY_DIR}/UninstallHelper.cmake"
  677. IMMEDIATE @ONLY)
  678. add_custom_target(uninstall
  679. COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/UninstallHelper.cmake)
  680. endif()
  681. if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
  682. add_subdirectory(packaging)
  683. endif()