@@ -232,6 +232,15 @@ class BuildSystemFrontendExecutionQueueDelegate
232
232
};
233
233
234
234
struct BuildSystemFrontendDelegateImpl {
235
+
236
+ // / The status of delegate.
237
+ enum class Status {
238
+ Uninitialized = 0 ,
239
+ Initialized,
240
+ InitializationFailure,
241
+ Cancelled,
242
+ };
243
+
235
244
llvm::SourceMgr& sourceMgr;
236
245
const BuildSystemInvocation& invocation;
237
246
@@ -248,6 +257,28 @@ struct BuildSystemFrontendDelegateImpl {
248
257
const BuildSystemInvocation& invocation)
249
258
: sourceMgr(sourceMgr), invocation(invocation),
250
259
executionQueueDelegate (*this ) {}
260
+
261
+ private:
262
+ // / The status of the delegate.
263
+ std::atomic<Status> status{Status::Uninitialized};
264
+
265
+ public:
266
+
267
+ // / Set the status of delegate to the given value.
268
+ // /
269
+ // / It is not possible to update the status once status is set to initialization failure.
270
+ void setStatus (Status newStatus) {
271
+ // Disallow changing status if there was an initialization failure.
272
+ if (status == Status::InitializationFailure) {
273
+ return ;
274
+ }
275
+ status = newStatus;
276
+ }
277
+
278
+ // / Returns the current status.
279
+ Status getStatus () {
280
+ return status;
281
+ }
251
282
};
252
283
253
284
bool BuildSystemFrontendExecutionQueueDelegate::showVerboseOutput () const {
@@ -378,6 +409,11 @@ BuildSystemFrontendDelegate::createExecutionQueue() {
378
409
379
410
void BuildSystemFrontendDelegate::cancel () {
380
411
auto delegateImpl = static_cast <BuildSystemFrontendDelegateImpl*>(impl);
412
+ assert (delegateImpl->getStatus () != BuildSystemFrontendDelegateImpl::Status::Uninitialized);
413
+
414
+ // Update the status to cancelled.
415
+ delegateImpl->setStatus (BuildSystemFrontendDelegateImpl::Status::Cancelled);
416
+
381
417
auto system = delegateImpl->system ;
382
418
if (system) {
383
419
system->cancel ();
@@ -388,6 +424,12 @@ void BuildSystemFrontendDelegate::resetForBuild() {
388
424
auto impl = static_cast <BuildSystemFrontendDelegateImpl*>(this ->impl );
389
425
390
426
impl->numFailedCommands = 0 ;
427
+ impl->numErrors = 0 ;
428
+
429
+ // Update status back to initialized on reset.
430
+ if (impl->getStatus () == BuildSystemFrontendDelegateImpl::Status::Cancelled) {
431
+ impl->setStatus (BuildSystemFrontendDelegateImpl::Status::Initialized);
432
+ }
391
433
}
392
434
393
435
void BuildSystemFrontendDelegate::hadCommandFailure () {
@@ -540,9 +582,28 @@ bool BuildSystemFrontend::initialize() {
540
582
}
541
583
542
584
bool BuildSystemFrontend::build (StringRef targetToBuild) {
585
+
586
+ auto delegateImpl =
587
+ static_cast <BuildSystemFrontendDelegateImpl*>(delegate.impl );
588
+
589
+ // We expect build to be called in these states only.
590
+ assert (delegateImpl->getStatus () == BuildSystemFrontendDelegateImpl::Status::Uninitialized
591
+ || delegateImpl->getStatus () == BuildSystemFrontendDelegateImpl::Status::Initialized);
592
+
593
+ // Set the delegate status to initialized.
594
+ delegateImpl->setStatus (BuildSystemFrontendDelegateImpl::Status::Initialized);
595
+
543
596
// Initialize the build system, if necessary
544
597
if (!buildSystem.hasValue ()) {
545
- if (!initialize ())
598
+ if (!initialize ()) {
599
+ // Set status to initialization failure. It is not possible to recover from this state.
600
+ delegateImpl->setStatus (BuildSystemFrontendDelegateImpl::Status::InitializationFailure);
601
+ return false ;
602
+ }
603
+ }
604
+
605
+ // If delegate was told to cancel while we were initializing, abort now.
606
+ if (delegateImpl->getStatus () == BuildSystemFrontendDelegateImpl::Status::Cancelled) {
546
607
return false ;
547
608
}
548
609
0 commit comments