Commit a9fb9a87 authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'ninja-swift'

a9180ccf Tests: add a check for the Swift compiler
d745551f Help: add some initial documentation for Swift support
9a182c9e Auxiliary: update vim syntax highlighting
e9b0063e Modules: add build rules for Swift Ninja support
b6412e3e Ninja: add placeholders to support Swift build
7d7f3116 Ninja: add support for Swift's output-file-map.json
d688c4c1 Swift: remove unnecessary unreleased Ninja infrastructure
07235822 Swift: Detect compiler version
...
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !3297
parents 28ee3114 a9180ccf
Pipeline #137335 passed with stage
in 0 seconds
......@@ -96,6 +96,7 @@ syn keyword cmakeProperty contained
\ CMAKE_CONFIGURE_DEPENDS
\ CMAKE_CXX_KNOWN_FEATURES
\ CMAKE_C_KNOWN_FEATURES
\ CMAKE_Swift_MODULE_DIRECTORY
\ COMMON_LANGUAGE_RUNTIME
\ COMPATIBLE_INTERFACE_BOOL
\ COMPATIBLE_INTERFACE_NUMBER_MAX
......@@ -287,6 +288,11 @@ syn keyword cmakeProperty contained
\ STRINGS
\ SUBDIRECTORIES
\ SUFFIX
\ Swift_DEPENDENCIES_FILE
\ Swift_DIAGNOSTICS_FILE
\ Swift_MODULE
\ Swift_MODULE_DIRECTORY
\ Swift_MODULE_NAME
\ SYMBOLIC
\ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
\ TARGET_MESSAGES
......
SWIFTC
------
.. include:: ENV_VAR.txt
Preferred executable for compiling ``Swift`` language files. Will only be used by
CMake on the first configuration to determine ``Swift`` compiler, after which the
value for ``SWIFTC`` is stored in the cache as
:variable:`CMAKE_Swift_COMPILER <CMAKE_<LANG>_COMPILER>`. For any configuration run
(including the first), the environment variable will be ignored if the
:variable:`CMAKE_Swift_COMPILER <CMAKE_<LANG>_COMPILER>` variable is defined.
......@@ -52,6 +52,7 @@ Environment Variables for Languages
/envvar/FFLAGS
/envvar/RC
/envvar/RCFLAGS
/envvar/SWIFTC
Environment Variables for CTest
===============================
......
......@@ -315,6 +315,9 @@ Properties on Targets
/prop_tgt/STATIC_LIBRARY_FLAGS
/prop_tgt/STATIC_LIBRARY_OPTIONS
/prop_tgt/SUFFIX
/prop_tgt/Swift_DEPENDENCIES_FILE
/prop_tgt/Swift_MODULE_DIRECTORY
/prop_tgt/Swift_MODULE_NAME
/prop_tgt/TYPE
/prop_tgt/VERSION
/prop_tgt/VISIBILITY_INLINES_HIDDEN
......@@ -439,6 +442,8 @@ Properties on Source Files
/prop_sf/SKIP_AUTOMOC
/prop_sf/SKIP_AUTORCC
/prop_sf/SKIP_AUTOUIC
/prop_sf/Swift_DEPENDENCIES_FILE
/prop_sf/Swift_DIAGNOSTICS_FILE
/prop_sf/SYMBOLIC
/prop_sf/VS_COPY_TO_OUT_DIR
/prop_sf/VS_CSHARP_tagname
......
......@@ -97,6 +97,7 @@ Variables that Provide Information
/variable/CMAKE_SOURCE_DIR
/variable/CMAKE_STATIC_LIBRARY_PREFIX
/variable/CMAKE_STATIC_LIBRARY_SUFFIX
/variable/CMAKE_Swift_MODULE_DIRECTORY
/variable/CMAKE_TOOLCHAIN_FILE
/variable/CMAKE_TWEAK_VERSION
/variable/CMAKE_VERBOSE_MAKEFILE
......
Swift_DEPENDENCIES_FILE
-----------------------
This property sets the path for the Swift dependency file (swiftdeps) for the
source.
Swift_DIAGNOSTICS_FILE
----------------------
This property controls where the Swift diagnostics are serialized.
Swift_DEPENDENCIES_FILE
-----------------------
This property sets the path for the Swift dependency file (swiftdep) for the
target.
Swift_MODULE_DIRECTORY
----------------------
Specify output directory for Swift modules provided by the target.
If the target contains Swift source files, this specifies the directory in which
the modules will be placed. When this property is not set, the modules will be
placed in the build directory corresponding to the target's source directory.
If the variable :variable:`CMAKE_Swift_MODULE_DIRECTORY` is set when a target is
created its value is used to initialise this property.
Swift_MODULE_NAME
-----------------
This property specifies the name of the Swift module. It is defaulted to the
name of the target.
Swift Language Support
----------------------
* Preliminary support for the Swift language with the :generator:`Ninja`
generator was added. Use the :envvar:`SWIFTC` environment variable to
specify a compiler.
* Support to emit an output file map was added to enable Swift compilation.
* A target property :prop_tgt:`Swift_DEPENDENCIES_FILE` was added to targets to
indicate where to save the target swift dependencies file. If one is not
specified, it will default to `<TARGET>.swiftdeps`.
* A target property :prop_tgt:`Swift_MODULE_NAME` was added to targets to
indicate the Swift module name. If it is not specified, it will default to
the name of the target.
* A source property :prop_sf:`Swift_DEPENDENCIES_FILE` was added to sources to
indicate where to save the target swift dependencies file. If one is not
specified, it will default to `<OBJECT>.swiftdeps`.
* A source property :prop_sf:`Swift_DIAGNOSTICS_FILE` was added to sources to
indicate where to write the serialised Swift diagnostics.
CMAKE_Swift_MODULE_DIRECTORY
----------------------------
Swift module output directory.
This variable is used to initialise the :prop_tgt:`Swift_MODULE_DIRECTORY`
property on all the targets. See the target property for additional
information.
......@@ -46,6 +46,14 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
endif()
endforeach()
# Check if compiler id detection gave us the compiler tool.
if(CMAKE_${lang}_COMPILER_ID_TOOL)
set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_ID_TOOL}")
set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_ID_TOOL}" PARENT_SCOPE)
elseif(NOT CMAKE_${lang}_COMPILER)
set(CMAKE_${lang}_COMPILER "CMAKE_${lang}_COMPILER-NOTFOUND" PARENT_SCOPE)
endif()
# If the compiler is still unknown, try to query its vendor.
if(CMAKE_${lang}_COMPILER AND NOT CMAKE_${lang}_COMPILER_ID)
foreach(userflags "${CMAKE_${lang}_COMPILER_ID_FLAGS_LIST}" "")
......@@ -76,6 +84,30 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
endif()
endif()
# For Swift we need to explicitly query the version.
if(lang STREQUAL "Swift"
AND CMAKE_${lang}_COMPILER
AND NOT CMAKE_${lang}_COMPILER_VERSION)
execute_process(
COMMAND "${CMAKE_${lang}_COMPILER}"
-version
OUTPUT_VARIABLE output ERROR_VARIABLE output
RESULT_VARIABLE result
TIMEOUT 10
)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Running the ${lang} compiler: \"${CMAKE_${lang}_COMPILER}\" -version\n"
"${output}\n"
)
if(output MATCHES [[Swift version ([0-9]+\.[0-9]+(\.[0-9]+)?)]])
set(CMAKE_${lang}_COMPILER_VERSION "${CMAKE_MATCH_1}")
if(NOT CMAKE_${lang}_COMPILER_ID)
set(CMAKE_Swift_COMPILER_ID "Apple")
endif()
endif()
endif()
if (COMPILER_QNXNTO AND CMAKE_${lang}_COMPILER_ID STREQUAL "GNU")
execute_process(
COMMAND "${CMAKE_${lang}_COMPILER}"
......@@ -124,13 +156,6 @@ function(CMAKE_DETERMINE_COMPILER_ID lang flagvar src)
message(STATUS "The ${lang} compiler identification is unknown")
endif()
# Check if compiler id detection gave us the compiler tool.
if(CMAKE_${lang}_COMPILER_ID_TOOL)
set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER_ID_TOOL}" PARENT_SCOPE)
elseif(NOT CMAKE_${lang}_COMPILER)
set(CMAKE_${lang}_COMPILER "CMAKE_${lang}_COMPILER-NOTFOUND" PARENT_SCOPE)
endif()
set(CMAKE_${lang}_COMPILER_ID "${CMAKE_${lang}_COMPILER_ID}" PARENT_SCOPE)
set(CMAKE_${lang}_PLATFORM_ID "${CMAKE_${lang}_PLATFORM_ID}" PARENT_SCOPE)
set(CMAKE_${lang}_COMPILER_ARCHITECTURE_ID "${CMAKE_${lang}_COMPILER_ARCHITECTURE_ID}" PARENT_SCOPE)
......
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
# Local system-specific compiler preferences for this language.
include(Platform/${CMAKE_SYSTEM_NAME}-Determine-Swift OPTIONAL)
include(Platform/${CMAKE_SYSTEM_NAME}-Swift OPTIONAL)
if(NOT CMAKE_Swift_COMPILER_NAMES)
set(CMAKE_Swift_COMPILER_NAMES swiftc)
endif()
if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
if(XCODE_VERSION VERSION_LESS 6.1)
message(FATAL_ERROR "Swift language not supported by Xcode ${XCODE_VERSION}")
endif()
set(CMAKE_Swift_COMPILER_XCODE_TYPE sourcecode.swift)
_cmake_find_compiler_path(Swift)
elseif("${CMAKE_GENERATOR}" STREQUAL "Ninja")
if(CMAKE_Swift_COMPILER)
_cmake_find_compiler_path(Swift)
else()
set(CMAKE_Swift_COMPILER_INIT NOTFOUND)
if(NOT $ENV{SWIFTC} STREQUAL "")
get_filename_component(CMAKE_Swift_COMPILER_INIT $ENV{SWIFTC} PROGRAM
PROGRAM_ARGS CMAKE_Swift_FLAGS_ENV_INIT)
if(CMAKE_Swift_FLAGS_ENV_INIT)
set(CMAKE_Swift_COMPILER_ARG1 "${CMAKE_Swift_FLAGS_ENV_INIT}" CACHE
STRING "First argument to the Swift compiler")
endif()
if(NOT EXISTS ${CMAKE_Swift_COMPILER_INIT})
message(FATAL_ERROR "Could not find compiler set in environment variable SWIFTC\n$ENV{SWIFTC}.\n${CMAKE_Swift_COMPILER_INIT}")
endif()
endif()
if(NOT CMAKE_Swift_COMPILER_INIT)
set(CMAKE_Swift_COMPILER_LIST swiftc ${_CMAKE_TOOLCHAIN_PREFIX}swiftc)
endif()
_cmake_find_compiler(Swift)
endif()
mark_as_advanced(CMAKE_Swift_COMPILER)
else()
message(FATAL_ERROR "Swift language not supported by \"${CMAKE_GENERATOR}\" generator")
endif()
......@@ -18,11 +49,13 @@ endif()
if(NOT CMAKE_Swift_COMPILER_ID_RUN)
set(CMAKE_Swift_COMPILER_ID_RUN 1)
list(APPEND CMAKE_Swift_COMPILER_ID_MATCH_VENDORS Apple)
set(CMAKE_Swift_COMPILER_ID_MATCH_VENDOR_REGEX_Apple "com.apple.xcode.tools.swift.compiler")
if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
list(APPEND CMAKE_Swift_COMPILER_ID_MATCH_VENDORS Apple)
set(CMAKE_Swift_COMPILER_ID_MATCH_VENDOR_REGEX_Apple "com.apple.xcode.tools.swift.compiler")
set(CMAKE_Swift_COMPILER_ID_TOOL_MATCH_REGEX "\nCompileSwiftSources[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]* -c[^\r\n]*CompilerIdSwift/CompilerId/main.swift")
set(CMAKE_Swift_COMPILER_ID_TOOL_MATCH_INDEX 2)
set(CMAKE_Swift_COMPILER_ID_TOOL_MATCH_REGEX "\nCompileSwiftSources[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]* -c[^\r\n]*CompilerIdSwift/CompilerId/main.swift")
set(CMAKE_Swift_COMPILER_ID_TOOL_MATCH_INDEX 2)
endif()
# Try to identify the compiler.
set(CMAKE_Swift_COMPILER_ID)
......@@ -40,6 +73,6 @@ unset(_CMAKE_PROCESSING_LANGUAGE)
# configure variables set in this file for fast reload later on
configure_file(${CMAKE_ROOT}/Modules/CMakeSwiftCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake
@ONLY
)
${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake @ONLY)
set(CMAKE_Swift_COMPILER_ENV_VAR "SWIFTC")
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
set(CMAKE_Swift_COMPILER "@CMAKE_Swift_COMPILER@")
set(CMAKE_Swift_COMPILER_ID "@CMAKE_Swift_COMPILER_ID@")
set(CMAKE_Swift_COMPILER_VERSION "@CMAKE_Swift_COMPILER_VERSION@")
set(CMAKE_Swift_COMPILER_LOADED 1)
set(CMAKE_Swift_COMPILER_WORKS "@CMAKE_Swift_COMPILER_WORKS@")
set(CMAKE_Swift_COMPILER_ENV_VAR "SWIFTC")
set(CMAKE_Swift_COMPILER_ID_RUN 1)
set(CMAKE_Swift_SOURCE_FILE_EXTENSIONS swift)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
set(CMAKE_Swift_OUTPUT_EXTENSION .o)
set(CMAKE_INCLUDE_FLAG_Swift "-I")
if(UNIX)
set(CMAKE_Swift_OUTPUT_EXTENSION .o)
else()
set(CMAKE_Swift_OUTPUT_EXTENSION .obj)
endif()
# Load compiler-specific information.
if(CMAKE_Swift_COMPILER_ID)
include(Compiler/${CMAKE_Swift_COMPILER_ID}-Swift OPTIONAL)
endif()
# load the system- and compiler specific files
if(CMAKE_Swift_COMPILER_ID)
# load a hardware specific file, mostly useful for embedded compilers
if(CMAKE_SYSTEM_PROCESSOR)
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
endif()
include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_Swift_COMPILER_ID}-Swift OPTIONAL)
endif()
# for most systems a module is the same as a shared library
# so unless the variable CMAKE_MODULE_EXISTS is set just
# copy the values from the LIBRARY variables
if(NOT CMAKE_MODULE_EXISTS)
set(CMAKE_SHARED_MODULE_Swift_FLAGS ${CMAKE_SHARED_LIBRARY_Swift_FLAGS})
set(CMAKE_SHARED_MODULE_CREATE_Swift_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_Swift_FLAGS})
set(CMAKE_INCLUDE_FLAG_Swift "-I")
set(CMAKE_INCLUDE_FLAG_SEP_Swift " ")
set(CMAKE_Swift_DEFINE_FLAG -D)
set(CMAKE_Swift_COMPILE_OPTIONS_TARGET "-target ")
set(CMAKE_Swift_COMPILER_ARG1 -frontend)
set(CMAKE_Swift_FLAGS_DEBUG_INIT "-g")
set(CMAKE_Swift_FLAGS_RELEASE_INIT "-O")
set(CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT "-O -g")
set(CMAKE_Swift_FLAGS_MINSIZEREL_INIT "-Osize")
# NOTE(compnerd) we do not have an object compile rule since we build the objects as part of the link step
if(NOT CMAKE_Swift_COMPILE_OBJECT)
set(CMAKE_Swift_COMPILE_OBJECT ":")
endif()
include(CMakeCommonLanguageInclude)
if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY)
if(CMAKE_Swift_COMPILER_TARGET)
set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <FLAGS> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
else()
set(CMAKE_Swift_CREATE_SHARED_LIBRARY "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -emit-library -o <TARGET> -module-name <SWIFT_MODULE_NAME> -module-link-name <SWIFT_LIBRARY_NAME> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <FLAGS> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
endif()
endif()
if(NOT CMAKE_Swift_CREATE_SHARED_MODULE)
set(CMAKE_Swift_CREATE_SHARED_MODULE ${CMAKE_Swift_CREATE_SHARED_LIBRARY})
endif()
if(NOT CMAKE_Swift_LINK_EXECUTABLE)
if(CMAKE_Swift_COMPILER_TARGET)
set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -target <CMAKE_Swift_COMPILER_TARGET> -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <FLAGS> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
else()
set(CMAKE_Swift_LINK_EXECUTABLE "${CMAKE_Swift_COMPILER} -output-file-map <SWIFT_OUTPUT_FILE_MAP> -incremental -emit-executable -o <TARGET> -emit-module -emit-module-path <SWIFT_MODULE> -emit-dependencies <FLAGS> <SWIFT_SOURCES> <LINK_FLAGS> <LINK_LIBRARIES>")
endif()
endif()
if(NOT CMAKE_Swift_CREATE_STATIC_LIBRARY)
set(CMAKE_Swift_ARCHIVE_CREATE "<CMAKE_AR> crs <TARGET> <OBJECTS>")
set(CMAKE_Swift_ARCHIVE_FINISH "")
endif()
set(CMAKE_Swift_INFORMATION_LOADED 1)
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.
if(CMAKE_Swift_COMPILER_FORCED)
# The compiler configuration was forced by the user.
# Assume the user has configured all compiler information.
......@@ -23,7 +22,6 @@ unset(CMAKE_Swift_COMPILER_WORKS CACHE)
if(NOT CMAKE_Swift_COMPILER_WORKS)
PrintTestCompilerStatus("Swift" "")
file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift
"import Foundation\n"
"print(\"CMake\")\n")
try_compile(CMAKE_Swift_COMPILER_WORKS ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/main.swift
......@@ -51,6 +49,11 @@ else()
"Determining if the Swift compiler works passed with "
"the following output:\n${__CMAKE_Swift_COMPILER_OUTPUT}\n\n")
endif()
# Re-configure to save learned information.
configure_file(${CMAKE_ROOT}/Modules/CMakeSwiftCompiler.cmake.in
${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake @ONLY)
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeSwiftCompiler.cmake)
endif()
unset(__CMAKE_Swift_COMPILER_OUTPUT)
......@@ -281,10 +281,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());
vars.Language = this->TargetLinkLanguage.c_str();
if (this->TargetLinkLanguage == "Swift") {
vars.SwiftPartialModules = "$SWIFT_PARTIAL_MODULES";
vars.TargetSwiftModule = "$TARGET_SWIFT_MODULE";
vars.TargetSwiftDoc = "$TARGET_SWIFT_DOC";
vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME";
vars.SwiftModule = "$SWIFT_MODULE";
vars.SwiftModuleName = "$SWIFT_MODULE_NAME";
vars.SwiftOutputFileMap = "$SWIFT_OUTPUT_FILE_MAP";
vars.SwiftSources = "$SWIFT_SOURCES";
}
std::string responseFlag;
......@@ -805,35 +808,82 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
outputs.push_back(targetOutputReal);
if (this->TargetLinkLanguage == "Swift") {
if (const char* name = gt.GetProperty("SWIFT_MODULE_NAME")) {
vars["TARGET_SWIFT_DOC"] = std::string(name) + ".swiftdoc";
vars["TARGET_SWIFT_MODULE"] = std::string(name) + ".swiftmodule";
} else {
vars["TARGET_SWIFT_DOC"] = gt.GetName() + ".swiftdoc";
vars["TARGET_SWIFT_MODULE"] = gt.GetName() + ".swiftmodule";
}
outputs.push_back(vars["TARGET_SWIFT_DOC"]);
outputs.push_back(vars["TARGET_SWIFT_MODULE"]);
vars["SWIFT_LIBRARY_NAME"] = [this]() -> std::string {
cmGeneratorTarget::Names targetNames =
this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName());
return targetNames.Base;
}();
vars["SWIFT_MODULE"] = [this]() -> std::string {
cmGeneratorTarget::Names targetNames =
this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName());
std::string directory =
this->GetLocalGenerator()->GetCurrentBinaryDirectory();
if (const char* prop = this->GetGeneratorTarget()->GetProperty(
"Swift_MODULE_DIRECTORY")) {
directory = prop;
}
std::string name = targetNames.Base + ".swiftmodule";
if (const char* prop =
this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) {
name = prop;
}
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
return this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(directory + "/" + name),
cmOutputConverter::SHELL);
}();
std::string partials;
std::vector<cmSourceFile const*> sources;
gt.GetObjectSources(sources, this->GetConfigName());
for (cmSourceFile const* source : sources) {
partials += " ";
if (const char* partial = source->GetProperty("SWIFT_PARTIAL_MODULE")) {
partials += partial;
} else {
partials += localGen.GetTargetDirectory(&gt) + "/" +
gt.GetObjectName(source) + ".swiftmodule";
vars["SWIFT_MODULE_NAME"] = [this]() -> std::string {
if (const char* name =
this->GetGeneratorTarget()->GetProperty("Swift_MODULE_NAME")) {
return name;
}
}
vars["SWIFT_PARTIAL_MODULES"] = partials;
return this->GetGeneratorTarget()->GetName();
}();
vars["SWIFT_OUTPUT_FILE_MAP"] =
this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(gt.GetSupportDirectory() +
"/output-file-map.json"),
cmOutputConverter::SHELL);
vars["SWIFT_SOURCES"] = [this]() -> std::string {
std::vector<cmSourceFile const*> sources;
std::stringstream oss;
this->GetGeneratorTarget()->GetObjectSources(sources,
this->GetConfigName());
cmLocalGenerator const* LocalGen = this->GetLocalGenerator();
for (const auto& source : sources) {
oss << " "
<< LocalGen->ConvertToOutputFormat(
this->ConvertToNinjaPath(this->GetSourceFilePath(source)),
cmOutputConverter::SHELL);
}
return oss.str();
}();
}
// Compute specific libraries to link with.
cmNinjaDeps explicitDeps = this->GetObjects();
cmNinjaDeps explicitDeps;
if (this->TargetLinkLanguage == "Swift") {
std::vector<cmSourceFile const*> sources;
this->GetGeneratorTarget()->GetObjectSources(sources,
this->GetConfigName());
for (const auto& source : sources) {
outputs.push_back(
this->ConvertToNinjaPath(this->GetObjectFilePath(source)));
explicitDeps.push_back(
this->ConvertToNinjaPath(this->GetSourceFilePath(source)));
}
outputs.push_back(vars["SWIFT_MODULE"]);
} else {
explicitDeps = this->GetObjects();
}
cmNinjaDeps implicitDeps = this->ComputeLinkDeps(this->TargetLinkLanguage);
if (!this->DeviceLinkObject.empty()) {
......
......@@ -19,7 +19,6 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmListFileCache.h" // for BT
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
......@@ -455,13 +454,6 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";
vars.ObjectDir = "$OBJECT_DIR";
vars.ObjectFileDir = "$OBJECT_FILE_DIR";
if (lang == "Swift") {
vars.SwiftAuxiliarySources = "$SWIFT_AUXILIARY_SOURCES";
vars.SwiftModuleName = "$SWIFT_MODULE_NAME";
vars.SwiftLibraryName = "$SWIFT_LIBRARY_NAME";
vars.SwiftPartialModule = "$SWIFT_PARTIAL_MODULE";
vars.SwiftPartialDoc = "$SWIFT_PARTIAL_DOC";
}
// For some cases we do an explicit preprocessor invocation.
bool const explicitPP = this->NeedExplicitPreprocessing(lang);
......@@ -924,6 +916,28 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
}
this->GetBuildFileStream() << "\n";
if (!this->SwiftOutputMap.empty()) {
std::string const mapFilePath = this->ConvertToNinjaPath(
this->GeneratorTarget->GetSupportDirectory() + "/output-file-map.json");
std::string const targetSwiftDepsPath = [this]() -> std::string {
cmGeneratorTarget const* target = this->GeneratorTarget;
if (const char* name = target->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
}
return this->ConvertToNinjaPath(target->GetSupportDirectory() + "/" +
target->GetName() + ".swiftdeps");
}();
// build the global target dependencies
// https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
Json::Value deps(Json::objectValue);
deps["swift-dependencies"] = targetSwiftDepsPath;
this->SwiftOutputMap[""] = deps;
cmGeneratedFileStream output(mapFilePath);
output << this->SwiftOutputMap;
}
}
void cmNinjaTargetGenerator::WriteObjectBuildStatement(
......@@ -948,43 +962,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
vars["INCLUDES"] = this->ComputeIncludes(source, language);
if (language == "Swift") {
// The swift compiler needs all the sources besides the one being compiled
// in order to do the type checking. List all these "auxiliary" sources.
std::string aux_sources;
cmGeneratorTarget::KindedSources const& sources =
this->GeneratorTarget->GetKindedSources(this->GetConfigName());
for (cmGeneratorTarget::SourceAndKind const& src : sources.Sources) {
if (src.Source.Value == source) {
continue;
}
aux_sources += " " + this->GetSourceFilePath(src.Source.Value);
}
vars["SWIFT_AUXILIARY_SOURCES"] = aux_sources;
if (const char* name =
this->GeneratorTarget->GetProperty("SWIFT_MODULE_NAME")) {
vars["SWIFT_MODULE_NAME"] = name;
} else {
vars["SWIFT_MODULE_NAME"] = this->GeneratorTarget->GetName();
}
cmGeneratorTarget::Names targetNames =
this->GeneratorTarget->GetLibraryNames(this->GetConfigName());
vars["SWIFT_LIBRARY_NAME"] = targetNames.Base;
if (const char* partial = source->GetProperty("SWIFT_PARTIAL_MODULE")) {
vars["SWIFT_PARTIAL_MODULE"] = partial;
} else {
vars["SWIFT_PARTIAL_MODULE"] = objectFileName + ".swiftmodule";
}
if (const char* partial = source->GetProperty("SWIFT_PARTIAL_DOC")) {
vars["SWIFT_PARTIAL_DOC"] = partial;
} else {
vars["SWIFT_PARTIAL_DOC"] = objectFileName + ".swiftdoc";
}
}
if (!this->NeedDepTypeMSVC(language)) {
bool replaceExt(false);
......@@ -1177,10 +1154,14 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
std::string const rspfile = objectFileName + ".rsp";
this->GetGlobalGenerator()->WriteBuild(
this->GetBuildFileStream(), comment, rule, outputs,
/*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps,
vars, rspfile, commandLineLengthLimit);
if (language == "Swift") {
this->EmitSwiftDependencyInfo(source);
} else {
this->GetGlobalGenerator()->WriteBuild(
this->GetBuildFileStream(), comment, rule, outputs,
/*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps,
orderOnlyDeps, vars, rspfile, commandLineLengthLimit);
}
if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) {
std::vector<std::string> outputList;
......@@ -1239,6 +1220,52 @@ void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang)
tdif << tdi;
}
void cmNinjaTargetGenerator::EmitSwiftDependencyInfo(
cmSourceFile const* source)
{
std::string const sourceFilePath =
this->ConvertToNinjaPath(this->GetSourceFilePath(source));
std::string const objectFilePath =
this->ConvertToNinjaPath(this->GetObjectFilePath(source));
std::string const swiftDepsPath = [source, objectFilePath]() -> std::string {
if (const char* name = source->GetProperty("Swift_DEPENDENCIES_FILE")) {
return name;
}
return objectFilePath + ".swiftdeps";
}();
std::string const swiftDiaPath = [source, objectFilePath]() -> std::string {
if (const char* name = source->GetProperty("Swift_DIAGNOSTICS_FILE")) {
return name;
}
return objectFilePath + ".dia";
}();
std::string const makeDepsPath = [this, source]() -> std::string {
cmLocalNinjaGenerator const* local = this->GetLocalGenerator();
std::string const objectFileName =
this->ConvertToNinjaPath(this->GetObjectFilePath(source));
std::string const objectFileDir =
cmSystemTools::GetFilenamePath(objectFileName);
if (this->Makefile->IsOn("CMAKE_Swift_DEPFLE_EXTNSION_REPLACE")) {
std::string dependFileName =
cmSystemTools::GetFilenameWithoutLastExtension(objectFileName) + ".d";
return local->ConvertToOutputFormat(objectFileDir + "/" + dependFileName,
cmOutputConverter::SHELL);
}
return local->ConvertToOutputFormat(objectFileName + ".d",
cmOutputConverter::SHELL);
}();
// build the source file mapping
// https://github.com/apple/swift/blob/master/docs/Driver.md#output-file-maps
Json::Value entry = Json::Value(Json::objectValue);
entry["object"] = objectFilePath;
entry["dependencies"] = makeDepsPath;
entry["swift-dependencies"] = swiftDepsPath;
entry["diagnostics"] = swiftDiaPath;
SwiftOutputMap[sourceFilePath] = entry;
}
void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
......
......@@ -5,6 +5,8 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cm_jsoncpp_value.h"
#include "cmCommonTargetGenerator.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmNinjaTypes.h"
......@@ -128,6 +130,8 @@ protected:
void WriteObjectBuildStatement(cmSourceFile const* source);
void WriteTargetDependInfo(std::string const& lang);
void EmitSwiftDependencyInfo(cmSourceFile const* source);
void ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName,
......@@ -171,7 +175,10 @@ private:
cmLocalNinjaGenerator* LocalGenerator;
/// List of object files for this target.
cmNinjaDeps Objects;
// Fortran Support
std::map<std::string, cmNinjaDeps> DDIFiles;
// Swift Support
Json::Value SwiftOutputMap;
std::vector<cmCustomCommand const*> CustomCommands;
cmNinjaDeps ExtraFiles;
};
......
......@@ -91,6 +91,31 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (replaceValues.Includes && variable == "INCLUDES") {