Skip to content

Add libSwiftScan entry-point to query target info. #40160

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 1 commit into from
Nov 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion include/swift-c/DependencyScan/DependencyScan.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,13 +300,17 @@ swiftscan_batch_scan_result_dispose(swiftscan_batch_scan_result_t *result);
SWIFTSCAN_PUBLIC void
swiftscan_scan_invocation_dispose(swiftscan_scan_invocation_t invocation);

//=== Feature-Query Functions -----------------------------------------===//
//=== Feature-Query Functions ---------------------------------------------===//
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
swiftscan_compiler_supported_arguments_query();

SWIFTSCAN_PUBLIC swiftscan_string_set_t *
swiftscan_compiler_supported_features_query();

//=== Target-Info Functions -----------------------------------------------===//
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
swiftscan_compiler_target_info_query(swiftscan_scan_invocation_t invocation);

//=== Scanner Functions ---------------------------------------------------===//

/// Container of the configuration state and shared cache for dependency
Expand Down
40 changes: 40 additions & 0 deletions include/swift/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===--- TargetInfo.h - Target Info Output ---------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file provides a high-level API for emitting target info
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_TARGETINFO_H
#define SWIFT_TARGETINFO_H

#include "swift/Basic/LLVM.h"

namespace llvm {
class Triple;
class VersionTuple;
}

namespace swift {
class CompilerInvocation;

namespace targetinfo {
void printTargetInfo(const CompilerInvocation &invocation,
llvm::raw_ostream &out);

void printTripleInfo(const llvm::Triple &triple,
llvm::Optional<llvm::VersionTuple> runtimeVersion,
llvm::raw_ostream &out);
} // namespace targetinfo
} // namespace swift

#endif
4 changes: 4 additions & 0 deletions include/swift/DependencyScan/DependencyScanningTool.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
namespace swift {
namespace dependencies {

/// Given a set of arguments to a print-target-info frontend tool query, produce the
/// JSON target info.
llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Command);

/// The high-level implementation of the dependency scanner that runs on
/// an individual worker thread.
class DependencyScanningTool {
Expand Down
1 change: 1 addition & 0 deletions lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ add_swift_host_library(swiftBasic STATIC
StableHasher.cpp
Statistic.cpp
StringExtras.cpp
TargetInfo.cpp
TaskQueue.cpp
ThreadSafeRefCounted.cpp
Unicode.cpp
Expand Down
154 changes: 154 additions & 0 deletions lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
//===--- TargetInfo.cpp - Target information printing --------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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/Basic/TargetInfo.h"
#include "swift/Basic/Version.h"
#include "swift/Basic/Platform.h"
#include "swift/Frontend/Frontend.h"

#include "llvm/Support/raw_ostream.h"

using namespace swift;

/// Print information about a
static void printCompatibilityLibrary(
llvm::VersionTuple runtimeVersion, llvm::VersionTuple maxVersion,
StringRef filter, StringRef libraryName, bool &printedAny,
llvm::raw_ostream &out) {
if (runtimeVersion > maxVersion)
return;

if (printedAny) {
out << ",";
}

out << "\n";
out << " {\n";

out << " \"libraryName\": \"";
out.write_escaped(libraryName);
out << "\",\n";

out << " \"filter\": \"";
out.write_escaped(filter);
out << "\"\n";
out << " }";

printedAny = true;
}

/// Print information about the selected target in JSON.
void targetinfo::printTargetInfo(const CompilerInvocation &invocation,
llvm::raw_ostream &out) {
out << "{\n";

// Compiler version, as produced by --version.
out << " \"compilerVersion\": \"";
out.write_escaped(version::getSwiftFullVersion(
version::Version::getCurrentLanguageVersion()));
out << "\",\n";

// Target triple and target variant triple.
auto runtimeVersion =
invocation.getIRGenOptions().AutolinkRuntimeCompatibilityLibraryVersion;
auto &langOpts = invocation.getLangOptions();
out << " \"target\": ";
printTripleInfo(langOpts.Target, runtimeVersion, out);
out << ",\n";

if (auto &variant = langOpts.TargetVariant) {
out << " \"targetVariant\": ";
printTripleInfo(*variant, runtimeVersion, out);
out << ",\n";
}

// Various paths.
auto &searchOpts = invocation.getSearchPathOptions();
out << " \"paths\": {\n";

if (!searchOpts.SDKPath.empty()) {
out << " \"sdkPath\": \"";
out.write_escaped(searchOpts.SDKPath);
out << "\",\n";
}

auto outputPaths = [&](StringRef name, const std::vector<std::string> &paths){
out << " \"" << name << "\": [\n";
llvm::interleave(paths, [&out](const std::string &path) {
out << " \"";
out.write_escaped(path);
out << "\"";
}, [&out] {
out << ",\n";
});
out << "\n ],\n";
};

outputPaths("runtimeLibraryPaths", searchOpts.RuntimeLibraryPaths);
outputPaths("runtimeLibraryImportPaths",
searchOpts.RuntimeLibraryImportPaths);

out << " \"runtimeResourcePath\": \"";
out.write_escaped(searchOpts.RuntimeResourcePath);
out << "\"\n";

out << " }\n";

out << "}\n";
}

// Print information about the target triple in JSON.
void targetinfo::printTripleInfo(const llvm::Triple &triple,
llvm::Optional<llvm::VersionTuple> runtimeVersion,
llvm::raw_ostream &out) {
out << "{\n";

out << " \"triple\": \"";
out.write_escaped(triple.getTriple());
out << "\",\n";

out << " \"unversionedTriple\": \"";
out.write_escaped(getUnversionedTriple(triple).getTriple());
out << "\",\n";

out << " \"moduleTriple\": \"";
out.write_escaped(getTargetSpecificModuleTriple(triple).getTriple());
out << "\",\n";

if (runtimeVersion) {
out << " \"swiftRuntimeCompatibilityVersion\": \"";
out.write_escaped(runtimeVersion->getAsString());
out << "\",\n";

// Compatibility libraries that need to be linked.
out << " \"compatibilityLibraries\": [";
bool printedAnyCompatibilityLibrary = false;
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName) \
printCompatibilityLibrary( \
*runtimeVersion, llvm::VersionTuple Version, #Filter, LibraryName, \
printedAnyCompatibilityLibrary, out);
#include "swift/Frontend/BackDeploymentLibs.def"

if (printedAnyCompatibilityLibrary) {
out << "\n ";
}
out << " ],\n";
} else {
out << " \"compatibilityLibraries\": [ ],\n";
}

out << " \"librariesRequireRPath\": "
<< (tripleRequiresRPathForSwiftLibrariesInOS(triple) ? "true" : "false")
<< "\n";

out << " }";
}
32 changes: 32 additions & 0 deletions lib/DependencyScan/DependencyScanningTool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@

#include "swift/DependencyScan/DependencyScanningTool.h"
#include "swift/DependencyScan/SerializedModuleDependencyCacheFormat.h"
#include "swift/DependencyScan/StringUtils.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsFrontend.h"
#include "swift/Basic/LLVMInitialize.h"
#include "swift/Basic/TargetInfo.h"
#include "swift/DependencyScan/DependencyScanImpl.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
Expand All @@ -24,6 +26,36 @@
namespace swift {
namespace dependencies {

llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Command) {
// We must reset option occurences because we are handling an unrelated
// command-line to those possibly parsed parsed before using the same tool.
// We must do so because LLVM options parsing is done using a managed
// static `GlobalParser`.
llvm::cl::ResetAllOptionOccurrences();
// Parse arguments.
std::string CommandString;
for (const auto *c : Command) {
CommandString.append(c);
CommandString.append(" ");
}
SmallVector<const char *, 4> Args;
llvm::BumpPtrAllocator Alloc;
llvm::StringSaver Saver(Alloc);
llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args);
SourceManager dummySM;
DiagnosticEngine DE(dummySM);
CompilerInvocation Invocation;
if (Invocation.parseArgs(Args, DE)) {
return std::make_error_code(std::errc::invalid_argument);
}

// Store the result to a string.
std::string ResultStr;
llvm::raw_string_ostream StrOS(ResultStr);
swift::targetinfo::printTargetInfo(Invocation, StrOS);
return create_clone(ResultStr.c_str());
}

DependencyScanningTool::DependencyScanningTool()
: SharedCache(std::make_unique<GlobalModuleDependenciesCache>()),
VersionedPCMInstanceCacheCache(
Expand Down
Loading