Merge topic 'ninja-swift'

a9180ccf9a Tests: add a check for the Swift compiler
d745551fb6 Help: add some initial documentation for Swift support
9a182c9e5b Auxiliary: update vim syntax highlighting
e9b0063e8e Modules: add build rules for Swift Ninja support
b6412e3e38 Ninja: add placeholders to support Swift build
7d7f31161d Ninja: add support for Swift's output-file-map.json
d688c4c19d Swift: remove unnecessary unreleased Ninja infrastructure
0723582208 Swift: Detect compiler version
...

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !3297
This commit is contained in:
Brad King 2019-05-20 14:55:11 +00:00 committed by Kitware Robot
commit a9fb9a8774
27 changed files with 477 additions and 156 deletions

View File

@ -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

11
Help/envvar/SWIFTC.rst Normal file
View File

@ -0,0 +1,11 @@
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.

View File

@ -52,6 +52,7 @@ Environment Variables for Languages
/envvar/FFLAGS
/envvar/RC
/envvar/RCFLAGS
/envvar/SWIFTC
Environment Variables for CTest
===============================

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,5 @@
Swift_DEPENDENCIES_FILE
-----------------------
This property sets the path for the Swift dependency file (swiftdeps) for the
source.

View File

@ -0,0 +1,4 @@
Swift_DIAGNOSTICS_FILE
----------------------
This property controls where the Swift diagnostics are serialized.

View File

@ -0,0 +1,5 @@
Swift_DEPENDENCIES_FILE
-----------------------
This property sets the path for the Swift dependency file (swiftdep) for the
target.

View File

@ -0,0 +1,10 @@
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.

View File

@ -0,0 +1,5 @@
Swift_MODULE_NAME
-----------------
This property specifies the name of the Swift module. It is defaulted to the
name of the target.

View File

@ -0,0 +1,23 @@
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.

View File

@ -0,0 +1,8 @@
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.

View File

@ -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)

View File

@ -1,15 +1,46 @@
# 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")

View File

@ -1,5 +1,14 @@
# 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)

View File

@ -1,32 +1,61 @@
# 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)

View File

@ -1,7 +1,6 @@
# 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)

View File

@ -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;
}();
cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();
vars["SWIFT_MODULE"] = [this]() -> std::string {
cmGeneratorTarget::Names targetNames =
this->GetGeneratorTarget()->GetLibraryNames(this->GetConfigName());
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";
std::string directory =
this->GetLocalGenerator()->GetCurrentBinaryDirectory();
if (const char* prop = this->GetGeneratorTarget()->GetProperty(
"Swift_MODULE_DIRECTORY")) {
directory = prop;
}
}
vars["SWIFT_PARTIAL_MODULES"] = partials;
std::string name = targetNames.Base + ".swiftmodule";
if (const char* prop =
this->GetGeneratorTarget()->GetProperty("Swift_MODULE")) {
name = prop;
}
return this->GetLocalGenerator()->ConvertToOutputFormat(
this->ConvertToNinjaPath(directory + "/" + name),
cmOutputConverter::SHELL);
}();
vars["SWIFT_MODULE_NAME"] = [this]() -> std::string {
if (const char* name =
this->GetGeneratorTarget()->GetProperty("Swift_MODULE_NAME")) {
return name;
}
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()) {

View File

@ -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,

View File

@ -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;
};

View File

@ -91,6 +91,31 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
if (replaceValues.Includes && variable == "INCLUDES") {
return replaceValues.Includes;
}
if (replaceValues.SwiftLibraryName) {
if (variable == "SWIFT_LIBRARY_NAME") {
return replaceValues.SwiftLibraryName;
}
}
if (replaceValues.SwiftModule) {
if (variable == "SWIFT_MODULE") {
return replaceValues.SwiftModule;
}
}
if (replaceValues.SwiftModuleName) {
if (variable == "SWIFT_MODULE_NAME") {
return replaceValues.SwiftModuleName;
}
}
if (replaceValues.SwiftOutputFileMap) {
if (variable == "SWIFT_OUTPUT_FILE_MAP") {
return replaceValues.SwiftOutputFileMap;
}
}
if (replaceValues.SwiftSources) {
if (variable == "SWIFT_SOURCES") {
return replaceValues.SwiftSources;
}
}
if (replaceValues.TargetPDB) {
if (variable == "TARGET_PDB") {
return replaceValues.TargetPDB;
@ -162,46 +187,6 @@ std::string cmRulePlaceholderExpander::ExpandRuleVariable(
}
}
}
if (replaceValues.SwiftAuxiliarySources) {
if (variable == "SWIFT_AUXILIARY_SOURCES") {
return replaceValues.SwiftAuxiliarySources;
}
}
if (replaceValues.SwiftModuleName) {
if (variable == "SWIFT_MODULE_NAME") {
return replaceValues.SwiftModuleName;
}
}
if (replaceValues.SwiftLibraryName) {
if (variable == "SWIFT_LIBRARY_NAME") {
return replaceValues.SwiftLibraryName;
}
}
if (replaceValues.SwiftPartialDoc) {
if (variable == "SWIFT_PARTIAL_DOC") {
return replaceValues.SwiftPartialDoc;
}
}
if (replaceValues.SwiftPartialModule) {
if (variable == "SWIFT_PARTIAL_MODULE") {
return replaceValues.SwiftPartialModule;
}
}
if (replaceValues.SwiftPartialModules) {
if (variable == "SWIFT_PARTIAL_MODULES") {
return replaceValues.SwiftPartialModules;
}
}
if (replaceValues.TargetSwiftDoc) {
if (variable == "TARGET_SWIFT_DOC") {
return replaceValues.TargetSwiftDoc;
}
}
if (replaceValues.TargetSwiftModule) {
if (variable == "TARGET_SWIFT_MODULE") {
return replaceValues.TargetSwiftModule;
}
}
if (variable == "TARGET_SONAME" || variable == "SONAME_FLAG" ||
variable == "TARGET_INSTALLNAME_DIR") {
// All these variables depend on TargetSOName

View File

@ -58,14 +58,11 @@ public:
const char* Includes;
const char* DependencyFile;
const char* FilterPrefix;
const char* SwiftAuxiliarySources;
const char* SwiftModuleName;
const char* SwiftLibraryName;
const char* SwiftPartialModule;
const char* SwiftPartialDoc;
const char* TargetSwiftModule;
const char* TargetSwiftDoc;
const char* SwiftPartialModules;
const char* SwiftModule;
const char* SwiftModuleName;
const char* SwiftOutputFileMap;
const char* SwiftSources;
};
// Expand rule variables in CMake of the type found in language rules

View File

@ -335,6 +335,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
InitProperty("LINK_SEARCH_START_STATIC", nullptr);
InitProperty("LINK_SEARCH_END_STATIC", nullptr);
InitProperty("FOLDER", nullptr);
InitProperty("Swift_MODULE_DIRECTORY", nullptr);
InitProperty("VS_JUST_MY_CODE_DEBUGGING", nullptr);
#ifdef __APPLE__
if (this->GetGlobalGenerator()->IsXcode()) {

View File

@ -22,6 +22,7 @@ macro(ADD_TEST_MACRO NAME)
endmacro()
include(${CMAKE_CURRENT_SOURCE_DIR}/CheckFortran.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/CheckSwift.cmake)
# Fake a user home directory to avoid polluting the real one.
if(DEFINED ENV{HOME} AND NOT CTEST_NO_TEST_HOME)
@ -365,11 +366,16 @@ if(BUILD_TESTING)
((NOT CMAKE_OSX_SDKPRODUCT STREQUAL "Mac OS X") OR
(NOT CMAKE_OSX_SDKVERSION VERSION_LESS 10.10)))
if(CMAKE_GENERATOR STREQUAL "Xcode")
ADD_TEST_MACRO(SwiftMix SwiftMix)
ADD_TEST_MACRO(SwiftOnly SwiftOnly)
set(CMake_TEST_XCODE_SWIFT 1)
endif()
endif()
endif()
if(CMAKE_Swift_COMPILER OR CMake_TEST_XCODE_SWIFT)
ADD_TEST_MACRO(SwiftOnly SwiftOnly)
if(CMake_TEST_XCODE_SWIFT)
ADD_TEST_MACRO(SwiftMix SwiftMix)
endif()
endif()
if(CMAKE_Fortran_COMPILER)
ADD_TEST_MACRO(FortranOnly FortranOnly)
endif()

61
Tests/CheckSwift.cmake Normal file
View File

@ -0,0 +1,61 @@
if(NOT CMAKE_GENERATOR MATCHES "Xcode|Ninja")
set(CMAKE_Swift_COMPILER "")
return()
endif()
if(NOT DEFINED CMAKE_Swift_COMPILER)
set(_desc "Looking for a Swift compiler")
message(STATUS ${_desc})
file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckSwift)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckSwift/CMakeLists.txt"
"cmake_minimum_required(VERSION 3.14)
project(CheckSwift Swift)
file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
\"set(CMAKE_Swift_COMPILER \\\"\${CMAKE_Swift_COMPILER}\\\")\\n\"
\"set(CMAKE_Swift_FLAGS \\\"\${CMAKE_Swift_FLAGS}\\\")\\n\")
")
if(CMAKE_GENERATOR_INSTANCE)
set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
else()
set(_D_CMAKE_GENERATOR_INSTANCE "")
endif()
execute_process(WORKING_DIRECTORY
${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckSwift
COMMAND
${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
-A "${CMAKE_GENERATOR_PLATFORM}"
-T "${CMAKE_GENERATOR_TOOLSET}"
${_D_CMAKE_GENERATOR_INSTANCE}
TIMEOUT
60
OUTPUT_VARIABLE
output
ERROR_VARIABLE
output
RESULT_VARIABLE
result)
include(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/CheckSwift/result.cmake
OPTIONAL)
if(CMAKE_Swift_COMPILER AND "${result}" STREQUAL "0")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"${_desc} passed with the following output:\n"
"${output}\n")
else()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"${_desc} failed with the following output:\n"
"${output}\n")
endif()
message(STATUS "${_desc} - ${CMAKE_Swift_COMPILER}")
set(CMAKE_Swift_COMPILER "${CMAKE_Swift_COMPILER}" CACHE FILEPATH "Swift compiler")
set(CMAKE_Swift_FLAGS "${CMAKE_Swift_FLAGS}" CACHE STRING "Swift flags")
mark_as_advanced(CMAKE_Swift_COMPILER)
mark_as_advanced(CMAKE_Swift_FLAGS)
endif()

View File

@ -205,7 +205,7 @@ if(UNIX AND CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG AND CMAKE_EXECUTABLE_FORMAT STRE
add_RunCMake_test(RuntimePath)
endif()
add_RunCMake_test(ScriptMode)
add_RunCMake_test(Swift)
add_RunCMake_test(Swift -DCMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER})
add_RunCMake_test(TargetObjects)
add_RunCMake_test(TargetSources)
add_RunCMake_test(ToolchainFile)

View File

@ -4,6 +4,10 @@ if(RunCMake_GENERATOR STREQUAL Xcode)
if(XCODE_BELOW_6_1)
run_cmake(XcodeTooOld)
endif()
elseif(RunCMake_GENERATOR STREQUAL Ninja)
if(CMAKE_Swift_COMPILER)
# Add Ninja-specific Swift tests here.
endif()
else()
run_cmake(NotSupported)
endif()