mirror of
https://github.com/Kitware/CMake.git
synced 2026-02-25 10:18:34 -06:00
Makefiles Generators: use compiler for dependencies generation
Each source compilation generates a dependencies file. These dependencies files are consolidated in one file per target. This consolidation is done as part of command 'cmake -E cmake_depends` launched before evaluation of makefile dependency graph. The consolidation uses the same approach as `CMake` dependencies management. Fixes: #21321
This commit is contained in:
@@ -387,6 +387,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_DEFAULT_BUILD_TYPE
|
||||
/variable/CMAKE_DEFAULT_CONFIGS
|
||||
/variable/CMAKE_DISABLE_PRECOMPILE_HEADERS
|
||||
/variable/CMAKE_DEPENDS_USE_COMPILER
|
||||
/variable/CMAKE_ENABLE_EXPORTS
|
||||
/variable/CMAKE_EXE_LINKER_FLAGS
|
||||
/variable/CMAKE_EXE_LINKER_FLAGS_CONFIG
|
||||
|
||||
5
Help/release/dev/makefiles-dependencies-use-compiler.rst
Normal file
5
Help/release/dev/makefiles-dependencies-use-compiler.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
makefiles-dependencies-use-compiler
|
||||
-----------------------------------
|
||||
|
||||
* The :ref:`Makefile Generators` gained the capability, for a selection of
|
||||
compilers, to use the compiler itself to generate implicit dependencies.
|
||||
9
Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst
Normal file
9
Help/variable/CMAKE_DEPENDS_USE_COMPILER.rst
Normal file
@@ -0,0 +1,9 @@
|
||||
CMAKE_DEPENDS_USE_COMPILER
|
||||
--------------------------
|
||||
|
||||
.. versionadded:: 3.20
|
||||
|
||||
For the :ref:`Makefile Generators`, source dependencies are now, for a
|
||||
selection of compilers, generated by the compiler itself. By defining this
|
||||
variable with value ``FALSE``, you can restore the legacy behavior (i.e. using
|
||||
``CMake`` for dependencies discovery).
|
||||
@@ -152,7 +152,10 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
|
||||
set(CMAKE_EXECUTABLE_FORMAT "Unknown" CACHE INTERNAL "Executable file format")
|
||||
endif()
|
||||
|
||||
if(CMAKE_GENERATOR MATCHES "^Ninja" AND MSVC_${lang}_ARCHITECTURE_ID)
|
||||
if((CMAKE_GENERATOR MATCHES "^Ninja"
|
||||
OR ((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"))
|
||||
AND MSVC_${lang}_ARCHITECTURE_ID)
|
||||
foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
|
||||
CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX(${lang} "${userflags}")
|
||||
endforeach()
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
include(Compiler/Clang)
|
||||
__compiler_clang(C)
|
||||
|
||||
|
||||
if(NOT "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
|
||||
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
|
||||
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
|
||||
|
||||
@@ -2,6 +2,14 @@ include(Compiler/Clang)
|
||||
__compiler_clang(CXX)
|
||||
|
||||
if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
include(Compiler/Clang-OBJC)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJC)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
|
||||
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
|
||||
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
include(Compiler/Clang-OBJCXX)
|
||||
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJCXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
|
||||
|
||||
if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0)
|
||||
|
||||
@@ -8,6 +8,19 @@ endif()
|
||||
|
||||
if("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
set(CMAKE_C_CLANG_TIDY_DRIVER_MODE "cl")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
|
||||
@@ -3,6 +3,12 @@ __compiler_clang(CUDA)
|
||||
|
||||
# Set explicitly, because __compiler_clang() doesn't set this if we're simulating MSVC.
|
||||
set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CUDA_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
# C++03 isn't supported for CXX, but is for CUDA, so we need to set these manually.
|
||||
# Do this before __compiler_clang_cxx_standards() since that adds the feature.
|
||||
|
||||
@@ -3,6 +3,14 @@ __compiler_clang(CXX)
|
||||
__compiler_clang_cxx_standards(CXX)
|
||||
|
||||
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
|
||||
endif()
|
||||
|
||||
@@ -13,4 +21,9 @@ endif()
|
||||
|
||||
if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
set(CMAKE_CXX_CLANG_TIDY_DRIVER_MODE "cl")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
include(Compiler/Clang)
|
||||
__compiler_clang(OBJC)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJC)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
|
||||
set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
include(Compiler/Clang)
|
||||
__compiler_clang(OBJCXX)
|
||||
__compiler_clang_cxx_standards(OBJCXX)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJCXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
include(Compiler/GNU)
|
||||
__compiler_gnu(C)
|
||||
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.5)
|
||||
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
|
||||
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
include(Compiler/GNU)
|
||||
__compiler_gnu(CXX)
|
||||
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
if (WIN32)
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fno-keep-inline-dllexport")
|
||||
|
||||
@@ -1,2 +1,11 @@
|
||||
include(Compiler/GNU)
|
||||
__compiler_gnu(OBJC)
|
||||
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJC)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJC_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJC_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
include(Compiler/GNU)
|
||||
__compiler_gnu(OBJCXX)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_OBJCXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_OBJCXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_OBJCXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
|
||||
if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2)
|
||||
set(CMAKE_OBJCXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
|
||||
endif()
|
||||
|
||||
@@ -6,6 +6,12 @@ string(APPEND CMAKE_C_FLAGS_RELEASE_INIT " -DNDEBUG")
|
||||
string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
|
||||
|
||||
set(CMAKE_DEPFILE_FLAGS_C "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
if("x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
|
||||
|
||||
@@ -6,6 +6,12 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE_INIT " -DNDEBUG")
|
||||
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT " -DNDEBUG")
|
||||
|
||||
set(CMAKE_DEPFILE_FLAGS_CXX "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
if("x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@ include(Compiler/CMakeCommonCompilerMacros)
|
||||
#set(CMAKE_ISPC_VERBOSE_FLAG )
|
||||
|
||||
set(CMAKE_DEPFILE_FLAGS_ISPC "-M -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_ISPC_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_ISPC_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
string(APPEND CMAKE_ISPC_FLAGS_INIT " ")
|
||||
string(APPEND CMAKE_ISPC_FLAGS_DEBUG_INIT "-O0 -g")
|
||||
|
||||
@@ -30,6 +30,14 @@ if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 10.2.89)
|
||||
# to get header dependency information
|
||||
set(CMAKE_DEPFILE_FLAGS_CUDA "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
endif()
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
if (NOT CMAKE_DEPFILE_FLAGS_CUDA)
|
||||
set(CMAKE_CUDA_DEPENDS_EXTRA_COMMANDS "<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <DEFINES> <INCLUDES> <FLAGS> ${_CMAKE_COMPILE_AS_CUDA_FLAG} -M <SOURCE> -MT <OBJECT> -o <DEP_FILE>")
|
||||
endif()
|
||||
set(CMAKE_CUDA_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CUDA_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT "x${CMAKE_CUDA_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
set(CMAKE_CUDA_COMPILE_OPTIONS_PIE -Xcompiler=-fPIE)
|
||||
|
||||
@@ -1,2 +1,18 @@
|
||||
include(Platform/Windows-Clang)
|
||||
__windows_compiler_clang(C)
|
||||
|
||||
if("x${MAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
elseif("x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
include(Platform/Windows-Clang)
|
||||
set(_COMPILE_CXX_MSVC " -TP")
|
||||
__windows_compiler_clang(CXX)
|
||||
|
||||
if("x${MAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xMSVC")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
elseif("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -2,3 +2,10 @@ include(Platform/Windows-Intel)
|
||||
__windows_compiler_intel(C)
|
||||
set(CMAKE_NINJA_DEPTYPE_C intel) # special value handled by CMake
|
||||
set(CMAKE_DEPFILE_FLAGS_C "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -3,3 +3,10 @@ set(_COMPILE_CXX " /TP")
|
||||
__windows_compiler_intel(CXX)
|
||||
set(CMAKE_NINJA_DEPTYPE_CXX intel) # special value handled by CMake
|
||||
set(CMAKE_DEPFILE_FLAGS_CXX "-QMMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake")
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -3,3 +3,10 @@ if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 18.0)
|
||||
set(_FS_C " /FS")
|
||||
endif()
|
||||
__windows_compiler_msvc(C)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_C)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_C_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -4,3 +4,10 @@ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18.0)
|
||||
set(_FS_CXX " /FS")
|
||||
endif()
|
||||
__windows_compiler_msvc(CXX)
|
||||
|
||||
if((NOT DEFINED CMAKE_DEPENDS_USE_COMPILER OR CMAKE_DEPENDS_USE_COMPILER)
|
||||
AND CMAKE_GENERATOR MATCHES "Makefiles|WMake"
|
||||
AND CMAKE_DEPFILE_FLAGS_CXX)
|
||||
# dependencies are computed by the compiler itself
|
||||
set(CMAKE_CXX_DEPENDS_USE_COMPILER TRUE)
|
||||
endif()
|
||||
|
||||
@@ -437,6 +437,13 @@ macro(__windows_compiler_msvc lang)
|
||||
set(CMAKE_${lang}_LINKER_SUPPORTS_PDB ON)
|
||||
set(CMAKE_NINJA_DEPTYPE_${lang} msvc)
|
||||
__windows_compiler_msvc_enable_rc("${_PLATFORM_DEFINES} ${_PLATFORM_DEFINES_${lang}}")
|
||||
|
||||
# define generic information about compiler dependencies
|
||||
# activation is done on per language platform configuration basis
|
||||
if (MSVC_VERSION GREATER 1300)
|
||||
set(CMAKE_DEPFILE_FLAGS_${lang} "/showIncludes")
|
||||
set(CMAKE_${lang}_DEPFILE_FORMAT msvc)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(__windows_compiler_msvc_enable_rc flags)
|
||||
|
||||
@@ -224,6 +224,8 @@ set(SRCS
|
||||
cmDependsJava.h
|
||||
cmDependsJavaParserHelper.cxx
|
||||
cmDependsJavaParserHelper.h
|
||||
cmDependsCompiler.cxx
|
||||
cmDependsCompiler.h
|
||||
cmDocumentation.cxx
|
||||
cmDocumentationFormatter.cxx
|
||||
cmDocumentationSection.cxx
|
||||
|
||||
267
Source/cmDependsCompiler.cxx
Normal file
267
Source/cmDependsCompiler.cxx
Normal file
@@ -0,0 +1,267 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
|
||||
#include "cmDependsCompiler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
#include <cm/string_view>
|
||||
#include <cm/vector>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmsys/FStream.hxx"
|
||||
|
||||
#include "cmFileTime.h"
|
||||
#include "cmGlobalUnixMakefileGenerator3.h"
|
||||
#include "cmLocalUnixMakefileGenerator3.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSystemTools.h"
|
||||
|
||||
namespace {
|
||||
std::string& ReplaceAll(std::string& data, const std::string& toSearch,
|
||||
const std::string& replaceStr)
|
||||
{
|
||||
// Get the first occurrence
|
||||
auto pos = data.find(toSearch);
|
||||
// Repeat until the end is reached
|
||||
while (pos != std::string::npos) {
|
||||
// Replace this occurrence of Sub String
|
||||
data.replace(pos, toSearch.size(), replaceStr);
|
||||
// Get the next occurrence from the current position
|
||||
pos = data.find(toSearch, pos + replaceStr.size());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string& NormalizePath(std::string& item)
|
||||
{
|
||||
ReplaceAll(item, "$$", "$");
|
||||
ReplaceAll(item, "\\ ", " ");
|
||||
ReplaceAll(item, "\\#", "#");
|
||||
ReplaceAll(item, "\\", "/");
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
void ParseLine(const std::string& line, std::vector<std::string>& depends)
|
||||
{
|
||||
auto start = line.find_first_not_of(' ');
|
||||
if (start == std::string::npos || line[start] == '#') {
|
||||
return;
|
||||
}
|
||||
|
||||
auto index = start;
|
||||
while ((index = line.find(' ', index)) != std::string::npos) {
|
||||
if (line[index - 1] == '\\') {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto item = line.substr(start, index - start);
|
||||
if (item.back() != ':') {
|
||||
// check that ':' is not present after some spaces
|
||||
auto index2 = line.find_first_not_of(' ', index + 1);
|
||||
if (index2 == std::string::npos || line[index2] != ':') {
|
||||
// this is a dependency, add it
|
||||
depends.emplace_back(std::move(NormalizePath(item)));
|
||||
} else {
|
||||
index = index2;
|
||||
}
|
||||
}
|
||||
|
||||
start = line.find_first_not_of(' ', index + 1);
|
||||
index = start;
|
||||
}
|
||||
if (start != std::string::npos) {
|
||||
auto item = line.substr(start);
|
||||
if (line.back() != ':') {
|
||||
// this is a dependency, add it
|
||||
depends.emplace_back(std::move(NormalizePath(item)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool cmDependsCompiler::CheckDependencies(
|
||||
const std::string& internalDepFile, const std::vector<std::string>& depFiles,
|
||||
cmDepends::DependencyMap& dependencies,
|
||||
const std::function<bool(const std::string&)>& isValidPath)
|
||||
{
|
||||
bool status = true;
|
||||
bool forceReadDeps = true;
|
||||
|
||||
cmFileTime internalDepFileTime;
|
||||
// read cached dependencies stored in internal file
|
||||
if (cmSystemTools::FileExists(internalDepFile)) {
|
||||
internalDepFileTime.Load(internalDepFile);
|
||||
forceReadDeps = false;
|
||||
|
||||
// read current dependencies
|
||||
cmsys::ifstream fin(internalDepFile.c_str());
|
||||
if (fin) {
|
||||
std::string line;
|
||||
std::string depender;
|
||||
std::vector<std::string>* currentDependencies = nullptr;
|
||||
while (std::getline(fin, line)) {
|
||||
if (line.empty() || line.front() == '#') {
|
||||
continue;
|
||||
}
|
||||
// Drop carriage return character at the end
|
||||
if (line.back() == '\r') {
|
||||
line.pop_back();
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check if this a depender line
|
||||
if (line.front() != ' ') {
|
||||
depender = std::move(line);
|
||||
currentDependencies = &dependencies[depender];
|
||||
continue;
|
||||
}
|
||||
// This is a dependee line
|
||||
if (currentDependencies != nullptr) {
|
||||
currentDependencies->emplace_back(line.substr(1));
|
||||
}
|
||||
}
|
||||
fin.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Now, update dependencies map with all new compiler generated
|
||||
// dependencies files
|
||||
cmFileTime depFileTime;
|
||||
for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
|
||||
const auto& source = *dep++;
|
||||
const auto& target = *dep++;
|
||||
const auto& format = *dep++;
|
||||
const auto& depFile = *dep;
|
||||
|
||||
if (!cmSystemTools::FileExists(depFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!forceReadDeps) {
|
||||
depFileTime.Load(depFile);
|
||||
}
|
||||
if (forceReadDeps || depFileTime.Newer(internalDepFileTime)) {
|
||||
status = false;
|
||||
if (this->Verbose) {
|
||||
cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
|
||||
"\" is newer than depends file \"",
|
||||
internalDepFile, "\".\n"));
|
||||
}
|
||||
cmsys::ifstream fin(depFile.c_str());
|
||||
if (!fin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<std::string> depends;
|
||||
std::string line;
|
||||
if (format == "msvc"_s) {
|
||||
if (!isValidPath) {
|
||||
// insert source as first dependency
|
||||
depends.push_back(source);
|
||||
}
|
||||
while (cmSystemTools::GetLineFromStream(fin, line)) {
|
||||
depends.emplace_back(std::move(line));
|
||||
}
|
||||
} else {
|
||||
while (cmSystemTools::GetLineFromStream(fin, line)) {
|
||||
if (line.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (line.back() == '\\') {
|
||||
line.pop_back();
|
||||
}
|
||||
ParseLine(line, depends);
|
||||
}
|
||||
|
||||
// depending of the effective format of the dependencies file generated
|
||||
// by the compiler, the target can be wrongly identified as a
|
||||
// dependency so remove it from the list
|
||||
if (depends.front() == target) {
|
||||
depends.erase(depends.begin());
|
||||
}
|
||||
|
||||
if (isValidPath) {
|
||||
// remove first dependency because it must not be filtered out
|
||||
depends.erase(depends.begin());
|
||||
}
|
||||
}
|
||||
|
||||
if (isValidPath) {
|
||||
cm::erase_if(depends, isValidPath);
|
||||
// insert source as first dependency
|
||||
depends.insert(depends.begin(), source);
|
||||
}
|
||||
|
||||
dependencies[target] = std::move(depends);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void cmDependsCompiler::WriteDependencies(
|
||||
const cmDepends::DependencyMap& dependencies, std::ostream& makeDepends,
|
||||
std::ostream& internalDepends)
|
||||
{
|
||||
// dependencies file consumed by make tool
|
||||
const auto& lineContinue = static_cast<cmGlobalUnixMakefileGenerator3*>(
|
||||
this->LocalGenerator->GetGlobalGenerator())
|
||||
->LineContinueDirective;
|
||||
const auto& binDir = this->LocalGenerator->GetBinaryDirectory();
|
||||
cmDepends::DependencyMap makeDependencies(dependencies);
|
||||
std::unordered_set<cm::string_view> phonyTargets;
|
||||
|
||||
// external dependencies file
|
||||
for (auto& node : makeDependencies) {
|
||||
auto& deps = node.second;
|
||||
std::transform(
|
||||
deps.cbegin(), deps.cend(), deps.begin(),
|
||||
[this, &binDir](const std::string& dep) {
|
||||
return LocalGenerator->ConvertToMakefilePath(
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
|
||||
});
|
||||
|
||||
makeDepends << this->LocalGenerator->ConvertToMakefilePath(node.first)
|
||||
<< ": " << deps.front();
|
||||
// first dependency is the source, remove it because should not be declared
|
||||
// as phony target
|
||||
deps.erase(deps.begin());
|
||||
for (const auto& dep : deps) {
|
||||
makeDepends << ' ' << lineContinue << " " << dep;
|
||||
phonyTargets.emplace(dep.data(), dep.length());
|
||||
}
|
||||
makeDepends << std::endl << std::endl;
|
||||
}
|
||||
|
||||
// add phony targets
|
||||
for (const auto& target : phonyTargets) {
|
||||
makeDepends << std::endl << target << ':' << std::endl;
|
||||
}
|
||||
|
||||
// internal dependencies file
|
||||
for (const auto& node : dependencies) {
|
||||
internalDepends << node.first << std::endl;
|
||||
for (const auto& dep : node.second) {
|
||||
internalDepends << ' ' << dep << std::endl;
|
||||
}
|
||||
internalDepends << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void cmDependsCompiler::ClearDependencies(
|
||||
const std::vector<std::string>& depFiles)
|
||||
{
|
||||
for (auto dep = depFiles.begin(); dep != depFiles.end(); dep++) {
|
||||
dep += 3;
|
||||
cmSystemTools::RemoveFile(*dep);
|
||||
}
|
||||
}
|
||||
60
Source/cmDependsCompiler.h
Normal file
60
Source/cmDependsCompiler.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include "cmConfigure.h" // IWYU pragma: keep
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmDepends.h"
|
||||
|
||||
class cmLocalUnixMakefileGenerator3;
|
||||
|
||||
/** \class cmDepends
|
||||
* \brief Dependencies files manager.
|
||||
*
|
||||
* This class is responsible for maintaining a compiler_depends.make file in
|
||||
* the build tree corresponding to an object file.
|
||||
*/
|
||||
class cmDependsCompiler
|
||||
{
|
||||
public:
|
||||
cmDependsCompiler() = default;
|
||||
~cmDependsCompiler() = default;
|
||||
|
||||
/** should this be verbose in its output */
|
||||
void SetVerbose(bool verb) { this->Verbose = verb; }
|
||||
|
||||
/** Set the local generator for the directory in which we are
|
||||
scanning dependencies. This is not a full local generator; it
|
||||
has been setup to do relative path conversions for the current
|
||||
directory. */
|
||||
void SetLocalGenerator(cmLocalUnixMakefileGenerator3* lg)
|
||||
{
|
||||
this->LocalGenerator = lg;
|
||||
}
|
||||
|
||||
/** Read dependencies for the target file. Return true if
|
||||
dependencies didn't changed and false if not.
|
||||
Up-to-date Dependencies will be stored in deps. */
|
||||
bool CheckDependencies(
|
||||
const std::string& internalDepFile,
|
||||
const std::vector<std::string>& depFiles,
|
||||
cmDepends::DependencyMap& dependencies,
|
||||
const std::function<bool(const std::string&)>& isValidPath);
|
||||
|
||||
/** Write dependencies for the target file. */
|
||||
void WriteDependencies(const cmDepends::DependencyMap& dependencies,
|
||||
std::ostream& makeDepends,
|
||||
std::ostream& internalDepends);
|
||||
|
||||
/** Clear dependencies for the target so they will be regenerated. */
|
||||
void ClearDependencies(const std::vector<std::string>& depFiles);
|
||||
|
||||
private:
|
||||
bool Verbose = false;
|
||||
cmLocalUnixMakefileGenerator3* LocalGenerator = nullptr;
|
||||
};
|
||||
@@ -127,6 +127,12 @@ public:
|
||||
void WriteConvenienceRules(std::ostream& ruleFileStream,
|
||||
std::set<std::string>& emitted);
|
||||
|
||||
// Make tool supports dependency files generated by compiler
|
||||
bool SupportsCompilerDependencies()
|
||||
{
|
||||
return this->ToolSupportsCompilerDependencies;
|
||||
}
|
||||
|
||||
/** Get the command to use for a target that has no rule. This is
|
||||
used for multiple output dependencies and for cmake_force. */
|
||||
std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
|
||||
@@ -219,6 +225,10 @@ protected:
|
||||
|
||||
bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }
|
||||
|
||||
// Specify if the make tool is able to consume dependency files
|
||||
// generated by the compiler
|
||||
bool ToolSupportsCompilerDependencies = true;
|
||||
|
||||
// Some make programs (Borland) do not keep a rule if there are no
|
||||
// dependencies or commands. This is a problem for creating rules
|
||||
// that might not do anything but might have other dependencies
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
@@ -19,6 +20,7 @@
|
||||
#include "cmCMakePath.h"
|
||||
#include "cmCustomCommand.h" // IWYU pragma: keep
|
||||
#include "cmCustomCommandGenerator.h"
|
||||
#include "cmDependsCompiler.h"
|
||||
#include "cmFileTimeCache.h"
|
||||
#include "cmGeneratedFileStream.h"
|
||||
#include "cmGeneratorExpression.h"
|
||||
@@ -52,8 +54,9 @@
|
||||
# include "cmDependsJava.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
// Helper function used below.
|
||||
static std::string cmSplitExtension(std::string const& in, std::string& base)
|
||||
std::string cmSplitExtension(std::string const& in, std::string& base)
|
||||
{
|
||||
std::string ext;
|
||||
std::string::size_type dot_pos = in.rfind('.');
|
||||
@@ -67,6 +70,43 @@ static std::string cmSplitExtension(std::string const& in, std::string& base)
|
||||
return ext;
|
||||
}
|
||||
|
||||
// Helper predicate for removing absolute paths that don't point to the
|
||||
// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
|
||||
// is set ON, to only consider in-project dependencies during the build.
|
||||
class NotInProjectDir
|
||||
{
|
||||
public:
|
||||
// Constructor with the source and binary directory's path
|
||||
NotInProjectDir(cm::string_view sourceDir, cm::string_view binaryDir)
|
||||
: SourceDir(sourceDir)
|
||||
, BinaryDir(binaryDir)
|
||||
{
|
||||
}
|
||||
|
||||
// Operator evaluating the predicate
|
||||
bool operator()(const std::string& p) const
|
||||
{
|
||||
auto path = cmCMakePath(p).Normal();
|
||||
|
||||
// Keep all relative paths:
|
||||
if (path.IsRelative()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it's an absolute path, check if it starts with the source
|
||||
// directory:
|
||||
return !(cmCMakePath(SourceDir).IsPrefix(path) ||
|
||||
cmCMakePath(BinaryDir).IsPrefix(path));
|
||||
}
|
||||
|
||||
private:
|
||||
// The path to the source directory
|
||||
cm::string_view SourceDir;
|
||||
// The path to the binary directory
|
||||
cm::string_view BinaryDir;
|
||||
};
|
||||
}
|
||||
|
||||
cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3(
|
||||
cmGlobalGenerator* gg, cmMakefile* mf)
|
||||
: cmLocalCommonGenerator(gg, mf, mf->GetCurrentBinaryDirectory())
|
||||
@@ -554,8 +594,10 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
|
||||
}
|
||||
}
|
||||
|
||||
// Write the list of commands.
|
||||
os << cmWrap("\t", commands, "", "\n") << "\n";
|
||||
if (!commands.empty()) {
|
||||
// Write the list of commands.
|
||||
os << cmWrap("\t", commands, "", "\n") << "\n";
|
||||
}
|
||||
if (symbolic && !this->IsWatcomWMake()) {
|
||||
os << ".PHONY : " << tgt << "\n";
|
||||
}
|
||||
@@ -1300,91 +1342,153 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
|
||||
cmSystemTools::Error("Target DependInfo.cmake file not found");
|
||||
}
|
||||
|
||||
bool status = true;
|
||||
|
||||
// Check if any multiple output pairs have a missing file.
|
||||
this->CheckMultipleOutputs(verbose);
|
||||
|
||||
std::string const targetDir = cmSystemTools::GetFilenamePath(tgtInfo);
|
||||
std::string const internalDependFile = targetDir + "/depend.internal";
|
||||
std::string const dependFile = targetDir + "/depend.make";
|
||||
if (!this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
|
||||
// dependencies are managed by CMake itself
|
||||
|
||||
// If the target DependInfo.cmake file has changed since the last
|
||||
// time dependencies were scanned then force rescanning. This may
|
||||
// happen when a new source file is added and CMake regenerates the
|
||||
// project but no other sources were touched.
|
||||
bool needRescanDependInfo = false;
|
||||
cmFileTimeCache* ftc =
|
||||
this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
|
||||
{
|
||||
int result;
|
||||
if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
|
||||
if (verbose) {
|
||||
cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo,
|
||||
"\" is newer than depender \"",
|
||||
internalDependFile, "\".\n"));
|
||||
std::string const internalDependFile = targetDir + "/depend.internal";
|
||||
std::string const dependFile = targetDir + "/depend.make";
|
||||
|
||||
// If the target DependInfo.cmake file has changed since the last
|
||||
// time dependencies were scanned then force rescanning. This may
|
||||
// happen when a new source file is added and CMake regenerates the
|
||||
// project but no other sources were touched.
|
||||
bool needRescanDependInfo = false;
|
||||
cmFileTimeCache* ftc =
|
||||
this->GlobalGenerator->GetCMakeInstance()->GetFileTimeCache();
|
||||
{
|
||||
int result;
|
||||
if (!ftc->Compare(internalDependFile, tgtInfo, &result) || result < 0) {
|
||||
if (verbose) {
|
||||
cmSystemTools::Stdout(cmStrCat("Dependee \"", tgtInfo,
|
||||
"\" is newer than depender \"",
|
||||
internalDependFile, "\".\n"));
|
||||
}
|
||||
needRescanDependInfo = true;
|
||||
}
|
||||
needRescanDependInfo = true;
|
||||
}
|
||||
|
||||
// If the directory information is newer than depend.internal, include
|
||||
// dirs may have changed. In this case discard all old dependencies.
|
||||
bool needRescanDirInfo = false;
|
||||
{
|
||||
std::string dirInfoFile =
|
||||
cmStrCat(this->GetCurrentBinaryDirectory(),
|
||||
"/CMakeFiles/CMakeDirectoryInformation.cmake");
|
||||
int result;
|
||||
if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
|
||||
result < 0) {
|
||||
if (verbose) {
|
||||
cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile,
|
||||
"\" is newer than depender \"",
|
||||
internalDependFile, "\".\n"));
|
||||
}
|
||||
needRescanDirInfo = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the implicit dependencies to see if they are up to date.
|
||||
// The build.make file may have explicit dependencies for the object
|
||||
// files but these will not affect the scanning process so they need
|
||||
// not be considered.
|
||||
cmDepends::DependencyMap validDependencies;
|
||||
bool needRescanDependencies = false;
|
||||
if (!needRescanDirInfo) {
|
||||
cmDependsC checker;
|
||||
checker.SetVerbose(verbose);
|
||||
checker.SetFileTimeCache(ftc);
|
||||
// cmDependsC::Check() fills the vector validDependencies() with the
|
||||
// dependencies for those files where they are still valid, i.e.
|
||||
// neither the files themselves nor any files they depend on have
|
||||
// changed. We don't do that if the CMakeDirectoryInformation.cmake
|
||||
// file has changed, because then potentially all dependencies have
|
||||
// changed. This information is given later on to cmDependsC, which
|
||||
// then only rescans the files where it did not get valid dependencies
|
||||
// via this dependency vector. This means that in the normal case, when
|
||||
// only few or one file have been edited, then also only this one file
|
||||
// is actually scanned again, instead of all files for this target.
|
||||
needRescanDependencies =
|
||||
!checker.Check(dependFile, internalDependFile, validDependencies);
|
||||
}
|
||||
|
||||
if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
|
||||
// The dependencies must be regenerated.
|
||||
std::string targetName = cmSystemTools::GetFilenameName(targetDir);
|
||||
targetName = targetName.substr(0, targetName.length() - 4);
|
||||
std::string message =
|
||||
cmStrCat("Scanning dependencies of target ", targetName);
|
||||
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
|
||||
cmsysTerminal_Color_ForegroundBold,
|
||||
message.c_str(), true, color);
|
||||
|
||||
status = this->ScanDependencies(targetDir, dependFile,
|
||||
internalDependFile, validDependencies);
|
||||
}
|
||||
}
|
||||
|
||||
// If the directory information is newer than depend.internal, include dirs
|
||||
// may have changed. In this case discard all old dependencies.
|
||||
bool needRescanDirInfo = false;
|
||||
{
|
||||
std::string dirInfoFile =
|
||||
cmStrCat(this->GetCurrentBinaryDirectory(),
|
||||
"/CMakeFiles/CMakeDirectoryInformation.cmake");
|
||||
int result;
|
||||
if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
|
||||
result < 0) {
|
||||
if (verbose) {
|
||||
cmSystemTools::Stdout(cmStrCat("Dependee \"", dirInfoFile,
|
||||
"\" is newer than depender \"",
|
||||
internalDependFile, "\".\n"));
|
||||
auto depends =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
|
||||
if (!depends.empty()) {
|
||||
// dependencies are managed by compiler
|
||||
auto depFiles = cmExpandedList(depends);
|
||||
std::string const internalDepFile =
|
||||
targetDir + "/compiler_depend.internal";
|
||||
std::string const depFile = targetDir + "/compiler_depend.make";
|
||||
cmDepends::DependencyMap dependencies;
|
||||
cmDependsCompiler depsManager;
|
||||
bool projectOnly = cmIsOn(
|
||||
this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_IN_PROJECT_ONLY"));
|
||||
|
||||
depsManager.SetVerbose(verbose);
|
||||
depsManager.SetLocalGenerator(this);
|
||||
|
||||
if (!depsManager.CheckDependencies(
|
||||
internalDepFile, depFiles, dependencies,
|
||||
projectOnly ? NotInProjectDir(this->GetSourceDirectory(),
|
||||
this->GetBinaryDirectory())
|
||||
: std::function<bool(const std::string&)>())) {
|
||||
// regenerate dependencies files
|
||||
std::string targetName =
|
||||
cmCMakePath(targetDir).GetFileName().RemoveExtension().GenericString();
|
||||
auto message = cmStrCat(
|
||||
"Consolidate compiler generated dependencies of target ", targetName);
|
||||
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
|
||||
cmsysTerminal_Color_ForegroundBold,
|
||||
message.c_str(), true, color);
|
||||
|
||||
// Open the make depends file. This should be copy-if-different
|
||||
// because the make tool may try to reload it needlessly otherwise.
|
||||
cmGeneratedFileStream ruleFileStream(
|
||||
depFile, false, this->GlobalGenerator->GetMakefileEncoding());
|
||||
ruleFileStream.SetCopyIfDifferent(true);
|
||||
if (!ruleFileStream) {
|
||||
return false;
|
||||
}
|
||||
needRescanDirInfo = true;
|
||||
|
||||
// Open the cmake dependency tracking file. This should not be
|
||||
// copy-if-different because dependencies are re-scanned when it is
|
||||
// older than the DependInfo.cmake.
|
||||
cmGeneratedFileStream internalRuleFileStream(
|
||||
internalDepFile, false, this->GlobalGenerator->GetMakefileEncoding());
|
||||
if (!internalRuleFileStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->WriteDisclaimer(ruleFileStream);
|
||||
this->WriteDisclaimer(internalRuleFileStream);
|
||||
|
||||
depsManager.WriteDependencies(dependencies, ruleFileStream,
|
||||
internalRuleFileStream);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the implicit dependencies to see if they are up to date.
|
||||
// The build.make file may have explicit dependencies for the object
|
||||
// files but these will not affect the scanning process so they need
|
||||
// not be considered.
|
||||
cmDepends::DependencyMap validDependencies;
|
||||
bool needRescanDependencies = false;
|
||||
if (!needRescanDirInfo) {
|
||||
cmDependsC checker;
|
||||
checker.SetVerbose(verbose);
|
||||
checker.SetFileTimeCache(ftc);
|
||||
// cmDependsC::Check() fills the vector validDependencies() with the
|
||||
// dependencies for those files where they are still valid, i.e. neither
|
||||
// the files themselves nor any files they depend on have changed.
|
||||
// We don't do that if the CMakeDirectoryInformation.cmake file has
|
||||
// changed, because then potentially all dependencies have changed.
|
||||
// This information is given later on to cmDependsC, which then only
|
||||
// rescans the files where it did not get valid dependencies via this
|
||||
// dependency vector. This means that in the normal case, when only
|
||||
// few or one file have been edited, then also only this one file is
|
||||
// actually scanned again, instead of all files for this target.
|
||||
needRescanDependencies =
|
||||
!checker.Check(dependFile, internalDependFile, validDependencies);
|
||||
}
|
||||
|
||||
if (needRescanDependInfo || needRescanDirInfo || needRescanDependencies) {
|
||||
// The dependencies must be regenerated.
|
||||
std::string targetName = cmSystemTools::GetFilenameName(targetDir);
|
||||
targetName = targetName.substr(0, targetName.length() - 4);
|
||||
std::string message =
|
||||
cmStrCat("Scanning dependencies of target ", targetName);
|
||||
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
|
||||
cmsysTerminal_Color_ForegroundBold,
|
||||
message.c_str(), true, color);
|
||||
|
||||
return this->ScanDependencies(targetDir, dependFile, internalDependFile,
|
||||
validDependencies);
|
||||
}
|
||||
|
||||
// The dependencies are already up-to-date.
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool cmLocalUnixMakefileGenerator3::ScanDependencies(
|
||||
@@ -1723,166 +1827,193 @@ void cmLocalUnixMakefileGenerator3::ClearDependencies(cmMakefile* mf,
|
||||
cmDepends clearer;
|
||||
clearer.SetVerbose(verbose);
|
||||
for (std::string const& file : files) {
|
||||
std::string dir = cmSystemTools::GetFilenamePath(file);
|
||||
auto snapshot = mf->GetState()->CreateBaseSnapshot();
|
||||
cmMakefile lmf(mf->GetGlobalGenerator(), snapshot);
|
||||
lmf.ReadListFile(file);
|
||||
|
||||
// Clear the implicit dependency makefile.
|
||||
std::string dependFile = dir + "/depend.make";
|
||||
clearer.Clear(dependFile);
|
||||
if (!lmf.GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES").empty()) {
|
||||
std::string dir = cmSystemTools::GetFilenamePath(file);
|
||||
|
||||
// Remove the internal dependency check file to force
|
||||
// regeneration.
|
||||
std::string internalDependFile = dir + "/depend.internal";
|
||||
cmSystemTools::RemoveFile(internalDependFile);
|
||||
}
|
||||
}
|
||||
// Clear the implicit dependency makefile.
|
||||
std::string dependFile = dir + "/depend.make";
|
||||
clearer.Clear(dependFile);
|
||||
|
||||
namespace {
|
||||
// Helper predicate for removing absolute paths that don't point to the
|
||||
// source or binary directory. It is used when CMAKE_DEPENDS_IN_PROJECT_ONLY
|
||||
// is set ON, to only consider in-project dependencies during the build.
|
||||
class NotInProjectDir
|
||||
{
|
||||
public:
|
||||
// Constructor with the source and binary directory's path
|
||||
NotInProjectDir(cm::string_view sourceDir, cm::string_view binaryDir)
|
||||
: SourceDir(sourceDir)
|
||||
, BinaryDir(binaryDir)
|
||||
{
|
||||
}
|
||||
|
||||
// Operator evaluating the predicate
|
||||
bool operator()(const std::string& p) const
|
||||
{
|
||||
auto path = cmCMakePath(p).Normal();
|
||||
|
||||
// Keep all relative paths:
|
||||
if (path.IsRelative()) {
|
||||
return false;
|
||||
// Remove the internal dependency check file to force
|
||||
// regeneration.
|
||||
std::string internalDependFile = dir + "/depend.internal";
|
||||
cmSystemTools::RemoveFile(internalDependFile);
|
||||
}
|
||||
// If it's an absolute path, check if it starts with the source
|
||||
// directory:
|
||||
return !(cmCMakePath(SourceDir).IsPrefix(path) ||
|
||||
cmCMakePath(BinaryDir).IsPrefix(path));
|
||||
}
|
||||
|
||||
private:
|
||||
// The path to the source directory
|
||||
cm::string_view SourceDir;
|
||||
// The path to the binary directory
|
||||
cm::string_view BinaryDir;
|
||||
};
|
||||
auto depsFiles = lmf.GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
|
||||
if (!depsFiles.empty()) {
|
||||
auto dir = cmCMakePath(file).GetParentPath();
|
||||
// Clear the implicit dependency makefile.
|
||||
auto depFile = cmCMakePath(dir).Append("compiler_depend.make");
|
||||
clearer.Clear(depFile.GenericString());
|
||||
|
||||
// Remove the internal dependency check file
|
||||
auto internalDepFile =
|
||||
cmCMakePath(dir).Append("compiler_depend.internal");
|
||||
cmSystemTools::RemoveFile(internalDepFile.GenericString());
|
||||
|
||||
// Touch timestamp file to force dependencies regeneration
|
||||
auto DepTimestamp = cmCMakePath(dir).Append("compiler_depend.ts");
|
||||
cmSystemTools::Touch(DepTimestamp.GenericString(), true);
|
||||
|
||||
// clear the dependencies files generated by the compiler
|
||||
std::vector<std::string> dependencies = cmExpandedList(depsFiles);
|
||||
cmDependsCompiler depsManager;
|
||||
depsManager.SetVerbose(verbose);
|
||||
depsManager.ClearDependencies(dependencies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
|
||||
std::ostream& cmakefileStream, cmGeneratorTarget* target)
|
||||
{
|
||||
ImplicitDependLanguageMap const& implicitLangs =
|
||||
this->GetImplicitDepends(target);
|
||||
// To enable dependencies filtering
|
||||
cmakefileStream << "\n"
|
||||
<< "# Consider dependencies only in project.\n"
|
||||
<< "set(CMAKE_DEPENDS_IN_PROJECT_ONLY "
|
||||
<< (cmIsOn(this->Makefile->GetSafeDefinition(
|
||||
"CMAKE_DEPENDS_IN_PROJECT_ONLY"))
|
||||
? "ON"
|
||||
: "OFF")
|
||||
<< ")\n\n";
|
||||
|
||||
auto const& implicitLangs =
|
||||
this->GetImplicitDepends(target, cmDependencyScannerKind::CMake);
|
||||
|
||||
// list the languages
|
||||
cmakefileStream
|
||||
<< "# The set of languages for which implicit dependencies are needed:\n";
|
||||
cmakefileStream << "# The set of languages for which implicit "
|
||||
"dependencies are needed:\n";
|
||||
cmakefileStream << "set(CMAKE_DEPENDS_LANGUAGES\n";
|
||||
for (auto const& implicitLang : implicitLangs) {
|
||||
cmakefileStream << " \"" << implicitLang.first << "\"\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
|
||||
// now list the files for each language
|
||||
cmakefileStream
|
||||
<< "# The set of files for implicit dependencies of each language:\n";
|
||||
for (auto const& implicitLang : implicitLangs) {
|
||||
cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << implicitLang.first
|
||||
<< "\n";
|
||||
ImplicitDependFileMap const& implicitPairs = implicitLang.second;
|
||||
if (!implicitLangs.empty()) {
|
||||
// now list the files for each language
|
||||
cmakefileStream
|
||||
<< "# The set of files for implicit dependencies of each language:\n";
|
||||
for (auto const& implicitLang : implicitLangs) {
|
||||
const auto& lang = implicitLang.first;
|
||||
|
||||
// for each file pair
|
||||
for (auto const& implicitPair : implicitPairs) {
|
||||
for (auto const& di : implicitPair.second) {
|
||||
cmakefileStream << " \"" << di << "\" ";
|
||||
cmakefileStream << "\"" << implicitPair.first << "\"\n";
|
||||
cmakefileStream << "set(CMAKE_DEPENDS_CHECK_" << lang << "\n";
|
||||
auto const& implicitPairs = implicitLang.second;
|
||||
|
||||
// for each file pair
|
||||
for (auto const& implicitPair : implicitPairs) {
|
||||
for (auto const& di : implicitPair.second) {
|
||||
cmakefileStream << " \"" << di << "\" ";
|
||||
cmakefileStream << "\"" << implicitPair.first << "\"\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
cmakefileStream << " )\n";
|
||||
|
||||
// Tell the dependency scanner what compiler is used.
|
||||
std::string cidVar =
|
||||
cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID");
|
||||
cmProp cid = this->Makefile->GetDefinition(cidVar);
|
||||
if (cmNonempty(cid)) {
|
||||
cmakefileStream << "set(CMAKE_" << implicitLang.first
|
||||
<< "_COMPILER_ID \"" << *cid << "\")\n";
|
||||
}
|
||||
// Tell the dependency scanner what compiler is used.
|
||||
std::string cidVar = cmStrCat("CMAKE_", lang, "_COMPILER_ID");
|
||||
cmProp cid = this->Makefile->GetDefinition(cidVar);
|
||||
if (cmNonempty(cid)) {
|
||||
cmakefileStream << "set(CMAKE_" << lang << "_COMPILER_ID \"" << *cid
|
||||
<< "\")\n";
|
||||
}
|
||||
|
||||
if (implicitLang.first == "Fortran") {
|
||||
std::string smodSep =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
|
||||
std::string smodExt =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
|
||||
cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
|
||||
<< "\")\n";
|
||||
cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt
|
||||
<< "\")\n";
|
||||
}
|
||||
if (lang == "Fortran") {
|
||||
std::string smodSep =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_SEP");
|
||||
std::string smodExt =
|
||||
this->Makefile->GetSafeDefinition("CMAKE_Fortran_SUBMODULE_EXT");
|
||||
cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_SEP \"" << smodSep
|
||||
<< "\")\n";
|
||||
cmakefileStream << "set(CMAKE_Fortran_SUBMODULE_EXT \"" << smodExt
|
||||
<< "\")\n";
|
||||
}
|
||||
|
||||
// Build a list of preprocessor definitions for the target.
|
||||
std::set<std::string> defines;
|
||||
this->GetTargetDefines(target, this->GetConfigName(), implicitLang.first,
|
||||
defines);
|
||||
if (!defines.empty()) {
|
||||
/* clang-format off */
|
||||
// Build a list of preprocessor definitions for the target.
|
||||
std::set<std::string> defines;
|
||||
this->GetTargetDefines(target, this->GetConfigName(), lang, defines);
|
||||
if (!defines.empty()) {
|
||||
/* clang-format off */
|
||||
cmakefileStream
|
||||
<< "\n"
|
||||
<< "# Preprocessor definitions for this target.\n"
|
||||
<< "set(CMAKE_TARGET_DEFINITIONS_" << implicitLang.first << "\n";
|
||||
/* clang-format on */
|
||||
for (std::string const& define : defines) {
|
||||
cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
|
||||
<< "\n";
|
||||
<< "set(CMAKE_TARGET_DEFINITIONS_" << lang << "\n";
|
||||
/* clang-format on */
|
||||
for (std::string const& define : defines) {
|
||||
cmakefileStream << " " << cmOutputConverter::EscapeForCMake(define)
|
||||
<< "\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
|
||||
// Target-specific include directories:
|
||||
cmakefileStream << "\n"
|
||||
<< "# The include file search paths:\n";
|
||||
cmakefileStream << "set(CMAKE_" << lang << "_TARGET_INCLUDE_PATH\n";
|
||||
std::vector<std::string> includes;
|
||||
|
||||
this->GetIncludeDirectories(includes, target, lang,
|
||||
this->GetConfigName());
|
||||
std::string const& binaryDir = this->GetState()->GetBinaryDirectory();
|
||||
if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
|
||||
std::string const& sourceDir = this->GetState()->GetSourceDirectory();
|
||||
cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
|
||||
}
|
||||
for (std::string const& include : includes) {
|
||||
cmakefileStream << " \""
|
||||
<< this->MaybeConvertToRelativePath(binaryDir, include)
|
||||
<< "\"\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
|
||||
// Target-specific include directories:
|
||||
cmakefileStream << "\n"
|
||||
<< "# The include file search paths:\n";
|
||||
cmakefileStream << "set(CMAKE_" << implicitLang.first
|
||||
<< "_TARGET_INCLUDE_PATH\n";
|
||||
std::vector<std::string> includes;
|
||||
|
||||
this->GetIncludeDirectories(includes, target, implicitLang.first,
|
||||
this->GetConfigName());
|
||||
std::string const& binaryDir = this->GetState()->GetBinaryDirectory();
|
||||
if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
|
||||
std::string const& sourceDir = this->GetState()->GetSourceDirectory();
|
||||
cm::erase_if(includes, ::NotInProjectDir(sourceDir, binaryDir));
|
||||
// Store include transform rule properties. Write the directory
|
||||
// rules first because they may be overridden by later target rules.
|
||||
std::vector<std::string> transformRules;
|
||||
if (cmProp xform =
|
||||
this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
|
||||
cmExpandList(*xform, transformRules);
|
||||
}
|
||||
for (std::string const& include : includes) {
|
||||
cmakefileStream << " \""
|
||||
<< this->MaybeConvertToRelativePath(binaryDir, include)
|
||||
<< "\"\n";
|
||||
if (cmProp xform =
|
||||
target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
|
||||
cmExpandList(*xform, transformRules);
|
||||
}
|
||||
if (!transformRules.empty()) {
|
||||
cmakefileStream << "\nset(CMAKE_INCLUDE_TRANSFORMS\n";
|
||||
for (std::string const& tr : transformRules) {
|
||||
cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr)
|
||||
<< "\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
|
||||
// Store include transform rule properties. Write the directory
|
||||
// rules first because they may be overridden by later target rules.
|
||||
std::vector<std::string> transformRules;
|
||||
if (cmProp xform =
|
||||
this->Makefile->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
|
||||
cmExpandList(*xform, transformRules);
|
||||
}
|
||||
if (cmProp xform =
|
||||
target->GetProperty("IMPLICIT_DEPENDS_INCLUDE_TRANSFORM")) {
|
||||
cmExpandList(*xform, transformRules);
|
||||
}
|
||||
if (!transformRules.empty()) {
|
||||
cmakefileStream << "set(CMAKE_INCLUDE_TRANSFORMS\n";
|
||||
for (std::string const& tr : transformRules) {
|
||||
cmakefileStream << " " << cmOutputConverter::EscapeForCMake(tr) << "\n";
|
||||
auto const& compilerLangs =
|
||||
this->GetImplicitDepends(target, cmDependencyScannerKind::Compiler);
|
||||
|
||||
// list the dependency files managed by the compiler
|
||||
cmakefileStream << "\n# The set of dependency files which are needed:\n";
|
||||
cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
|
||||
for (auto const& compilerLang : compilerLangs) {
|
||||
auto depFormat = this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
|
||||
auto const& compilerPairs = compilerLang.second;
|
||||
for (auto const& compilerPair : compilerPairs) {
|
||||
for (auto const& src : compilerPair.second) {
|
||||
cmakefileStream << " \"" << src << "\" \""
|
||||
<< this->MaybeConvertToRelativePath(
|
||||
this->GetBinaryDirectory(), compilerPair.first)
|
||||
<< "\" \"" << depFormat << "\" \""
|
||||
<< this->MaybeConvertToRelativePath(
|
||||
this->GetBinaryDirectory(), compilerPair.first)
|
||||
<< ".d\"\n";
|
||||
}
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
cmakefileStream << " )\n";
|
||||
}
|
||||
|
||||
void cmLocalUnixMakefileGenerator3::WriteDisclaimer(std::ostream& os)
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
#include <utility>
|
||||
|
||||
#include <cm/memory>
|
||||
#include <cm/string_view>
|
||||
#include <cmext/algorithm>
|
||||
#include <cmext/string_view>
|
||||
|
||||
#include "cmComputeLinkInformation.h"
|
||||
#include "cmCustomCommand.h"
|
||||
@@ -326,7 +328,45 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
|
||||
<< cmSystemTools::ConvertToOutputPath(
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull))
|
||||
<< "\n\n";
|
||||
<< "\n";
|
||||
|
||||
std::string depsUseCompiler = "CMAKE_DEPENDS_USE_COMPILER";
|
||||
if (!this->Makefile->IsDefinitionSet(depsUseCompiler) ||
|
||||
this->Makefile->IsOn(depsUseCompiler)) {
|
||||
std::string compilerDependFile =
|
||||
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
|
||||
*this->BuildFileStream
|
||||
<< "# Include any dependencies generated by the "
|
||||
"compiler for this target.\n"
|
||||
<< this->GlobalGenerator->IncludeDirective << " " << root
|
||||
<< cmSystemTools::ConvertToOutputPath(
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
this->LocalGenerator->GetBinaryDirectory(), compilerDependFile))
|
||||
<< "\n\n";
|
||||
|
||||
if (!cmSystemTools::FileExists(compilerDependFile)) {
|
||||
// Write an empty dependency file.
|
||||
cmGeneratedFileStream depFileStream(
|
||||
compilerDependFile, false,
|
||||
this->GlobalGenerator->GetMakefileEncoding());
|
||||
depFileStream << "# Empty compiler generated dependencies file for "
|
||||
<< this->GeneratorTarget->GetName() << ".\n"
|
||||
<< "# This may be replaced when dependencies are built.\n";
|
||||
}
|
||||
|
||||
std::string compilerDependTimestamp =
|
||||
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
|
||||
if (!cmSystemTools::FileExists(compilerDependTimestamp)) {
|
||||
// Write a dependency timestamp file.
|
||||
cmGeneratedFileStream depFileStream(
|
||||
compilerDependTimestamp, false,
|
||||
this->GlobalGenerator->GetMakefileEncoding());
|
||||
depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
|
||||
<< "# Timestamp file for compiler generated dependencies "
|
||||
"management for "
|
||||
<< this->GeneratorTarget->GetName() << ".\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->NoRuleMessages) {
|
||||
// Include the progress variables for the target.
|
||||
@@ -473,6 +513,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
return;
|
||||
}
|
||||
|
||||
// Use compiler to generate dependencies, if supported.
|
||||
bool compilerGenerateDeps =
|
||||
this->GlobalGenerator->SupportsCompilerDependencies() &&
|
||||
cmIsOn(this->Makefile->GetDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_DEPENDS_USE_COMPILER")));
|
||||
auto scanner = compilerGenerateDeps ? cmDependencyScannerKind::Compiler
|
||||
: cmDependencyScannerKind::CMake;
|
||||
|
||||
// Get the full path name of the object file.
|
||||
std::string const& objectName =
|
||||
this->GeneratorTarget->GetObjectName(&source);
|
||||
@@ -512,7 +560,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
std::string srcFullPath =
|
||||
cmSystemTools::CollapseFullPath(source.GetFullPath());
|
||||
this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
|
||||
objFullPath, srcFullPath);
|
||||
objFullPath, srcFullPath, scanner);
|
||||
|
||||
this->LocalGenerator->AppendRuleDepend(depends,
|
||||
this->FlagFileNameFull.c_str());
|
||||
@@ -554,8 +602,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
depends.push_back(
|
||||
this->GeneratorTarget->GetPchFile(config, lang, arch));
|
||||
}
|
||||
this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang,
|
||||
objFullPath, pchHeader);
|
||||
this->LocalGenerator->AddImplicitDepends(
|
||||
this->GeneratorTarget, lang, objFullPath, pchHeader, scanner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,7 +737,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
source.GetFullPath(), cmOutputConverter::SHELL);
|
||||
|
||||
// Construct the build message.
|
||||
std::vector<std::string> no_commands;
|
||||
std::vector<std::string> no_depends;
|
||||
std::vector<std::string> commands;
|
||||
|
||||
// add in a progress call if needed
|
||||
@@ -783,6 +831,26 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
"$(" + lang + "_INCLUDES)");
|
||||
vars.Includes = includesString.c_str();
|
||||
|
||||
std::string dependencyTarget;
|
||||
std::string shellDependencyFile;
|
||||
std::string dependencyTimestamp;
|
||||
if (compilerGenerateDeps) {
|
||||
dependencyTarget = this->LocalGenerator->EscapeForShell(
|
||||
this->LocalGenerator->ConvertToMakefilePath(
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
this->LocalGenerator->GetBinaryDirectory(), relativeObj)));
|
||||
vars.DependencyTarget = dependencyTarget.c_str();
|
||||
|
||||
auto depFile = cmStrCat(obj, ".d");
|
||||
shellDependencyFile = this->LocalGenerator->ConvertToOutputFormat(
|
||||
depFile, cmOutputConverter::SHELL);
|
||||
vars.DependencyFile = shellDependencyFile.c_str();
|
||||
|
||||
dependencyTimestamp = this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
this->LocalGenerator->GetBinaryDirectory(),
|
||||
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
|
||||
}
|
||||
|
||||
// At the moment, it is assumed that C, C++, Fortran, and CUDA have both
|
||||
// assembly and preprocessor capabilities. The same is true for the
|
||||
// ability to export compile commands
|
||||
@@ -954,6 +1022,53 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
}
|
||||
}
|
||||
|
||||
std::string flagsWithDeps(flags);
|
||||
|
||||
if (compilerGenerateDeps) {
|
||||
// Injects dependency computation
|
||||
auto depFlags = this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_DEPFILE_FLAGS_", lang));
|
||||
|
||||
if (!depFlags.empty()) {
|
||||
// Add dependency flags
|
||||
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
|
||||
depFlags, vars);
|
||||
flagsWithDeps.append(1, ' ');
|
||||
flagsWithDeps.append(depFlags);
|
||||
}
|
||||
vars.Flags = flagsWithDeps.c_str();
|
||||
|
||||
const auto& extraCommands = this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
|
||||
if (!extraCommands.empty()) {
|
||||
auto commandList = cmExpandedList(extraCommands);
|
||||
compileCommands.insert(compileCommands.end(), commandList.cbegin(),
|
||||
commandList.cend());
|
||||
}
|
||||
|
||||
const auto& depFormat = this->Makefile->GetRequiredDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_DEPFILE_FORMAT"));
|
||||
|
||||
if (depFormat == "msvc"_s) {
|
||||
// compiler must be launched through a wrapper to pick-up dependencies
|
||||
std::string depFilter =
|
||||
"$(CMAKE_COMMAND) -E cmake_cl_compile_depends ";
|
||||
depFilter += cmStrCat("--dep-file=", shellDependencyFile);
|
||||
depFilter +=
|
||||
cmStrCat(" --working-dir=",
|
||||
this->LocalGenerator->ConvertToOutputFormat(
|
||||
this->LocalGenerator->GetCurrentBinaryDirectory(),
|
||||
cmOutputConverter::SHELL));
|
||||
const auto& prefix = this->Makefile->GetSafeDefinition(
|
||||
cmStrCat("CMAKE_", lang, "_CL_SHOWINCLUDES_PREFIX"));
|
||||
depFilter += cmStrCat(" --filter-prefix=",
|
||||
this->LocalGenerator->ConvertToOutputFormat(
|
||||
prefix, cmOutputConverter::SHELL));
|
||||
depFilter += " -- ";
|
||||
compileCommands.front().insert(0, depFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// Expand placeholders in the commands.
|
||||
for (std::string& compileCommand : compileCommands) {
|
||||
compileCommand = cmStrCat(launcher, compileCommand);
|
||||
@@ -979,8 +1094,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
cmExpandList(evaluated_outputs, outputs);
|
||||
}
|
||||
}
|
||||
if (!ispcHeaderRelative
|
||||
.empty()) { // can't move ispcHeader as vars is using it
|
||||
if (!ispcHeaderRelative.empty()) {
|
||||
// can't move ispcHeader as vars is using it
|
||||
outputs.emplace_back(ispcHeaderRelative);
|
||||
}
|
||||
|
||||
@@ -988,10 +1103,19 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
|
||||
this->CleanFiles.insert(outputs.begin() + 1, outputs.end());
|
||||
}
|
||||
|
||||
if (compilerGenerateDeps) {
|
||||
depends.push_back(dependencyTimestamp);
|
||||
}
|
||||
|
||||
// Write the rule.
|
||||
this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs, depends,
|
||||
commands);
|
||||
|
||||
if (compilerGenerateDeps) {
|
||||
// set back flags without dependency generation
|
||||
vars.Flags = flags.c_str();
|
||||
}
|
||||
|
||||
bool do_preprocess_rules = lang_has_preprocessor &&
|
||||
this->LocalGenerator->GetCreatePreprocessedSourceRules();
|
||||
bool do_assembly_rules =
|
||||
@@ -1388,10 +1512,10 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
|
||||
|
||||
std::string registerFileCmd;
|
||||
|
||||
// The generated register file contains macros that when expanded register
|
||||
// the device routines. Because the routines are the same for all
|
||||
// architectures the register file will be the same too. Thus generate it
|
||||
// only on the first invocation to reduce overhead.
|
||||
// The generated register file contains macros that when expanded
|
||||
// register the device routines. Because the routines are the same for
|
||||
// all architectures the register file will be the same too. Thus
|
||||
// generate it only on the first invocation to reduce overhead.
|
||||
if (fatbinaryDepends.size() == 1) {
|
||||
std::string registerFileRel =
|
||||
this->LocalGenerator->MaybeConvertToRelativePath(
|
||||
@@ -1426,7 +1550,8 @@ void cmMakefileTargetGenerator::WriteDeviceLinkRule(
|
||||
fatbinaryOutputRel, fatbinaryDepends,
|
||||
{ fatbinaryCommand }, false);
|
||||
|
||||
// Compile the stub that registers the kernels and contains the fatbinaries.
|
||||
// Compile the stub that registers the kernels and contains the
|
||||
// fatbinaries.
|
||||
cmRulePlaceholderExpander::RuleVariables vars;
|
||||
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
|
||||
vars.CMTargetType =
|
||||
@@ -1839,9 +1964,9 @@ bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
|
||||
if (size_t const limit = cmSystemTools::CalculateCommandLineLengthLimit()) {
|
||||
// Compute the total length of our list of object files with room
|
||||
// for argument separation and quoting. This does not convert paths
|
||||
// relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so the
|
||||
// actual list will likely be much shorter than this. However, in the
|
||||
// worst case all objects will remain as absolute paths.
|
||||
// relative to CMAKE_CURRENT_BINARY_DIR like the final list will be, so
|
||||
// the actual list will likely be much shorter than this. However, in
|
||||
// the worst case all objects will remain as absolute paths.
|
||||
size_t length = 0;
|
||||
for (std::string const& obj : this->Objects) {
|
||||
length += obj.size() + 3;
|
||||
|
||||
183
Source/cmcmd.cxx
183
Source/cmcmd.cxx
@@ -33,6 +33,13 @@
|
||||
# include "bindexplib.h"
|
||||
#endif
|
||||
|
||||
#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
|
||||
# include <algorithm>
|
||||
|
||||
# include "cmCMakePath.h"
|
||||
# include "cmProcessTools.h"
|
||||
#endif
|
||||
|
||||
#if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32) && !defined(__CYGWIN__)
|
||||
# include "cmVisualStudioWCEPlatformParser.h"
|
||||
#endif
|
||||
@@ -66,6 +73,7 @@ int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
|
||||
int cmcmd_cmake_ninja_dyndep(std::vector<std::string>::const_iterator argBeg,
|
||||
std::vector<std::string>::const_iterator argEnd);
|
||||
|
||||
namespace {
|
||||
void CMakeCommandUsage(const char* program)
|
||||
{
|
||||
std::ostringstream errorStream;
|
||||
@@ -144,8 +152,7 @@ void CMakeCommandUsage(const char* program)
|
||||
cmSystemTools::Error(errorStream.str());
|
||||
}
|
||||
|
||||
static bool cmTarFilesFrom(std::string const& file,
|
||||
std::vector<std::string>& files)
|
||||
bool cmTarFilesFrom(std::string const& file, std::vector<std::string>& files)
|
||||
{
|
||||
if (cmSystemTools::FileIsDirectory(file)) {
|
||||
std::ostringstream e;
|
||||
@@ -180,7 +187,7 @@ static bool cmTarFilesFrom(std::string const& file,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cmCatFile(const std::string& fileToAppend)
|
||||
void cmCatFile(const std::string& fileToAppend)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
_setmode(fileno(stdout), _O_BINARY);
|
||||
@@ -190,7 +197,7 @@ static void cmCatFile(const std::string& fileToAppend)
|
||||
std::cout << source.rdbuf();
|
||||
}
|
||||
|
||||
static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
|
||||
bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
|
||||
{
|
||||
if (cmSystemTools::FileIsSymlink(dir)) {
|
||||
if (!cmSystemTools::RemoveFile(dir)) {
|
||||
@@ -208,9 +215,123 @@ static bool cmRemoveDirectory(const std::string& dir, bool recursive = true)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int HandleIWYU(const std::string& runCmd,
|
||||
const std::string& /* sourceFile */,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
|
||||
class CLIncludeParser : public cmProcessTools::LineParser
|
||||
{
|
||||
public:
|
||||
CLIncludeParser(cm::string_view includePrefix, cmsys::ofstream& depFile,
|
||||
std::ostream& output)
|
||||
: IncludePrefix(includePrefix)
|
||||
, DepFile(depFile)
|
||||
, Output(output)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
bool ProcessLine() override
|
||||
{
|
||||
if (cmHasPrefix(this->Line, this->IncludePrefix)) {
|
||||
this->DepFile << cmCMakePath(
|
||||
cmTrimWhitespace(this->Line.c_str() +
|
||||
this->IncludePrefix.size()))
|
||||
.GenericString()
|
||||
<< std::endl;
|
||||
} else {
|
||||
this->Output << this->Line << std::endl << std::flush;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
cm::string_view IncludePrefix;
|
||||
cmsys::ofstream& DepFile;
|
||||
std::ostream& Output;
|
||||
};
|
||||
|
||||
class CLOutputLogger : public cmProcessTools::OutputLogger
|
||||
{
|
||||
public:
|
||||
CLOutputLogger(std::ostream& log)
|
||||
: cmProcessTools::OutputLogger(log)
|
||||
{
|
||||
}
|
||||
|
||||
bool ProcessLine() override
|
||||
{
|
||||
*this->Log << std::flush;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int CLCompileAndDependencies(const std::vector<std::string>& args)
|
||||
{
|
||||
std::string depFile;
|
||||
std::string currentBinaryDir;
|
||||
std::string filterPrefix;
|
||||
std::vector<std::string> command;
|
||||
for (auto it = args.cbegin() + 2; it != args.cend(); it++) {
|
||||
if (cmHasLiteralPrefix(*it, "--dep-file=")) {
|
||||
depFile = it->substr(11);
|
||||
} else if (cmHasLiteralPrefix(*it, "--working-dir=")) {
|
||||
currentBinaryDir = it->substr(14);
|
||||
} else if (cmHasLiteralPrefix(*it, "--filter-prefix=")) {
|
||||
filterPrefix = it->substr(16);
|
||||
} else if (*it == "--") {
|
||||
command.insert(command.begin(), ++it, args.cend());
|
||||
break;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<cmsysProcess, void (*)(cmsysProcess*)> cp(
|
||||
cmsysProcess_New(), cmsysProcess_Delete);
|
||||
std::vector<const char*> argv(command.size() + 1);
|
||||
std::transform(command.begin(), command.end(), argv.begin(),
|
||||
[](std::string const& s) { return s.c_str(); });
|
||||
argv.back() = nullptr;
|
||||
cmsysProcess_SetCommand(cp.get(), argv.data());
|
||||
cmsysProcess_SetWorkingDirectory(cp.get(), currentBinaryDir.c_str());
|
||||
|
||||
cmsys::ofstream fout(depFile.c_str());
|
||||
if (!fout) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
CLIncludeParser includeParser(filterPrefix, fout, std::cout);
|
||||
CLOutputLogger errLogger(std::cerr);
|
||||
|
||||
// Start the process.
|
||||
cmProcessTools::RunProcess(cp.get(), &includeParser, &errLogger);
|
||||
|
||||
int status = 0;
|
||||
// handle status of process
|
||||
switch (cmsysProcess_GetState(cp.get())) {
|
||||
case cmsysProcess_State_Exited:
|
||||
status = cmsysProcess_GetExitValue(cp.get());
|
||||
break;
|
||||
case cmsysProcess_State_Exception:
|
||||
status = 1;
|
||||
break;
|
||||
case cmsysProcess_State_Error:
|
||||
status = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != 0) {
|
||||
// remove the dependencies file because potentially invalid
|
||||
fout.close();
|
||||
cmSystemTools::RemoveFile(depFile);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
int HandleIWYU(const std::string& runCmd, const std::string& /* sourceFile */,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
{
|
||||
// Construct the iwyu command line by taking what was given
|
||||
// and adding all the arguments we give to the compiler.
|
||||
@@ -235,8 +356,8 @@ static int HandleIWYU(const std::string& runCmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
{
|
||||
// Construct the clang-tidy command line by taking what was given
|
||||
// and adding our compiler command line. The clang-tidy tool will
|
||||
@@ -265,9 +386,8 @@ static int HandleTidy(const std::string& runCmd, const std::string& sourceFile,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int HandleLWYU(const std::string& runCmd,
|
||||
const std::string& /* sourceFile */,
|
||||
const std::vector<std::string>&)
|
||||
int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */,
|
||||
const std::vector<std::string>&)
|
||||
{
|
||||
// Construct the ldd -r -u (link what you use lwyu) command line
|
||||
// ldd -u -r lwuy target
|
||||
@@ -298,9 +418,8 @@ static int HandleLWYU(const std::string& runCmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HandleCppLint(const std::string& runCmd,
|
||||
const std::string& sourceFile,
|
||||
const std::vector<std::string>&)
|
||||
int HandleCppLint(const std::string& runCmd, const std::string& sourceFile,
|
||||
const std::vector<std::string>&)
|
||||
{
|
||||
// Construct the cpplint command line.
|
||||
std::vector<std::string> cpplint_cmd = cmExpandedList(runCmd, true);
|
||||
@@ -326,9 +445,8 @@ static int HandleCppLint(const std::string& runCmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int HandleCppCheck(const std::string& runCmd,
|
||||
const std::string& sourceFile,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
int HandleCppCheck(const std::string& runCmd, const std::string& sourceFile,
|
||||
const std::vector<std::string>& orig_cmd)
|
||||
{
|
||||
// Construct the cpplint command line.
|
||||
std::vector<std::string> cppcheck_cmd = cmExpandedList(runCmd, true);
|
||||
@@ -391,7 +509,7 @@ struct CoCompiler
|
||||
bool NoOriginalCommand;
|
||||
};
|
||||
|
||||
static const std::array<CoCompiler, 5> CoCompilers = {
|
||||
const std::array<CoCompiler, 5> CoCompilers = {
|
||||
{ // Table of options and handlers.
|
||||
{ "--cppcheck=", HandleCppCheck, false },
|
||||
{ "--cpplint=", HandleCppLint, false },
|
||||
@@ -405,6 +523,7 @@ struct CoCompileJob
|
||||
std::string Command;
|
||||
CoCompileHandler Handler;
|
||||
};
|
||||
}
|
||||
|
||||
// called when args[0] == "__run_co_compile"
|
||||
int cmcmd::HandleCoCompileCommands(std::vector<std::string> const& args)
|
||||
@@ -586,7 +705,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
} else if (args[2] == "--ignore-eol") {
|
||||
filesDiffer = cmsys::SystemTools::TextFilesDiffer(args[3], args[4]);
|
||||
} else {
|
||||
::CMakeCommandUsage(args[0].c_str());
|
||||
CMakeCommandUsage(args[0].c_str());
|
||||
return 2;
|
||||
}
|
||||
|
||||
@@ -621,8 +740,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
if (outValid) {
|
||||
// The def file already exists and all input files are older than the
|
||||
// existing def file.
|
||||
// The def file already exists and all input files are older than
|
||||
// the existing def file.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1162,6 +1281,13 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(CMAKE_BOOTSTRAP) || defined(CMAKE_BOOTSTRAP_MAKEFILES)
|
||||
// Internal CMake compiler dependencies filtering
|
||||
if (args[1] == "cmake_cl_compile_depends") {
|
||||
return CLCompileAndDependencies(args);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Internal CMake link script support.
|
||||
if (args[1] == "cmake_link_script" && args.size() >= 3) {
|
||||
return cmcmd::ExecuteLinkScript(args);
|
||||
@@ -1412,7 +1538,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
|
||||
}
|
||||
}
|
||||
|
||||
::CMakeCommandUsage(args[0].c_str());
|
||||
CMakeCommandUsage(args[0].c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1779,8 +1905,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
|
||||
skipNextArg = false;
|
||||
continue;
|
||||
}
|
||||
// We use ++ as seperator between the preprocessing step definition and the
|
||||
// rc compilation step becase we need to prepend a -- to seperate the
|
||||
// We use ++ as seperator between the preprocessing step definition and
|
||||
// the rc compilation step becase we need to prepend a -- to seperate the
|
||||
// source file properly from other options when using clang-cl for
|
||||
// preprocessing.
|
||||
if (arg == "++") {
|
||||
@@ -1830,7 +1956,8 @@ int cmcmd::RunLLVMRC(std::vector<std::string> const& args)
|
||||
return 1;
|
||||
}
|
||||
// Since we might have skipped the last argument to llvm-rc
|
||||
// we need to make sure the llvm-rc source file is present in the commandline
|
||||
// we need to make sure the llvm-rc source file is present in the
|
||||
// commandline
|
||||
if (resource_compile.back() != intermediate_file) {
|
||||
resource_compile.push_back(intermediate_file);
|
||||
}
|
||||
@@ -2123,8 +2250,8 @@ int cmVSLink::LinkIncremental()
|
||||
// http://blogs.msdn.com/zakramer/archive/2006/05/22/603558.aspx
|
||||
|
||||
// 1. Compiler compiles the application and generates the *.obj files.
|
||||
// 2. An empty manifest file is generated if this is a clean build and if
|
||||
// not the previous one is reused.
|
||||
// 2. An empty manifest file is generated if this is a clean build and
|
||||
// if not the previous one is reused.
|
||||
// 3. The resource compiler (rc.exe) compiles the *.manifest file to a
|
||||
// *.res file.
|
||||
// 4. Linker generates the binary (EXE or DLL) with the /incremental
|
||||
|
||||
@@ -102,6 +102,12 @@ target_link_libraries(zot zot_pch)
|
||||
if(NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
|
||||
target_precompile_headers(zot_pch PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/zot_pch.hxx)
|
||||
endif()
|
||||
if (CMAKE_CXX_DEPENDS_USE_COMPILER AND
|
||||
CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.4")
|
||||
# Mixing pre-compile headers and flags to generate dependencies (-M options family)
|
||||
# causes the compiler to crash
|
||||
set_property(TARGET zot_pch PROPERTY DISABLE_PRECOMPILE_HEADERS ON)
|
||||
endif()
|
||||
|
||||
# Test the #include line macro transformation rule support.
|
||||
set_property(
|
||||
|
||||
@@ -67,7 +67,11 @@ else()
|
||||
endif()
|
||||
|
||||
# Test escaping of special characters in include directory paths.
|
||||
set(special_chars "~@%&{}()!'")
|
||||
set(special_chars "~@&{}()!'")
|
||||
if(NOT CMAKE_GENERATOR MATCHES "(Unix|MinGW|MSYS) Makefiles")
|
||||
# when compiler is used for dependencies, special characters for make are not escaped
|
||||
string(APPEND special_chars "%")
|
||||
endif()
|
||||
if(NOT CMAKE_GENERATOR STREQUAL "Watcom WMake")
|
||||
# Watcom seems to have no way to encode these characters.
|
||||
string(APPEND special_chars "#=[]")
|
||||
|
||||
46
Tests/RunCMake/BuildDepends/CompilerDependencies.cmake
Normal file
46
Tests/RunCMake/BuildDepends/CompilerDependencies.cmake
Normal file
@@ -0,0 +1,46 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(main ${CMAKE_CURRENT_BINARY_DIR}/main.c)
|
||||
|
||||
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
|
||||
set(check_pairs
|
||||
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.c\"
|
||||
\"$<TARGET_FILE:main>|${CMAKE_CURRENT_BINARY_DIR}/main.h\"
|
||||
)
|
||||
set(check_exes
|
||||
\"$<TARGET_FILE:main>\"
|
||||
)
|
||||
|
||||
if (check_step EQUAL 2)
|
||||
include(\"${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Makefile.cmake\")
|
||||
if (NOT CMAKE_DEPEND_INFO_FILES)
|
||||
set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPEND_INFO_FILES not found.\")
|
||||
else()
|
||||
include(\"${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_DEPEND_INFO_FILES}\")
|
||||
if (NOT CMAKE_DEPENDS_DEPENDENCY_FILES)
|
||||
set(RunCMake_TEST_FAILED \"Variable CMAKE_DEPENDS_DEPENDENCY_FILES not found.\")
|
||||
else()
|
||||
list(GET CMAKE_DEPENDS_DEPENDENCY_FILES 1 OBJECT_FILE)
|
||||
list(GET CMAKE_DEPENDS_DEPENDENCY_FILES 3 DEP_FILE)
|
||||
if (NOT EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
|
||||
set(RunCMake_TEST_FAILED \"File \${DEP_FILE} not found.\")
|
||||
else()
|
||||
set (TARGET_DEP_FILE \"${CMAKE_CURRENT_BINARY_DIR}/\${DEP_FILE}\")
|
||||
cmake_path(REPLACE_FILENAME TARGET_DEP_FILE \"compiler_depend.make\")
|
||||
file(READ \"\${TARGET_DEP_FILE}\" DEPENDS_CONTENT)
|
||||
if (WIN32)
|
||||
string (REPLACE \"\\\\\" \"/\" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
|
||||
string (TOLOWER \"\${DEPENDS_CONTENT}\" DEPENDS_CONTENT)
|
||||
string (TOLOWER \"\${OBJECT_FILE}\" OBJECT_FILE)
|
||||
else()
|
||||
string(REPLACE \"\\\\ \" \" \" DEPENDS_CONTENT \"\${DEPENDS_CONTENT}\")
|
||||
endif()
|
||||
if(NOT DEPENDS_CONTENT MATCHES \"\${OBJECT_FILE} *:.+main.c\"
|
||||
OR NOT DEPENDS_CONTENT MATCHES \"main.h\")
|
||||
set(RunCMake_TEST_FAILED \"Dependency file '\${TARGET_DEP_FILE}' badly generated.\")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
")
|
||||
@@ -0,0 +1,9 @@
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h" [[
|
||||
#define COUNT 1
|
||||
]])
|
||||
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.c" [[
|
||||
#include "main.h"
|
||||
|
||||
int main(void) { return COUNT; }
|
||||
]])
|
||||
@@ -0,0 +1,3 @@
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/main.h" [[
|
||||
#define COUNT 2
|
||||
]])
|
||||
@@ -113,3 +113,13 @@ if(CMake_TEST_BuildDepends_GNU_AS)
|
||||
set(ENV{ASM} "${CMake_TEST_BuildDepends_GNU_AS}")
|
||||
run_BuildDepends(GNU-AS)
|
||||
endif()
|
||||
|
||||
if ((RunCMake_GENERATOR STREQUAL "Unix Makefiles"
|
||||
AND (CMAKE_C_COMPILER_ID STREQUAL "GNU"
|
||||
OR CMAKE_C_COMPILER_ID STREQUAL "Clang"
|
||||
OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"))
|
||||
OR (RunCMake_GENERATOR STREQUAL "NMake Makefiles"
|
||||
AND MSVC_VERSION GREATER 1300
|
||||
AND CMAKE_C_COMPILER_ID STREQUAL "MSVC"))
|
||||
run_BuildDepends(CompilerDependencies)
|
||||
endif()
|
||||
|
||||
@@ -203,7 +203,10 @@ if(NOT DEFINED CMake_TEST_BuildDepends_GNU_AS
|
||||
set(CMake_TEST_BuildDepends_GNU_AS "${_gnu_as}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_RunCMake_test(BuildDepends
|
||||
-DMSVC_VERSION=${MSVC_VERSION}
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
-DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS}
|
||||
)
|
||||
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
|
||||
|
||||
3
Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake
Normal file
3
Tests/RunCMake/Make/TargetMessages-OFF-build-check.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
set (CHECK_TARGET_MESSAGES OFF)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
|
||||
@@ -1,5 +1 @@
|
||||
^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*
|
||||
)*Scanning dependencies of target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*$
|
||||
.*
|
||||
|
||||
3
Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake
Normal file
3
Tests/RunCMake/Make/TargetMessages-ON-build-check.cmake
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
set (CHECK_TARGET_MESSAGES ON)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
|
||||
@@ -1,8 +1 @@
|
||||
^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*
|
||||
)*Scanning dependencies of target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*
|
||||
Built target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*$
|
||||
.*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
set (CHECK_TARGET_MESSAGES OFF)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
|
||||
@@ -1,5 +1 @@
|
||||
^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*
|
||||
)*Scanning dependencies of target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*$
|
||||
.*
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
set (CHECK_TARGET_MESSAGES ON)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/TargetMessages-validation.cmake")
|
||||
@@ -1,8 +1 @@
|
||||
^(([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*
|
||||
)*Scanning dependencies of target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*
|
||||
Built target CustomTarget(
|
||||
([^B]|B[^u]|Bu[^i]|Bui[^l]|Buil[^t]|Built[^ ])[^
|
||||
]*)*$
|
||||
.*
|
||||
|
||||
10
Tests/RunCMake/Make/TargetMessages-validation.cmake
Normal file
10
Tests/RunCMake/Make/TargetMessages-validation.cmake
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
if (CHECK_TARGET_MESSAGES)
|
||||
if (NOT actual_stdout MATCHES "Built target CustomTarget")
|
||||
set (RunCMake_TEST_FAILED "Not found expected 'Built target' message.")
|
||||
endif()
|
||||
else()
|
||||
if (actual_stdout MATCHES "Built target CustomTarget")
|
||||
set (RunCMake_TEST_FAILED "Found unexpected 'Built target' message.")
|
||||
endif()
|
||||
endif()
|
||||
@@ -1054,12 +1054,14 @@ else
|
||||
CMAKE_CXX_SOURCES="${CMAKE_CXX_SOURCES} \
|
||||
cmDepends \
|
||||
cmDependsC \
|
||||
cmDependsCompiler \
|
||||
cmGlobalUnixMakefileGenerator3 \
|
||||
cmLocalUnixMakefileGenerator3 \
|
||||
cmMakefileExecutableTargetGenerator \
|
||||
cmMakefileLibraryTargetGenerator \
|
||||
cmMakefileTargetGenerator \
|
||||
cmMakefileUtilityTargetGenerator \
|
||||
cmProcessTools \
|
||||
"
|
||||
|
||||
JSONCPP_CXX_SOURCES=
|
||||
|
||||
Reference in New Issue
Block a user