cmake_minimum_required(VERSION 3.20.0) if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) set(iwyu_standalone_build ON) message(STATUS "IWYU: standalone build") else() set(iwyu_standalone_build OFF) message(STATUS "IWYU: build as part of LLVM") endif() if (iwyu_standalone_build) cmake_policy(SET CMP0048 NEW) if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif() project(include-what-you-use) find_package(LLVM CONFIG REQUIRED) find_package(Clang CONFIG REQUIRED) list(APPEND CMAKE_MODULE_PATH ${LLVM_DIR}) include(AddLLVM) include(HandleLLVMOptions) set(iwyu_llvm_dir ${LLVM_DIR}) set(iwyu_include_dirs ${LLVM_INCLUDE_DIRS} ${CLANG_INCLUDE_DIRS} ) else() set(iwyu_llvm_dir ${CMAKE_SOURCE_DIR}) set(iwyu_include_dirs ${LLVM_SOURCE_DIR}/include ${LLVM_EXTERNAL_CLANG_SOURCE_DIR}/include ${LLVM_BINARY_DIR}/include ${LLVM_BINARY_DIR}/tools/clang/include ) endif() message(STATUS "IWYU: configuring for LLVM ${LLVM_VERSION} from ${iwyu_llvm_dir}") # The good default is given by the llvm toolchain installation itself, but still # in case both static and shared libraries are available, allow to override that # default. option(IWYU_LINK_CLANG_DYLIB "Link against the clang dynamic library" ${CLANG_LINK_CLANG_DYLIB} ) # IWYU needs to know where to find Clang builtin headers (stddef.h, stdint.h, # etc). The builtin headers are shipped in the Clang resource directory. # You can configure IWYU's resource directory lookup using two options: # # * IWYU_RESOURCE_RELATIVE_TO: which executable to serve as the base path for # relative resource dir lookups ('iwyu' or 'clang') # * IWYU_RESOURCE_DIR: a path relative to the executable above, resolved at # runtime (analogous to Clang's CLANG_RESOURCE_DIR) # # IWYU configures with IWYU_RESOURCE_RELATIVE_TO=clang and IWYU_RESOURCE_DIR="" # by default, because the builtin headers are always available next to Clang for # development and local test. # # When packaging IWYU, you can: # # * configure it relative to 'clang' and add a package dependency from IWYU to # Clang to ensure the headers are available # * configure it relative to 'iwyu' and add custom package install steps to copy # the headers from the Clang tree into the IWYU install tree # # Generally if you override the defaults, you are responsible for making sure # the headers are where you said they would be. if (NOT IWYU_RESOURCE_RELATIVE_TO) # This might look counter-intuitive, but it is most likely what you want for # local developer builds and packaging builds. See above for details. set(IWYU_RESOURCE_RELATIVE_TO "clang") endif() if (IWYU_RESOURCE_RELATIVE_TO STREQUAL "clang") # Point resource bin path to the clang target's output name if nothing else # specified (e.g. /usr/lib/llvm-/bin/clang). set(iwyu_resource_binary_path $) elseif (IWYU_RESOURCE_RELATIVE_TO STREQUAL "iwyu") # Leave bin path empty so IWYU can resolve its own path at runtime. set(iwyu_resource_binary_path "") else() message(FATAL_ERROR "Invalid IWYU_RESOURCE_RELATIVE_TO value: " "'${IWYU_RESOURCE_RELATIVE_TO}'. Must be 'iwyu' or 'clang'.") endif() if (NOT IWYU_RESOURCE_DIR) # CLANG_RESOURCE_DIR is not exported so will be empty for standalone builds. # It might, but usually doesn't, have a value in non-standalone builds, where # IWYU is part of LLVM's CMake system. set(iwyu_resource_dir "${CLANG_RESOURCE_DIR}") else() set(iwyu_resource_dir "${IWYU_RESOURCE_DIR}") endif() message(STATUS "IWYU: Resource dir will be computed at runtime with IWYU_RESOURCE_DIR=" "'${iwyu_resource_dir}' relative to '${IWYU_RESOURCE_RELATIVE_TO}'") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) # Pick up Git revision so we can report it in version information. include(FindGit) if (GIT_FOUND AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git") execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE iwyu_git_rev OUTPUT_STRIP_TRAILING_WHITESPACE ) else() message(WARNING "IWYU Git version not found, DO NOT release from this tree!") endif() set(LLVM_LINK_COMPONENTS Option Support AllTargetsAsmParsers AllTargetsDescs AllTargetsInfos ) add_llvm_executable(include-what-you-use iwyu.cc iwyu_ast_util.cc iwyu_cache.cc iwyu_driver.cc iwyu_getopt.cc iwyu_globals.cc iwyu_include_picker.cc iwyu_lexer_utils.cc iwyu_location_util.cc iwyu_output.cc iwyu_path_util.cc iwyu_port.cc iwyu_preprocessor.cc iwyu_regex.cc iwyu_verrs.cc ) # Add a dependency on clang-resource-headers if it exists, to ensure the builtin # headers are available where Clang/IWYU expects them after build. # This should only have any effect in non-standalone builds. if (TARGET clang-resource-headers) add_dependencies(include-what-you-use clang-resource-headers) endif() # LLVM requires C++17, so follow suit. set_target_properties(include-what-you-use PROPERTIES CXX_STANDARD_REQUIRED ON CXX_STANDARD 17 CXX_EXTENSIONS OFF ) separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS}) target_compile_definitions(include-what-you-use PRIVATE ${LLVM_DEFINITIONS_LIST} IWYU_GIT_REV="${iwyu_git_rev}" IWYU_RESOURCE_BINARY_PATH="${iwyu_resource_binary_path}" IWYU_RESOURCE_DIR="${iwyu_resource_dir}" ) target_include_directories(include-what-you-use PRIVATE ${iwyu_include_dirs} ) if (MINGW) target_compile_options(include-what-you-use PRIVATE # Work around 'too many sections' error with MINGW/GCC. -Wa,-mbig-obj ) endif() if (MSVC) target_compile_options(include-what-you-use PRIVATE # Suppress ''destructor'' : destructor never returns, potential memory leak. /wd4722 # Disable exceptions in MSVC STL. /D_HAS_EXCEPTIONS=0 # Suppress C1128: number of sections exceeded object file format limit. /bigobj ) endif() # Link dynamically or statically depending on user preference. if (IWYU_LINK_CLANG_DYLIB) target_link_libraries(include-what-you-use PRIVATE clang-cpp) else() target_link_libraries(include-what-you-use PRIVATE clangBasic clangLex clangAST clangSema clangFrontend clangFrontendTool clangDriver # Revision [1] in clang moved PCHContainerOperations from Frontend # to Serialization, but this broke builds that set # -DBUILD_SHARED_LIBS=on. Revision [2] is a followup that works # around the issue by adding an explicit dependency on Serialization # wherever there was a dependency on Frontend. Since we depend on # Frontend, we need an explicit dependency on Serialization too. # [1] https://llvm.org/viewvc/llvm-project?view=revision&revision=348907 # [2] https://llvm.org/viewvc/llvm-project?view=revision&revision=348915 clangSerialization clangToolingInclusionsStdlib ) endif() # Add platform-specific link dependencies. if (WIN32) target_link_libraries(include-what-you-use PRIVATE shlwapi # for PathMatchSpecA ) endif() # Install programs. include(GNUInstallDirs) install(TARGETS include-what-you-use RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) install(PROGRAMS fix_includes.py iwyu_tool.py DESTINATION ${CMAKE_INSTALL_BINDIR} ) # Install mapping files. file(GLOB mapping_files *.imp) install(FILES ${mapping_files} DESTINATION ${CMAKE_INSTALL_DATADIR}/include-what-you-use ) # Install man page on Unix-like systems. if (UNIX) install(FILES include-what-you-use.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 ) endif() find_package(Python3 COMPONENTS Interpreter) if (Python3_Interpreter_FOUND) # Map the various IWYU test scripts to CTest tests. enable_testing() function(iwyu_add_test name file) add_test(NAME ${name} COMMAND ${Python3_EXECUTABLE} run_iwyu_tests.py --run-test-file=${file} -- $ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) set_tests_properties(${name} PROPERTIES SKIP_RETURN_CODE 77) endfunction() execute_process( COMMAND ${Python3_EXECUTABLE} run_iwyu_tests.py --list-test-files WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE test_names_and_files ) string(REPLACE "\n" ";" test_names_list ${test_names_and_files}) foreach (test_name_and_file IN ITEMS ${test_names_list}) string(REPLACE ":" ";" test_name_and_file ${test_name_and_file}) iwyu_add_test(${test_name_and_file}) endforeach() add_test(NAME fix_includes_test COMMAND ${Python3_EXECUTABLE} fix_includes_test.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_test(NAME iwyu_tool_test COMMAND ${Python3_EXECUTABLE} iwyu_tool_test.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) endif()