Skip to content

Commit 437dac1

Browse files
authored
Merge pull request #926 from swiftlang/jan_svoboda/better-isResultValid-API
Provide more powerful `isResultValid` API
2 parents 5f2a3a1 + a066c26 commit 437dac1

File tree

7 files changed

+77
-1
lines changed

7 files changed

+77
-1
lines changed

examples/c-api/buildsystem/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ fancy_tool_create_command(void *context, const llb_data_t* name) {
100100
delegate.execute_command_detached = NULL;
101101
delegate.cancel_detached_command = NULL;
102102
delegate.is_result_valid = NULL;
103+
delegate.is_result_valid_with_fallback = NULL;
103104
return llb_buildsystem_external_command_create(name, delegate);
104105
}
105106

products/libllbuild/BuildSystem-C-API.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,34 @@ class CAPIExternalCommand : public ExternalCommand {
11461146
}
11471147

11481148
bool isResultValid(BuildSystem& system, const BuildValue& value) override {
1149+
if (cAPIDelegate.is_result_valid_with_fallback) {
1150+
struct FallbackContext {
1151+
BuildSystem *buildSystem;
1152+
1153+
static bool handle(void* c_ctx,
1154+
llb_buildsystem_command_t* c_command,
1155+
llb_build_value* c_value) {
1156+
auto* command = (CAPIExternalCommand*)c_command;
1157+
auto* value = (CAPIBuildValue*)c_value;
1158+
1159+
auto* ctx = static_cast<FallbackContext*>(c_ctx);
1160+
BuildSystem& system = *ctx->buildSystem;
1161+
delete ctx;
1162+
1163+
return command->ExternalCommand::isResultValid(system, value->getInternalBuildValue());
1164+
}
1165+
};
1166+
1167+
auto value_p = (llb_build_value *)new CAPIBuildValue(BuildValue(value));
1168+
return cAPIDelegate.is_result_valid_with_fallback(
1169+
cAPIDelegate.context,
1170+
(llb_buildsystem_command_t*)this,
1171+
value_p,
1172+
new FallbackContext{&system},
1173+
FallbackContext::handle
1174+
);
1175+
}
1176+
11491177
if (cAPIDelegate.is_result_valid) {
11501178
auto value_p = (llb_build_value *)new CAPIBuildValue(BuildValue(value));
11511179
return cAPIDelegate.is_result_valid(

products/libllbuild/include/llbuild/buildsystem.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,12 @@ typedef struct llb_buildsystem_external_command_delegate_t_ {
776776
llb_buildsystem_command_t* command,
777777
const llb_build_value* value);
778778

779+
bool (*is_result_valid_with_fallback)(void* context,
780+
llb_buildsystem_command_t* command,
781+
const llb_build_value* value,
782+
void* fallback_ctx,
783+
bool (*fallback)(void* fallback_ctx, llb_buildsystem_command_t*, llb_build_value*));
784+
779785
/// Callback a client may use to tear down data structures associated with the context
780786
/// pointer.
781787
void (*destroy_context)(void* context);

products/libllbuild/include/llbuild/llbuild-defines.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@
8484
/// compile for multiple versions of the API.
8585
///
8686
/// Version History:
87+
/// 19: Added isResultValid API with a fallback to CAPIExternalCommand.
88+
///
8789
/// 18: Added support for configuring outputs of dynamic tasks via the C API.
8890
///
8991
/// 17: Added `llb_buildsystem_dependency_data_format_makefile_ignoring_subsequent_outputs`
@@ -121,6 +123,6 @@
121123
/// 1: Added `environment` parameter to llb_buildsystem_invocation_t.
122124
///
123125
/// 0: Pre-history
124-
#define LLBUILD_C_API_VERSION 18
126+
#define LLBUILD_C_API_VERSION 19
125127

126128
#endif

products/llbuildSwift/BuildSystemBindings.swift

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ private final class ToolWrapper {
220220
_delegate.is_result_valid = {
221221
return BuildSystem.toCommandWrapper($0!).isResultValid($1!, $2!)
222222
}
223+
_delegate.is_result_valid_with_fallback = {
224+
return BuildSystem.toCommandWrapper($0!).isResultValid($1!, $2!, $3!, $4!)
225+
}
223226
} else {
224227
_delegate.execute_command_ex = nil
225228
_delegate.is_result_valid = nil
@@ -362,6 +365,20 @@ public protocol ProducesCustomBuildValue: AnyObject {
362365
/// - command: A handle to the executing command.
363366
/// - buildValue: The most recently computed build value.
364367
func isResultValid(_ command: Command, _ buildValue: BuildValue) -> Bool
368+
369+
/// Called to check if the current result for this command remains valid.
370+
///
371+
/// - command: A handle to the executing command.
372+
/// - buildValue: The most recently computed build value.
373+
/// - fallback: The default implementation: llbuild::buildsystem::ExternalCommand::isResultValid().
374+
func isResultValid(_ command: Command, _ buildValue: BuildValue, _ fallback: @escaping (Command, BuildValue) -> Bool) -> Bool
375+
}
376+
377+
public extension ProducesCustomBuildValue {
378+
func isResultValid(_ command: Command, _ buildValue: BuildValue, _ fallback: @escaping (Command, BuildValue) -> Bool) -> Bool {
379+
// This should default to the fallback, but instead we defer to ProducesCustomBuildValue.isResultValid(_:_:) for backward compatibility.
380+
return isResultValid(command, buildValue)
381+
}
365382
}
366383

367384
// Extension to provide a default implementation of execute(_ Command, _ commandInterface) and
@@ -545,6 +562,23 @@ private final class CommandWrapper {
545562

546563
return (command as! ProducesCustomBuildValue).isResultValid(_command, buildValue)
547564
}
565+
566+
func isResultValid(
567+
_: OpaquePointer,
568+
_ value: OpaquePointer,
569+
_ fallbackCtx: UnsafeMutableRawPointer?,
570+
_ fallback: @escaping (UnsafeMutableRawPointer?, OpaquePointer?, OpaquePointer?) -> Bool
571+
) -> Bool {
572+
guard let buildValue = BuildValue.construct(from: value) else {
573+
fatalError("Could not decode incoming build value.")
574+
}
575+
576+
func fallbackWrapper(_ command: Command, value: BuildValue) -> Bool {
577+
return fallback(fallbackCtx, command.handle, BuildValue.clone(value))
578+
}
579+
580+
return (command as! ProducesCustomBuildValue).isResultValid(_command, buildValue, fallbackWrapper)
581+
}
548582
}
549583

550584
/// Encapsulates a diagnostic as reported by the build system.

products/llbuildSwift/BuildValue.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ public class BuildValue: CustomStringConvertible, Equatable, Hashable {
173173

174174
return llb_build_value_clone(value.internalBuildValue)
175175
}
176+
177+
static func clone(_ value: BuildValue) -> OpaquePointer {
178+
return llb_build_value_clone(value.internalBuildValue)
179+
}
176180

177181
/// The kind of the build value.
178182
/// The kind also defines the subclass, so kind == .invalid means the instance should be of type Invalid

unittests/CAPI/BuildSystem-C-API.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ depinfo_tester_tool_create_command(void *context, const llb_data_t* name) {
151151
delegate.execute_command_detached = NULL;
152152
delegate.cancel_detached_command = NULL;
153153
delegate.is_result_valid = NULL;
154+
delegate.is_result_valid_with_fallback = NULL;
154155
return llb_buildsystem_external_command_create(name, delegate);
155156
}
156157

0 commit comments

Comments
 (0)