endif()
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-dM" "-E" "-c" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
- set(CMAKE_PCH_EXTENSION .gch)
- if (NOT CMAKE_GENERATOR MATCHES "Xcode")
- set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+ if(NOT "x${lang}" STREQUAL "xFortran")
+ set(CMAKE_PCH_EXTENSION .gch)
+ if (NOT CMAKE_GENERATOR MATCHES "Xcode")
+ set(CMAKE_PCH_PROLOGUE "#pragma GCC system_header")
+ endif()
+ set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include <PCH_HEADER>)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include <PCH_HEADER>)
endif()
- set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -include <PCH_HEADER>)
- set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -x ${__pch_header_${lang}} -include <PCH_HEADER>)
endmacro()
endif()
list(APPEND CMAKE_${lang}_COMPILER_PREDEFINES_COMMAND "-QdM" "-P" "-Za" "${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp")
- # Precompile Headers
- set(CMAKE_PCH_EXTENSION .pchi)
- set(CMAKE_LINK_PCH ON)
- set(CMAKE_PCH_EPILOGUE "#pragma hdrstop")
- set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -Wno-pch-messages -pch-use <PCH_FILE> -include <PCH_HEADER>)
- set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -Wno-pch-messages -pch-create <PCH_FILE> -include <PCH_HEADER>)
+ if(NOT "x${lang}" STREQUAL "xFortran")
+ # Precompile Headers
+ set(CMAKE_PCH_EXTENSION .pchi)
+ set(CMAKE_LINK_PCH ON)
+ set(CMAKE_PCH_EPILOGUE "#pragma hdrstop")
+ set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH -Winvalid-pch -Wno-pch-messages -pch-use <PCH_FILE> -include <PCH_HEADER>)
+ set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH -Winvalid-pch -Wno-pch-messages -pch-create <PCH_FILE> -include <PCH_HEADER>)
+ endif()
endmacro()
endif()
# Since OpenSSL 3.0.0, the new version format is MAJOR.MINOR.PATCH and
# a new OPENSSL_VERSION_STR macro contains exactly that
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" OPENSSL_VERSION_STR
- REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]+\"([0-9])+\.([0-9])+\.([0-9])+\".*")
- string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9]+\.[0-9]+\.[0-9]+)\".*$"
+ REGEX "^#[\t ]*define[\t ]+OPENSSL_VERSION_STR[\t ]+\"([0-9])+\\.([0-9])+\\.([0-9])+\".*")
+ string(REGEX REPLACE "^.*OPENSSL_VERSION_STR[\t ]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\".*$"
"\\1" OPENSSL_VERSION_STR "${OPENSSL_VERSION_STR}")
set(OPENSSL_VERSION "${OPENSSL_VERSION_STR}")
+
+ unset(OPENSSL_VERSION_STR)
endif ()
endif ()
execute_process(COMMAND ${Subversion_SVN_EXECUTABLE} --version
OUTPUT_VARIABLE Subversion_VERSION_SVN
+ ERROR_VARIABLE _Subversion_VERSION_STDERR
+ RESULT_VARIABLE _Subversion_VERSION_RESULT
OUTPUT_STRIP_TRAILING_WHITESPACE)
# restore the previous LC_ALL
set(ENV{LC_ALL} ${_Subversion_SAVED_LC_ALL})
- string(REGEX REPLACE "^(.*\n)?svn, version ([.0-9]+).*"
- "\\2" Subversion_VERSION_SVN "${Subversion_VERSION_SVN}")
+ if(_Subversion_VERSION_RESULT EQUAL 0)
+ string(REGEX REPLACE "^(.*\n)?svn, version ([.0-9]+).*"
+ "\\2" Subversion_VERSION_SVN "${Subversion_VERSION_SVN}")
+ else()
+ unset(Subversion_VERSION_SVN)
+ if(_Subversion_VERSION_STDERR MATCHES "svn: error: The subversion command line tools are no longer provided by Xcode")
+ set(Subversion_SVN_EXECUTABLE Subversion_SVN_EXECUTABLE-NOTFOUND)
+ endif()
+ endif()
macro(Subversion_WC_INFO dir prefix)
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 17)
-set(CMake_VERSION_PATCH 3)
+set(CMake_VERSION_PATCH 4)
#set(CMake_VERSION_RC 0)
set(CMake_VERSION_IS_DIRTY 0)
if(NOT CMake_VERSION_NO_GIT)
# If this source was exported by 'git archive', use its commit info.
- set(git_info [==[e647949539 CMake 3.17.3]==])
+ set(git_info [==[103d6faed9 CMake 3.17.4]==])
# Otherwise, try to identify the current development source version.
if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
info.DefFileGenerated = false;
#endif
if (info.DefFileGenerated) {
- info.DefFile = this->ObjectDirectory /* has slash */ + "exports.def";
+ info.DefFile =
+ this->GetObjectDirectory(config) /* has slash */ + "exports.def";
} else if (!info.Sources.empty()) {
info.DefFile = info.Sources.front()->GetFullPath();
}
}
std::string& filename = inserted.first->second;
- this->AddSource(pchSource, true);
-
auto pchSf = this->Makefile->GetOrCreateSource(
pchSource, false, cmSourceFileLocationKind::Known);
continue;
}
lg->AddUnityBuild(gt.get());
- lg->AddPchDependencies(gt.get());
+ // Targets that re-use a PCH are handled below.
+ if (!gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
+ lg->AddPchDependencies(gt.get());
+ }
+ }
+ }
+ for (const auto& lg : this->LocalGenerators) {
+ for (const auto& gt : lg->GetGeneratorTargets()) {
+ if (gt->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
+ gt->GetType() == cmStateEnums::UTILITY ||
+ gt->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ continue;
+ }
+ // Handle targets that re-use a PCH from an above-handled target.
+ if (gt->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
+ lg->AddPchDependencies(gt.get());
+ }
}
}
// The above transformations may have changed the classification of sources.
if (this->ExpressEdition) {
fout << "# Visual Studio Express 16 for Windows Desktop\n";
} else {
- fout << "# Visual Studio 16\n";
+ fout << "# Visual Studio Version 16\n";
}
break;
}
return GRAPHVIZ_NODE_SHAPE_LIBRARY_UNKNOWN;
}
}
+
+struct DependeesDir
+{
+ template <typename T>
+ static const cmLinkItem& src(const T& con)
+ {
+ return con.src;
+ }
+
+ template <typename T>
+ static const cmLinkItem& dst(const T& con)
+ {
+ return con.dst;
+ }
+};
+
+struct DependersDir
+{
+ template <typename T>
+ static const cmLinkItem& src(const T& con)
+ {
+ return con.dst;
+ }
+
+ template <typename T>
+ static const cmLinkItem& dst(const T& con)
+ {
+ return con.src;
+ }
+};
}
cmGraphVizWriter::cmGraphVizWriter(std::string const& fileName,
return;
}
+ // write global data directly
this->WriteConnection(this->GlobalFileStream, depender, dependee, scopeType);
if (this->GeneratePerTarget) {
- auto fileStream = PerTargetFileStreams[depender.AsStr()].get();
- this->WriteNode(*fileStream, dependee);
- this->WriteConnection(*fileStream, depender, dependee, scopeType);
+ PerTargetConnections[depender].emplace_back(depender, dependee, scopeType);
}
if (this->GenerateDependers) {
- auto fileStream = TargetDependersFileStreams[dependee.AsStr()].get();
- this->WriteNode(*fileStream, depender);
- this->WriteConnection(*fileStream, depender, dependee, scopeType);
+ TargetDependersConnections[dependee].emplace_back(dependee, depender,
+ scopeType);
}
}
}
}
+ // write global data and collect all connection data for per target graphs
for (auto const gt : sortedGeneratorTargets) {
auto item = cmLinkItem(gt, false, gt->GetBacktrace());
this->VisitItem(item);
}
+
+ if (this->GeneratePerTarget) {
+ WritePerTargetConnections<DependeesDir>(PerTargetConnections,
+ PerTargetFileStreams);
+ }
+
+ if (this->GenerateDependers) {
+ WritePerTargetConnections<DependersDir>(TargetDependersConnections,
+ TargetDependersFileStreams);
+ }
+}
+
+void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap,
+ const cmLinkItem& rootItem,
+ Connections& extendedCons,
+ std::set<cmLinkItem>& visitedItems)
+{
+ // some "targets" are not in map, e.g. linker flags as -lm or
+ // targets without dependency.
+ // in both cases we are finished with traversing the graph
+ if (connectionMap.find(rootItem) == connectionMap.cend()) {
+ return;
+ }
+
+ const Connections& origCons = connectionMap.at(rootItem);
+
+ for (const Connection& con : origCons) {
+ extendedCons.emplace_back(con);
+ const cmLinkItem& dstItem = con.dst;
+ bool const visited = visitedItems.find(dstItem) != visitedItems.cend();
+ if (!visited) {
+ visitedItems.insert(dstItem);
+ FindAllConnections(connectionMap, dstItem, extendedCons, visitedItems);
+ }
+ }
+}
+
+void cmGraphVizWriter::FindAllConnections(const ConnectionsMap& connectionMap,
+ const cmLinkItem& rootItem,
+ Connections& extendedCons)
+{
+ std::set<cmLinkItem> visitedItems = { rootItem };
+ FindAllConnections(connectionMap, rootItem, extendedCons, visitedItems);
+}
+
+template <typename DirFunc>
+void cmGraphVizWriter::WritePerTargetConnections(
+ const ConnectionsMap& connections, const FileStreamMap& streams)
+{
+ // the per target connections must be extended by indirect dependencies
+ ConnectionsMap extendedConnections;
+ for (auto const& conPerTarget : connections) {
+ const cmLinkItem& rootItem = conPerTarget.first;
+ Connections& extendedCons = extendedConnections[conPerTarget.first];
+ FindAllConnections(connections, rootItem, extendedCons);
+ }
+
+ for (auto const& conPerTarget : extendedConnections) {
+ const cmLinkItem& rootItem = conPerTarget.first;
+
+ // some of the nodes are excluded completely and are not written
+ if (this->ItemExcluded(rootItem)) {
+ continue;
+ }
+
+ const Connections& cons = conPerTarget.second;
+ auto fileStream = streams.at(rootItem.AsStr()).get();
+
+ for (const Connection& con : cons) {
+ const cmLinkItem& src = DirFunc::src(con);
+ const cmLinkItem& dst = DirFunc::dst(con);
+ this->WriteNode(*fileStream, con.dst);
+ this->WriteConnection(*fileStream, src, dst, con.scopeType);
+ }
+ }
}
void cmGraphVizWriter::WriteHeader(cmGeneratedFileStream& fs,
#include <map>
#include <memory>
+#include <set>
#include <string>
+#include <utility>
#include <vector>
#include "cmsys/RegularExpression.hxx"
#include "cmGeneratedFileStream.h"
+#include "cmLinkItem.h"
#include "cmLinkItemGraphVisitor.h"
#include "cmStateTypes.h"
-class cmLinkItem;
class cmGlobalGenerator;
/** This class implements writing files for graphviz (dot) for graphs
using FileStreamMap =
std::map<std::string, std::unique_ptr<cmGeneratedFileStream>>;
+ struct Connection
+ {
+ Connection(cmLinkItem s, cmLinkItem d, std::string scope)
+ : src(std::move(s))
+ , dst(std::move(d))
+ , scopeType(std::move(scope))
+ {
+ }
+
+ cmLinkItem src;
+ cmLinkItem dst;
+ std::string scopeType;
+ };
+ using Connections = std::vector<Connection>;
+ using ConnectionsMap = std::map<cmLinkItem, Connections>;
+
void VisitLink(cmLinkItem const& depender, cmLinkItem const& dependee,
bool isDirectLink, std::string const& scopeType = "");
cmLinkItem const& dependeeTargetName,
std::string const& edgeStyle);
+ void FindAllConnections(const ConnectionsMap& connectionMap,
+ const cmLinkItem& rootItem,
+ Connections& extendedCons,
+ std::set<cmLinkItem>& visitedItems);
+
+ void FindAllConnections(const ConnectionsMap& connectionMap,
+ const cmLinkItem& rootItem,
+ Connections& extendedCons);
+
+ template <typename DirFunc>
+ void WritePerTargetConnections(const ConnectionsMap& connections,
+ const FileStreamMap& streams);
+
bool ItemExcluded(cmLinkItem const& item);
bool ItemNameFilteredOut(std::string const& itemName);
bool TargetTypeEnabled(cmStateEnums::TargetType targetType) const;
FileStreamMap PerTargetFileStreams;
FileStreamMap TargetDependersFileStreams;
+ ConnectionsMap PerTargetConnections;
+ ConnectionsMap TargetDependersConnections;
+
std::string GraphName;
std::string GraphHeader;
std::string GraphNodePrefix;
static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config));
- build.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") +
- genTarget->GetName() + ".rsp");
+ std::string path = localGen.GetHomeRelativeOutputPath();
+ if (!path.empty()) {
+ path += '/';
+ }
+ build.RspFile = this->ConvertToNinjaPath(
+ cmStrCat(path, "CMakeFiles/", genTarget->GetName(),
+ globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp"));
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(
globalGen->GetRuleCmdLength(linkBuild.Rule);
}
- linkBuild.RspFile = this->ConvertToNinjaPath(std::string("CMakeFiles/") +
- gt->GetName() + ".rsp");
+ std::string path = localGen.GetHomeRelativeOutputPath();
+ if (!path.empty()) {
+ path += '/';
+ }
+ linkBuild.RspFile = this->ConvertToNinjaPath(
+ cmStrCat(path, "CMakeFiles/", gt->GetName(),
+ globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp"));
// Gather order-only dependencies.
this->GetLocalGenerator()->AppendTargetDepends(gt, linkBuild.OrderOnlyDeps,
ensure_files_match(
${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_default_options.dot
${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot)
+
+ensure_files_match(
+ ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_target_dependencies.dot.GraphicApplication
+ ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot.GraphicApplication)
+
+ensure_files_match(
+ ${RunCMake_TEST_SOURCE_DIR}/expected_outputs/dependency_graph_target_dependers.dot.CompilerFlags.dependers
+ ${RunCMake_TEST_BINARY_DIR}/generated_dependency_graph.dot.CompilerFlags.dependers)
--- /dev/null
+digraph "GraphicApplication" {
+node [
+ fontsize = "12"
+];
+ "node5" [ label = "GraphicApplication", shape = egg ];
+ "node2" [ label = "CoreLibrary", shape = octagon ];
+ "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary
+ "node0" [ label = "CompilerFlags", shape = pentagon ];
+ "node2" -> "node0" // CoreLibrary -> CompilerFlags
+ "node3" [ label = "GoofyLoggingLibrary\n(SeriousLoggingLibrary)\n(TheBestLoggingLibrary)", shape = pentagon ];
+ "node2" -> "node3" [ style = dotted ] // CoreLibrary -> GoofyLoggingLibrary
+ "node6" [ label = "GraphicLibrary", shape = doubleoctagon ];
+ "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary
+ "node7" [ label = "\"-lm\"", shape = septagon ];
+ "node6" -> "node7" [ style = dotted ] // GraphicLibrary -> "-lm"
+ "node0" [ label = "CompilerFlags", shape = pentagon ];
+ "node6" -> "node0" // GraphicLibrary -> CompilerFlags
+ "node2" [ label = "CoreLibrary", shape = octagon ];
+ "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary
+ "node8" [ label = "GraphicLibraryObjects", shape = hexagon ];
+ "node6" -> "node8" [ style = dotted ] // GraphicLibrary -> GraphicLibraryObjects
+}
--- /dev/null
+digraph "CompilerFlags" {
+node [
+ fontsize = "12"
+];
+ "node0" [ label = "CompilerFlags", shape = pentagon ];
+ "node2" [ label = "CoreLibrary", shape = octagon ];
+ "node2" -> "node0" // CoreLibrary -> CompilerFlags
+ "node1" [ label = "ConsoleApplication", shape = egg ];
+ "node1" -> "node2" [ style = dotted ] // ConsoleApplication -> CoreLibrary
+ "node5" [ label = "GraphicApplication", shape = egg ];
+ "node5" -> "node2" [ style = dotted ] // GraphicApplication -> CoreLibrary
+ "node6" [ label = "GraphicLibrary", shape = doubleoctagon ];
+ "node6" -> "node2" [ style = dotted ] // GraphicLibrary -> CoreLibrary
+ "node5" [ label = "GraphicApplication", shape = egg ];
+ "node5" -> "node6" [ style = dotted ] // GraphicApplication -> GraphicLibrary
+ "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ];
+ "node9" -> "node2" [ style = dotted ] // GraphicDriverOpenGL -> CoreLibrary
+ "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ];
+ "node10" -> "node2" [ style = dotted ] // GraphicDriverVulkan -> CoreLibrary
+ "node6" [ label = "GraphicLibrary", shape = doubleoctagon ];
+ "node6" -> "node0" // GraphicLibrary -> CompilerFlags
+ "node9" [ label = "GraphicDriverOpenGL", shape = tripleoctagon ];
+ "node9" -> "node0" [ style = dotted ] // GraphicDriverOpenGL -> CompilerFlags
+ "node10" [ label = "GraphicDriverVulkan", shape = tripleoctagon ];
+ "node10" -> "node0" [ style = dotted ] // GraphicDriverVulkan -> CompilerFlags
+}
enable_language(C)
+set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+
file(TOUCH ${CMAKE_BINARY_DIR}/empty.cmake)
include(${CMAKE_BINARY_DIR}/empty.cmake)
add_definitions(-DHAVE_PCH_SUPPORT)
endif()
+# Add this before the target from which we will reuse the PCH
+# to test that generators can handle reversed ordering.
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+
add_library(empty empty.c)
target_precompile_headers(empty PRIVATE
<stdio.h>
)
target_include_directories(empty PUBLIC include)
-add_library(foo foo.c)
-target_include_directories(foo PUBLIC include)
target_precompile_headers(foo REUSE_FROM empty)
# should not cause problems if configured multiple times
}
#endif
-#if (__cplusplus >= 201703L || defined(__INTEL_COMPILER) && defined(__cpp_if_constexpr))
+#if (__cplusplus >= 201703L || defined(__INTEL_COMPILER) && defined(__cpp_deduction_guides))
#include <optional>
template <typename T,
typename std::invoke_result<decltype(&T::get), T>::type = nullptr>