Skip to content

Commit 40a1b32

Browse files
committed
Add libSwiftScan entry-point to query target info.
This provides the library with functionality to answer `-print-target-info` queries in place of calls to `swift-frontend`.
1 parent 9c5e5ef commit 40a1b32

File tree

11 files changed

+303
-137
lines changed

11 files changed

+303
-137
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,17 @@ swiftscan_batch_scan_result_dispose(swiftscan_batch_scan_result_t *result);
300300
SWIFTSCAN_PUBLIC void
301301
swiftscan_scan_invocation_dispose(swiftscan_scan_invocation_t invocation);
302302

303-
//=== Feature-Query Functions -----------------------------------------===//
303+
//=== Feature-Query Functions ---------------------------------------------===//
304304
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
305305
swiftscan_compiler_supported_arguments_query();
306306

307307
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
308308
swiftscan_compiler_supported_features_query();
309309

310+
//=== Target-Info Functions -----------------------------------------------===//
311+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
312+
swiftscan_compiler_target_info_query(swiftscan_scan_invocation_t invocation);
313+
310314
//=== Scanner Functions ---------------------------------------------------===//
311315

312316
/// Container of the configuration state and shared cache for dependency

include/swift/Basic/TargetInfo.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--- TargetInfo.h - Target Info Output ---------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides a high-level API for emitting target info
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_TARGETINFO_H
18+
#define SWIFT_TARGETINFO_H
19+
20+
#include "swift/Basic/LLVM.h"
21+
22+
namespace llvm {
23+
class Triple;
24+
class VersionTuple;
25+
}
26+
27+
namespace swift {
28+
class CompilerInvocation;
29+
30+
namespace targetinfo {
31+
void printTargetInfo(const CompilerInvocation &invocation,
32+
llvm::raw_ostream &out);
33+
34+
void printTripleInfo(const llvm::Triple &triple,
35+
llvm::Optional<llvm::VersionTuple> runtimeVersion,
36+
llvm::raw_ostream &out);
37+
} // namespace targetinfo
38+
} // namespace swift
39+
40+
#endif

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
namespace swift {
2525
namespace dependencies {
2626

27+
/// Given a set of arguments to a print-target-info frontend tool query, produce the
28+
/// JSON target info.
29+
llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Command);
30+
2731
/// The high-level implementation of the dependency scanner that runs on
2832
/// an individual worker thread.
2933
class DependencyScanningTool {

lib/Basic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ add_swift_host_library(swiftBasic STATIC
6868
StableHasher.cpp
6969
Statistic.cpp
7070
StringExtras.cpp
71+
TargetInfo.cpp
7172
TaskQueue.cpp
7273
ThreadSafeRefCounted.cpp
7374
Unicode.cpp

lib/Basic/TargetInfo.cpp

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//===--- TargetInfo.cpp - Target information printing --------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "swift/Basic/TargetInfo.h"
14+
#include "swift/Basic/Version.h"
15+
#include "swift/Basic/Platform.h"
16+
#include "swift/Frontend/Frontend.h"
17+
18+
#include "llvm/Support/raw_ostream.h"
19+
20+
using namespace swift;
21+
22+
/// Print information about a
23+
static void printCompatibilityLibrary(
24+
llvm::VersionTuple runtimeVersion, llvm::VersionTuple maxVersion,
25+
StringRef filter, StringRef libraryName, bool &printedAny,
26+
llvm::raw_ostream &out) {
27+
if (runtimeVersion > maxVersion)
28+
return;
29+
30+
if (printedAny) {
31+
out << ",";
32+
}
33+
34+
out << "\n";
35+
out << " {\n";
36+
37+
out << " \"libraryName\": \"";
38+
out.write_escaped(libraryName);
39+
out << "\",\n";
40+
41+
out << " \"filter\": \"";
42+
out.write_escaped(filter);
43+
out << "\"\n";
44+
out << " }";
45+
46+
printedAny = true;
47+
}
48+
49+
/// Print information about the selected target in JSON.
50+
void targetinfo::printTargetInfo(const CompilerInvocation &invocation,
51+
llvm::raw_ostream &out) {
52+
out << "{\n";
53+
54+
// Compiler version, as produced by --version.
55+
out << " \"compilerVersion\": \"";
56+
out.write_escaped(version::getSwiftFullVersion(
57+
version::Version::getCurrentLanguageVersion()));
58+
out << "\",\n";
59+
60+
// Target triple and target variant triple.
61+
auto runtimeVersion =
62+
invocation.getIRGenOptions().AutolinkRuntimeCompatibilityLibraryVersion;
63+
auto &langOpts = invocation.getLangOptions();
64+
out << " \"target\": ";
65+
printTripleInfo(langOpts.Target, runtimeVersion, out);
66+
out << ",\n";
67+
68+
if (auto &variant = langOpts.TargetVariant) {
69+
out << " \"targetVariant\": ";
70+
printTripleInfo(*variant, runtimeVersion, out);
71+
out << ",\n";
72+
}
73+
74+
// Various paths.
75+
auto &searchOpts = invocation.getSearchPathOptions();
76+
out << " \"paths\": {\n";
77+
78+
if (!searchOpts.SDKPath.empty()) {
79+
out << " \"sdkPath\": \"";
80+
out.write_escaped(searchOpts.SDKPath);
81+
out << "\",\n";
82+
}
83+
84+
auto outputPaths = [&](StringRef name, const std::vector<std::string> &paths){
85+
out << " \"" << name << "\": [\n";
86+
llvm::interleave(paths, [&out](const std::string &path) {
87+
out << " \"";
88+
out.write_escaped(path);
89+
out << "\"";
90+
}, [&out] {
91+
out << ",\n";
92+
});
93+
out << "\n ],\n";
94+
};
95+
96+
outputPaths("runtimeLibraryPaths", searchOpts.RuntimeLibraryPaths);
97+
outputPaths("runtimeLibraryImportPaths",
98+
searchOpts.RuntimeLibraryImportPaths);
99+
100+
out << " \"runtimeResourcePath\": \"";
101+
out.write_escaped(searchOpts.RuntimeResourcePath);
102+
out << "\"\n";
103+
104+
out << " }\n";
105+
106+
out << "}\n";
107+
}
108+
109+
// Print information about the target triple in JSON.
110+
void targetinfo::printTripleInfo(const llvm::Triple &triple,
111+
llvm::Optional<llvm::VersionTuple> runtimeVersion,
112+
llvm::raw_ostream &out) {
113+
out << "{\n";
114+
115+
out << " \"triple\": \"";
116+
out.write_escaped(triple.getTriple());
117+
out << "\",\n";
118+
119+
out << " \"unversionedTriple\": \"";
120+
out.write_escaped(getUnversionedTriple(triple).getTriple());
121+
out << "\",\n";
122+
123+
out << " \"moduleTriple\": \"";
124+
out.write_escaped(getTargetSpecificModuleTriple(triple).getTriple());
125+
out << "\",\n";
126+
127+
if (runtimeVersion) {
128+
out << " \"swiftRuntimeCompatibilityVersion\": \"";
129+
out.write_escaped(runtimeVersion->getAsString());
130+
out << "\",\n";
131+
132+
// Compatibility libraries that need to be linked.
133+
out << " \"compatibilityLibraries\": [";
134+
bool printedAnyCompatibilityLibrary = false;
135+
#define BACK_DEPLOYMENT_LIB(Version, Filter, LibraryName) \
136+
printCompatibilityLibrary( \
137+
*runtimeVersion, llvm::VersionTuple Version, #Filter, LibraryName, \
138+
printedAnyCompatibilityLibrary, out);
139+
#include "swift/Frontend/BackDeploymentLibs.def"
140+
141+
if (printedAnyCompatibilityLibrary) {
142+
out << "\n ";
143+
}
144+
out << " ],\n";
145+
} else {
146+
out << " \"compatibilityLibraries\": [ ],\n";
147+
}
148+
149+
out << " \"librariesRequireRPath\": "
150+
<< (tripleRequiresRPathForSwiftLibrariesInOS(triple) ? "true" : "false")
151+
<< "\n";
152+
153+
out << " }";
154+
}

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
#include "swift/DependencyScan/DependencyScanningTool.h"
1414
#include "swift/DependencyScan/SerializedModuleDependencyCacheFormat.h"
15+
#include "swift/DependencyScan/StringUtils.h"
1516
#include "swift/AST/DiagnosticEngine.h"
1617
#include "swift/AST/DiagnosticsFrontend.h"
1718
#include "swift/Basic/LLVMInitialize.h"
19+
#include "swift/Basic/TargetInfo.h"
1820
#include "swift/DependencyScan/DependencyScanImpl.h"
1921
#include "llvm/Support/CommandLine.h"
2022
#include "llvm/Support/FileSystem.h"
@@ -24,6 +26,36 @@
2426
namespace swift {
2527
namespace dependencies {
2628

29+
llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Command) {
30+
// We must reset option occurences because we are handling an unrelated
31+
// command-line to those possibly parsed parsed before using the same tool.
32+
// We must do so because LLVM options parsing is done using a managed
33+
// static `GlobalParser`.
34+
llvm::cl::ResetAllOptionOccurrences();
35+
// Parse arguments.
36+
std::string CommandString;
37+
for (const auto *c : Command) {
38+
CommandString.append(c);
39+
CommandString.append(" ");
40+
}
41+
SmallVector<const char *, 4> Args;
42+
llvm::BumpPtrAllocator Alloc;
43+
llvm::StringSaver Saver(Alloc);
44+
llvm::cl::TokenizeGNUCommandLine(CommandString, Saver, Args);
45+
SourceManager dummySM;
46+
DiagnosticEngine DE(dummySM);
47+
CompilerInvocation Invocation;
48+
if (Invocation.parseArgs(Args, DE)) {
49+
return std::make_error_code(std::errc::invalid_argument);
50+
}
51+
52+
// Store the result to a string.
53+
std::string ResultStr;
54+
llvm::raw_string_ostream StrOS(ResultStr);
55+
swift::targetinfo::printTargetInfo(Invocation, StrOS);
56+
return create_clone(ResultStr.c_str());
57+
}
58+
2759
DependencyScanningTool::DependencyScanningTool()
2860
: SharedCache(std::make_unique<GlobalModuleDependenciesCache>()),
2961
VersionedPCMInstanceCacheCache(

0 commit comments

Comments
 (0)