mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/main' into rebranch
This commit is contained in:
332
include/swift-c/DependencyScan/DependencyScan.h
Normal file
332
include/swift-c/DependencyScan/DependencyScan.h
Normal file
@@ -0,0 +1,332 @@
|
||||
//===--- DependencyScan.h - C API for Swift Dependency Scanning ---*- C -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This C API is primarily intended to serve as the Swift Driver's
|
||||
// dependency scanning facility (https://github.com/apple/swift-driver).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_C_DEPENDENCY_SCAN_H
|
||||
#define SWIFT_C_DEPENDENCY_SCAN_H
|
||||
|
||||
#include "DependencyScanMacros.h"
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/// The version constants for the SwiftDependencyScan C API.
|
||||
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
|
||||
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
|
||||
#define SWIFTSCAN_VERSION_MAJOR 0
|
||||
#define SWIFTSCAN_VERSION_MINOR 1
|
||||
|
||||
SWIFTSCAN_BEGIN_DECLS
|
||||
|
||||
//=== Public Scanner Data Types -------------------------------------------===//
|
||||
|
||||
/**
|
||||
* A character string used to pass around dependency scan result metadata.
|
||||
* Lifetime of the string is strictly tied to the object whose field it
|
||||
* represents. When the owning object is released, string memory is freed.
|
||||
*/
|
||||
typedef struct {
|
||||
const void *data;
|
||||
size_t length;
|
||||
} swiftscan_string_ref_t;
|
||||
|
||||
typedef struct {
|
||||
swiftscan_string_ref_t *strings;
|
||||
size_t count;
|
||||
} swiftscan_string_set_t;
|
||||
|
||||
typedef enum {
|
||||
SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL = 0,
|
||||
SWIFTSCAN_DEPENDENCY_INFO_SWIFT_BINARY = 1,
|
||||
SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER = 2,
|
||||
SWIFTSCAN_DEPENDENCY_INFO_CLANG = 3
|
||||
} swiftscan_dependency_info_kind_t;
|
||||
|
||||
/// Opaque container of the details specific to a given module dependency.
|
||||
typedef struct swiftscan_module_details_s *swiftscan_module_details_t;
|
||||
|
||||
/// Opaque container to a dependency info of a given module.
|
||||
typedef struct swiftscan_dependency_info_s *swiftscan_dependency_info_t;
|
||||
|
||||
/// Opaque container to an overall result of a dependency scan.
|
||||
typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t;
|
||||
|
||||
/// Opaque container to contain the result of a dependency prescan.
|
||||
typedef struct swiftscan_import_set_s *swiftscan_import_set_t;
|
||||
|
||||
/// Full Dependency Graph (Result)
|
||||
typedef struct {
|
||||
swiftscan_dependency_info_t *modules;
|
||||
size_t count;
|
||||
} swiftscan_dependency_set_t;
|
||||
|
||||
//=== Batch Scan Input Specification --------------------------------------===//
|
||||
|
||||
/// Opaque container to a container of batch scan entry information.
|
||||
typedef struct swiftscan_batch_scan_entry_s *swiftscan_batch_scan_entry_t;
|
||||
|
||||
typedef struct {
|
||||
swiftscan_batch_scan_entry_t *modules;
|
||||
size_t count;
|
||||
} swiftscan_batch_scan_input_t;
|
||||
|
||||
typedef struct {
|
||||
swiftscan_dependency_graph_t *results;
|
||||
size_t count;
|
||||
} swiftscan_batch_scan_result_t;
|
||||
|
||||
//=== Scanner Invocation Specification ------------------------------------===//
|
||||
|
||||
/// Opaque container of all relevant context required to launch a dependency
|
||||
/// scan (command line arguments, working directory, etc.)
|
||||
typedef struct swiftscan_scan_invocation_s *swiftscan_scan_invocation_t;
|
||||
|
||||
//=== Dependency Result Functions -----------------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_dependency_graph_get_main_module_name(
|
||||
swiftscan_dependency_graph_t result);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_dependency_set_t *
|
||||
swiftscan_dependency_graph_get_dependencies(
|
||||
swiftscan_dependency_graph_t result);
|
||||
|
||||
//=== Dependency Module Info Functions ------------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_module_info_get_module_name(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_module_info_get_module_path(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_module_info_get_source_files(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_module_info_get_direct_dependencies(swiftscan_dependency_info_t info);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_module_details_t
|
||||
swiftscan_module_info_get_details(swiftscan_dependency_info_t info);
|
||||
|
||||
//=== Dependency Module Info Details Functions ----------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_dependency_info_kind_t
|
||||
swiftscan_module_detail_get_kind(swiftscan_module_details_t details);
|
||||
|
||||
//=== Swift Textual Module Details query APIs -----------------------------===//
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_textual_detail_get_module_interface_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_compiled_module_candidates(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_textual_detail_get_bridging_header_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_bridging_source_files(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_bridging_module_dependencies(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_command_line(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_extra_pcm_args(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_textual_detail_get_context_hash(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC bool swiftscan_swift_textual_detail_get_is_framework(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
//=== Swift Binary Module Details query APIs ------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_binary_detail_get_compiled_module_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_binary_detail_get_module_doc_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_binary_detail_get_module_source_info_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
//=== Swift Placeholder Module Details query APIs -------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_placeholder_detail_get_compiled_module_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_placeholder_detail_get_module_doc_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_swift_placeholder_detail_get_module_source_info_path(
|
||||
swiftscan_module_details_t details);
|
||||
|
||||
//=== Clang Module Details query APIs -------------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_clang_detail_get_module_map_path(swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_clang_detail_get_context_hash(swiftscan_module_details_t details);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_clang_detail_get_command_line(swiftscan_module_details_t details);
|
||||
|
||||
//=== Batch Scan Input Functions ------------------------------------------===//
|
||||
|
||||
/// Create an \c swiftscan_batch_scan_input_t instance.
|
||||
/// The returned \c swiftscan_batch_scan_input_t is owned by the caller and must be disposed
|
||||
/// of using \c swiftscan_batch_scan_input_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_batch_scan_input_t *
|
||||
swiftscan_batch_scan_input_create();
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_input_set_modules(swiftscan_batch_scan_input_t *input,
|
||||
int count,
|
||||
swiftscan_batch_scan_entry_t *modules);
|
||||
|
||||
//=== Batch Scan Entry Functions ------------------------------------------===//
|
||||
|
||||
/// Create an \c swiftscan_batch_scan_entry_t instance.
|
||||
/// The returned \c swiftscan_batch_scan_entry_t is owned by the caller and must be disposed
|
||||
/// of using \c swiftscan_batch_scan_entry_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_batch_scan_entry_t
|
||||
swiftscan_batch_scan_entry_create();
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_entry_set_module_name(swiftscan_batch_scan_entry_t entry,
|
||||
const char *name);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_entry_set_arguments(swiftscan_batch_scan_entry_t entry,
|
||||
const char *arguments);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_entry_set_is_swift(swiftscan_batch_scan_entry_t entry,
|
||||
bool is_swift);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_batch_scan_entry_get_module_name(swiftscan_batch_scan_entry_t entry);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_batch_scan_entry_get_arguments(swiftscan_batch_scan_entry_t entry);
|
||||
|
||||
SWIFTSCAN_PUBLIC bool
|
||||
swiftscan_batch_scan_entry_get_is_swift(swiftscan_batch_scan_entry_t entry);
|
||||
|
||||
//=== Prescan Result Functions --------------------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_import_set_get_imports(swiftscan_import_set_t result);
|
||||
|
||||
//=== Scanner Invocation Functions ----------------------------------------===//
|
||||
|
||||
/// Create an \c swiftscan_scan_invocation_t instance.
|
||||
/// The returned \c swiftscan_scan_invocation_t is owned by the caller and must be disposed
|
||||
/// of using \c swiftscan_scan_invocation_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_scan_invocation_t swiftscan_scan_invocation_create();
|
||||
|
||||
SWIFTSCAN_PUBLIC void swiftscan_scan_invocation_set_working_directory(
|
||||
swiftscan_scan_invocation_t invocation, const char *working_directory);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_scan_invocation_set_argv(swiftscan_scan_invocation_t invocation,
|
||||
int argc, const char **argv);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
|
||||
swiftscan_scan_invocation_get_working_directory(
|
||||
swiftscan_scan_invocation_t invocation);
|
||||
|
||||
SWIFTSCAN_PUBLIC int
|
||||
swiftscan_scan_invocation_get_argc(swiftscan_scan_invocation_t invocation);
|
||||
|
||||
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
|
||||
swiftscan_scan_invocation_get_argv(swiftscan_scan_invocation_t invocation);
|
||||
|
||||
//=== Cleanup Functions ---------------------------------------------------===//
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_dependency_graph_dispose(swiftscan_dependency_graph_t result);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_import_set_dispose(swiftscan_import_set_t result);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_entry_dispose(swiftscan_batch_scan_entry_t entry);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_input_dispose(swiftscan_batch_scan_input_t *input);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_batch_scan_result_dispose(swiftscan_batch_scan_result_t *result);
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_scan_invocation_dispose(swiftscan_scan_invocation_t invocation);
|
||||
|
||||
//=== Scanner Functions ---------------------------------------------------===//
|
||||
|
||||
/// Container of the configuration state and shared cache for dependency
|
||||
/// scanning.
|
||||
typedef void *swiftscan_scanner_t;
|
||||
|
||||
/// Create an \c swiftscan_scanner_t instance.
|
||||
/// The returned \c swiftscan_scanner_t is owned by the caller and must be disposed
|
||||
/// of using \c swiftscan_scanner_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_scanner_t swiftscan_scanner_create(void);
|
||||
SWIFTSCAN_PUBLIC void swiftscan_scanner_dispose(swiftscan_scanner_t);
|
||||
|
||||
/// Invoke a dependency scan using arguments specified in the \c
|
||||
/// swiftscan_scan_invocation_t argument. The returned \c
|
||||
/// swiftscan_dependency_graph_t is owned by the caller and must be disposed of
|
||||
/// using \c swiftscan_dependency_graph_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_dependency_graph_t swiftscan_dependency_graph_create(
|
||||
swiftscan_scanner_t scanner, swiftscan_scan_invocation_t invocation);
|
||||
|
||||
/// Invoke the scan for an input batch of modules specified in the
|
||||
/// \c swiftscan_batch_scan_input_t argument. The returned
|
||||
/// \c swiftscan_batch_scan_result_t is owned by the caller and must be disposed
|
||||
/// of using \c swiftscan_batch_scan_result_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_batch_scan_result_t *
|
||||
swiftscan_batch_scan_result_create(swiftscan_scanner_t scanner,
|
||||
swiftscan_batch_scan_input_t *batch_input,
|
||||
swiftscan_scan_invocation_t invocation);
|
||||
|
||||
/// Invoke the import prescan using arguments specified in the \c
|
||||
/// swiftscan_scan_invocation_t argument. The returned \c swiftscan_import_set_t
|
||||
/// is owned by the caller and must be disposed of using \c
|
||||
/// swiftscan_import_set_dispose .
|
||||
SWIFTSCAN_PUBLIC swiftscan_import_set_t swiftscan_import_set_create(
|
||||
swiftscan_scanner_t scanner, swiftscan_scan_invocation_t invocation);
|
||||
|
||||
SWIFTSCAN_END_DECLS
|
||||
|
||||
#endif // SWIFT_C_DEPENDENCY_SCAN_H
|
||||
31
include/swift-c/DependencyScan/DependencyScanMacros.h
Normal file
31
include/swift-c/DependencyScan/DependencyScanMacros.h
Normal file
@@ -0,0 +1,31 @@
|
||||
//===-- DependencyScanMacros.h - Swift Dependency Scanning Macros -*- C -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define SWIFTSCAN_BEGIN_DECLS extern "C" {
|
||||
# define SWIFTSCAN_END_DECLS }
|
||||
#else
|
||||
# define SWIFTSCAN_BEGIN_DECLS
|
||||
# define SWIFTSCAN_END_DECLS
|
||||
#endif
|
||||
|
||||
#ifndef SWIFTSCAN_PUBLIC
|
||||
# ifdef _WIN32
|
||||
# ifdef libSwiftScan_EXPORTS
|
||||
# define SWIFTSCAN_PUBLIC __declspec(dllexport)
|
||||
# else
|
||||
# define SWIFTSCAN_PUBLIC __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# define SWIFTSCAN_PUBLIC
|
||||
# endif
|
||||
#endif
|
||||
4
include/swift-c/DependencyScan/module.modulemap
Normal file
4
include/swift-c/DependencyScan/module.modulemap
Normal file
@@ -0,0 +1,4 @@
|
||||
module _InternalSwiftScan {
|
||||
header "DependencyScan.h"
|
||||
link "_InternalSwiftScan"
|
||||
}
|
||||
159
include/swift/DependencyScan/DependencyScanImpl.h
Normal file
159
include/swift/DependencyScan/DependencyScanImpl.h
Normal file
@@ -0,0 +1,159 @@
|
||||
//===-------------- DependencyScanImpl.h - Swift Compiler -----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation details of the dependency scanning C API
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#ifndef SWIFT_C_DEPENDENCY_SCAN_IMPL_H
|
||||
#define SWIFT_C_DEPENDENCY_SCAN_IMPL_H
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
|
||||
namespace swift {
|
||||
namespace dependencies {
|
||||
class DependencyScanningTool;
|
||||
}
|
||||
} // namespace swift
|
||||
|
||||
struct swiftscan_dependency_graph_s {
|
||||
/// The name of the main module for this dependency graph (root node)
|
||||
swiftscan_string_ref_t main_module_name;
|
||||
|
||||
/// The complete list of modules discovered
|
||||
swiftscan_dependency_set_t *dependencies;
|
||||
};
|
||||
|
||||
struct swiftscan_dependency_info_s {
|
||||
/// The module's name
|
||||
/// The format is:
|
||||
/// `<module-kind>:<module-name>`
|
||||
/// where `module-kind` is one of:
|
||||
/// "swiftTextual"
|
||||
/// "swiftBinary"
|
||||
/// "swiftPlaceholder"
|
||||
/// "clang""
|
||||
swiftscan_string_ref_t module_name;
|
||||
|
||||
/// The path for the module.
|
||||
swiftscan_string_ref_t module_path;
|
||||
|
||||
/// The source files used to build this module.
|
||||
swiftscan_string_set_t *source_files;
|
||||
|
||||
/**
|
||||
* The list of modules which this module direct depends on.
|
||||
* The format is:
|
||||
* `<module-kind>:<module-name>`
|
||||
*/
|
||||
swiftscan_string_set_t *direct_dependencies;
|
||||
|
||||
/// Specific details of a particular kind of module.
|
||||
swiftscan_module_details_t details;
|
||||
};
|
||||
|
||||
/// Swift modules to be built from a module interface, may have a bridging
|
||||
/// header.
|
||||
typedef struct {
|
||||
/// The module interface from which this module was built, if any.
|
||||
swiftscan_string_ref_t module_interface_path;
|
||||
|
||||
/// The paths of potentially ready-to-use compiled modules for the interface.
|
||||
swiftscan_string_set_t *compiled_module_candidates;
|
||||
|
||||
/// The bridging header, if any.
|
||||
swiftscan_string_ref_t bridging_header_path;
|
||||
|
||||
/// The source files referenced by the bridging header.
|
||||
swiftscan_string_set_t *bridging_source_files;
|
||||
|
||||
/// (Clang) modules on which the bridging header depends.
|
||||
swiftscan_string_set_t *bridging_module_dependencies;
|
||||
|
||||
/// Options to the compile command required to build this module interface
|
||||
swiftscan_string_set_t *command_line;
|
||||
|
||||
/// To build a PCM to be used by this Swift module, we need to append these
|
||||
/// arguments to the generic PCM build arguments reported from the dependency
|
||||
/// graph.
|
||||
swiftscan_string_set_t *extra_pcm_args;
|
||||
|
||||
/// The hash value that will be used for the generated module
|
||||
swiftscan_string_ref_t context_hash;
|
||||
|
||||
/// A flag to indicate whether or not this module is a framework.
|
||||
bool is_framework;
|
||||
} swiftscan_swift_textual_details_t;
|
||||
|
||||
/// Swift modules with only a binary module file.
|
||||
typedef struct {
|
||||
/// The path to the pre-compiled binary module
|
||||
swiftscan_string_ref_t compiled_module_path;
|
||||
|
||||
/// The path to the .swiftModuleDoc file.
|
||||
swiftscan_string_ref_t module_doc_path;
|
||||
|
||||
/// The path to the .swiftSourceInfo file.
|
||||
swiftscan_string_ref_t module_source_info_path;
|
||||
} swiftscan_swift_binary_details_t;
|
||||
|
||||
/// Swift placeholder modules carry additional details that specify their
|
||||
/// module doc path and source info paths.
|
||||
typedef struct {
|
||||
/// The path to the pre-compiled binary module
|
||||
swiftscan_string_ref_t compiled_module_path;
|
||||
|
||||
/// The path to the .swiftModuleDoc file.
|
||||
swiftscan_string_ref_t module_doc_path;
|
||||
|
||||
/// The path to the .swiftSourceInfo file.
|
||||
swiftscan_string_ref_t module_source_info_path;
|
||||
} swiftscan_swift_placeholder_details_t;
|
||||
|
||||
/// Clang modules are built from a module map file.
|
||||
typedef struct {
|
||||
/// The path to the module map used to build this module.
|
||||
swiftscan_string_ref_t module_map_path;
|
||||
|
||||
/// clang-generated context hash
|
||||
swiftscan_string_ref_t context_hash;
|
||||
|
||||
/// Options to the compile command required to build this clang modulemap
|
||||
swiftscan_string_set_t *command_line;
|
||||
} swiftscan_clang_details_t;
|
||||
|
||||
struct swiftscan_module_details_s {
|
||||
swiftscan_dependency_info_kind_t kind;
|
||||
union {
|
||||
swiftscan_swift_textual_details_t swift_textual_details;
|
||||
swiftscan_swift_binary_details_t swift_binary_details;
|
||||
swiftscan_swift_placeholder_details_t swift_placeholder_details;
|
||||
swiftscan_clang_details_t clang_details;
|
||||
};
|
||||
};
|
||||
|
||||
struct swiftscan_batch_scan_entry_s {
|
||||
swiftscan_string_ref_t module_name;
|
||||
swiftscan_string_ref_t arguments;
|
||||
bool is_swift;
|
||||
};
|
||||
|
||||
struct swiftscan_import_set_s {
|
||||
/// The complete list of imports discovered
|
||||
swiftscan_string_set_t *imports;
|
||||
};
|
||||
|
||||
struct swiftscan_scan_invocation_s {
|
||||
swiftscan_string_ref_t working_directory;
|
||||
swiftscan_string_set_t *argv;
|
||||
};
|
||||
|
||||
#endif // SWIFT_C_DEPENDENCY_SCAN_IMPL_H
|
||||
83
include/swift/DependencyScan/DependencyScanningTool.h
Normal file
83
include/swift/DependencyScan/DependencyScanningTool.h
Normal file
@@ -0,0 +1,83 @@
|
||||
//===-------------- DependencyScanningTool.h - Swift Compiler -------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DEPENDENCY_SCANNING_TOOL_H
|
||||
#define SWIFT_DEPENDENCY_SCANNING_TOOL_H
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/AST/ModuleDependencies.h"
|
||||
#include "swift/DependencyScan/ScanDependencies.h"
|
||||
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
namespace swift {
|
||||
namespace dependencies {
|
||||
|
||||
/// The high-level implementation of the dependency scanner that runs on
|
||||
/// an individual worker thread.
|
||||
class DependencyScanningTool {
|
||||
public:
|
||||
/// Construct a dependency scanning tool.
|
||||
DependencyScanningTool();
|
||||
|
||||
/// Collect the full module depenedency graph for the input, ignoring any
|
||||
/// placeholder modules.
|
||||
///
|
||||
/// \returns a \c StringError with the diagnostic output if errors
|
||||
/// occurred, \c swiftscan_dependency_result_t otherwise.
|
||||
llvm::ErrorOr<swiftscan_dependency_graph_t>
|
||||
getDependencies(ArrayRef<const char *> Command,
|
||||
const llvm::StringSet<> &PlaceholderModules);
|
||||
|
||||
/// Collect the set of imports for the input module
|
||||
///
|
||||
/// \returns a \c StringError with the diagnostic output if errors
|
||||
/// occurred, \c swiftscan_prescan_result_t otherwise.
|
||||
llvm::ErrorOr<swiftscan_import_set_t>
|
||||
getImports(ArrayRef<const char *> Command);
|
||||
|
||||
/// Collect the full module depenedency graph for the input collection of
|
||||
/// module names (batch inputs) and output them to the
|
||||
/// BatchScanInput-specified output locations.
|
||||
///
|
||||
/// \returns a \c std::error_code if errors occured during scan.
|
||||
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
|
||||
getDependencies(ArrayRef<const char *> Command,
|
||||
const std::vector<BatchScanInput> &BatchInput,
|
||||
const llvm::StringSet<> &PlaceholderModules);
|
||||
|
||||
private:
|
||||
/// Using the specified invocation command, instantiate a CompilerInstance
|
||||
/// that will be used for this scan.
|
||||
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
|
||||
initCompilerInstanceForScan(ArrayRef<const char *> Command);
|
||||
|
||||
/// Shared cache of module dependencies, re-used by individual full-scan queries
|
||||
/// during the lifetime of this Tool.
|
||||
std::unique_ptr<ModuleDependenciesCache> SharedCache;
|
||||
|
||||
/// Shared cache of compiler instances created during batch scanning, corresponding to
|
||||
/// command-line options specified in the batch scan input entry.
|
||||
std::unique_ptr<CompilerArgInstanceCacheMap> VersionedPCMInstanceCacheCache;
|
||||
|
||||
/// A shared consumer that, for now, just prints the encountered diagnostics.
|
||||
PrintingDiagnosticConsumer PDC;
|
||||
llvm::BumpPtrAllocator Alloc;
|
||||
llvm::StringSaver Saver;
|
||||
};
|
||||
|
||||
} // end namespace dependencies
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_DEPENDENCY_SCANNING_TOOL_H
|
||||
88
include/swift/DependencyScan/ScanDependencies.h
Normal file
88
include/swift/DependencyScan/ScanDependencies.h
Normal file
@@ -0,0 +1,88 @@
|
||||
//===--- ScanDependencies.h -- Scans the dependencies of a module ------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_DEPENDENCY_SCANDEPENDENCIES_H
|
||||
#define SWIFT_DEPENDENCY_SCANDEPENDENCIES_H
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
class StringSaver;
|
||||
}
|
||||
|
||||
namespace swift {
|
||||
|
||||
class CompilerInvocation;
|
||||
class CompilerInstance;
|
||||
class ModuleDependenciesCache;
|
||||
|
||||
namespace dependencies {
|
||||
|
||||
using CompilerArgInstanceCacheMap =
|
||||
llvm::StringMap<std::pair<std::unique_ptr<CompilerInstance>,
|
||||
std::unique_ptr<ModuleDependenciesCache>>>;
|
||||
|
||||
struct BatchScanInput {
|
||||
llvm::StringRef moduleName;
|
||||
llvm::StringRef arguments;
|
||||
llvm::StringRef outputPath;
|
||||
bool isSwift;
|
||||
};
|
||||
|
||||
// MARK: FrontendTool dependency scanner entry points
|
||||
/// Scans the dependencies of the main module of \c instance and writes out
|
||||
/// the resulting JSON according to the instance's output parameters.
|
||||
bool scanDependencies(CompilerInstance &instance);
|
||||
|
||||
/// Identify all imports in the translation unit's module.
|
||||
bool prescanDependencies(CompilerInstance &instance);
|
||||
|
||||
/// Batch scan the dependencies for modules specified in \c batchInputFile.
|
||||
bool batchScanDependencies(CompilerInstance &instance,
|
||||
llvm::StringRef batchInputFile);
|
||||
|
||||
/// Batch prescan the imports of modules specified in \c batchInputFile.
|
||||
bool batchPrescanDependencies(CompilerInstance &instance,
|
||||
llvm::StringRef batchInputFile);
|
||||
|
||||
// MARK: Dependency scanning execution
|
||||
/// Scans the dependencies of the main module of \c instance.
|
||||
llvm::ErrorOr<swiftscan_dependency_graph_t>
|
||||
performModuleScan(CompilerInstance &instance,
|
||||
ModuleDependenciesCache &cache);
|
||||
|
||||
/// Scans the main module of \c instance for all direct module imports
|
||||
llvm::ErrorOr<swiftscan_import_set_t>
|
||||
performModulePrescan(CompilerInstance &instance);
|
||||
|
||||
/// Batch scan the dependencies for modules specified in \c batchInputFile.
|
||||
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
|
||||
performBatchModuleScan(CompilerInstance &invocationInstance,
|
||||
ModuleDependenciesCache &invocationCache,
|
||||
CompilerArgInstanceCacheMap *versionedPCMInstanceCache,
|
||||
llvm::StringSaver &saver,
|
||||
const std::vector<BatchScanInput> &BatchInput);
|
||||
|
||||
/// Batch prescan the imports of modules specified in \c batchInputFile.
|
||||
std::vector<llvm::ErrorOr<swiftscan_import_set_t>>
|
||||
performBatchModulePrescan(CompilerInstance &invocationInstance,
|
||||
ModuleDependenciesCache &cache,
|
||||
llvm::StringSaver &saver,
|
||||
const std::vector<BatchScanInput> &BatchInput);
|
||||
|
||||
} // end namespace dependencies
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
41
include/swift/DependencyScan/StringUtils.h
Normal file
41
include/swift/DependencyScan/StringUtils.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//===----- StringUtils.h - Managed C String Utility Functions -----*- C -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
//=== Private Utility Functions--------------------------------------------===//
|
||||
namespace swift {
|
||||
namespace dependencies {
|
||||
|
||||
/// Create null string
|
||||
swiftscan_string_ref_t create_null();
|
||||
|
||||
/// Create a \c swiftscan_string_ref_t object from a nul-terminated C string. New
|
||||
/// \c swiftscan_string_ref_t will contain a copy of \p string.
|
||||
swiftscan_string_ref_t create_clone(const char *string);
|
||||
|
||||
/// Create an array of \c swiftscan_string_ref_t objects from a vector of C++ strings using the
|
||||
/// create_clone routine.
|
||||
swiftscan_string_set_t *create_set(const std::vector<std::string> &strings);
|
||||
|
||||
/// Create an array of swiftscan_string_ref_t objects from an array of C strings using the
|
||||
/// create_clone routine.
|
||||
swiftscan_string_set_t *create_set(int count, const char **strings);
|
||||
|
||||
/// Retrieve the character data associated with the given string.
|
||||
const char *get_C_string(swiftscan_string_ref_t string);
|
||||
}
|
||||
}
|
||||
@@ -491,8 +491,6 @@ public:
|
||||
DependencyTracker *getDependencyTracker() { return DepTracker.get(); }
|
||||
const DependencyTracker *getDependencyTracker() const { return DepTracker.get(); }
|
||||
|
||||
ModuleDependenciesCache *getModuleDependencyCache() { return ModDepCache.get(); }
|
||||
|
||||
UnifiedStatsReporter *getStatsReporter() const { return Stats.get(); }
|
||||
|
||||
/// Retrieve the main module containing the files being compiled.
|
||||
@@ -558,7 +556,6 @@ private:
|
||||
bool setUpVirtualFileSystemOverlays();
|
||||
void setUpLLVMArguments();
|
||||
void setUpDiagnosticOptions();
|
||||
void setUpModuleDependencyCacheIfNeeded();
|
||||
bool setUpModuleLoaders();
|
||||
bool setUpInputs();
|
||||
bool setUpASTContextIfNeeded();
|
||||
|
||||
@@ -134,7 +134,6 @@ public:
|
||||
DumpPCM, ///< Dump information about a precompiled Clang module
|
||||
|
||||
ScanDependencies, ///< Scan dependencies of Swift source files
|
||||
ScanClangDependencies, ///< Scan dependencies of a Clang module
|
||||
PrintVersion, ///< Print version information.
|
||||
PrintFeature, ///< Print supported feature of this compiler
|
||||
};
|
||||
|
||||
@@ -1121,10 +1121,6 @@ def scan_dependencies : Flag<["-"], "scan-dependencies">,
|
||||
HelpText<"Scan dependencies of the given Swift sources">, ModeOpt,
|
||||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
|
||||
|
||||
def scan_clang_dependencies : Flag<["-"], "scan-clang-dependencies">,
|
||||
HelpText<"Scan dependencies of the given Clang module">, ModeOpt,
|
||||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
|
||||
|
||||
def emit_supported_features : Flag<["-"], "emit-supported-features">,
|
||||
HelpText<"Emit a JSON file including all supported compiler features">, ModeOpt,
|
||||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>;
|
||||
|
||||
@@ -180,6 +180,7 @@ ModuleDependencies::collectCrossImportOverlayNames(ASTContext &ctx,
|
||||
llvm::StringMap<llvm::SmallSetVector<Identifier, 4>> result;
|
||||
// Mimic getModuleDefiningPath() for Swift and Clang module.
|
||||
if (auto *swiftDep = getAsSwiftTextualModule()) {
|
||||
if (swiftDep->swiftInterfaceFile.hasValue()) {
|
||||
// Prefer interface path to binary module path if we have it.
|
||||
modulePath = swiftDep->swiftInterfaceFile;
|
||||
assert(modulePath.hasValue());
|
||||
@@ -187,6 +188,11 @@ ModuleDependencies::collectCrossImportOverlayNames(ASTContext &ctx,
|
||||
if (llvm::sys::path::extension(parentDir) == ".swiftmodule") {
|
||||
modulePath = parentDir.str();
|
||||
}
|
||||
} else {
|
||||
// This must be a module compiled from source-code
|
||||
assert(!swiftDep->sourceFiles.empty());
|
||||
return result;
|
||||
}
|
||||
} else if (auto *swiftBinaryDep = getAsSwiftBinaryModule()) {
|
||||
modulePath = swiftBinaryDep->compiledModulePath;
|
||||
assert(modulePath.hasValue());
|
||||
|
||||
@@ -19,6 +19,7 @@ add_subdirectory(ASTSectionImporter)
|
||||
add_subdirectory(Basic)
|
||||
add_subdirectory(ClangImporter)
|
||||
add_subdirectory(Demangling)
|
||||
add_subdirectory(DependencyScan)
|
||||
add_subdirectory(Driver)
|
||||
add_subdirectory(Frontend)
|
||||
add_subdirectory(FrontendTool)
|
||||
|
||||
13
lib/DependencyScan/CMakeLists.txt
Normal file
13
lib/DependencyScan/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
#set_swift_llvm_is_available()
|
||||
|
||||
add_swift_host_library(swiftDependencyScan STATIC
|
||||
DependencyScanningTool.cpp
|
||||
ScanDependencies.cpp
|
||||
StringUtils.cpp)
|
||||
|
||||
target_link_libraries(swiftDependencyScan INTERFACE
|
||||
clangBasic)
|
||||
|
||||
target_link_libraries(swiftDependencyScan PRIVATE
|
||||
swiftClangImporter
|
||||
swiftFrontend)
|
||||
124
lib/DependencyScan/DependencyScanningTool.cpp
Normal file
124
lib/DependencyScan/DependencyScanningTool.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
//===------------ DependencyScanningTool.cpp - Swift Compiler -------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/DependencyScan/DependencyScanningTool.h"
|
||||
#include "swift/AST/DiagnosticEngine.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/Basic/LLVMInitialize.h"
|
||||
#include "swift/DependencyScan/DependencyScanImpl.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace swift {
|
||||
namespace dependencies {
|
||||
|
||||
DependencyScanningTool::DependencyScanningTool()
|
||||
: SharedCache(std::make_unique<ModuleDependenciesCache>()),
|
||||
VersionedPCMInstanceCacheCache(
|
||||
std::make_unique<CompilerArgInstanceCacheMap>()),
|
||||
PDC(), Alloc(), Saver(Alloc) {}
|
||||
|
||||
llvm::ErrorOr<swiftscan_dependency_graph_t>
|
||||
DependencyScanningTool::getDependencies(
|
||||
ArrayRef<const char *> Command,
|
||||
const llvm::StringSet<> &PlaceholderModules) {
|
||||
// The primary instance used to scan the query Swift source-code
|
||||
auto InstanceOrErr = initCompilerInstanceForScan(Command);
|
||||
if (std::error_code EC = InstanceOrErr.getError())
|
||||
return EC;
|
||||
auto Instance = std::move(*InstanceOrErr);
|
||||
|
||||
// Execute the scanning action, retreiving the in-memory result
|
||||
auto DependenciesOrErr = performModuleScan(*Instance.get(), *SharedCache);
|
||||
if (DependenciesOrErr.getError())
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
auto Dependencies = std::move(*DependenciesOrErr);
|
||||
|
||||
return Dependencies;
|
||||
}
|
||||
|
||||
llvm::ErrorOr<swiftscan_import_set_t>
|
||||
DependencyScanningTool::getImports(ArrayRef<const char *> Command) {
|
||||
// The primary instance used to scan the query Swift source-code
|
||||
auto InstanceOrErr = initCompilerInstanceForScan(Command);
|
||||
if (std::error_code EC = InstanceOrErr.getError())
|
||||
return EC;
|
||||
auto Instance = std::move(*InstanceOrErr);
|
||||
|
||||
// Execute the scanning action, retreiving the in-memory result
|
||||
auto DependenciesOrErr = performModulePrescan(*Instance.get());
|
||||
if (DependenciesOrErr.getError())
|
||||
return std::make_error_code(std::errc::not_supported);
|
||||
auto Dependencies = std::move(*DependenciesOrErr);
|
||||
|
||||
return Dependencies;
|
||||
}
|
||||
|
||||
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
|
||||
DependencyScanningTool::getDependencies(
|
||||
ArrayRef<const char *> Command,
|
||||
const std::vector<BatchScanInput> &BatchInput,
|
||||
const llvm::StringSet<> &PlaceholderModules) {
|
||||
// The primary instance used to scan Swift modules
|
||||
auto InstanceOrErr = initCompilerInstanceForScan(Command);
|
||||
if (std::error_code EC = InstanceOrErr.getError())
|
||||
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>(
|
||||
BatchInput.size(), std::make_error_code(std::errc::invalid_argument));
|
||||
auto Instance = std::move(*InstanceOrErr);
|
||||
|
||||
auto batchScanResults = performBatchModuleScan(
|
||||
*Instance.get(), *SharedCache, VersionedPCMInstanceCacheCache.get(),
|
||||
Saver, BatchInput);
|
||||
|
||||
return batchScanResults;
|
||||
}
|
||||
|
||||
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
|
||||
DependencyScanningTool::initCompilerInstanceForScan(
|
||||
ArrayRef<const char *> Command) {
|
||||
// State unique to an individual scan
|
||||
auto Instance = std::make_unique<CompilerInstance>();
|
||||
Instance->addDiagnosticConsumer(&PDC);
|
||||
|
||||
// Basic error checking on the arguments
|
||||
if (Command.empty()) {
|
||||
Instance->getDiags().diagnose(SourceLoc(), diag::error_no_frontend_args);
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
CompilerInvocation Invocation;
|
||||
SmallString<128> WorkingDirectory;
|
||||
llvm::sys::fs::current_path(WorkingDirectory);
|
||||
|
||||
// Parse arguments.
|
||||
std::string CommandString;
|
||||
for (const auto *c : Command) {
|
||||
CommandString.append(c);
|
||||
CommandString.append(" ");
|
||||
}
|
||||
SmallVector<const char *, 4> Args;
|
||||
llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args);
|
||||
if (Invocation.parseArgs(Args, Instance->getDiags())) {
|
||||
return std::make_error_code(std::errc::invalid_argument);
|
||||
}
|
||||
|
||||
// Setup the instance
|
||||
Instance->setup(Invocation);
|
||||
(void)Instance->getMainModule();
|
||||
|
||||
return Instance;
|
||||
}
|
||||
|
||||
} // namespace dependencies
|
||||
} // namespace swift
|
||||
1403
lib/DependencyScan/ScanDependencies.cpp
Normal file
1403
lib/DependencyScan/ScanDependencies.cpp
Normal file
File diff suppressed because it is too large
Load Diff
62
lib/DependencyScan/StringUtils.cpp
Normal file
62
lib/DependencyScan/StringUtils.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
//===- StringUtils.cpp - Routines for manipulating swiftscan_string_ref_t -===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/DependencyScan/StringUtils.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace swift {
|
||||
namespace dependencies {
|
||||
|
||||
swiftscan_string_ref_t create_null() {
|
||||
swiftscan_string_ref_t str;
|
||||
str.data = nullptr;
|
||||
str.length = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t create_clone(const char *string) {
|
||||
if (!string)
|
||||
return create_null();
|
||||
|
||||
if (string[0] == '\0')
|
||||
return create_null();
|
||||
|
||||
swiftscan_string_ref_t str;
|
||||
str.data = strdup(string);
|
||||
str.length = strlen(string);
|
||||
return str;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *create_set(const std::vector<std::string> &strings) {
|
||||
swiftscan_string_set_t *set = new swiftscan_string_set_t;
|
||||
set->count = strings.size();
|
||||
set->strings = new swiftscan_string_ref_t[set->count];
|
||||
for (unsigned SI = 0, SE = set->count; SI < SE; ++SI)
|
||||
set->strings[SI] = create_clone(strings[SI].c_str());
|
||||
return set;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *create_set(int count, const char **strings) {
|
||||
swiftscan_string_set_t *set = new swiftscan_string_set_t;
|
||||
set->count = count;
|
||||
set->strings = new swiftscan_string_ref_t[set->count];
|
||||
for (unsigned SI = 0, SE = set->count; SI < SE; ++SI)
|
||||
set->strings[SI] = create_clone(strings[SI]);
|
||||
return set;
|
||||
}
|
||||
|
||||
const char *get_C_string(swiftscan_string_ref_t string) {
|
||||
return static_cast<const char *>(string.data);
|
||||
}
|
||||
} // namespace dependencies
|
||||
} // namespace swift
|
||||
@@ -379,8 +379,6 @@ ArgsToFrontendOptionsConverter::determineRequestedAction(const ArgList &args) {
|
||||
return FrontendOptions::ActionType::EmitImportedModules;
|
||||
if (Opt.matches(OPT_scan_dependencies))
|
||||
return FrontendOptions::ActionType::ScanDependencies;
|
||||
if (Opt.matches(OPT_scan_clang_dependencies))
|
||||
return FrontendOptions::ActionType::ScanClangDependencies;
|
||||
if (Opt.matches(OPT_parse))
|
||||
return FrontendOptions::ActionType::Parse;
|
||||
if (Opt.matches(OPT_resolve_imports))
|
||||
|
||||
@@ -321,22 +321,11 @@ void CompilerInstance::setupDependencyTrackerIfNeeded() {
|
||||
DepTracker = std::make_unique<DependencyTracker>(*collectionMode);
|
||||
}
|
||||
|
||||
void CompilerInstance::setUpModuleDependencyCacheIfNeeded() {
|
||||
const auto &Invocation = getInvocation();
|
||||
const auto &opts = Invocation.getFrontendOptions();
|
||||
if (opts.RequestedAction == FrontendOptions::ActionType::ScanDependencies ||
|
||||
opts.RequestedAction == FrontendOptions::ActionType::ScanClangDependencies) {
|
||||
ModDepCache = std::make_unique<ModuleDependenciesCache>();
|
||||
}
|
||||
}
|
||||
|
||||
bool CompilerInstance::setup(const CompilerInvocation &Invok) {
|
||||
Invocation = Invok;
|
||||
|
||||
setupDependencyTrackerIfNeeded();
|
||||
|
||||
setUpModuleDependencyCacheIfNeeded();
|
||||
|
||||
// If initializing the overlay file system fails there's no sense in
|
||||
// continuing because the compiler will read the wrong files.
|
||||
if (setUpVirtualFileSystemOverlays())
|
||||
|
||||
@@ -66,7 +66,6 @@ bool FrontendOptions::needsProperModuleName(ActionType action) {
|
||||
case ActionType::DumpTypeInfo:
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("Unknown ActionType");
|
||||
@@ -80,7 +79,6 @@ bool FrontendOptions::shouldActionOnlyParse(ActionType action) {
|
||||
case ActionType::DumpInterfaceHash:
|
||||
case ActionType::EmitImportedModules:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return true;
|
||||
@@ -98,7 +96,6 @@ bool FrontendOptions::doesActionRequireSwiftStandardLibrary(ActionType action) {
|
||||
case ActionType::DumpInterfaceHash:
|
||||
case ActionType::EmitImportedModules:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::EmitPCH:
|
||||
case ActionType::EmitPCM:
|
||||
@@ -146,7 +143,6 @@ bool FrontendOptions::doesActionRequireInputs(ActionType action) {
|
||||
case ActionType::DumpInterfaceHash:
|
||||
case ActionType::EmitImportedModules:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::EmitPCH:
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
@@ -191,7 +187,6 @@ bool FrontendOptions::doesActionPerformEndOfPipelineActions(ActionType action) {
|
||||
case ActionType::DumpInterfaceHash:
|
||||
case ActionType::EmitImportedModules:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::CompileModuleFromInterface:
|
||||
case ActionType::TypecheckModuleFromInterface:
|
||||
case ActionType::ResolveImports:
|
||||
@@ -308,7 +303,6 @@ FrontendOptions::formatForPrincipalOutputFileForAction(ActionType action) {
|
||||
return TY_ClangModuleFile;
|
||||
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
return TY_JSONDependencies;
|
||||
case ActionType::PrintFeature:
|
||||
return TY_JSONFeatures;
|
||||
@@ -352,7 +346,6 @@ bool FrontendOptions::canActionEmitDependencies(ActionType action) {
|
||||
case ActionType::EmitImportedModules:
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
return true;
|
||||
}
|
||||
llvm_unreachable("unhandled action");
|
||||
@@ -378,7 +371,6 @@ bool FrontendOptions::canActionEmitReferenceDependencies(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
@@ -432,7 +424,6 @@ bool FrontendOptions::canActionEmitModuleSummary(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::Typecheck:
|
||||
case ActionType::MergeModules:
|
||||
case ActionType::EmitModuleOnly:
|
||||
@@ -471,7 +462,6 @@ bool FrontendOptions::canActionEmitObjCHeader(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
@@ -511,7 +501,6 @@ bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
@@ -557,7 +546,6 @@ bool FrontendOptions::canActionEmitModule(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
@@ -604,7 +592,6 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
case ActionType::Typecheck:
|
||||
@@ -652,7 +639,6 @@ bool FrontendOptions::doesActionProduceOutput(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintFeature:
|
||||
return true;
|
||||
|
||||
@@ -700,7 +686,6 @@ bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) {
|
||||
case ActionType::DumpTypeInfo:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return true;
|
||||
@@ -728,7 +713,6 @@ bool FrontendOptions::doesActionGenerateSIL(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
@@ -777,7 +761,6 @@ bool FrontendOptions::doesActionGenerateIR(ActionType action) {
|
||||
case ActionType::EmitPCM:
|
||||
case ActionType::DumpPCM:
|
||||
case ActionType::ScanDependencies:
|
||||
case ActionType::ScanClangDependencies:
|
||||
case ActionType::PrintVersion:
|
||||
case ActionType::PrintFeature:
|
||||
return false;
|
||||
|
||||
@@ -4,7 +4,6 @@ add_swift_host_library(swiftFrontendTool STATIC
|
||||
ImportedModules.cpp
|
||||
LoadedModuleTrace.cpp
|
||||
MakeStyleDependencies.cpp
|
||||
ScanDependencies.cpp
|
||||
TBD.cpp)
|
||||
add_dependencies(swiftFrontendTool
|
||||
swift-syntax-generated-headers
|
||||
@@ -15,6 +14,7 @@ target_link_libraries(swiftFrontendTool INTERFACE
|
||||
target_link_libraries(swiftFrontendTool PRIVATE
|
||||
swiftClangImporter
|
||||
swiftDemangling
|
||||
swiftDependencyScan
|
||||
swiftFrontend
|
||||
swiftIDE
|
||||
swiftImmediate
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
@@ -21,8 +21,8 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/FrontendTool/FrontendTool.h"
|
||||
#include "swift/DependencyScan/ScanDependencies.h"
|
||||
#include "Dependencies.h"
|
||||
#include "ScanDependencies.h"
|
||||
#include "TBD.h"
|
||||
#include "swift/Subsystems.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
@@ -1134,10 +1134,17 @@ withSemanticAnalysis(CompilerInstance &Instance, FrontendObserver *observer,
|
||||
static bool performScanDependencies(CompilerInstance &Instance) {
|
||||
auto batchScanInput =
|
||||
Instance.getASTContext().SearchPathOpts.BatchScanInputFilePath;
|
||||
ModuleDependenciesCache SingleUseCache;
|
||||
if (batchScanInput.empty()) {
|
||||
return scanDependencies(Instance);
|
||||
if (Instance.getInvocation().getFrontendOptions().ImportPrescan)
|
||||
return dependencies::prescanDependencies(Instance);
|
||||
else
|
||||
return dependencies::scanDependencies(Instance);
|
||||
} else {
|
||||
return batchScanModuleDependencies(Instance, batchScanInput);
|
||||
if (Instance.getInvocation().getFrontendOptions().ImportPrescan)
|
||||
return dependencies::batchPrescanDependencies(Instance, batchScanInput);
|
||||
else
|
||||
return dependencies::batchScanDependencies(Instance, batchScanInput);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1224,8 +1231,6 @@ static bool performAction(CompilerInstance &Instance,
|
||||
// MARK: Dependency Scanning Actions
|
||||
case FrontendOptions::ActionType::ScanDependencies:
|
||||
return performScanDependencies(Instance);
|
||||
case FrontendOptions::ActionType::ScanClangDependencies:
|
||||
return scanClangDependencies(Instance);
|
||||
|
||||
// MARK: General Compilation Actions
|
||||
case FrontendOptions::ActionType::Parse:
|
||||
|
||||
@@ -1,969 +0,0 @@
|
||||
//===--- ScanDependencies.cpp -- Scans the dependencies of a module -------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ScanDependencies.h"
|
||||
#include "swift/AST/ASTContext.h"
|
||||
#include "swift/AST/Decl.h"
|
||||
#include "swift/AST/DiagnosticEngine.h"
|
||||
#include "swift/AST/DiagnosticsFrontend.h"
|
||||
#include "swift/AST/Module.h"
|
||||
#include "swift/AST/ModuleDependencies.h"
|
||||
#include "swift/AST/ModuleLoader.h"
|
||||
#include "swift/AST/SourceFile.h"
|
||||
#include "swift/ClangImporter/ClangImporter.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Basic/STLExtras.h"
|
||||
#include "swift/Frontend/Frontend.h"
|
||||
#include "swift/Frontend/FrontendOptions.h"
|
||||
#include "swift/Frontend/ModuleInterfaceLoader.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/StringSet.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/YAMLParser.h"
|
||||
#include <set>
|
||||
|
||||
using namespace swift;
|
||||
using namespace llvm::yaml;
|
||||
|
||||
namespace {
|
||||
struct BatchScanInput {
|
||||
StringRef moduleName;
|
||||
StringRef arguments;
|
||||
StringRef outputPath;
|
||||
bool isSwift;
|
||||
};
|
||||
|
||||
static std::string getScalaNodeText(Node *N) {
|
||||
SmallString<32> Buffer;
|
||||
return cast<ScalarNode>(N)->getValue(Buffer).str();
|
||||
}
|
||||
|
||||
/// Parse an entry like this, where the "platforms" key-value pair is optional:
|
||||
/// {
|
||||
/// "swiftModuleName": "Foo",
|
||||
/// "arguments": "-target 10.15",
|
||||
/// "output": "../Foo.json"
|
||||
/// },
|
||||
static bool parseBatchInputEntries(ASTContext &Ctx, llvm::StringSaver &saver,
|
||||
Node *Node, std::vector<BatchScanInput> &result) {
|
||||
auto *SN = cast<SequenceNode>(Node);
|
||||
if (!SN)
|
||||
return true;
|
||||
for (auto It = SN->begin(); It != SN->end(); ++It) {
|
||||
auto *MN = cast<MappingNode>(&*It);
|
||||
BatchScanInput entry;
|
||||
Optional<std::set<int8_t>> Platforms;
|
||||
for (auto &Pair: *MN) {
|
||||
auto Key = getScalaNodeText(Pair.getKey());
|
||||
auto* Value = Pair.getValue();
|
||||
if (Key == "clangModuleName") {
|
||||
entry.moduleName = saver.save(getScalaNodeText(Value));
|
||||
entry.isSwift = false;
|
||||
} else if (Key == "swiftModuleName") {
|
||||
entry.moduleName = saver.save(getScalaNodeText(Value));
|
||||
entry.isSwift = true;
|
||||
} else if (Key == "arguments") {
|
||||
entry.arguments = saver.save(getScalaNodeText(Value));
|
||||
} else if (Key == "output") {
|
||||
entry.outputPath = saver.save(getScalaNodeText(Value));
|
||||
} else {
|
||||
// Future proof.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (entry.moduleName.empty())
|
||||
return true;
|
||||
if (entry.outputPath.empty())
|
||||
return true;
|
||||
result.emplace_back(std::move(entry));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Optional<std::vector<BatchScanInput>>
|
||||
parseBatchScanInputFile(ASTContext &ctx, StringRef batchInputPath,
|
||||
llvm::StringSaver &saver) {
|
||||
assert(!batchInputPath.empty());
|
||||
namespace yaml = llvm::yaml;
|
||||
std::vector<BatchScanInput> result;
|
||||
|
||||
// Load the input file.
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
|
||||
llvm::MemoryBuffer::getFile(batchInputPath);
|
||||
if (!FileBufOrErr) {
|
||||
ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_missing,
|
||||
batchInputPath);
|
||||
return None;
|
||||
}
|
||||
StringRef Buffer = FileBufOrErr->get()->getBuffer();
|
||||
|
||||
// Use a new source manager instead of the one from ASTContext because we
|
||||
// don't want the Json file to be persistent.
|
||||
SourceManager SM;
|
||||
yaml::Stream Stream(llvm::MemoryBufferRef(Buffer, batchInputPath),
|
||||
SM.getLLVMSourceMgr());
|
||||
for (auto DI = Stream.begin(); DI != Stream.end(); ++ DI) {
|
||||
assert(DI != Stream.end() && "Failed to read a document");
|
||||
yaml::Node *N = DI->getRoot();
|
||||
assert(N && "Failed to find a root");
|
||||
if (parseBatchInputEntries(ctx, saver, N, result)) {
|
||||
ctx.Diags.diagnose(SourceLoc(), diag::batch_scan_input_file_corrupted,
|
||||
batchInputPath);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// Find all of the imported Clang modules starting with the given module name.
|
||||
static void findAllImportedClangModules(ASTContext &ctx, StringRef moduleName,
|
||||
ModuleDependenciesCache &cache,
|
||||
std::vector<std::string> &allModules,
|
||||
llvm::StringSet<> &knownModules) {
|
||||
if (!knownModules.insert(moduleName).second)
|
||||
return;
|
||||
allModules.push_back(moduleName.str());
|
||||
|
||||
auto dependencies = cache.findDependencies(
|
||||
moduleName, ModuleDependenciesKind::Clang);
|
||||
if (!dependencies)
|
||||
return;
|
||||
|
||||
for (const auto &dep : dependencies->getModuleDependencies()) {
|
||||
findAllImportedClangModules(ctx, dep, cache, allModules, knownModules);
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolve the direct dependencies of the given module.
|
||||
static std::vector<ModuleDependencyID> resolveDirectDependencies(
|
||||
CompilerInstance &instance, ModuleDependencyID module,
|
||||
ModuleDependenciesCache &cache,
|
||||
InterfaceSubContextDelegate &ASTDelegate) {
|
||||
auto &ctx = instance.getASTContext();
|
||||
auto knownDependencies = *cache.findDependencies(module.first, module.second);
|
||||
auto isSwift = knownDependencies.isSwiftTextualModule();
|
||||
|
||||
// Find the dependencies of every module this module directly depends on.
|
||||
std::set<ModuleDependencyID> result;
|
||||
for (auto dependsOn : knownDependencies.getModuleDependencies()) {
|
||||
// Figure out what kind of module we need.
|
||||
bool onlyClangModule = !isSwift || module.first == dependsOn;
|
||||
|
||||
// Retrieve the dependencies for this module.
|
||||
if (auto found = ctx.getModuleDependencies(
|
||||
dependsOn, onlyClangModule, cache, ASTDelegate)) {
|
||||
result.insert({dependsOn, found->getKind()});
|
||||
}
|
||||
}
|
||||
|
||||
if (isSwift) {
|
||||
// A record of all of the Clang modules referenced from this Swift module.
|
||||
std::vector<std::string> allClangModules;
|
||||
llvm::StringSet<> knownModules;
|
||||
|
||||
// If the Swift module has a bridging header, add those dependencies.
|
||||
if (knownDependencies.getBridgingHeader()) {
|
||||
auto clangImporter =
|
||||
static_cast<ClangImporter *>(ctx.getClangModuleLoader());
|
||||
if (!clangImporter->addBridgingHeaderDependencies(module.first, cache)) {
|
||||
// Grab the updated module dependencies.
|
||||
// FIXME: This is such a hack.
|
||||
knownDependencies = *cache.findDependencies(module.first, module.second);
|
||||
|
||||
// Add the Clang modules referenced from the bridging header to the
|
||||
// set of Clang modules we know about.
|
||||
auto swiftDeps = knownDependencies.getAsSwiftTextualModule();
|
||||
for (const auto &clangDep : swiftDeps->bridgingModuleDependencies) {
|
||||
findAllImportedClangModules(ctx, clangDep, cache, allClangModules,
|
||||
knownModules);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find all of the Clang modules this Swift module depends on.
|
||||
for (const auto &dep : result) {
|
||||
if (dep.second != ModuleDependenciesKind::Clang)
|
||||
continue;
|
||||
|
||||
findAllImportedClangModules(ctx, dep.first, cache, allClangModules,
|
||||
knownModules);
|
||||
}
|
||||
|
||||
// Look for overlays for each of the Clang modules. The Swift module
|
||||
// directly depends on these.
|
||||
for (const auto &clangDep : allClangModules) {
|
||||
if (auto found = ctx.getModuleDependencies(
|
||||
clangDep, /*onlyClangModule=*/false, cache, ASTDelegate)) {
|
||||
// ASTContext::getModuleDependencies returns dependencies for a module with a given name.
|
||||
// This Clang module may have the same name as the Swift module we are resolving, so we
|
||||
// need to make sure we don't add a dependency from a Swift module to itself.
|
||||
if ((found->getKind() == ModuleDependenciesKind::SwiftTextual ||
|
||||
found->getKind() == ModuleDependenciesKind::SwiftBinary ||
|
||||
found->getKind() == ModuleDependenciesKind::SwiftPlaceholder) &&
|
||||
clangDep != module.first) {
|
||||
result.insert({clangDep, found->getKind()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::vector<ModuleDependencyID>(result.begin(), result.end());
|
||||
}
|
||||
|
||||
static void discoverCrosssImportOverlayDependencies(
|
||||
CompilerInstance &instance, StringRef mainModuleName,
|
||||
ArrayRef<ModuleDependencyID> allDependencies,
|
||||
ModuleDependenciesCache &cache, InterfaceSubContextDelegate &ASTDelegate,
|
||||
llvm::function_ref<void(ModuleDependencyID)> action) {
|
||||
// Modules explicitly imported. Only these can be secondary module.
|
||||
llvm::SetVector<Identifier> newOverlays;
|
||||
for (auto dep: allDependencies) {
|
||||
auto moduleName = dep.first;
|
||||
auto dependencies = *cache.findDependencies(moduleName, dep.second);
|
||||
// Collect a map from secondary module name to cross-import overlay names.
|
||||
auto overlayMap = dependencies.collectCrossImportOverlayNames(
|
||||
instance.getASTContext(), moduleName);
|
||||
if (overlayMap.empty())
|
||||
continue;
|
||||
std::for_each(allDependencies.begin(), allDependencies.end(),
|
||||
[&](ModuleDependencyID Id) {
|
||||
// check if any explicitly imported modules can serve as a secondary
|
||||
// module, and add the overlay names to the dependencies list.
|
||||
for (auto overlayName: overlayMap[Id.first]) {
|
||||
if (std::find_if(allDependencies.begin(), allDependencies.end(),
|
||||
[&](ModuleDependencyID Id) { return Id.first == overlayName.str(); })
|
||||
== allDependencies.end()) {
|
||||
newOverlays.insert(overlayName);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// No new cross-import overlays are found, return.
|
||||
if (newOverlays.empty())
|
||||
return;
|
||||
// Construct a dummy main to resolve the newly discovered cross import overlays.
|
||||
StringRef dummyMainName = "DummyMainModuleForResolvingCrossImportOverlays";
|
||||
auto dummyMainDependencies = ModuleDependencies::forMainSwiftModule({});
|
||||
|
||||
// Update main module's dependencies to include these new overlays.
|
||||
auto mainDep = *cache.findDependencies(mainModuleName,
|
||||
ModuleDependenciesKind::SwiftTextual);
|
||||
std::for_each(newOverlays.begin(), newOverlays.end(), [&](Identifier modName) {
|
||||
dummyMainDependencies.addModuleDependency(modName.str());
|
||||
mainDep.addModuleDependency(modName.str());
|
||||
});
|
||||
cache.updateDependencies({mainModuleName.str(),
|
||||
ModuleDependenciesKind::SwiftTextual}, mainDep);
|
||||
|
||||
// Record the dummy main module's direct dependencies. The dummy main module
|
||||
// only directly depend on these newly discovered overlay modules.
|
||||
cache.recordDependencies(dummyMainName, dummyMainDependencies);
|
||||
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
|
||||
std::set<ModuleDependencyID>> allModules;
|
||||
|
||||
// Seed the all module list from the dummpy main module.
|
||||
allModules.insert({dummyMainName.str(), dummyMainDependencies.getKind()});
|
||||
|
||||
// Explore the dependencies of every module.
|
||||
for (unsigned currentModuleIdx = 0;
|
||||
currentModuleIdx < allModules.size();
|
||||
++currentModuleIdx) {
|
||||
auto module = allModules[currentModuleIdx];
|
||||
auto discoveredModules = resolveDirectDependencies(instance, module,
|
||||
cache, ASTDelegate);
|
||||
allModules.insert(discoveredModules.begin(), discoveredModules.end());
|
||||
}
|
||||
// Report any discovered modules to the clients, which include all overlays
|
||||
// and their dependencies.
|
||||
std::for_each(/* +1 to exclude dummy main*/allModules.begin() + 1,
|
||||
allModules.end(), action);
|
||||
}
|
||||
|
||||
/// Write a single JSON field.
|
||||
namespace {
|
||||
template<typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out,
|
||||
StringRef fieldName,
|
||||
const T &value,
|
||||
unsigned indentLevel,
|
||||
bool trailingComma);
|
||||
|
||||
/// Write a string value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out,
|
||||
StringRef value,
|
||||
unsigned indentLevel) {
|
||||
out << "\"";
|
||||
out << value;
|
||||
out << "\"";
|
||||
}
|
||||
|
||||
/// Write a boolean value as JSON.
|
||||
void writeJSONValue(llvm::raw_ostream &out,
|
||||
bool value,
|
||||
unsigned indentLevel) {
|
||||
out.write_escaped(value ? "true" : "false");
|
||||
}
|
||||
|
||||
/// Write a module identifier.
|
||||
void writeJSONValue(llvm::raw_ostream &out,
|
||||
const ModuleDependencyID &module,
|
||||
unsigned indentLevel) {
|
||||
out << "{\n";
|
||||
std::string moduleKind;
|
||||
if (module.second == ModuleDependenciesKind::SwiftTextual)
|
||||
moduleKind = "swift";
|
||||
else if (module.second == ModuleDependenciesKind::SwiftBinary)
|
||||
// FIXME: rename to be consistent in the clients (swift-driver)
|
||||
moduleKind = "swiftPrebuiltExternal";
|
||||
else if (module.second == ModuleDependenciesKind::SwiftPlaceholder)
|
||||
moduleKind = "swiftPlaceholder";
|
||||
else
|
||||
moduleKind = "clang";
|
||||
|
||||
writeJSONSingleField(
|
||||
out,
|
||||
moduleKind,
|
||||
module.first,
|
||||
indentLevel + 1,
|
||||
/*trailingComma=*/false);
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "}";
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template<typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out,
|
||||
ArrayRef<T> values,
|
||||
unsigned indentLevel) {
|
||||
out << "[\n";
|
||||
|
||||
for (const auto &value: values) {
|
||||
|
||||
out.indent((indentLevel + 1) * 2);
|
||||
|
||||
writeJSONValue(out, value, indentLevel + 1);
|
||||
|
||||
if (&value != &values.back()) {
|
||||
out << ",";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
|
||||
out.indent(indentLevel * 2);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
/// Write a JSON array.
|
||||
template<typename T>
|
||||
void writeJSONValue(llvm::raw_ostream &out,
|
||||
const std::vector<T> &values,
|
||||
unsigned indentLevel) {
|
||||
writeJSONValue(out, llvm::makeArrayRef(values), indentLevel);
|
||||
}
|
||||
|
||||
/// Write a single JSON field.
|
||||
template<typename T>
|
||||
void writeJSONSingleField(llvm::raw_ostream &out,
|
||||
StringRef fieldName,
|
||||
const T &value,
|
||||
unsigned indentLevel,
|
||||
bool trailingComma) {
|
||||
out.indent(indentLevel * 2);
|
||||
writeJSONValue(out, fieldName, indentLevel);
|
||||
out << ": ";
|
||||
writeJSONValue(out, value, indentLevel);
|
||||
if (trailingComma)
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static void writePrescanJSON(llvm::raw_ostream &out,
|
||||
const ModuleDependencies &mainModuleDependencies) {
|
||||
// Write out a JSON containing all main module imports.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER {
|
||||
out << "}\n";
|
||||
};
|
||||
|
||||
writeJSONSingleField(out, "imports", mainModuleDependencies.getModuleDependencies(), 0, false);
|
||||
}
|
||||
|
||||
static void writeJSON(llvm::raw_ostream &out,
|
||||
CompilerInstance &instance,
|
||||
ModuleDependenciesCache &cache,
|
||||
InterfaceSubContextDelegate &ASTDelegate,
|
||||
ArrayRef<ModuleDependencyID> allModules) {
|
||||
// Write out a JSON description of all of the dependencies.
|
||||
out << "{\n";
|
||||
SWIFT_DEFER {
|
||||
out << "}\n";
|
||||
};
|
||||
|
||||
// Name of the main module.
|
||||
writeJSONSingleField(out, "mainModuleName", allModules.front().first,
|
||||
/*indentLevel=*/1, /*trailingComma=*/true);
|
||||
|
||||
// Write out all of the modules.
|
||||
out << " \"modules\": [\n";
|
||||
SWIFT_DEFER {
|
||||
out << " ]\n";
|
||||
};
|
||||
for (const auto &module : allModules) {
|
||||
auto directDependencies = resolveDirectDependencies(
|
||||
instance, ModuleDependencyID(module.first, module.second), cache,
|
||||
ASTDelegate);
|
||||
|
||||
// Grab the completed module dependencies.
|
||||
auto moduleDeps = *cache.findDependencies(module.first, module.second);
|
||||
|
||||
// The module we are describing.
|
||||
out.indent(2 * 2);
|
||||
writeJSONValue(out, module, 2);
|
||||
out << ",\n";
|
||||
|
||||
out.indent(2 * 2);
|
||||
out << "{\n";
|
||||
|
||||
auto swiftPlaceholderDeps = moduleDeps.getAsPlaceholderDependencyModule();
|
||||
auto swiftTextualDeps = moduleDeps.getAsSwiftTextualModule();
|
||||
auto swiftBinaryDeps = moduleDeps.getAsSwiftBinaryModule();
|
||||
auto clangDeps = moduleDeps.getAsClangModule();
|
||||
|
||||
// Module path.
|
||||
const char *modulePathSuffix =
|
||||
moduleDeps.isSwiftModule() ? ".swiftmodule" : ".pcm";
|
||||
|
||||
std::string modulePath;
|
||||
if (swiftPlaceholderDeps)
|
||||
modulePath = swiftPlaceholderDeps->compiledModulePath;
|
||||
else if (swiftBinaryDeps)
|
||||
modulePath = swiftBinaryDeps->compiledModulePath;
|
||||
else
|
||||
modulePath = module.first + modulePathSuffix;
|
||||
|
||||
writeJSONSingleField(out, "modulePath", modulePath, /*indentLevel=*/3,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Source files.
|
||||
if (swiftTextualDeps) {
|
||||
writeJSONSingleField(out, "sourceFiles", swiftTextualDeps->sourceFiles, 3,
|
||||
/*trailingComma=*/true);
|
||||
} else if (clangDeps) {
|
||||
writeJSONSingleField(out, "sourceFiles", clangDeps->fileDependencies, 3,
|
||||
/*trailingComma=*/true);
|
||||
}
|
||||
|
||||
// Direct dependencies.
|
||||
if (swiftTextualDeps || swiftBinaryDeps || clangDeps)
|
||||
writeJSONSingleField(out, "directDependencies", directDependencies, 3,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Swift and Clang-specific details.
|
||||
out.indent(3 * 2);
|
||||
out << "\"details\": {\n";
|
||||
out.indent(4 * 2);
|
||||
if (swiftTextualDeps) {
|
||||
out << "\"swift\": {\n";
|
||||
|
||||
/// Swift interface file, if there is one. The main module, for example, will not have
|
||||
/// an interface file.
|
||||
if (swiftTextualDeps->swiftInterfaceFile) {
|
||||
writeJSONSingleField(out, "moduleInterfacePath",
|
||||
*swiftTextualDeps->swiftInterfaceFile, 5,
|
||||
/*trailingComma=*/true);
|
||||
writeJSONSingleField(out, "contextHash",
|
||||
swiftTextualDeps->contextHash, 5,
|
||||
/*trailingComma=*/true);
|
||||
out.indent(5 * 2);
|
||||
out << "\"commandLine\": [\n";
|
||||
for (auto &arg :swiftTextualDeps->buildCommandLine) {
|
||||
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << arg << "\"";
|
||||
if (&arg != &swiftTextualDeps->buildCommandLine.back())
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
out.indent(5 * 2);
|
||||
out << "\"compiledModuleCandidates\": [\n";
|
||||
for (auto &candidate: swiftTextualDeps->compiledModuleCandidates) {
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << candidate << "\"";
|
||||
if (&candidate != &swiftTextualDeps->compiledModuleCandidates.back())
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << "],\n";
|
||||
}
|
||||
writeJSONSingleField(
|
||||
out, "isFramework",
|
||||
swiftTextualDeps->isFramework, 5,
|
||||
/*trailingComma=*/!swiftTextualDeps->extraPCMArgs.empty() ||
|
||||
swiftTextualDeps->bridgingHeaderFile.hasValue());
|
||||
if (!swiftTextualDeps->extraPCMArgs.empty()) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"extraPcmArgs\": [\n";
|
||||
for (auto &arg : swiftTextualDeps->extraPCMArgs) {
|
||||
out.indent(6 * 2);
|
||||
out << "\"" << arg << "\"";
|
||||
if (&arg != &swiftTextualDeps->extraPCMArgs.back())
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
out.indent(5 * 2);
|
||||
out << (swiftTextualDeps->bridgingHeaderFile.hasValue() ? "],\n" : "]\n");
|
||||
}
|
||||
/// Bridging header and its source file dependencies, if any.
|
||||
if (swiftTextualDeps->bridgingHeaderFile) {
|
||||
out.indent(5 * 2);
|
||||
out << "\"bridgingHeader\": {\n";
|
||||
writeJSONSingleField(out, "path", *swiftTextualDeps->bridgingHeaderFile, 6,
|
||||
/*trailingComma=*/true);
|
||||
writeJSONSingleField(out, "sourceFiles", swiftTextualDeps->bridgingSourceFiles,
|
||||
6,
|
||||
/*trailingComma=*/true);
|
||||
writeJSONSingleField(out, "moduleDependencies",
|
||||
swiftTextualDeps->bridgingModuleDependencies, 6,
|
||||
/*trailingComma=*/false);
|
||||
out.indent(5 * 2);
|
||||
out << "}\n";
|
||||
}
|
||||
} else if (swiftPlaceholderDeps) {
|
||||
out << "\"swiftPlaceholder\": {\n";
|
||||
|
||||
// Module doc file
|
||||
if (swiftPlaceholderDeps->moduleDocPath != "")
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftPlaceholderDeps->moduleDocPath,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Source Info file
|
||||
if (swiftPlaceholderDeps->moduleDocPath != "")
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftPlaceholderDeps->sourceInfoPath,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/false);
|
||||
} else if (swiftBinaryDeps) {
|
||||
out << "\"swiftPrebuiltExternal\": {\n";
|
||||
assert(swiftBinaryDeps->compiledModulePath != "" &&
|
||||
"Expected .swiftmodule for a Binary Swift Module Dependency.");
|
||||
writeJSONSingleField(out, "compiledModulePath",
|
||||
swiftBinaryDeps->compiledModulePath,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
// Module doc file
|
||||
if (swiftBinaryDeps->moduleDocPath != "")
|
||||
writeJSONSingleField(out, "moduleDocPath",
|
||||
swiftBinaryDeps->moduleDocPath,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Module Source Info file
|
||||
if (swiftBinaryDeps->moduleDocPath != "")
|
||||
writeJSONSingleField(out, "moduleSourceInfoPath",
|
||||
swiftBinaryDeps->sourceInfoPath,
|
||||
/*indentLevel=*/5,
|
||||
/*trailingComma=*/false);
|
||||
} else {
|
||||
out << "\"clang\": {\n";
|
||||
|
||||
// Module map file.
|
||||
writeJSONSingleField(out, "moduleMapPath", clangDeps->moduleMapFile, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Context hash.
|
||||
writeJSONSingleField(out, "contextHash", clangDeps->contextHash, 5,
|
||||
/*trailingComma=*/true);
|
||||
|
||||
// Command line.
|
||||
writeJSONSingleField(out, "commandLine", clangDeps->nonPathCommandLine, 5,
|
||||
/*trailingComma=*/false);
|
||||
}
|
||||
|
||||
out.indent(4 * 2);
|
||||
out << "}\n";
|
||||
out.indent(3 * 2);
|
||||
out << "}\n";
|
||||
out.indent(2 * 2);
|
||||
out << "}";
|
||||
|
||||
if (&module != &allModules.back())
|
||||
out << ",";
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
static bool diagnoseCycle(CompilerInstance &instance,
|
||||
ModuleDependenciesCache &cache,
|
||||
ModuleDependencyID mainId,
|
||||
InterfaceSubContextDelegate &astDelegate) {
|
||||
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
|
||||
std::set<ModuleDependencyID>> openSet;
|
||||
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
|
||||
std::set<ModuleDependencyID>> closeSet;
|
||||
// Start from the main module.
|
||||
openSet.insert(mainId);
|
||||
while(!openSet.empty()) {
|
||||
auto &lastOpen = openSet.back();
|
||||
auto beforeSize = openSet.size();
|
||||
for (auto dep: resolveDirectDependencies(instance, lastOpen, cache,
|
||||
astDelegate)) {
|
||||
if (closeSet.count(dep))
|
||||
continue;
|
||||
if (openSet.insert(dep)) {
|
||||
break;
|
||||
} else {
|
||||
// Find a cycle, diagnose.
|
||||
auto startIt = std::find(openSet.begin(), openSet.end(), dep);
|
||||
assert(startIt != openSet.end());
|
||||
llvm::SmallString<64> buffer;
|
||||
for (auto it = startIt; it != openSet.end(); ++ it) {
|
||||
buffer.append(it->first);
|
||||
buffer.append((it->second == ModuleDependenciesKind::SwiftTextual ||
|
||||
it->second == ModuleDependenciesKind::SwiftBinary)?
|
||||
".swiftmodule": ".pcm");
|
||||
buffer.append(" -> ");
|
||||
}
|
||||
buffer.append(startIt->first);
|
||||
buffer.append((startIt->second == ModuleDependenciesKind::SwiftTextual ||
|
||||
startIt->second == ModuleDependenciesKind::SwiftBinary)?
|
||||
".swiftmodule": ".pcm");
|
||||
instance.getASTContext().Diags.diagnose(SourceLoc(),
|
||||
diag::scanner_find_cycle,
|
||||
buffer.str());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// No new node added. We can close this node
|
||||
if (openSet.size() == beforeSize) {
|
||||
closeSet.insert(openSet.back());
|
||||
openSet.pop_back();
|
||||
} else {
|
||||
assert(openSet.size() == beforeSize + 1);
|
||||
}
|
||||
}
|
||||
assert(openSet.empty());
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool scanModuleDependencies(CompilerInstance &instance,
|
||||
StringRef moduleName,
|
||||
bool isClang,
|
||||
StringRef outputPath) {
|
||||
ASTContext &ctx = instance.getASTContext();
|
||||
auto &FEOpts = instance.getInvocation().getFrontendOptions();
|
||||
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
|
||||
auto ModuleCachePath = getModuleCachePathFromClang(ctx
|
||||
.getClangModuleLoader()->getClangInstance());
|
||||
|
||||
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
|
||||
std::set<ModuleDependencyID>> allModules;
|
||||
// Retrieve the instance's module dependency cache.
|
||||
ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
|
||||
assert(cache &&
|
||||
"Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
|
||||
InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
|
||||
ctx.SearchPathOpts, ctx.LangOpts,
|
||||
ctx.ClangImporterOpts,
|
||||
LoaderOpts,
|
||||
/*buildModuleCacheDirIfAbsent*/false,
|
||||
ModuleCachePath,
|
||||
FEOpts.PrebuiltModuleCachePath,
|
||||
FEOpts.SerializeModuleInterfaceDependencyHashes,
|
||||
FEOpts.shouldTrackSystemDependencies());
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream out(outputPath, EC, llvm::sys::fs::F_None);
|
||||
Optional<ModuleDependencies> rootDeps;
|
||||
if (isClang) {
|
||||
// Loading the clang module using Clang importer.
|
||||
// This action will populate the cache with the main module's dependencies.
|
||||
rootDeps = ctx.getModuleDependencies(moduleName, /*IsClang*/true, *cache,
|
||||
ASTDelegate);
|
||||
} else {
|
||||
// Loading the swift module's dependencies.
|
||||
rootDeps = ctx.getSwiftModuleDependencies(moduleName, *cache, ASTDelegate);
|
||||
}
|
||||
if (!rootDeps.hasValue()) {
|
||||
// We cannot find the clang module, abort.
|
||||
return true;
|
||||
}
|
||||
// Add the main module.
|
||||
allModules.insert({moduleName.str(), isClang ? ModuleDependenciesKind::Clang:
|
||||
ModuleDependenciesKind::SwiftTextual});
|
||||
|
||||
// Output module prescan.
|
||||
if (FEOpts.ImportPrescan) {
|
||||
writePrescanJSON(out, rootDeps.getValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Explore the dependencies of every module.
|
||||
for (unsigned currentModuleIdx = 0;
|
||||
currentModuleIdx < allModules.size();
|
||||
++currentModuleIdx) {
|
||||
auto module = allModules[currentModuleIdx];
|
||||
auto discoveredModules =
|
||||
resolveDirectDependencies(instance, module, *cache, ASTDelegate);
|
||||
allModules.insert(discoveredModules.begin(), discoveredModules.end());
|
||||
}
|
||||
// Write out the JSON description.
|
||||
writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool swift::scanClangDependencies(CompilerInstance &instance) {
|
||||
return scanModuleDependencies(instance,
|
||||
instance.getMainModule()->getNameStr(),
|
||||
/*isClang*/true,
|
||||
instance.getInvocation().getFrontendOptions()
|
||||
.InputsAndOutputs.getSingleOutputFilename());
|
||||
}
|
||||
|
||||
bool swift::batchScanModuleDependencies(CompilerInstance &instance,
|
||||
llvm::StringRef batchInputFile) {
|
||||
const CompilerInvocation &invok = instance.getInvocation();
|
||||
|
||||
(void)instance.getMainModule();
|
||||
llvm::BumpPtrAllocator alloc;
|
||||
llvm::StringSaver saver(alloc);
|
||||
auto results = parseBatchScanInputFile(instance.getASTContext(),
|
||||
batchInputFile, saver);
|
||||
if (!results.hasValue())
|
||||
return true;
|
||||
auto &diags = instance.getDiags();
|
||||
ForwardingDiagnosticConsumer FDC(diags);
|
||||
// Keep track of all compiler instances we have created.
|
||||
llvm::StringMap<std::unique_ptr<CompilerInstance>> subInstanceMap;
|
||||
for (auto &entry: *results) {
|
||||
CompilerInstance *pInstance = nullptr;
|
||||
if (entry.arguments.empty()) {
|
||||
// Use the compiler's instance if no arguments are specified.
|
||||
pInstance = &instance;
|
||||
} else if (subInstanceMap.count(entry.arguments)) {
|
||||
// Use the previously created instance if we've seen the arguments before.
|
||||
pInstance = subInstanceMap[entry.arguments].get();
|
||||
} else {
|
||||
// Create a new instance by the arguments and save it in the map.
|
||||
pInstance = subInstanceMap.insert({entry.arguments,
|
||||
std::make_unique<CompilerInstance>()}).first->getValue().get();
|
||||
SmallVector<const char*, 4> args;
|
||||
llvm::cl::TokenizeGNUCommandLine(entry.arguments, saver, args);
|
||||
CompilerInvocation subInvok = invok;
|
||||
pInstance->addDiagnosticConsumer(&FDC);
|
||||
if (subInvok.parseArgs(args, diags)) {
|
||||
instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
|
||||
entry.arguments);
|
||||
return true;
|
||||
}
|
||||
if (pInstance->setup(subInvok)) {
|
||||
instance.getDiags().diagnose(SourceLoc(), diag::scanner_arguments_invalid,
|
||||
entry.arguments);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
assert(pInstance);
|
||||
// Scan using the chosen compiler instance.
|
||||
if (scanModuleDependencies(*pInstance, entry.moduleName, !entry.isSwift,
|
||||
entry.outputPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool swift::scanDependencies(CompilerInstance &instance) {
|
||||
ASTContext &Context = instance.getASTContext();
|
||||
ModuleDecl *mainModule = instance.getMainModule();
|
||||
const CompilerInvocation &invocation = instance.getInvocation();
|
||||
const FrontendOptions &opts = invocation.getFrontendOptions();
|
||||
|
||||
std::string path = opts.InputsAndOutputs.getSingleOutputFilename();
|
||||
std::error_code EC;
|
||||
llvm::raw_fd_ostream out(path, EC, llvm::sys::fs::F_None);
|
||||
|
||||
if (out.has_error() || EC) {
|
||||
Context.Diags.diagnose(SourceLoc(), diag::error_opening_output, path,
|
||||
EC.message());
|
||||
out.clear_error();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Main module file name.
|
||||
auto newExt = file_types::getExtension(file_types::TY_SwiftModuleFile);
|
||||
llvm::SmallString<32> mainModulePath = mainModule->getName().str();
|
||||
llvm::sys::path::replace_extension(mainModulePath, newExt);
|
||||
|
||||
std::string apinotesVer = (llvm::Twine("-fapinotes-swift-version=")
|
||||
+ instance.getASTContext().LangOpts.EffectiveLanguageVersion
|
||||
.asAPINotesVersionString()).str();
|
||||
// Compute the dependencies of the main module.
|
||||
auto mainDependencies =
|
||||
ModuleDependencies::forMainSwiftModule({
|
||||
// ExtraPCMArgs
|
||||
"-Xcc", "-target", "-Xcc", instance.getASTContext().LangOpts.Target.str(),
|
||||
"-Xcc", apinotesVer
|
||||
});
|
||||
|
||||
// Compute Implicit dependencies of the main module
|
||||
{
|
||||
llvm::StringSet<> alreadyAddedModules;
|
||||
for (auto fileUnit : mainModule->getFiles()) {
|
||||
auto sf = dyn_cast<SourceFile>(fileUnit);
|
||||
if (!sf)
|
||||
continue;
|
||||
|
||||
mainDependencies.addModuleDependencies(*sf, alreadyAddedModules);
|
||||
}
|
||||
|
||||
const auto &importInfo = mainModule->getImplicitImportInfo();
|
||||
|
||||
// Swift standard library.
|
||||
switch (importInfo.StdlibKind) {
|
||||
case ImplicitStdlibKind::None:
|
||||
case ImplicitStdlibKind::Builtin:
|
||||
break;
|
||||
|
||||
case ImplicitStdlibKind::Stdlib:
|
||||
mainDependencies.addModuleDependency("Swift", &alreadyAddedModules);
|
||||
break;
|
||||
}
|
||||
|
||||
// Add any implicit module names.
|
||||
for (const auto &import : importInfo.AdditionalUnloadedImports) {
|
||||
mainDependencies.addModuleDependency(import.module.getModulePath(), &alreadyAddedModules);
|
||||
}
|
||||
|
||||
// Already-loaded, implicitly imported module names.
|
||||
for (const auto &import : importInfo.AdditionalImports) {
|
||||
mainDependencies.addModuleDependency(import.module.importedModule->getNameStr(), &alreadyAddedModules);
|
||||
}
|
||||
|
||||
// Add the bridging header.
|
||||
if (!importInfo.BridgingHeaderPath.empty()) {
|
||||
mainDependencies.addBridgingHeader(importInfo.BridgingHeaderPath);
|
||||
}
|
||||
|
||||
// If we are to import the underlying Clang module of the same name,
|
||||
// add a dependency with the same name to trigger the search.
|
||||
if (importInfo.ShouldImportUnderlyingModule) {
|
||||
mainDependencies.addModuleDependency(mainModule->getName().str(),
|
||||
&alreadyAddedModules);
|
||||
}
|
||||
}
|
||||
|
||||
// If import-prescan is specified, discover and serialize main module dependencies only and exit.
|
||||
if (opts.ImportPrescan) {
|
||||
writePrescanJSON(out, mainDependencies);
|
||||
// This process succeeds regardless of whether any errors occurred.
|
||||
// FIXME: We shouldn't need this, but it's masking bugs in our scanning
|
||||
// logic where we don't create a fresh context when scanning Swift interfaces
|
||||
// that includes their own command-line flags.
|
||||
Context.Diags.resetHadAnyError();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the main module.
|
||||
StringRef mainModuleName = mainModule->getNameStr();
|
||||
llvm::SetVector<ModuleDependencyID, std::vector<ModuleDependencyID>,
|
||||
std::set<ModuleDependencyID>> allModules;
|
||||
|
||||
allModules.insert({mainModuleName.str(), mainDependencies.getKind()});
|
||||
|
||||
// Retrieve the instance's module dependency cache.
|
||||
ModuleDependenciesCache *cache = instance.getModuleDependencyCache();
|
||||
assert(cache &&
|
||||
"Dependency Scanner expected a ModuleDependenciesCache on a compiler instance.");
|
||||
cache->recordDependencies(mainModuleName, std::move(mainDependencies));
|
||||
|
||||
auto &ctx = instance.getASTContext();
|
||||
auto ModuleCachePath = getModuleCachePathFromClang(ctx
|
||||
.getClangModuleLoader()->getClangInstance());
|
||||
auto &FEOpts = instance.getInvocation().getFrontendOptions();
|
||||
ModuleInterfaceLoaderOptions LoaderOpts(FEOpts);
|
||||
InterfaceSubContextDelegateImpl ASTDelegate(ctx.SourceMgr, ctx.Diags,
|
||||
ctx.SearchPathOpts, ctx.LangOpts,
|
||||
ctx.ClangImporterOpts,
|
||||
LoaderOpts,
|
||||
/*buildModuleCacheDirIfAbsent*/false,
|
||||
ModuleCachePath,
|
||||
FEOpts.PrebuiltModuleCachePath,
|
||||
FEOpts.SerializeModuleInterfaceDependencyHashes,
|
||||
FEOpts.shouldTrackSystemDependencies());
|
||||
|
||||
// Explore the dependencies of every module.
|
||||
for (unsigned currentModuleIdx = 0;
|
||||
currentModuleIdx < allModules.size();
|
||||
++currentModuleIdx) {
|
||||
auto module = allModules[currentModuleIdx];
|
||||
auto discoveredModules =
|
||||
resolveDirectDependencies(instance, module, *cache, ASTDelegate);
|
||||
allModules.insert(discoveredModules.begin(), discoveredModules.end());
|
||||
}
|
||||
|
||||
// We have all explicit imports now, resolve cross import overlays.
|
||||
discoverCrosssImportOverlayDependencies(instance, mainModuleName,
|
||||
/*All transitive dependencies*/allModules.getArrayRef().slice(1), *cache,
|
||||
ASTDelegate, [&](ModuleDependencyID id) {
|
||||
allModules.insert(id);
|
||||
});
|
||||
|
||||
// Dignose cycle in dependency graph.
|
||||
if (diagnoseCycle(instance, *cache, /*MainModule*/allModules.front(), ASTDelegate))
|
||||
return true;
|
||||
|
||||
// Write out the JSON description.
|
||||
writeJSON(out, instance, *cache, ASTDelegate, allModules.getArrayRef());
|
||||
|
||||
// Update the dependency tracker.
|
||||
if (auto depTracker = instance.getDependencyTracker()) {
|
||||
for (auto module : allModules) {
|
||||
auto deps = cache->findDependencies(module.first, module.second);
|
||||
if (!deps)
|
||||
continue;
|
||||
|
||||
if (auto swiftDeps = deps->getAsSwiftTextualModule()) {
|
||||
if (auto swiftInterfaceFile = swiftDeps->swiftInterfaceFile)
|
||||
depTracker->addDependency(*swiftInterfaceFile, /*IsSystem=*/false);
|
||||
for (const auto &sourceFile : swiftDeps->sourceFiles)
|
||||
depTracker->addDependency(sourceFile, /*IsSystem=*/false);
|
||||
for (const auto &bridgingSourceFile : swiftDeps->bridgingSourceFiles)
|
||||
depTracker->addDependency(bridgingSourceFile, /*IsSystem=*/false);
|
||||
} else if (auto clangDeps = deps->getAsClangModule()) {
|
||||
if (!clangDeps->moduleMapFile.empty())
|
||||
depTracker->addDependency(clangDeps->moduleMapFile, /*IsSystem=*/false);
|
||||
for (const auto &sourceFile : clangDeps->fileDependencies)
|
||||
depTracker->addDependency(sourceFile, /*IsSystem=*/false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This process succeeds regardless of whether any errors occurred.
|
||||
// FIXME: We shouldn't need this, but it's masking bugs in our scanning
|
||||
// logic where we don't create a fresh context when scanning Swift interfaces
|
||||
// that includes their own command-line flags.
|
||||
Context.Diags.resetHadAnyError();
|
||||
return false;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
//===--- ScanDependencies.h -- Scans the dependencies of a module ------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H
|
||||
#define SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
class CompilerInvocation;
|
||||
class CompilerInstance;
|
||||
|
||||
/// Batch scan the dependencies for modules specified in \c batchInputFile.
|
||||
bool batchScanModuleDependencies(CompilerInstance &instance,
|
||||
llvm::StringRef batchInputFile);
|
||||
|
||||
/// Scans the dependencies of the main module of \c instance.
|
||||
bool scanDependencies(CompilerInstance &instance);
|
||||
|
||||
/// Scans the dependencies of the underlying clang module of the main module
|
||||
/// of \c instance.
|
||||
bool scanClangDependencies(CompilerInstance &instance);
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: mkdir -p %t/clang-module-cache
|
||||
// RUN: %target-swift-frontend -scan-clang-dependencies -module-cache-path %t/clang-module-cache %s -o %t/deps.json -I %S/Inputs/CHeaders -I %S/Inputs/Swift -emit-dependencies -emit-dependencies-path %t/deps.d -import-objc-header %S/Inputs/CHeaders/Bridging.h -swift-version 4 -disable-implicit-swift-modules -module-name C
|
||||
|
||||
// Check the contents of the JSON output
|
||||
// RUN: %FileCheck %s < %t/deps.json
|
||||
|
||||
// CHECK: "mainModuleName": "C",
|
||||
// CHECK-NEXT: "modules": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "clang": "C"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "modulePath": "C.pcm",
|
||||
// CHECK-NEXT: "sourceFiles": [
|
||||
|
||||
|
||||
// CHECK: "directDependencies": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "clang": "B"
|
||||
// CHECK-NEXT: }
|
||||
@@ -28,6 +28,7 @@ add_swift_tool_subdirectory(swift-llvm-opt)
|
||||
add_swift_tool_subdirectory(swift-api-digester)
|
||||
add_swift_tool_subdirectory(swift-ast-script)
|
||||
add_swift_tool_subdirectory(swift-refactor)
|
||||
add_swift_tool_subdirectory(libSwiftScan)
|
||||
if(SWIFT_BUILD_SYNTAXPARSERLIB)
|
||||
add_swift_tool_subdirectory(libSwiftSyntaxParser)
|
||||
if(SWIFT_INCLUDE_TESTS)
|
||||
|
||||
28
tools/libSwiftScan/CMakeLists.txt
Normal file
28
tools/libSwiftScan/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
include(SwiftWindowsSupport)
|
||||
swift_swap_compiler_if_needed("libSwiftScan")
|
||||
|
||||
# Use an 'internal' name, this is primarily intended for SwiftDriver to import.
|
||||
set(SWIFT_SCAN_LIB_NAME "_InternalSwiftScan")
|
||||
|
||||
set(LLVM_EXPORTED_SYMBOL_FILE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/libSwiftScan.exports)
|
||||
|
||||
add_swift_host_library(libSwiftScan SHARED
|
||||
libSwiftScan.cpp
|
||||
c-include-check.c)
|
||||
|
||||
add_dependencies(libSwiftScan
|
||||
clang
|
||||
swiftDependencyScan)
|
||||
|
||||
target_link_libraries(libSwiftScan PRIVATE
|
||||
swiftDependencyScan)
|
||||
|
||||
set_target_properties(libSwiftScan
|
||||
PROPERTIES
|
||||
OUTPUT_NAME ${SWIFT_SCAN_LIB_NAME})
|
||||
|
||||
add_llvm_symbol_exports(libSwiftScan ${LLVM_EXPORTED_SYMBOL_FILE})
|
||||
|
||||
# Adds -dead_strip option
|
||||
add_link_opts(libSwiftScan)
|
||||
5
tools/libSwiftScan/c-include-check.c
Normal file
5
tools/libSwiftScan/c-include-check.c
Normal file
@@ -0,0 +1,5 @@
|
||||
// This file serves as a sanity check to ensure that the header is parseable
|
||||
// from C and that no C++ code has sneaked in.
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
typedef swiftscan_module_details_t _check_module_details_exists;
|
||||
463
tools/libSwiftScan/libSwiftScan.cpp
Normal file
463
tools/libSwiftScan/libSwiftScan.cpp
Normal file
@@ -0,0 +1,463 @@
|
||||
//===------------ DependencyScanImpl.cpp - Swift Compiler -----------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implementation of the dependency scanning C API
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Basic/LLVMInitialize.h"
|
||||
#include "swift/DependencyScan/DependencyScanImpl.h"
|
||||
#include "swift/DependencyScan/DependencyScanningTool.h"
|
||||
#include "swift/DependencyScan/StringUtils.h"
|
||||
|
||||
using namespace swift::dependencies;
|
||||
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DependencyScanningTool, swiftscan_scanner_t);
|
||||
|
||||
//=== Private Cleanup Functions -------------------------------------------===//
|
||||
|
||||
/// Free the given string.
|
||||
void swiftscan_string_dispose(swiftscan_string_ref_t string) {
|
||||
if (string.data)
|
||||
free(const_cast<void *>(string.data));
|
||||
}
|
||||
|
||||
/// Free the given string set.
|
||||
void swiftscan_string_set_dispose(swiftscan_string_set_t *set) {
|
||||
for (unsigned SI = 0, SE = set->count; SI < SE; ++SI)
|
||||
swiftscan_string_dispose(set->strings[SI]);
|
||||
delete[] set->strings;
|
||||
delete set;
|
||||
}
|
||||
|
||||
void swiftscan_dependency_info_details_dispose(
|
||||
swiftscan_module_details_t details) {
|
||||
swiftscan_module_details_s *details_impl = details;
|
||||
switch (details_impl->kind) {
|
||||
case SWIFTSCAN_DEPENDENCY_INFO_SWIFT_TEXTUAL:
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_textual_details.module_interface_path);
|
||||
swiftscan_string_set_dispose(
|
||||
details_impl->swift_textual_details.compiled_module_candidates);
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_textual_details.bridging_header_path);
|
||||
swiftscan_string_set_dispose(
|
||||
details_impl->swift_textual_details.bridging_source_files);
|
||||
swiftscan_string_set_dispose(
|
||||
details_impl->swift_textual_details.bridging_module_dependencies);
|
||||
swiftscan_string_set_dispose(
|
||||
details_impl->swift_textual_details.command_line);
|
||||
swiftscan_string_set_dispose(
|
||||
details_impl->swift_textual_details.extra_pcm_args);
|
||||
swiftscan_string_dispose(details_impl->swift_textual_details.context_hash);
|
||||
break;
|
||||
case SWIFTSCAN_DEPENDENCY_INFO_SWIFT_BINARY:
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_binary_details.compiled_module_path);
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_binary_details.module_doc_path);
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_binary_details.module_source_info_path);
|
||||
break;
|
||||
case SWIFTSCAN_DEPENDENCY_INFO_SWIFT_PLACEHOLDER:
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_placeholder_details.compiled_module_path);
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_placeholder_details.module_doc_path);
|
||||
swiftscan_string_dispose(
|
||||
details_impl->swift_placeholder_details.module_source_info_path);
|
||||
break;
|
||||
case SWIFTSCAN_DEPENDENCY_INFO_CLANG:
|
||||
swiftscan_string_dispose(details_impl->clang_details.module_map_path);
|
||||
swiftscan_string_dispose(details_impl->clang_details.context_hash);
|
||||
swiftscan_string_set_dispose(details_impl->clang_details.command_line);
|
||||
break;
|
||||
}
|
||||
delete details_impl;
|
||||
}
|
||||
|
||||
void swiftscan_dependency_info_dispose(swiftscan_dependency_info_t info) {
|
||||
swiftscan_string_dispose(info->module_name);
|
||||
swiftscan_string_dispose(info->module_path);
|
||||
swiftscan_string_set_dispose(info->source_files);
|
||||
swiftscan_string_set_dispose(info->direct_dependencies);
|
||||
swiftscan_dependency_info_details_dispose(info->details);
|
||||
delete info;
|
||||
}
|
||||
|
||||
void swiftscan_dependency_set_dispose(swiftscan_dependency_set_t *set) {
|
||||
for (size_t i = 0; i < set->count; ++i) {
|
||||
swiftscan_dependency_info_dispose(set->modules[i]);
|
||||
}
|
||||
delete[] set->modules;
|
||||
delete set;
|
||||
}
|
||||
|
||||
//=== Scanner Functions ---------------------------------------------------===//
|
||||
|
||||
swiftscan_scanner_t swiftscan_scanner_create(void) {
|
||||
INITIALIZE_LLVM();
|
||||
return wrap(new DependencyScanningTool());
|
||||
}
|
||||
|
||||
void swiftscan_scanner_dispose(swiftscan_scanner_t c_scanner) {
|
||||
delete unwrap(c_scanner);
|
||||
}
|
||||
|
||||
swiftscan_dependency_graph_t
|
||||
swiftscan_dependency_graph_create(swiftscan_scanner_t scanner,
|
||||
swiftscan_scan_invocation_t invocation) {
|
||||
DependencyScanningTool *ScanningTool = unwrap(scanner);
|
||||
int argc = invocation->argv->count;
|
||||
std::vector<const char *> Compilation;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
Compilation.push_back(get_C_string(invocation->argv->strings[i]));
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto ScanResult = ScanningTool->getDependencies(Compilation, {});
|
||||
if (ScanResult.getError())
|
||||
return nullptr;
|
||||
auto DependencyGraph = std::move(*ScanResult);
|
||||
return DependencyGraph;
|
||||
}
|
||||
|
||||
swiftscan_batch_scan_result_t *
|
||||
swiftscan_batch_scan_result_create(swiftscan_scanner_t scanner,
|
||||
swiftscan_batch_scan_input_t *batch_input,
|
||||
swiftscan_scan_invocation_t invocation) {
|
||||
DependencyScanningTool *ScanningTool = unwrap(scanner);
|
||||
int argc = invocation->argv->count;
|
||||
std::vector<const char *> Compilation;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
Compilation.push_back(get_C_string(invocation->argv->strings[i]));
|
||||
|
||||
std::vector<BatchScanInput> BatchInput;
|
||||
for (size_t i = 0; i < batch_input->count; ++i) {
|
||||
swiftscan_batch_scan_entry_s *Entry = batch_input->modules[i];
|
||||
BatchInput.push_back({get_C_string(Entry->module_name),
|
||||
get_C_string(Entry->arguments),
|
||||
/*outputPath*/ "", Entry->is_swift});
|
||||
}
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto BatchScanResult =
|
||||
ScanningTool->getDependencies(Compilation, BatchInput, {});
|
||||
swiftscan_batch_scan_result_t *Result = new swiftscan_batch_scan_result_t;
|
||||
auto ResultGraphs = new swiftscan_dependency_graph_t[BatchScanResult.size()];
|
||||
for (size_t i = 0; i < BatchScanResult.size(); ++i) {
|
||||
auto &ResultOrErr = BatchScanResult[i];
|
||||
if (ResultOrErr.getError()) {
|
||||
ResultGraphs[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
ResultGraphs[i] = ResultOrErr.get();
|
||||
}
|
||||
|
||||
Result->results = ResultGraphs;
|
||||
Result->count = BatchScanResult.size();
|
||||
return Result;
|
||||
}
|
||||
|
||||
swiftscan_import_set_t
|
||||
swiftscan_import_set_create(swiftscan_scanner_t scanner,
|
||||
swiftscan_scan_invocation_t invocation) {
|
||||
DependencyScanningTool *ScanningTool = unwrap(scanner);
|
||||
int argc = invocation->argv->count;
|
||||
std::vector<const char *> Compilation;
|
||||
for (int i = 0; i < argc; ++i)
|
||||
Compilation.push_back(get_C_string(invocation->argv->strings[i]));
|
||||
|
||||
// Execute the scan and bridge the result
|
||||
auto PreScanResult = ScanningTool->getImports(Compilation);
|
||||
if (PreScanResult.getError())
|
||||
return nullptr;
|
||||
auto ImportSet = std::move(*PreScanResult);
|
||||
return ImportSet;
|
||||
}
|
||||
|
||||
//=== Dependency Result Functions -----------------------------------------===//
|
||||
|
||||
swiftscan_string_ref_t swiftscan_dependency_graph_get_main_module_name(
|
||||
swiftscan_dependency_graph_t result) {
|
||||
return result->main_module_name;
|
||||
}
|
||||
|
||||
swiftscan_dependency_set_t *swiftscan_dependency_graph_get_dependencies(
|
||||
swiftscan_dependency_graph_t result) {
|
||||
return result->dependencies;
|
||||
}
|
||||
|
||||
//=== Module Dependency Info query APIs -----------------------------------===//
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_module_info_get_module_name(swiftscan_dependency_info_t info) {
|
||||
return info->module_name;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_module_info_get_module_path(swiftscan_dependency_info_t info) {
|
||||
return info->module_path;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_module_info_get_source_files(swiftscan_dependency_info_t info) {
|
||||
return info->source_files;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *swiftscan_module_info_get_direct_dependencies(
|
||||
swiftscan_dependency_info_t info) {
|
||||
return info->direct_dependencies;
|
||||
}
|
||||
|
||||
swiftscan_module_details_t
|
||||
swiftscan_module_info_get_details(swiftscan_dependency_info_t info) {
|
||||
return info->details;
|
||||
}
|
||||
|
||||
//=== Swift Textual Module Details query APIs -----------------------------===//
|
||||
|
||||
swiftscan_dependency_info_kind_t
|
||||
swiftscan_module_detail_get_kind(swiftscan_module_details_t details) {
|
||||
return details->kind;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_textual_detail_get_module_interface_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.module_interface_path;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_compiled_module_candidates(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.compiled_module_candidates;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_textual_detail_get_bridging_header_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.bridging_header_path;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_bridging_source_files(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.bridging_source_files;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_swift_textual_detail_get_bridging_module_dependencies(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.bridging_module_dependencies;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *swiftscan_swift_textual_detail_get_command_line(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.command_line;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *swiftscan_swift_textual_detail_get_extra_pcm_args(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.extra_pcm_args;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_textual_detail_get_context_hash(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.context_hash;
|
||||
}
|
||||
|
||||
bool swiftscan_swift_textual_detail_get_is_framework(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_textual_details.is_framework;
|
||||
}
|
||||
|
||||
//=== Swift Binary Module Details query APIs ------------------------------===//
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_binary_detail_get_compiled_module_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_binary_details.compiled_module_path;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_binary_detail_get_module_doc_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_binary_details.module_doc_path;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_swift_binary_detail_get_module_source_info_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_binary_details.module_source_info_path;
|
||||
}
|
||||
|
||||
//=== Swift Placeholder Module Details query APIs -------------------------===//
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_swift_placeholder_detail_get_compiled_module_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_placeholder_details.module_source_info_path;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_swift_placeholder_detail_get_module_doc_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_placeholder_details.module_source_info_path;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_swift_placeholder_detail_get_module_source_info_path(
|
||||
swiftscan_module_details_t details) {
|
||||
return details->swift_placeholder_details.module_source_info_path;
|
||||
}
|
||||
|
||||
//=== Clang Module Details query APIs -------------------------------------===//
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_clang_detail_get_module_map_path(swiftscan_module_details_t details) {
|
||||
return details->clang_details.module_map_path;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_clang_detail_get_context_hash(swiftscan_module_details_t details) {
|
||||
return details->clang_details.context_hash;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_clang_detail_get_command_line(swiftscan_module_details_t details) {
|
||||
return details->clang_details.command_line;
|
||||
}
|
||||
|
||||
//=== Batch Scan Input Functions ------------------------------------------===//
|
||||
|
||||
swiftscan_batch_scan_input_t *swiftscan_batch_scan_input_create() {
|
||||
return new swiftscan_batch_scan_input_t;
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_input_set_modules(
|
||||
swiftscan_batch_scan_input_t *input, int count,
|
||||
swiftscan_batch_scan_entry_t *modules) {
|
||||
input->count = count;
|
||||
input->modules = modules;
|
||||
}
|
||||
|
||||
//=== Batch Scan Entry Functions ------------------------------------------===//
|
||||
|
||||
swiftscan_batch_scan_entry_t swiftscan_batch_scan_entry_create() {
|
||||
return new swiftscan_batch_scan_entry_s;
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_entry_set_module_name(
|
||||
swiftscan_batch_scan_entry_t entry, const char *name) {
|
||||
entry->module_name = create_clone(name);
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_entry_set_arguments(
|
||||
swiftscan_batch_scan_entry_t entry, const char *arguments) {
|
||||
entry->arguments = create_clone(arguments);
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_entry_set_is_swift(swiftscan_batch_scan_entry_t entry,
|
||||
bool is_swift) {
|
||||
entry->is_swift = is_swift;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_batch_scan_entry_get_module_name(swiftscan_batch_scan_entry_t entry) {
|
||||
return entry->module_name;
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t
|
||||
swiftscan_batch_scan_entry_get_arguments(swiftscan_batch_scan_entry_t entry) {
|
||||
return entry->arguments;
|
||||
}
|
||||
|
||||
bool swiftscan_batch_scan_entry_get_is_swift(
|
||||
swiftscan_batch_scan_entry_t entry) {
|
||||
return entry->is_swift;
|
||||
}
|
||||
|
||||
//=== Prescan Result Functions --------------------------------------------===//
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_import_set_get_imports(swiftscan_import_set_t result) {
|
||||
return result->imports;
|
||||
}
|
||||
|
||||
//=== Scanner Invocation Functions ----------------------------------------===//
|
||||
|
||||
swiftscan_scan_invocation_t swiftscan_scan_invocation_create() {
|
||||
return new swiftscan_scan_invocation_s;
|
||||
}
|
||||
|
||||
void swiftscan_scan_invocation_set_working_directory(
|
||||
swiftscan_scan_invocation_t invocation, const char *working_directory) {
|
||||
invocation->working_directory = create_clone(working_directory);
|
||||
}
|
||||
|
||||
SWIFTSCAN_PUBLIC void
|
||||
swiftscan_scan_invocation_set_argv(swiftscan_scan_invocation_t invocation,
|
||||
int argc, const char **argv) {
|
||||
invocation->argv = create_set(argc, argv);
|
||||
}
|
||||
|
||||
swiftscan_string_ref_t swiftscan_scan_invocation_get_working_directory(
|
||||
swiftscan_scan_invocation_t invocation) {
|
||||
return invocation->working_directory;
|
||||
}
|
||||
|
||||
int swiftscan_scan_invocation_get_argc(swiftscan_scan_invocation_t invocation) {
|
||||
return invocation->argv->count;
|
||||
}
|
||||
|
||||
swiftscan_string_set_t *
|
||||
swiftscan_scan_invocation_get_argv(swiftscan_scan_invocation_t invocation) {
|
||||
return invocation->argv;
|
||||
}
|
||||
|
||||
//=== Public Cleanup Functions --------------------------------------------===//
|
||||
|
||||
void swiftscan_dependency_graph_dispose(swiftscan_dependency_graph_t result) {
|
||||
swiftscan_string_dispose(result->main_module_name);
|
||||
swiftscan_dependency_set_dispose(result->dependencies);
|
||||
delete result;
|
||||
}
|
||||
|
||||
void swiftscan_import_set_dispose(swiftscan_import_set_t result) {
|
||||
swiftscan_string_set_dispose(result->imports);
|
||||
delete result;
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_entry_dispose(swiftscan_batch_scan_entry_t entry) {
|
||||
swiftscan_string_dispose(entry->module_name);
|
||||
swiftscan_string_dispose(entry->arguments);
|
||||
delete entry;
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_input_dispose(swiftscan_batch_scan_input_t *input) {
|
||||
for (size_t i = 0; i < input->count; ++i) {
|
||||
swiftscan_batch_scan_entry_dispose(input->modules[i]);
|
||||
}
|
||||
delete[] input->modules;
|
||||
delete input;
|
||||
}
|
||||
|
||||
void swiftscan_batch_scan_result_dispose(
|
||||
swiftscan_batch_scan_result_t *result) {
|
||||
for (size_t i = 0; i < result->count; ++i) {
|
||||
swiftscan_dependency_graph_dispose(result->results[i]);
|
||||
}
|
||||
delete[] result->results;
|
||||
delete result;
|
||||
}
|
||||
|
||||
void swiftscan_scan_invocation_dispose(swiftscan_scan_invocation_t invocation) {
|
||||
swiftscan_string_dispose(invocation->working_directory);
|
||||
swiftscan_string_set_dispose(invocation->argv);
|
||||
delete invocation;
|
||||
}
|
||||
53
tools/libSwiftScan/libSwiftScan.exports
Normal file
53
tools/libSwiftScan/libSwiftScan.exports
Normal file
@@ -0,0 +1,53 @@
|
||||
swiftscan_dependency_graph_get_main_module_name
|
||||
swiftscan_dependency_graph_get_dependencies
|
||||
swiftscan_module_info_get_module_name
|
||||
swiftscan_module_info_get_module_path
|
||||
swiftscan_module_info_get_source_files
|
||||
swiftscan_module_info_get_direct_dependencies
|
||||
swiftscan_module_info_get_details
|
||||
swiftscan_module_detail_get_kind
|
||||
swiftscan_swift_textual_detail_get_module_interface_path
|
||||
swiftscan_swift_textual_detail_get_compiled_module_candidates
|
||||
swiftscan_swift_textual_detail_get_bridging_header_path
|
||||
swiftscan_swift_textual_detail_get_bridging_source_files
|
||||
swiftscan_swift_textual_detail_get_bridging_module_dependencies
|
||||
swiftscan_swift_textual_detail_get_command_line
|
||||
swiftscan_swift_textual_detail_get_extra_pcm_args
|
||||
swiftscan_swift_textual_detail_get_context_hash
|
||||
swiftscan_swift_textual_detail_get_is_framework
|
||||
swiftscan_swift_binary_detail_get_compiled_module_path
|
||||
swiftscan_swift_binary_detail_get_module_doc_path
|
||||
swiftscan_swift_binary_detail_get_module_source_info_path
|
||||
swiftscan_swift_placeholder_detail_get_compiled_module_path
|
||||
swiftscan_swift_placeholder_detail_get_module_doc_path
|
||||
swiftscan_swift_placeholder_detail_get_module_source_info_path
|
||||
swiftscan_clang_detail_get_module_map_path
|
||||
swiftscan_clang_detail_get_context_hash
|
||||
swiftscan_clang_detail_get_command_line
|
||||
swiftscan_batch_scan_input_set_modules
|
||||
swiftscan_batch_scan_entry_set_module_name
|
||||
swiftscan_batch_scan_entry_set_arguments
|
||||
swiftscan_batch_scan_entry_set_is_swift
|
||||
swiftscan_batch_scan_entry_get_module_name
|
||||
swiftscan_batch_scan_entry_get_arguments
|
||||
swiftscan_batch_scan_entry_get_is_swift
|
||||
swiftscan_import_set_get_imports
|
||||
swiftscan_scan_invocation_set_working_directory
|
||||
swiftscan_scan_invocation_set_argv
|
||||
swiftscan_scan_invocation_get_working_directory
|
||||
swiftscan_scan_invocation_get_argc
|
||||
swiftscan_scan_invocation_get_argv
|
||||
swiftscan_scan_invocation_create
|
||||
swiftscan_batch_scan_input_create
|
||||
swiftscan_batch_scan_entry_create
|
||||
swiftscan_dependency_graph_create
|
||||
swiftscan_batch_scan_result_create
|
||||
swiftscan_import_set_create
|
||||
swiftscan_scanner_create
|
||||
swiftscan_scan_invocation_dispose
|
||||
swiftscan_batch_scan_input_dispose
|
||||
swiftscan_batch_scan_entry_dispose
|
||||
swiftscan_dependency_graph_dispose
|
||||
swiftscan_batch_scan_result_dispose
|
||||
swiftscan_import_set_dispose
|
||||
swiftscan_scanner_dispose
|
||||
@@ -7,6 +7,7 @@ if(SWIFT_INCLUDE_TOOLS)
|
||||
add_subdirectory(AST)
|
||||
add_subdirectory(Basic)
|
||||
add_subdirectory(ClangImporter)
|
||||
add_subdirectory(DependencyScan)
|
||||
add_subdirectory(Driver)
|
||||
add_subdirectory(FrontendTool)
|
||||
add_subdirectory(Localization)
|
||||
|
||||
11
unittests/DependencyScan/CMakeLists.txt
Normal file
11
unittests/DependencyScan/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
add_swift_unittest(swiftScanTests
|
||||
ScanFixture.cpp
|
||||
ModuleDeps.cpp)
|
||||
|
||||
target_link_libraries(swiftScanTests
|
||||
PRIVATE
|
||||
swiftDependencyScan
|
||||
libSwiftScan)
|
||||
|
||||
target_compile_definitions(swiftScanTests PRIVATE
|
||||
SWIFTLIB_DIR=\"${SWIFTLIB_DIR}\")
|
||||
187
unittests/DependencyScan/ModuleDeps.cpp
Normal file
187
unittests/DependencyScan/ModuleDeps.cpp
Normal file
@@ -0,0 +1,187 @@
|
||||
//===---------------------- ModuleDeps.cpp --------------------------------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ScanFixture.h"
|
||||
#include "swift/Basic/Platform.h"
|
||||
#include "swift/Basic/Defer.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <string>
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::unittest;
|
||||
using namespace swift::dependencies;
|
||||
|
||||
static std::string createFilename(StringRef base, StringRef name) {
|
||||
SmallString<256> path = base;
|
||||
llvm::sys::path::append(path, name);
|
||||
return llvm::Twine(path).str();
|
||||
}
|
||||
|
||||
static bool emitFileWithContents(StringRef path, StringRef contents,
|
||||
std::string *pathOut = nullptr) {
|
||||
int FD;
|
||||
if (llvm::sys::fs::openFileForWrite(path, FD))
|
||||
return true;
|
||||
if (pathOut)
|
||||
*pathOut = path.str();
|
||||
llvm::raw_fd_ostream file(FD, /*shouldClose=*/true);
|
||||
file << contents;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool emitFileWithContents(StringRef base, StringRef name,
|
||||
StringRef contents,
|
||||
std::string *pathOut = nullptr) {
|
||||
return emitFileWithContents(createFilename(base, name), contents, pathOut);
|
||||
}
|
||||
|
||||
TEST_F(ScanTest, TestModuleDeps) {
|
||||
SmallString<256> tempDir;
|
||||
ASSERT_FALSE(llvm::sys::fs::createUniqueDirectory("ScanTest.TestModuleDeps", tempDir));
|
||||
SWIFT_DEFER { llvm::sys::fs::remove_directories(tempDir); };
|
||||
|
||||
// Create test input file
|
||||
std::string TestPathStr = createFilename(tempDir, "foo.swift");
|
||||
ASSERT_FALSE(emitFileWithContents(tempDir, "foo.swift", "import A\n"));
|
||||
llvm::dbgs() << "Input File: " << TestPathStr << "\n";
|
||||
|
||||
// Create includes
|
||||
std::string IncludeDirPath = createFilename(tempDir, "include");
|
||||
ASSERT_FALSE(llvm::sys::fs::create_directory(IncludeDirPath));
|
||||
std::string CHeadersDirPath = createFilename(IncludeDirPath, "CHeaders");
|
||||
ASSERT_FALSE(llvm::sys::fs::create_directory(CHeadersDirPath));
|
||||
std::string SwiftDirPath = createFilename(IncludeDirPath, "Swift");
|
||||
ASSERT_FALSE(llvm::sys::fs::create_directory(SwiftDirPath));
|
||||
|
||||
// Create imported module Swift interface files
|
||||
ASSERT_FALSE(emitFileWithContents(SwiftDirPath, "A.swiftinterface",
|
||||
"// swift-interface-format-version: 1.0\n\
|
||||
// swift-module-flags: -module-name A\n\
|
||||
import Swift\n\
|
||||
@_exported import A\n\
|
||||
public func overlayFuncA() { }\n"));
|
||||
ASSERT_FALSE(emitFileWithContents(SwiftDirPath, "E.swiftinterface",
|
||||
"// swift-interface-format-version: 1.0\n\
|
||||
// swift-module-flags: -module-name E\n\
|
||||
import Swift\n\
|
||||
public func funcE()\n"));
|
||||
ASSERT_FALSE(emitFileWithContents(SwiftDirPath, "F.swiftinterface",
|
||||
"// swift-interface-format-version: 1.0\n\
|
||||
// swift-module-flags: -module-name\n\
|
||||
import Swift\n\
|
||||
@_exported import F\n\
|
||||
public func funcF() { }"));
|
||||
ASSERT_FALSE(emitFileWithContents(SwiftDirPath, "G.swiftinterface",
|
||||
"// swift-interface-format-version: 1.0\n\
|
||||
// swift-module-flags: -module-name G -swift-version 5 -target x86_64-apple-macosx10.9\n\
|
||||
#if swift(>=5.0)\n\
|
||||
@_exported import G\n\
|
||||
import Swift\n\
|
||||
public func overlayFuncG() { }\n\
|
||||
let stringG : String = \"Build\"\n\
|
||||
#endif"));
|
||||
|
||||
// Create imported module C modulemap/headers
|
||||
ASSERT_FALSE(
|
||||
emitFileWithContents(CHeadersDirPath, "A.h", "void funcA(void);"));
|
||||
ASSERT_FALSE(emitFileWithContents(CHeadersDirPath, "B.h", "#include \"A.h\"\
|
||||
void funcB(void);"));
|
||||
ASSERT_FALSE(emitFileWithContents(CHeadersDirPath, "C.h", "#include \"B.h\"\n\
|
||||
void funcC(void);\
|
||||
const char* stringC() { return \"Module\"; }"));
|
||||
ASSERT_FALSE(
|
||||
emitFileWithContents(CHeadersDirPath, "D.h", "void funcD(void);"));
|
||||
ASSERT_FALSE(
|
||||
emitFileWithContents(CHeadersDirPath, "F.h", "void funcF(void);"));
|
||||
ASSERT_FALSE(emitFileWithContents(
|
||||
CHeadersDirPath, "G.h",
|
||||
"#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 110000\n\
|
||||
#include \"X.h\"\n\
|
||||
#endif\n\
|
||||
void funcG(void);"));
|
||||
ASSERT_FALSE(
|
||||
emitFileWithContents(CHeadersDirPath, "X.h", "void funcX(void);"));
|
||||
ASSERT_FALSE(emitFileWithContents(CHeadersDirPath, "Bridging.h",
|
||||
"#include \"BridgingOther.h\"\n\
|
||||
int bridging_other(void);"));
|
||||
ASSERT_FALSE(emitFileWithContents(CHeadersDirPath, "BridgingOther.h",
|
||||
"#include \"F.h\"\n\
|
||||
int bridging_other(void);"));
|
||||
|
||||
ASSERT_FALSE(
|
||||
emitFileWithContents(CHeadersDirPath, "module.modulemap", "module A {\n\
|
||||
header \"A.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module B {\n\
|
||||
header \"B.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module C {\n\
|
||||
header \"C.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module D {\n\
|
||||
header \"D.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module F {\n\
|
||||
header \"F.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module G {\n\
|
||||
header \"G.h\"\n\
|
||||
export *\n\
|
||||
}\n\
|
||||
module X {\n\
|
||||
header \"X.h\"\n\
|
||||
export *\n\
|
||||
}"));
|
||||
|
||||
// Paths to shims and stdlib
|
||||
llvm::SmallString<128> ShimsLibDir = StdLibDir;
|
||||
llvm::sys::path::append(ShimsLibDir, "shims");
|
||||
auto Target = llvm::Triple(llvm::sys::getDefaultTargetTriple());
|
||||
llvm::sys::path::append(StdLibDir, getPlatformNameForTriple(Target));
|
||||
|
||||
std::vector<std::string> CommandStrArr = {
|
||||
std::string("'") + TestPathStr + std::string("'"),
|
||||
std::string("-I ") + std::string("'") + SwiftDirPath + std::string("'"),
|
||||
std::string("-I ") + std::string("'") + CHeadersDirPath + std::string("'"),
|
||||
std::string("-I ") + std::string("'") + StdLibDir.str().str() + std::string("'"),
|
||||
std::string("-I ") + std::string("'") + ShimsLibDir.str().str() + std::string("'")
|
||||
};
|
||||
|
||||
// On Windows we need to add an extra escape for path separator characters because otherwise
|
||||
// the command line tokenizer will treat them as escape characters.
|
||||
for (size_t i = 0; i < CommandStrArr.size(); ++i) {
|
||||
std::replace(CommandStrArr[i].begin(), CommandStrArr[i].end(), '\\', '/');
|
||||
}
|
||||
|
||||
std::vector<const char*> Command;
|
||||
llvm::dbgs() << "Compiler Command: \n";
|
||||
for (auto &command : CommandStrArr) {
|
||||
Command.push_back(command.c_str());
|
||||
llvm::dbgs() << command.c_str() << "\n";
|
||||
}
|
||||
auto DependenciesOrErr = ScannerTool.getDependencies(Command, {});
|
||||
ASSERT_FALSE(DependenciesOrErr.getError());
|
||||
auto Dependencies = DependenciesOrErr.get();
|
||||
// TODO: Output/verify dependency graph correctness
|
||||
// llvm::dbgs() << "Deps: " << Dependencies << "\n";
|
||||
|
||||
swiftscan_dependency_graph_dispose(Dependencies);
|
||||
}
|
||||
31
unittests/DependencyScan/ScanFixture.cpp
Normal file
31
unittests/DependencyScan/ScanFixture.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//===-------- ScanFixture.cpp - Dependency scanning tests -*- C++ -------*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ScanFixture.h"
|
||||
#include "swift/Basic/LLVMInitialize.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace swift;
|
||||
using namespace swift::unittest;
|
||||
using namespace swift::dependencies;
|
||||
|
||||
ScanTest::ScanTest() : ScannerTool(), StdLibDir(SWIFTLIB_DIR) {
|
||||
INITIALIZE_LLVM();
|
||||
// Create a temporary filesystem workspace for this test.
|
||||
llvm::sys::fs::createUniqueDirectory("ScanTest.Workspace",
|
||||
TemporaryTestWorkspace);
|
||||
}
|
||||
|
||||
ScanTest::~ScanTest() {
|
||||
llvm::sys::fs::remove_directories(TemporaryTestWorkspace);
|
||||
}
|
||||
40
unittests/DependencyScan/ScanFixture.h
Normal file
40
unittests/DependencyScan/ScanFixture.h
Normal file
@@ -0,0 +1,40 @@
|
||||
//===-------- ScanFixture.h - Dependency scanning tests -*- C++ ---------*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift-c/DependencyScan/DependencyScan.h"
|
||||
#include "swift/DependencyScan/DependencyScanningTool.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include <string>
|
||||
|
||||
using namespace swift::dependencies;
|
||||
|
||||
namespace swift {
|
||||
namespace unittest {
|
||||
|
||||
class ScanTest : public ::testing::Test {
|
||||
public:
|
||||
ScanTest();
|
||||
~ScanTest();
|
||||
|
||||
protected:
|
||||
// The tool used to execute tests' scanning queries
|
||||
DependencyScanningTool ScannerTool;
|
||||
|
||||
// Test workspace directory
|
||||
llvm::SmallString<256> TemporaryTestWorkspace;
|
||||
|
||||
// Path to where the Swift standard library can be found
|
||||
llvm::SmallString<128> StdLibDir;
|
||||
};
|
||||
|
||||
} // end namespace unittest
|
||||
} // end namespace swift
|
||||
Reference in New Issue
Block a user