From 438b4361cc761a2950689668f008cfe06c1510f7 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 10 Jan 2023 18:49:57 +0100 Subject: [PATCH] build: use modern cmake (#21589) Replace old-school cmake with the so-called "Modern CMake", meaning preferring using targets and properties over directory settings and variables. This allows greater flexibility, robustness and clarity over how the code works. The following deprecated commands will be replaced with their modern alternatives that operates on a specific target, rather than all targets in the current directory: - add_compile_options -> target_compile_options - include_directories -> target_include_directories - link_libraries -> target_link_libraries - add_definitions -> target_compile_definitions There are mainly four main targets that we currently use: nvim, libnvim, nvim-test (used by unittests) and ${texe} (used by check-single-includes). The goal is to explicitly define the dependencies of each target fully, rather than having everything be dependent on everything else. --- CMakeLists.txt | 375 ++----------------- cmake.config/CMakeLists.txt | 20 + cmake/FindIconv.cmake | 3 + cmake/GetCompileFlags.cmake | 120 +++--- src/nvim/CMakeLists.txt | 467 +++++++++++++++++++----- test/functional/fixtures/CMakeLists.txt | 23 +- test/includes/CMakeLists.txt | 1 - 7 files changed, 483 insertions(+), 526 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9eb701dd3f..878d5134ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,10 @@ endif() # Point CMake at any custom modules we may ship list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") -# We don't support building in-tree. +include(CheckCCompilerFlag) +include(CheckCSourceCompiles) +include(InstallHelpers) +include(LuaHelpers) # Find Lua interpreter include(PreventInTreeBuilds) include(Util) @@ -78,9 +81,6 @@ endif() list(INSERT CMAKE_PREFIX_PATH 0 ${DEPS_PREFIX}) set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${DEPS_PREFIX}/lib/pkgconfig") -# used for check_c_compiler_flag -include(CheckCCompilerFlag) - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") # CMake tries to treat /sw and /opt/local as extension of the system path, but # that doesn't really work out very well. Once you have a dependency that @@ -98,7 +98,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") OUTPUT_STRIP_TRAILING_WHITESPACE) set(CMAKE_OSX_DEPLOYMENT_TARGET "${MACOS_VERSION}") endif() - message("Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}") + message(STATUS "Using deployment target ${CMAKE_OSX_DEPLOYMENT_TARGET}") # Work around some old, broken detection by CMake for knowing when to use the # isystem flag. Apple's compilers have supported this for quite some time @@ -115,8 +115,6 @@ if(WIN32 OR CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(USE_FNAME_CASE TRUE) endif() -option(ENABLE_LIBINTL "enable libintl" ON) -option(ENABLE_LIBICONV "enable libiconv" ON) if (MINGW) # Disable LTO by default as it may not compile # See https://github.com/Alexpux/MINGW-packages/issues/3516 @@ -192,24 +190,9 @@ if(CMAKE_C_FLAGS_RELWITHDEBINFO MATCHES DNDEBUG) string(REPLACE "-DNDEBUG" "" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}") endif() -option(ENABLE_IWYU "Run include-what-you-use with the compiler." OFF) -if(ENABLE_IWYU) - find_program(IWYU_PRG NAMES include-what-you-use iwyu) - if(NOT IWYU_PRG) - message(FATAL_ERROR "ENABLE_IWYU is ON but include-what-you-use is not found!") - endif() - set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_PRG} - -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/mapping.imp - -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.libc.imp - -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.symbols.imp - -Xiwyu --no_default_mappings) - add_definitions(-DEXITFREE) -endif() - # gcc 4.0+ sets _FORTIFY_SOURCE=2 automatically. This currently # does not work with Neovim due to some uses of dynamically-sized structures. # https://github.com/neovim/neovim/issues/223 -include(CheckCSourceCompiles) # Include the build type's default flags in the check for _FORTIFY_SOURCE, # otherwise we may incorrectly identify the level as acceptable and find out @@ -221,300 +204,8 @@ if(${INIT_FLAGS_NAME}) set(CMAKE_REQUIRED_FLAGS "${${INIT_FLAGS_NAME}}") endif() -# Include because some toolchains define _FORTIFY_SOURCE=2 in -# internal header files, which should in turn be #included by . -check_c_source_compiles(" -#include - -#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1 -#error \"_FORTIFY_SOURCE > 1\" -#endif -int -main(void) -{ - return 0; -} -" HAS_ACCEPTABLE_FORTIFY) - -if(NOT HAS_ACCEPTABLE_FORTIFY) - message(STATUS "Unsupported _FORTIFY_SOURCE found, forcing _FORTIFY_SOURCE=1") - # Extract possible prefix to _FORTIFY_SOURCE (e.g. -Wp,-D_FORTIFY_SOURCE). - STRING(REGEX MATCH "[^\ ]+-D_FORTIFY_SOURCE" _FORTIFY_SOURCE_PREFIX "${CMAKE_C_FLAGS}") - STRING(REPLACE "-D_FORTIFY_SOURCE" "" _FORTIFY_SOURCE_PREFIX "${_FORTIFY_SOURCE_PREFIX}" ) - if(NOT _FORTIFY_SOURCE_PREFIX STREQUAL "") - message(STATUS "Detected _FORTIFY_SOURCE Prefix=${_FORTIFY_SOURCE_PREFIX}") - endif() - # -U in add_definitions doesn't end up in the correct spot, so we add it to - # the flags variable instead. - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FORTIFY_SOURCE_PREFIX}-U_FORTIFY_SOURCE ${_FORTIFY_SOURCE_PREFIX}-D_FORTIFY_SOURCE=1") -endif() - -# Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374). -# TODO: Figure out the root cause. -if(CMAKE_EXE_LINKER_FLAGS MATCHES "--sort-common" OR - CMAKE_SHARED_LINKER_FLAGS MATCHES "--sort-common" OR - CMAKE_MODULE_LINKER_FLAGS MATCHES "--sort-common") - message(STATUS "Removing --sort-common from linker flags") - string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") - - # If no linker flags remain for a -Wl argument, remove it. - # '-Wl$' will match LDFLAGS="-Wl,--sort-common", - # '-Wl ' will match LDFLAGS="-Wl,--sort-common -Wl,..." - string(REGEX REPLACE "-Wl($| )" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") - string(REGEX REPLACE "-Wl($| )" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") - string(REGEX REPLACE "-Wl($| )" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") -endif() - -check_c_source_compiles(" -#include -int main(void) -{ - void *trace[1]; - backtrace(trace, 1); - return 0; -} -" HAVE_EXECINFO_BACKTRACE) - -check_c_source_compiles(" -int main(void) -{ - int a = 42; - __builtin_add_overflow(a, a, &a); - __builtin_sub_overflow(a, a, &a); - return 0; -} -" HAVE_BUILTIN_ADD_OVERFLOW) - -option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF) -if(MSVC) - # XXX: /W4 gives too many warnings. #3241 - add_compile_options(-W1 -wd4311) - add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE) - add_definitions(-DMSWIN) -else() - add_compile_options(-Wall -Wextra -pedantic -Wno-unused-parameter - -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion - -Wdouble-promotion - -Wmissing-noreturn - -Wmissing-format-attribute - -Wmissing-prototypes) - - check_c_compiler_flag(-Wimplicit-fallthrough HAVE_WIMPLICIT_FALLTHROUGH_FLAG) - if(HAVE_WIMPLICIT_FALLTHROUGH_FLAG) - add_compile_options(-Wimplicit-fallthrough) - endif() - - if(ENABLE_COMPILER_SUGGESTIONS) - # Clang doesn't have -Wsuggest-attribute so check for each one. - check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE) - if(HAVE_WSUGGEST_ATTRIBUTE_PURE) - add_compile_options(-Wsuggest-attribute=pure) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST) - if(HAVE_WSUGGEST_ATTRIBUTE_CONST) - add_compile_options(-Wsuggest-attribute=const) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC) - if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC) - add_compile_options(-Wsuggest-attribute=malloc) - endif() - - check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD) - if(HAVE_WSUGGEST_ATTRIBUTE_COLD) - add_compile_options(-Wsuggest-attribute=cold) - endif() - endif() - - # On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang - # 3.4.1 used there. - if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND CMAKE_C_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wno-c11-extensions) - endif() -endif() - -if(MINGW) - # Use POSIX compatible stdio in Mingw - add_definitions(-D__USE_MINGW_ANSI_STDIO) - add_definitions(-DMSWIN) -endif() -if(WIN32) - # Windows Vista is the minimum supported version - add_definitions(-D_WIN32_WINNT=0x0600) -endif() - -# OpenBSD's GCC (4.2.1) doesn't have -Wvla -check_c_compiler_flag(-Wvla HAS_WVLA_FLAG) -if(HAS_WVLA_FLAG) - add_compile_options(-Wvla) -endif() - -if(UNIX) - # -fstack-protector breaks non Unix builds even in Mingw-w64 - check_c_compiler_flag(-fstack-protector-strong HAS_FSTACK_PROTECTOR_STRONG_FLAG) - check_c_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR_FLAG) - - if(HAS_FSTACK_PROTECTOR_STRONG_FLAG) - add_compile_options(-fstack-protector-strong) - link_libraries(-fstack-protector-strong) - elseif(HAS_FSTACK_PROTECTOR_FLAG) - add_compile_options(-fstack-protector --param ssp-buffer-size=4) - link_libraries(-fstack-protector --param ssp-buffer-size=4) - endif() -endif() - -check_c_compiler_flag(-fno-common HAVE_FNO_COMMON) -if (HAVE_FNO_COMMON) - add_compile_options(-fno-common) -endif() - -check_c_compiler_flag(-fdiagnostics-color=auto HAS_DIAG_COLOR_FLAG) -if(HAS_DIAG_COLOR_FLAG) - if(CMAKE_GENERATOR MATCHES "Ninja") - add_compile_options(-fdiagnostics-color=always) - else() - add_compile_options(-fdiagnostics-color=auto) - endif() -endif() - -option(CI_BUILD "CI, extra flags will be set" OFF) - -if(CI_BUILD) - message(STATUS "CI build enabled") - if(MSVC) - add_compile_options(-WX) - else() - add_compile_options(-Werror) - if(DEFINED ENV{BUILD_UCHAR}) - # Get some test coverage for unsigned char - add_compile_options(-funsigned-char) - endif() - endif() -endif() - option(LOG_LIST_ACTIONS "Add list actions logging" OFF) -add_definitions(-DINCLUDE_GENERATED_DECLARATIONS) - -if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") - if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") - set(NO_UNDEFINED "-Wl,--no-undefined -lsocket") - elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(NO_UNDEFINED "-Wl,--no-undefined") - endif() - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${NO_UNDEFINED}") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${NO_UNDEFINED}") - - # For O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags on older systems - # (pre POSIX.1-2008: glibc 2.11 and earlier). #4042 - # For ptsname(). #6743 - add_definitions(-D_GNU_SOURCE) -endif() - -include_directories("${PROJECT_BINARY_DIR}/cmake.config") -include_directories("${PROJECT_SOURCE_DIR}/src") - -find_package(LibUV 1.28.0 REQUIRED) -include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS}) - -find_package(Msgpack 1.0.0 REQUIRED) -include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS}) - -find_package(LibLUV 1.43.0 REQUIRED) -include_directories(SYSTEM ${LIBLUV_INCLUDE_DIRS}) - -find_package(TreeSitter REQUIRED) -include_directories(SYSTEM ${TreeSitter_INCLUDE_DIRS}) - -list(APPEND CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") -list(APPEND CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") -check_c_source_compiles(" -#include -int -main(void) -{ - TSQueryCursor *cursor = ts_query_cursor_new(); - ts_query_cursor_set_match_limit(cursor, 32); - return 0; -} -" TS_HAS_SET_MATCH_LIMIT) -if(TS_HAS_SET_MATCH_LIMIT) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_MATCH_LIMIT") -endif() -check_c_source_compiles(" -#include -#include -int -main(void) -{ - ts_set_allocator(malloc, calloc, realloc, free); - return 0; -} -" TS_HAS_SET_ALLOCATOR) -if(TS_HAS_SET_ALLOCATOR) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNVIM_TS_HAS_SET_ALLOCATOR") -endif() - -# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing. -option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF) - -if(PREFER_LUA) - find_package(Lua 5.1 EXACT REQUIRED) - set(LUA_PREFERRED_INCLUDE_DIRS ${LUA_INCLUDE_DIR}) - set(LUA_PREFERRED_LIBRARIES ${LUA_LIBRARIES}) - # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped. - find_package(LuaJit) -else() - find_package(LuaJit REQUIRED) - set(LUA_PREFERRED_INCLUDE_DIRS ${LUAJIT_INCLUDE_DIRS}) - set(LUA_PREFERRED_LIBRARIES ${LUAJIT_LIBRARIES}) -endif() - -list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") -check_c_source_compiles(" -#include - -int -main(void) -{ - return MSGPACK_OBJECT_FLOAT32; -} -" MSGPACK_HAS_FLOAT32) -list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") -if(MSGPACK_HAS_FLOAT32) - add_definitions(-DNVIM_MSGPACK_HAS_FLOAT32) -endif() - -find_package(UNIBILIUM 2.0 REQUIRED) -include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS}) - -list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") -list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") -check_c_source_compiles(" -#include - -int -main(void) -{ - unibi_str_from_var(unibi_var_from_str(\"\")); - return unibi_num_from_var(unibi_var_from_num(0)); -} -" UNIBI_HAS_VAR_FROM) -list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") -list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") -if(UNIBI_HAS_VAR_FROM) - add_definitions(-DNVIM_UNIBI_HAS_VAR_FROM) -endif() - -find_package(LibTermkey 0.22 REQUIRED) -include_directories(SYSTEM ${LIBTERMKEY_INCLUDE_DIRS}) - -find_package(LIBVTERM 0.3 REQUIRED) -include_directories(SYSTEM ${LIBVTERM_INCLUDE_DIRS}) - option(CLANG_ASAN_UBSAN "Enable Clang address & undefined behavior sanitizer for nvim binary." OFF) option(CLANG_MSAN "Enable Clang memory sanitizer for nvim binary." OFF) option(CLANG_TSAN "Enable Clang thread sanitizer for nvim binary." OFF) @@ -529,22 +220,6 @@ if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MA message(FATAL_ERROR "Sanitizers are only supported for Clang") endif() -if(ENABLE_LIBICONV) - find_package(Iconv REQUIRED) - include_directories(SYSTEM ${Iconv_INCLUDE_DIRS}) -endif() - -if(ENABLE_LIBINTL) - # LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464 - find_package(LibIntl REQUIRED) - include_directories(SYSTEM ${LibIntl_INCLUDE_DIRS}) -endif() - -# Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD -# explicitly to indicate a strong preference for pthread. -set(CMAKE_THREAD_PREFER_PTHREAD ON) -find_package(Threads REQUIRED) - # Place targets in bin/ or lib/ for all build configurations set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -556,8 +231,6 @@ foreach(CFGNAME ${CMAKE_CONFIGURATION_TYPES}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${CFGNAME} ${CMAKE_BINARY_DIR}/lib) endforeach() -# Find Lua interpreter -include(LuaHelpers) set(LUA_DEPENDENCIES lpeg mpack bit) if(NOT LUA_PRG) foreach(CURRENT_LUA_PRG luajit lua5.1 lua5.2 lua) @@ -607,13 +280,6 @@ if(LUAC_PRG) message(STATUS "Using Lua compiler: ${LUAC_PRG}") endif() -# Setup busted. -find_program(BUSTED_PRG NAMES busted busted.bat) -find_program(BUSTED_LUA_PRG busted-lua) -if(NOT BUSTED_OUTPUT_TYPE) - set(BUSTED_OUTPUT_TYPE "nvim") -endif() - # # Lint # @@ -644,8 +310,6 @@ add_glob_target( add_custom_target(lintlua) add_dependencies(lintlua lintlua-luacheck lintlua-stylua) -include(InstallHelpers) - add_glob_target( TARGET lintsh COMMAND ${SHELLCHECK_PRG} @@ -685,6 +349,11 @@ install_helper( FILES ${CMAKE_SOURCE_DIR}/src/man/nvim.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) +option(ENABLE_LIBICONV "enable libiconv" ON) +if(ENABLE_LIBICONV) + find_package(Iconv REQUIRED) +endif() + # # Go down the tree. # @@ -702,17 +371,17 @@ if(WIN32) DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim-qt/runtime/plugin) endif() +# Setup busted. +find_program(BUSTED_PRG NAMES busted busted.bat) +find_program(BUSTED_LUA_PRG busted-lua) +if(NOT BUSTED_OUTPUT_TYPE) + set(BUSTED_OUTPUT_TYPE "nvim") +endif() + # Setup some test-related bits. We do this after going down the tree because we # need some of the targets. if(BUSTED_PRG) - get_property(TEST_INCLUDE_DIRS DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - PROPERTY INCLUDE_DIRECTORIES) - - # When running tests from 'ninja' we need to use the - # console pool: to do so we need to use the USES_TERMINAL - # option, but this is only available in CMake 3.2 - set(TEST_TARGET_ARGS) - list(APPEND TEST_TARGET_ARGS "USES_TERMINAL") + get_target_property(TEST_INCLUDE_DIRS main_lib INTERFACE_INCLUDE_DIRECTORIES) set(UNITTEST_PREREQS nvim-test unittest-headers) set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test pwsh-test streams-test tty-test ${GENERATED_HELP_TAGS}) @@ -732,7 +401,7 @@ if(BUSTED_PRG) -DCIRRUS_CI=$ENV{CIRRUS_CI} -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS ${UNITTEST_PREREQS} - ${TEST_TARGET_ARGS}) + USES_TERMINAL) set_target_properties(unittest PROPERTIES FOLDER test) else() message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}") @@ -763,7 +432,7 @@ if(BUSTED_PRG) -DCIRRUS_CI=$ENV{CIRRUS_CI} -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS ${FUNCTIONALTEST_PREREQS} - ${TEST_TARGET_ARGS}) + USES_TERMINAL) set_target_properties(functionaltest PROPERTIES FOLDER test) add_custom_target(benchmark @@ -779,7 +448,7 @@ if(BUSTED_PRG) -DCIRRUS_CI=$ENV{CIRRUS_CI} -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS ${BENCHMARK_PREREQS} - ${TEST_TARGET_ARGS}) + USES_TERMINAL) set_target_properties(benchmark PROPERTIES FOLDER test) endif() @@ -797,7 +466,7 @@ if(BUSTED_LUA_PRG) -DCIRRUS_CI=$ENV{CIRRUS_CI} -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake DEPENDS ${FUNCTIONALTEST_PREREQS} - ${TEST_TARGET_ARGS}) + USES_TERMINAL) set_target_properties(functionaltest-lua PROPERTIES FOLDER test) endif() diff --git a/cmake.config/CMakeLists.txt b/cmake.config/CMakeLists.txt index 183954b889..0ea2124401 100644 --- a/cmake.config/CMakeLists.txt +++ b/cmake.config/CMakeLists.txt @@ -5,6 +5,26 @@ include(CheckIncludeFiles) include(CheckCSourceRuns) include(CheckCSourceCompiles) +check_c_source_compiles(" +#include +int main(void) +{ + void *trace[1]; + backtrace(trace, 1); + return 0; +} +" HAVE_EXECINFO_BACKTRACE) + +check_c_source_compiles(" +int main(void) +{ + int a = 42; + __builtin_add_overflow(a, a, &a); + __builtin_sub_overflow(a, a, &a); + return 0; +} +" HAVE_BUILTIN_ADD_OVERFLOW) + check_type_size("int" SIZEOF_INT LANGUAGE C) check_type_size("long" SIZEOF_LONG LANGUAGE C) check_type_size("intmax_t" SIZEOF_INTMAX_T LANGUAGE C) diff --git a/cmake/FindIconv.cmake b/cmake/FindIconv.cmake index 1d0164dae9..63290fe889 100644 --- a/cmake/FindIconv.cmake +++ b/cmake/FindIconv.cmake @@ -1,3 +1,6 @@ +# TODO(dundargoc): FindIconv is shipped by default on cmake version 3.11+. This +# file can be removed once we decide to upgrade minimum cmake version. + # - Try to find iconv # Once done, this will define # diff --git a/cmake/GetCompileFlags.cmake b/cmake/GetCompileFlags.cmake index 3b027690f8..9b3c053871 100644 --- a/cmake/GetCompileFlags.cmake +++ b/cmake/GetCompileFlags.cmake @@ -1,79 +1,57 @@ function(get_compile_flags _compile_flags) - # Create template akin to CMAKE_C_COMPILE_OBJECT. - set(compile_flags " ") - - string(REPLACE - "" - "${CMAKE_C_COMPILER}" - compile_flags - "${compile_flags}") - - # Get flags set by add_definitions(). - get_property(compile_definitions DIRECTORY PROPERTY COMPILE_DEFINITIONS) - get_target_property(compile_definitions_target nvim COMPILE_DEFINITIONS) - if(compile_definitions_target) - list(APPEND compile_definitions ${compile_definitions_target}) - list(REMOVE_DUPLICATES compile_definitions) - endif() - # NOTE: list(JOIN) requires CMake 3.12, string(CONCAT) requires CMake 3. - string(REPLACE ";" " -D" compile_definitions "${compile_definitions}") - if(compile_definitions) - set(compile_definitions " -D${compile_definitions}") - endif() - string(REPLACE - "" - "${compile_definitions}" - compile_flags - "${compile_flags}") - - # Get flags set by add_compile_options(). - get_property(compile_options DIRECTORY PROPERTY COMPILE_OPTIONS) - get_target_property(compile_options_target nvim COMPILE_OPTIONS) - if(compile_options_target) - list(APPEND compile_options ${compile_options_target}) - list(REMOVE_DUPLICATES compile_options) - endif() - # NOTE: list(JOIN) requires CMake 3.12. - string(REPLACE ";" " " compile_options "${compile_options}") - string(REPLACE - "" - "${compile_options}" - compile_flags - "${compile_flags}") - - # Get general C flags. - string(REPLACE - "" - "${CMAKE_C_FLAGS}" - compile_flags - "${compile_flags}") - - # Get C flags specific to build type. string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type) - string(REPLACE - "" - "${CMAKE_C_FLAGS_${build_type}}" - compile_flags - "${compile_flags}") + set(compile_flags ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${build_type}}) + + # Get flags set by target_compile_options(). + get_target_property(opt main_lib INTERFACE_COMPILE_OPTIONS) + if(opt) + list(APPEND compile_flags ${opt}) + endif() + + get_target_property(opt nvim COMPILE_OPTIONS) + if(opt) + list(APPEND compile_flags ${opt}) + endif() + + # Get flags set by target_compile_definitions(). + get_target_property(defs main_lib INTERFACE_COMPILE_DEFINITIONS) + if(defs) + foreach(def ${defs}) + list(APPEND compile_flags "-D${def}") + endforeach() + endif() + + get_target_property(defs nvim COMPILE_DEFINITIONS) + if(defs) + foreach(def ${defs}) + list(APPEND compile_flags "-D${def}") + endforeach() + endif() # Get include directories. - get_property(include_directories_list DIRECTORY PROPERTY INCLUDE_DIRECTORIES) - list(REMOVE_DUPLICATES include_directories_list) - foreach(include_directory ${include_directories_list}) - set(include_directories "${include_directories} -I${include_directory}") - endforeach() - string(REPLACE - "" - "${include_directories}" - compile_flags - "${compile_flags}") + get_target_property(dirs main_lib INTERFACE_INCLUDE_DIRECTORIES) + if(dirs) + foreach(dir ${dirs}) + list(APPEND compile_flags "-I${dir}") + endforeach() + endif() - # Clean duplicate whitespace. - string(REPLACE - " " - " " - compile_flags - "${compile_flags}") + get_target_property(dirs main_lib INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) + if(dirs) + foreach(dir ${dirs}) + list(APPEND compile_flags "-I${dir}") + endforeach() + endif() + + get_target_property(dirs nvim INCLUDE_DIRECTORIES) + if(dirs) + foreach(dir ${dirs}) + list(APPEND compile_flags "-I${dir}") + endforeach() + endif() + + list(REMOVE_DUPLICATES compile_flags) + string(REPLACE ";" " " compile_flags "${compile_flags}") set(${_compile_flags} "${compile_flags}" PARENT_SCOPE) endfunction() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index ac982e8be8..46191faf62 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -1,25 +1,338 @@ -option(USE_GCOV "Enable gcov support" OFF) +add_library(main_lib INTERFACE) +add_executable(nvim main.c) +add_library(libuv_lib INTERFACE) +find_package(LibUV 1.28.0 REQUIRED) +target_include_directories(libuv_lib SYSTEM INTERFACE ${LIBUV_INCLUDE_DIRS}) +target_link_libraries(libuv_lib INTERFACE ${LIBUV_LIBRARIES}) + +find_package(Msgpack 1.0.0 REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${MSGPACK_INCLUDE_DIRS}) +target_link_libraries(main_lib INTERFACE ${MSGPACK_LIBRARIES}) + +find_package(LibLUV 1.43.0 REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${LIBLUV_INCLUDE_DIRS}) +# Use "luv" as imported library, to work around CMake using "-lluv" for +# "luv.so". #10407 +add_library(luv UNKNOWN IMPORTED) +set_target_properties(luv PROPERTIES IMPORTED_LOCATION ${LIBLUV_LIBRARIES}) +target_link_libraries(main_lib INTERFACE luv) + +find_package(TreeSitter REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${TreeSitter_INCLUDE_DIRS}) +target_link_libraries(main_lib INTERFACE ${TreeSitter_LIBRARIES}) + +find_package(UNIBILIUM 2.0 REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${UNIBILIUM_INCLUDE_DIRS}) +target_link_libraries(main_lib INTERFACE ${UNIBILIUM_LIBRARIES}) + +find_package(LibTermkey 0.22 REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${LIBTERMKEY_INCLUDE_DIRS}) +target_link_libraries(main_lib INTERFACE ${LIBTERMKEY_LIBRARIES}) + +find_package(LIBVTERM 0.3 REQUIRED) +target_include_directories(main_lib SYSTEM INTERFACE ${LIBVTERM_INCLUDE_DIRS}) +target_link_libraries(main_lib INTERFACE ${LIBVTERM_LIBRARIES}) + +if(Iconv_FOUND) + target_include_directories(main_lib SYSTEM INTERFACE ${Iconv_INCLUDE_DIRS}) + if(Iconv_LIBRARIES) + target_link_libraries(main_lib INTERFACE ${Iconv_LIBRARIES}) + endif() +endif() + +option(ENABLE_LIBINTL "enable libintl" ON) +if(ENABLE_LIBINTL) + # LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464 + find_package(LibIntl REQUIRED) + target_include_directories(main_lib SYSTEM INTERFACE ${LibIntl_INCLUDE_DIRS}) + if (LibIntl_FOUND) + target_link_libraries(main_lib INTERFACE ${LibIntl_LIBRARY}) + endif() +endif() + +# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing. +option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF) +if(PREFER_LUA) + find_package(Lua 5.1 EXACT REQUIRED) + target_include_directories(main_lib SYSTEM INTERFACE ${LUA_INCLUDE_DIR}) + target_link_libraries(main_lib INTERFACE ${LUA_LIBRARIES}) + # Passive (not REQUIRED): if LUAJIT_FOUND is not set, nvim-test is skipped. + find_package(LuaJit) +else() + find_package(LuaJit REQUIRED) + target_include_directories(main_lib SYSTEM INTERFACE ${LUAJIT_INCLUDE_DIRS}) + target_link_libraries(main_lib INTERFACE ${LUAJIT_LIBRARIES}) +endif() + +# Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD +# explicitly to indicate a strong preference for pthread. +set(CMAKE_THREAD_PREFER_PTHREAD ON) +find_package(Threads REQUIRED) +target_link_libraries(main_lib INTERFACE ${CMAKE_THREAD_LIBS_INIT}) + +option(ENABLE_IWYU "Run include-what-you-use with the compiler." OFF) +if(ENABLE_IWYU) + find_program(IWYU_PRG NAMES include-what-you-use iwyu) + if(NOT IWYU_PRG) + message(FATAL_ERROR "ENABLE_IWYU is ON but include-what-you-use is not found!") + endif() + set(CMAKE_C_INCLUDE_WHAT_YOU_USE ${IWYU_PRG} + -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/mapping.imp + -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.libc.imp + -Xiwyu --mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/gcc.symbols.imp + -Xiwyu --no_default_mappings) + target_compile_definitions(main_lib INTERFACE EXITFREE) +endif() + +if(MSVC) + # XXX: /W4 gives too many warnings. #3241 + target_compile_options(main_lib INTERFACE -W1 -wd4311) + target_compile_definitions(main_lib INTERFACE _CRT_SECURE_NO_WARNINGS _CRT_NONSTDC_NO_DEPRECATE) +else() + target_compile_options(main_lib INTERFACE -Wall -Wextra -pedantic -Wno-unused-parameter + -Wstrict-prototypes -std=gnu99 -Wshadow -Wconversion + -Wdouble-promotion + -Wmissing-noreturn + -Wmissing-format-attribute + -Wmissing-prototypes) +endif() + +# On FreeBSD 64 math.h uses unguarded C11 extension, which taints clang +# 3.4.1 used there. +if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND CMAKE_C_COMPILER_ID MATCHES "Clang") + target_compile_options(main_lib INTERFACE -Wno-c11-extensions) +endif() + +check_c_compiler_flag(-Wimplicit-fallthrough HAVE_WIMPLICIT_FALLTHROUGH_FLAG) +if(HAVE_WIMPLICIT_FALLTHROUGH_FLAG) + target_compile_options(main_lib INTERFACE -Wimplicit-fallthrough) +endif() + +option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF) +if(ENABLE_COMPILER_SUGGESTIONS) + # Clang doesn't have -Wsuggest-attribute so check for each one. + check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE) + if(HAVE_WSUGGEST_ATTRIBUTE_PURE) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=pure) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST) + if(HAVE_WSUGGEST_ATTRIBUTE_CONST) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=const) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC) + if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=malloc) + endif() + + check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD) + if(HAVE_WSUGGEST_ATTRIBUTE_COLD) + target_compile_options(main_lib INTERFACE -Wsuggest-attribute=cold) + endif() +endif() + +if(MINGW) + # Use POSIX compatible stdio in Mingw + target_compile_definitions(main_lib INTERFACE __USE_MINGW_ANSI_STDIO) +endif() +if(WIN32) + # Windows Vista is the minimum supported version + target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0600 MSWIN) +endif() + +# OpenBSD's GCC (4.2.1) doesn't have -Wvla +check_c_compiler_flag(-Wvla HAS_WVLA_FLAG) +if(HAS_WVLA_FLAG) + target_compile_options(main_lib INTERFACE -Wvla) +endif() + +check_c_compiler_flag(-fno-common HAVE_FNO_COMMON) +if (HAVE_FNO_COMMON) + target_compile_options(main_lib INTERFACE -fno-common) +endif() + +check_c_compiler_flag(-fdiagnostics-color=auto HAS_DIAG_COLOR_FLAG) +if(HAS_DIAG_COLOR_FLAG) + if(CMAKE_GENERATOR MATCHES "Ninja") + target_compile_options(main_lib INTERFACE -fdiagnostics-color=always) + else() + target_compile_options(main_lib INTERFACE -fdiagnostics-color=auto) + endif() +endif() + +option(CI_BUILD "CI, extra flags will be set" OFF) +if(CI_BUILD) + message(STATUS "CI build enabled") + if(MSVC) + target_compile_options(main_lib INTERFACE -WX) + else() + target_compile_options(main_lib INTERFACE -Werror) + if(DEFINED ENV{BUILD_UCHAR}) + # Get some test coverage for unsigned char + target_compile_options(main_lib INTERFACE -funsigned-char) + endif() + endif() +endif() + +list(APPEND CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") +list(APPEND CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") +check_c_source_compiles(" +#include + +int +main(void) +{ + unibi_str_from_var(unibi_var_from_str(\"\")); + return unibi_num_from_var(unibi_var_from_num(0)); +} +" UNIBI_HAS_VAR_FROM) +list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${UNIBILIUM_INCLUDE_DIRS}") +list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${UNIBILIUM_LIBRARIES}") +if(UNIBI_HAS_VAR_FROM) + target_compile_definitions(main_lib INTERFACE NVIM_UNIBI_HAS_VAR_FROM) +endif() + +list(APPEND CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") +check_c_source_compiles(" +#include + +int +main(void) +{ + return MSGPACK_OBJECT_FLOAT32; +} +" MSGPACK_HAS_FLOAT32) +list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${MSGPACK_INCLUDE_DIRS}") +if(MSGPACK_HAS_FLOAT32) + target_compile_definitions(main_lib INTERFACE NVIM_MSGPACK_HAS_FLOAT32) +endif() + +list(APPEND CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") +list(APPEND CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") +check_c_source_compiles(" +#include +int +main(void) +{ + TSQueryCursor *cursor = ts_query_cursor_new(); + ts_query_cursor_set_match_limit(cursor, 32); + return 0; +} +" TS_HAS_SET_MATCH_LIMIT) +if(TS_HAS_SET_MATCH_LIMIT) + target_compile_definitions(main_lib INTERFACE NVIM_TS_HAS_SET_MATCH_LIMIT) +endif() +check_c_source_compiles(" +#include +#include +int +main(void) +{ + ts_set_allocator(malloc, calloc, realloc, free); + return 0; +} +" TS_HAS_SET_ALLOCATOR) +if(TS_HAS_SET_ALLOCATOR) + target_compile_definitions(main_lib INTERFACE NVIM_TS_HAS_SET_ALLOCATOR) +endif() +list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${TreeSitter_INCLUDE_DIRS}") +list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES "${TreeSitter_LIBRARIES}") + +# Include because some toolchains define _FORTIFY_SOURCE=2 in +# internal header files, which should in turn be #included by . +check_c_source_compiles(" +#include + +#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 1 +#error \"_FORTIFY_SOURCE > 1\" +#endif +int +main(void) +{ + return 0; +} +" HAS_ACCEPTABLE_FORTIFY) + +if(NOT HAS_ACCEPTABLE_FORTIFY) + message(STATUS "Unsupported _FORTIFY_SOURCE found, forcing _FORTIFY_SOURCE=1") + # Extract possible prefix to _FORTIFY_SOURCE (e.g. -Wp,-D_FORTIFY_SOURCE). + string(REGEX MATCH "[^\ ]+-D_FORTIFY_SOURCE" _FORTIFY_SOURCE_PREFIX "${CMAKE_C_FLAGS}") + string(REPLACE "-D_FORTIFY_SOURCE" "" _FORTIFY_SOURCE_PREFIX "${_FORTIFY_SOURCE_PREFIX}" ) + if(NOT _FORTIFY_SOURCE_PREFIX STREQUAL "") + message(STATUS "Detected _FORTIFY_SOURCE Prefix=${_FORTIFY_SOURCE_PREFIX}") + endif() + # -U in add_definitions doesn't end up in the correct spot, so we add it to + # the flags variable instead. + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_FORTIFY_SOURCE_PREFIX}-U_FORTIFY_SOURCE ${_FORTIFY_SOURCE_PREFIX}-D_FORTIFY_SOURCE=1") +endif() + +target_compile_definitions(main_lib INTERFACE INCLUDE_GENERATED_DECLARATIONS) + +# Remove --sort-common from linker flags, as this seems to cause bugs (see #2641, #3374). +# TODO: Figure out the root cause. +if(CMAKE_EXE_LINKER_FLAGS MATCHES "--sort-common" OR + CMAKE_SHARED_LINKER_FLAGS MATCHES "--sort-common" OR + CMAKE_MODULE_LINKER_FLAGS MATCHES "--sort-common") + message(STATUS "Removing --sort-common from linker flags") + string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REGEX REPLACE ",--sort-common(=[^,]+)?" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") + + # If no linker flags remain for a -Wl argument, remove it. + # '-Wl$' will match LDFLAGS="-Wl,--sort-common", + # '-Wl ' will match LDFLAGS="-Wl,--sort-common -Wl,..." + string(REGEX REPLACE "-Wl($| )" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") + string(REGEX REPLACE "-Wl($| )" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") + string(REGEX REPLACE "-Wl($| )" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") +endif() + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang") + if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + target_link_libraries(nvim PRIVATE -Wl,--no-undefined -lsocket) + elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_link_libraries(nvim PRIVATE -Wl,--no-undefined) + endif() + + # For O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags on older systems + # (pre POSIX.1-2008: glibc 2.11 and earlier). #4042 + # For ptsname(). #6743 + target_compile_definitions(main_lib INTERFACE _GNU_SOURCE) +endif() + +option(USE_GCOV "Enable gcov support" OFF) if(USE_GCOV) if(CLANG_TSAN) # GCOV and TSAN results in false data race reports message(FATAL_ERROR "USE_GCOV cannot be used with CLANG_TSAN") endif() message(STATUS "Enabling gcov support") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") - set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --coverage") - add_definitions(-DUSE_GCOV) + target_compile_options(main_lib INTERFACE --coverage) + target_link_libraries(main_lib INTERFACE --coverage) + target_compile_definitions(main_lib INTERFACE USE_GCOV) endif() if(WIN32) if(MINGW) # Enable wmain - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -municode") + target_link_libraries(nvim PRIVATE -municode) endif() elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework CoreServices") - set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -framework CoreServices") + target_link_libraries(nvim PRIVATE "-framework CoreServices") +endif() + +if(UNIX) + # -fstack-protector breaks non Unix builds even in Mingw-w64 + check_c_compiler_flag(-fstack-protector-strong HAS_FSTACK_PROTECTOR_STRONG_FLAG) + check_c_compiler_flag(-fstack-protector HAS_FSTACK_PROTECTOR_FLAG) + if(HAS_FSTACK_PROTECTOR_STRONG_FLAG) + target_compile_options(main_lib INTERFACE -fstack-protector-strong) + target_link_libraries(main_lib INTERFACE -fstack-protector-strong) + elseif(HAS_FSTACK_PROTECTOR_FLAG) + target_compile_options(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) + target_link_libraries(main_lib INTERFACE -fstack-protector --param ssp-buffer-size=4) + endif() endif() set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators) @@ -82,9 +395,11 @@ glob_wrapper(API_HEADERS api/*.h) list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h) glob_wrapper(MSGPACK_RPC_HEADERS msgpack_rpc/*.h) -include_directories(${GENERATED_DIR}) -include_directories(${CACHED_GENERATED_DIR}) -include_directories(${GENERATED_INCLUDES_DIR}) +target_include_directories(main_lib INTERFACE ${GENERATED_DIR}) +target_include_directories(main_lib INTERFACE ${CACHED_GENERATED_DIR}) +target_include_directories(main_lib INTERFACE ${GENERATED_INCLUDES_DIR}) +target_include_directories(main_lib INTERFACE "${PROJECT_BINARY_DIR}/cmake.config") +target_include_directories(main_lib INTERFACE "${PROJECT_SOURCE_DIR}/src") file(MAKE_DIRECTORY ${TOUCHES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) @@ -118,8 +433,6 @@ foreach(subdir list(APPEND NVIM_HEADERS ${headers}) endforeach() -glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) - # Sort file lists to ensure generated files are created in the same order from # build to build. list(SORT NVIM_SOURCES) @@ -158,22 +471,22 @@ if(NOT MSVC) endif() if(NOT "${MIN_LOG_LEVEL}" MATCHES "^$") - add_definitions(-DMIN_LOG_LEVEL=${MIN_LOG_LEVEL}) + target_compile_definitions(main_lib INTERFACE MIN_LOG_LEVEL=${MIN_LOG_LEVEL}) endif() if(CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) - add_definitions(-DEXITFREE) + target_compile_definitions(main_lib INTERFACE EXITFREE) endif() -get_directory_property(gen_cdefs COMPILE_DEFINITIONS) -foreach(gen_cdef ${gen_cdefs} DO_NOT_DEFINE_EMPTY_ATTRIBUTES) +get_target_property(prop main_lib INTERFACE_COMPILE_DEFINITIONS) +foreach(gen_cdef DO_NOT_DEFINE_EMPTY_ATTRIBUTES ${prop}) if(NOT ${gen_cdef} MATCHES "INCLUDE_GENERATED_DECLARATIONS") list(APPEND gen_cflags "-D${gen_cdef}") endif() endforeach() -get_directory_property(gen_includes INCLUDE_DIRECTORIES) -foreach(gen_include ${gen_includes} ${LUA_PREFERRED_INCLUDE_DIRS}) +get_target_property(prop main_lib INTERFACE_INCLUDE_DIRECTORIES) +foreach(gen_include ${prop}) list(APPEND gen_cflags "-I${gen_include}") endforeach() if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_OSX_SYSROOT) @@ -185,14 +498,6 @@ separate_arguments(C_FLAGS_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS}) separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${build_type}}) set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY}) -function(get_preproc_output varname iname) - if(MSVC) - set(${varname} /P /Fi${iname} /nologo PARENT_SCOPE) - else() - set(${varname} -E -o ${iname} PARENT_SCOPE) - endif() -endfunction() - set(NVIM_VERSION_GIT_H ${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef_git.h) add_custom_target(update_version_stamp COMMAND ${CMAKE_COMMAND} @@ -233,7 +538,11 @@ foreach(sfile ${NVIM_SOURCES} set(gf_h_h "${GENERATED_INCLUDES_DIR}/${r}.h.generated.h") set(gf_i "${GENERATED_DIR}/${r}.i") - get_preproc_output(PREPROC_OUTPUT ${gf_i}) + if(MSVC) + set(PREPROC_OUTPUT /P /Fi${gf_i} /nologo) + else() + set(PREPROC_OUTPUT -E -o ${gf_i}) + endif() set(depends "${HEADER_GENERATOR}" "${sfile}") if("${f}" STREQUAL "version.c") @@ -388,77 +697,44 @@ endforeach() # Our dependencies come first. if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD") - list(APPEND NVIM_LINK_LIBRARIES pthread c++abi) -endif() - -if (LibIntl_FOUND) - list(APPEND NVIM_LINK_LIBRARIES ${LibIntl_LIBRARY}) -endif() - -if(Iconv_LIBRARIES) - list(APPEND NVIM_LINK_LIBRARIES ${Iconv_LIBRARIES}) + target_link_libraries(main_lib INTERFACE pthread c++abi) endif() if(WIN32) - list(APPEND NVIM_LINK_LIBRARIES netapi32) + target_link_libraries(main_lib INTERFACE netapi32) endif() -# Use "luv" as imported library, to work around CMake using "-lluv" for -# "luv.so". #10407 -add_library(luv UNKNOWN IMPORTED) -set_property(TARGET luv PROPERTY IMPORTED_LOCATION ${LIBLUV_LIBRARIES}) - -# Put these last on the link line, since multiple things may depend on them. -list(APPEND NVIM_LINK_LIBRARIES - luv - ${LIBUV_LIBRARIES} - ${MSGPACK_LIBRARIES} - ${LIBVTERM_LIBRARIES} - ${LIBTERMKEY_LIBRARIES} - ${UNIBILIUM_LIBRARIES} - ${UTF8PROC_LIBRARIES} - ${TreeSitter_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) - if(UNIX) - list(APPEND NVIM_LINK_LIBRARIES - m) + target_link_libraries(main_lib INTERFACE m) if (NOT CMAKE_SYSTEM_NAME STREQUAL "SunOS") - list(APPEND NVIM_LINK_LIBRARIES - util) + target_link_libraries(main_lib INTERFACE util) endif() endif() -set(NVIM_EXEC_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUA_PREFERRED_LIBRARIES}) - -add_executable(nvim ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} +target_sources(nvim PRIVATE ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} ${NVIM_GENERATED_SOURCES} ${NVIM_SOURCES} ${NVIM_HEADERS} ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS}) set_target_properties(nvim PROPERTIES - EXPORT_COMPILE_COMMANDS ON) + EXPORT_COMPILE_COMMANDS ON + ENABLE_EXPORTS TRUE) if(${CMAKE_VERSION} VERSION_LESS 3.20) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) endif() -target_link_libraries(nvim ${NVIM_EXEC_LINK_LIBRARIES}) +target_link_libraries(nvim PRIVATE main_lib PUBLIC libuv_lib) install_helper(TARGETS nvim) if(MSVC) install(FILES $ DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL) endif() -set_property(TARGET nvim APPEND PROPERTY - INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) -set_property(TARGET nvim PROPERTY ENABLE_EXPORTS TRUE) - if(ENABLE_LTO) include(CheckIPOSupported) check_ipo_supported(RESULT IPO_SUPPORTED) if(IPO_SUPPORTED AND (NOT CMAKE_BUILD_TYPE MATCHES Debug)) - set_property(TARGET nvim PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + set_target_properties(nvim PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) endif() endif() @@ -580,8 +856,6 @@ add_library( ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_SOURCES} ${NVIM_GENERATED_FOR_HEADERS} ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS} ) -set_property(TARGET libnvim APPEND PROPERTY - INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS}) if(MSVC) set(LIBNVIM_NAME libnvim) else() @@ -593,12 +867,13 @@ set_target_properties( POSITION_INDEPENDENT_CODE ON OUTPUT_NAME ${LIBNVIM_NAME} ) -target_compile_options(libnvim PRIVATE -DMAKE_LIB) +target_compile_definitions(libnvim PRIVATE MAKE_LIB) +target_link_libraries(libnvim PRIVATE main_lib PUBLIC libuv_lib) if(NOT LUAJIT_FOUND) message(STATUS "luajit not found, skipping nvim-test (unit tests) target") else() - set(NVIM_TEST_LINK_LIBRARIES ${NVIM_LINK_LIBRARIES} ${LUAJIT_LIBRARIES}) + glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c) add_library( nvim-test MODULE @@ -608,39 +883,46 @@ else() ${EXTERNAL_SOURCES} ${EXTERNAL_HEADERS} ${UNIT_TEST_FIXTURES} ) - target_link_libraries(nvim-test ${NVIM_TEST_LINK_LIBRARIES}) - target_link_libraries(libnvim ${NVIM_TEST_LINK_LIBRARIES}) - set_property( - TARGET nvim-test - APPEND PROPERTY INCLUDE_DIRECTORIES ${LUAJIT_INCLUDE_DIRS} - ) + target_link_libraries(nvim-test PRIVATE ${LUAJIT_LIBRARIES} main_lib PUBLIC libuv_lib) + if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_link_libraries(nvim-test PRIVATE "-framework CoreServices") + endif() + target_include_directories(nvim-test PRIVATE ${LUAJIT_INCLUDE_DIRS}) set_target_properties( nvim-test PROPERTIES POSITION_INDEPENDENT_CODE ON ) - target_compile_options(nvim-test PRIVATE -DUNIT_TESTING) + target_compile_definitions(nvim-test PRIVATE UNIT_TESTING) endif() if(CLANG_ASAN_UBSAN) message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.") if(CI_BUILD) # Try to recover from all sanitize issues so we get reports about all failures - set(SANITIZE_RECOVER -fsanitize-recover=all) + target_compile_options(nvim PRIVATE -fsanitize-recover=all) else() - set(SANITIZE_RECOVER -fno-sanitize-recover=all) + target_compile_options(nvim PRIVATE -fno-sanitize-recover=all) endif() - set_property(TARGET nvim APPEND PROPERTY COMPILE_OPTIONS ${SANITIZE_RECOVER} -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize=address -fsanitize=undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/src/.asan-blacklist) - set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=address -fsanitize=undefined ") + target_compile_options(nvim PRIVATE + -fno-omit-frame-pointer + -fno-optimize-sibling-calls + -fsanitize=address + -fsanitize=undefined + -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/src/.asan-blacklist) + target_link_libraries(nvim PRIVATE -fsanitize=address -fsanitize=undefined) elseif(CLANG_MSAN) message(STATUS "Enabling Clang memory sanitizer for nvim.") - set_property(TARGET nvim APPEND PROPERTY COMPILE_OPTIONS -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer -fno-optimize-sibling-calls) - set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=memory -fsanitize-memory-track-origins ") + target_compile_options(nvim PRIVATE + -fsanitize=memory + -fsanitize-memory-track-origins + -fno-omit-frame-pointer + -fno-optimize-sibling-calls) + target_link_libraries(nvim PRIVATE -fsanitize=memory -fsanitize-memory-track-origins) elseif(CLANG_TSAN) message(STATUS "Enabling Clang thread sanitizer for nvim.") - set_property(TARGET nvim APPEND PROPERTY COMPILE_OPTIONS -fsanitize=thread) - set_property(TARGET nvim APPEND PROPERTY COMPILE_OPTIONS -fPIE) - set_property(TARGET nvim APPEND_STRING PROPERTY LINK_FLAGS "-fsanitize=thread ") + target_compile_options(nvim PRIVATE -fsanitize=thread -fPIE) + target_link_libraries(nvim PRIVATE -fsanitize=thread) endif() function(get_test_target prefix sfile relative_path_var target_var) @@ -683,10 +965,7 @@ foreach(hfile ${NVIM_HEADERS}) ${texe} EXCLUDE_FROM_ALL ${tsource} ${NVIM_HEADERS} ${NVIM_GENERATED_FOR_HEADERS}) - set_property( - TARGET ${texe} - APPEND PROPERTY INCLUDE_DIRECTORIES ${LUA_PREFERRED_INCLUDE_DIRS} - ) + target_link_libraries(${texe} PRIVATE main_lib) set_target_properties(${texe} PROPERTIES FOLDER test) list(FIND NO_SINGLE_CHECK_HEADERS "${relative_path}" hfile_exclude_idx) diff --git a/test/functional/fixtures/CMakeLists.txt b/test/functional/fixtures/CMakeLists.txt index a5410c2f8c..6e64b1e4dc 100644 --- a/test/functional/fixtures/CMakeLists.txt +++ b/test/functional/fixtures/CMakeLists.txt @@ -1,14 +1,23 @@ -add_executable(tty-test EXCLUDE_FROM_ALL tty-test.c) -target_link_libraries(tty-test ${LIBUV_LIBRARIES}) +add_library(test_lib INTERFACE) +if(MINGW) + target_link_libraries(test_lib INTERFACE -municode) +endif() +if(WIN32) + target_compile_definitions(test_lib INTERFACE MSWIN) +endif() +target_link_libraries(test_lib INTERFACE nvim) +add_executable(tty-test EXCLUDE_FROM_ALL tty-test.c) add_executable(shell-test EXCLUDE_FROM_ALL shell-test.c) # Fake pwsh (powershell) for testing make_filter_cmd(). #16271 add_executable(pwsh-test EXCLUDE_FROM_ALL shell-test.c) add_executable(printargs-test EXCLUDE_FROM_ALL printargs-test.c) add_executable(printenv-test EXCLUDE_FROM_ALL printenv-test.c) -if(MINGW) - set_target_properties(printenv-test PROPERTIES LINK_FLAGS -municode) -endif() - add_executable(streams-test EXCLUDE_FROM_ALL streams-test.c) -target_link_libraries(streams-test ${LIBUV_LIBRARIES}) + +target_link_libraries(tty-test PRIVATE test_lib) +target_link_libraries(shell-test PRIVATE test_lib) +target_link_libraries(pwsh-test PRIVATE test_lib) +target_link_libraries(printargs-test PRIVATE test_lib) +target_link_libraries(printenv-test PRIVATE test_lib) +target_link_libraries(streams-test PRIVATE test_lib) diff --git a/test/includes/CMakeLists.txt b/test/includes/CMakeLists.txt index b4da4c0611..0d30736091 100644 --- a/test/includes/CMakeLists.txt +++ b/test/includes/CMakeLists.txt @@ -23,7 +23,6 @@ foreach(hfile ${PRE_HEADERS}) COMMAND ${CMAKE_C_COMPILER} -std=c99 -E -P ${CMAKE_CURRENT_SOURCE_DIR}/${hfile} ${gen_cflags} - -I${LIBUV_INCLUDE_DIRS} -o ${CMAKE_CURRENT_BINARY_DIR}/${post_hfile}) list(APPEND POST_HEADERS ${post_hfile}) endforeach()