Skip to content

Dependency Scanning Library #34786

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Jan 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
f3d217e
[Dependency Scanning] Add a C++ itnerface for a tool that answers dep…
artemcm Nov 16, 2020
6cbb141
[Dependency Scanning] Add a unittest harness to invoke the dependency…
artemcm Nov 16, 2020
7d1d8a4
[Dependency Scanning] Factor ModuleDependenciesCache out of a Compile…
artemcm Nov 17, 2020
07e07a1
[Dependency Scanning] Add DependencyScanningTool entry-point for batc…
artemcm Nov 17, 2020
79d559e
[Dependency Scanning] Deprecate and remove `-scan-clang-dependencies`
artemcm Nov 17, 2020
aabcb22
Rename `SwiftScan` directory into `DependencyScan`
artemcm Nov 17, 2020
dad1435
[Dependency Scanning] Factor out import prescan into separate utility
artemcm Nov 18, 2020
082fc48
[Dependency Scanning] Refactor dependency scanner to return an in-mem…
artemcm Nov 20, 2020
75a8cfa
[Dependency Scanning] Add a C API layer for dependency scanning tool,…
artemcm Dec 2, 2020
75b8a0e
[Dependency Scanning] Add entry-point to DependencyScanningTool and t…
artemcm Dec 2, 2020
2ad9600
[Dependency Scanning] Use an opaque type for dependency module detail…
artemcm Dec 2, 2020
d0220e5
[Dependency Scanning] Add entry-point to DependencyScanningTool and t…
artemcm Dec 4, 2020
fcf9433
[Dependency Scanning] Change C API prefix to: `swiftscan` from `ds` a…
artemcm Dec 7, 2020
5cacff4
[Dependency Scanning] Make a module's dependency info an opaque struc…
artemcm Dec 7, 2020
409de73
[Dependency Scanning] Make the overall dependency scan result (inter-…
artemcm Dec 7, 2020
c6705ad
[Dependency Scanning] Make the batch scan entry container an opaque type
artemcm Dec 7, 2020
cff741b
[Dependency Scanning] Make the prescan dependency scan result (import…
artemcm Dec 7, 2020
108e9da
[Dependency Scanning] Make scanner invocation context (argc, argv, wo…
artemcm Dec 7, 2020
ca16944
[Dependency Scanning] Export opaque types as pointers to C structs in…
artemcm Dec 7, 2020
d017fd4
[Dependency Scanning] Add setters for the scanner invocation context …
artemcm Dec 7, 2020
53e53db
[Dependency Scanning] Factor the shared library libSwiftScan into `to…
artemcm Dec 8, 2020
f91c8a8
[Dependency Scanning] Refactor string implementation to always malloc…
artemcm Dec 8, 2020
5f49c9f
[Dependency Scanning] Fix modulemap module name for the _InternalSwif…
artemcm Dec 9, 2020
d1cc689
[Dependency Scanning] Fix the DependencyScan unit test harness to ref…
artemcm Dec 9, 2020
41a09a4
[Dependency Scanning] Establish object ownership convention by using …
artemcm Dec 9, 2020
d621e22
[Dependency Scanning] Use DEFINE_SIMPLE_CONVERSION_FUNCTIONS macro in…
artemcm Dec 9, 2020
295e4f4
[Dependency Scanning] Bugfix: check for null C string before checking…
artemcm Dec 14, 2020
58e5402
[Dependency Scanning] Use `size_t` for array sizes and re-arrange arr…
artemcm Dec 15, 2020
39483f0
[Dependency Scanning] Cache compiler instance/module depenency cache …
artemcm Dec 16, 2020
fd03158
[Dependency Scanning] Remove the C string getter in favour of client-…
artemcm Dec 17, 2020
41f65d7
Do not use Designated Initializers as they are not yet supported by a…
artemcm Dec 18, 2020
2121d32
[Dependency Scanning] Skip over source-code (not interface) modules w…
artemcm Jan 7, 2021
94b727f
[Dependency Scanning] Update cached batch scan compiler instances wit…
artemcm Jan 7, 2021
cc400bf
[Dependency Scanning] Ensure INITIALIZE_LLVM() is invoked on scanner …
artemcm Jan 7, 2021
4eae21c
Change file generation in the DependencyScan.ModuleDeps unittest to h…
artemcm Jan 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
332 changes: 332 additions & 0 deletions include/swift-c/DependencyScan/DependencyScan.h
Original file line number Diff line number Diff line change
@@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"llvm/Support/CBindingWrapping.h" provides some utilities that might help things here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

#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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These accessors that return swiftscan_string_t or swiftscan_string_set_t * are not clear about ownership. I see you have swiftscan_string_dispose and swiftscan_string_set_dispose methods, but the implementation looks like they are returned unowned. If not every API is consistent about whether the caller needs to dispose of the result, I recommend putting it in the doc comment for the accessors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved by tying the lifetime of the string to the object it is associated with. swiftscan_string_dispose and swiftscan_string_set_dispose are no longer part of the public API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, I propose we adopt Foundation-style ownership signals here

@CodaFi, thank you taking a look at this PR and proposing this convention.
The API now consistently follows this naming scheme, providing a create and dispose functions for all objects that the library's clients may take ownership of.


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 changes: 31 additions & 0 deletions include/swift-c/DependencyScan/DependencyScanMacros.h
Original file line number Diff line number Diff line change
@@ -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 changes: 4 additions & 0 deletions include/swift-c/DependencyScan/module.modulemap
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module _InternalSwiftScan {
header "DependencyScan.h"
link "_InternalSwiftScan"
}
Loading