Merge pull request #81 from hughbe/used-llvm
Use LLVM_ATTRIBUTE_USED instead of compiler specific code
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3f009fd..66e3088 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,7 @@
find_package(Lit REQUIRED)
find_package(FileCheck REQUIRED)
+find_package(PythonInterp)
# Check if we should build the Swift bindings.
if (";${LLBUILD_SUPPORT_BINDINGS};" MATCHES ";Swift;")
diff --git a/include/llbuild/Core/BuildEngine.h b/include/llbuild/Core/BuildEngine.h
index 959ea5a..b42ce59 100644
--- a/include/llbuild/Core/BuildEngine.h
+++ b/include/llbuild/Core/BuildEngine.h
@@ -20,6 +20,8 @@
#include <utility>
#include <vector>
+#include "llvm/ADT/Twine.h"
+
namespace llbuild {
namespace core {
@@ -204,6 +206,11 @@
/// the cycle (i.e., the node participating in the cycle will appear twice).
virtual void cycleDetected(const std::vector<Rule*>& items) = 0;
+ /// Called when a fatal error is encountered by the build engine.
+ ///
+ /// \param message The diagnostic message.
+ virtual void error(const llvm::Twine& message) = 0;
+
};
/// A build engine supports fast, incremental, persistent, and parallel
diff --git a/lib/BuildSystem/BuildSystem.cpp b/lib/BuildSystem/BuildSystem.cpp
index 8c3feb3..ea7aeaa 100644
--- a/lib/BuildSystem/BuildSystem.cpp
+++ b/lib/BuildSystem/BuildSystem.cpp
@@ -117,6 +117,7 @@
virtual Rule lookupRule(const KeyType& keyData) override;
virtual void cycleDetected(const std::vector<Rule*>& items) override;
+ virtual void error(const Twine& message) override;
public:
BuildSystemEngineDelegate(BuildSystemImpl& system) : system(system) {}
@@ -826,6 +827,10 @@
system.error(system.getMainFilename(), os.str());
}
+void BuildSystemEngineDelegate::error(const Twine& message) {
+ system.error(system.getMainFilename(), message);
+}
+
#pragma mark - BuildSystemImpl implementation
std::unique_ptr<BuildNode>
diff --git a/lib/Commands/BuildEngineCommand.cpp b/lib/Commands/BuildEngineCommand.cpp
index 602bf83..8f50c2b 100644
--- a/lib/Commands/BuildEngineCommand.cpp
+++ b/lib/Commands/BuildEngineCommand.cpp
@@ -214,6 +214,11 @@
virtual void cycleDetected(const std::vector<core::Rule*>& items) override {
assert(0 && "unexpected cycle!");
}
+
+ /// Called when a fatal error is encountered by the build engine.
+ virtual void error(const Twine &message) override {
+ assert(0 && ("error:" + message.str()).c_str());
+ }
};
AckermannDelegate delegate;
core::BuildEngine engine(delegate);
diff --git a/lib/Commands/NinjaBuildCommand.cpp b/lib/Commands/NinjaBuildCommand.cpp
index 3eb0b78..efef371 100644
--- a/lib/Commands/NinjaBuildCommand.cpp
+++ b/lib/Commands/NinjaBuildCommand.cpp
@@ -400,6 +400,8 @@
virtual core::Rule lookupRule(const core::KeyType& key) override;
virtual void cycleDetected(const std::vector<core::Rule*>& items) override;
+
+ virtual void error(const Twine& message) override;
};
/// Wrapper for information used during a single build.
@@ -1682,6 +1684,14 @@
context->isCancelled = true;
}
+void NinjaBuildEngineDelegate::error(const Twine& message) {
+ // Report the error.
+ context->emitError("error: " + message.str());
+
+ // Cancel the build.
+ context->isCancelled = true;
+}
+
}
int commands::executeNinjaBuildCommand(std::vector<std::string> args) {
diff --git a/lib/Core/BuildEngine.cpp b/lib/Core/BuildEngine.cpp
index d4b5c1d..1d93b08 100644
--- a/lib/Core/BuildEngine.cpp
+++ b/lib/Core/BuildEngine.cpp
@@ -816,9 +816,9 @@
std::string error;
bool result = db->setRuleResult(ruleInfo->rule, ruleInfo->result, &error);
if (!result) {
- // FIXME: Error handling.
- std::cerr << error << std::endl;
- exit(1);
+ delegate.error(error);
+ completeRemainingTasks();
+ return false;
}
}
@@ -1013,10 +1013,13 @@
assert(!cycleList.empty());
delegate.cycleDetected(cycleList);
+ completeRemainingTasks();
+ }
- // Complete all of the remaining tasks.
- //
- // FIXME: Should we have a task abort callback?
+ // Complete all of the remaining tasks.
+ //
+ // FIXME: Should we have a task abort callback?
+ void completeRemainingTasks() {
for (auto& it: taskInfos) {
// Complete the task, even though it did not update the value.
//
@@ -1091,9 +1094,8 @@
std::string error;
db->lookupRuleResult(ruleInfo.rule, &ruleInfo.result, &error);
if (!error.empty()) {
- // FIXME: Error handling.
- std::cerr << error << std::endl;
- exit(1);
+ delegate.error(error);
+ completeRemainingTasks();
}
}
@@ -1132,9 +1134,9 @@
std::string error;
bool result = db->setCurrentIteration(currentTimestamp, &error);
if (!result) {
- // FIXME: Error handling.
- std::cerr << error << std::endl;
- exit(1);
+ delegate.error(error);
+ static ValueType emptyValue{};
+ return emptyValue;
}
db->buildComplete();
}
@@ -1189,10 +1191,8 @@
void dumpGraphToFile(const std::string& path) {
FILE* fp = ::fopen(path.c_str(), "w");
if (!fp) {
- // FIXME: Error handling.
- std::cerr << "error: unable to open graph output path \""
- << path << "\"\n";
- exit(1);
+ delegate.error("error: unable to open graph output path \"" + path + "\"");
+ return;
}
// Write the graph header.
@@ -1260,9 +1260,9 @@
void taskNeedsInput(Task* task, const KeyType& key, uintptr_t inputID) {
// Validate the InputID.
if (inputID > BuildEngine::kMaximumInputID) {
- // FIXME: Error handling.
- std::cerr << "error: attempt to use reserved input ID\n";
- exit(1);
+ delegate.error("error: attempt to use reserved input ID");
+ completeRemainingTasks();
+ return;
}
addTaskInputRequest(task, key, inputID);
@@ -1278,9 +1278,9 @@
assert(taskInfo && "cannot request inputs for an unknown task");
if (!taskInfo->forRuleInfo->isInProgressComputing()) {
- // FIXME: Error handling.
- std::cerr << "error: invalid state for adding discovered dependency\n";
- exit(1);
+ delegate.error("error: invalid state for adding discovered dependency");
+ completeRemainingTasks();
+ return;
}
taskInfo->discoveredDependencies.push_back(key);
@@ -1294,9 +1294,9 @@
assert(taskInfo && "cannot request inputs for an unknown task");
if (!taskInfo->forRuleInfo->isInProgressComputing()) {
- // FIXME: Error handling.
- std::cerr << "error: invalid state for marking task complete\n";
- exit(1);
+ delegate.error("error: invalid state for marking task complete");
+ completeRemainingTasks();
+ return;
}
RuleInfo* ruleInfo = taskInfo->forRuleInfo;
diff --git a/perftests/Xcode/PerfTests/CorePerfTests.mm b/perftests/Xcode/PerfTests/CorePerfTests.mm
index f51cfd6..78216bf 100644
--- a/perftests/Xcode/PerfTests/CorePerfTests.mm
+++ b/perftests/Xcode/PerfTests/CorePerfTests.mm
@@ -141,6 +141,11 @@
fprintf(stderr, "error: unexpected cycle\n");
abort();
}
+
+ virtual void error(const Twine& message) override {
+ fprintf(stderr, "error: %s\n", message.str().c_str());
+ abort();
+ }
} Delegate;
__block core::BuildEngine Engine(Delegate);
int LastInputValue = 0;
@@ -216,6 +221,11 @@
fprintf(stderr, "error: unexpected cycle\n");
abort();
}
+
+ virtual void error(const Twine& message) override {
+ fprintf(stderr, "error: %s\n", message.str().c_str());
+ abort();
+ }
} Delegate;
__block core::BuildEngine Engine(Delegate);
int LastInputValue = 0;
@@ -295,6 +305,11 @@
fprintf(stderr, "error: unexpected cycle\n");
abort();
}
+
+ virtual void error(const Twine& message) override {
+ fprintf(stderr, "error: %s\n", message.str().c_str());
+ abort();
+ }
} Delegate;
__block core::BuildEngine Engine(Delegate);
int LastInputValue = 0;
diff --git a/products/libllbuild/Core-C-API.cpp b/products/libllbuild/Core-C-API.cpp
index 4a5a4da..3c8f904 100644
--- a/products/libllbuild/Core-C-API.cpp
+++ b/products/libllbuild/Core-C-API.cpp
@@ -86,6 +86,10 @@
assert(0 && "unexpected cycle!");
}
+ virtual void error(const Twine& message) override {
+ cAPIDelegate.error(cAPIDelegate.context, message.str().c_str());
+ }
+
public:
CAPIBuildEngineDelegate(llb_buildengine_delegate_t delegate)
: cAPIDelegate(delegate)
diff --git a/products/libllbuild/public-api/llbuild/core.h b/products/libllbuild/public-api/llbuild/core.h
index f2eb3cf..82f5899 100644
--- a/products/libllbuild/public-api/llbuild/core.h
+++ b/products/libllbuild/public-api/llbuild/core.h
@@ -104,6 +104,12 @@
void (*lookup_rule)(void* context,
const llb_data_t* key,
llb_rule_t* rule_out);
+
+ /// Callback for fatal errors the build engine encounters.
+ ///
+ /// Xparam context The user context pointer.
+ /// Xparam message Error message.
+ void (*error)(void* context, const char* message);
} llb_buildengine_delegate_t;
/// Create a new build engine object.
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index b847e66..3441e2d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -28,6 +28,7 @@
endif()
set(lit_command
+ ${PYTHON_EXECUTABLE}
${LIT_EXECUTABLE}
${LIT_ARGS}
--param build_mode=${build_mode})
diff --git a/unittests/Core/BuildEngineTest.cpp b/unittests/Core/BuildEngineTest.cpp
index fb70e54..a10f771 100644
--- a/unittests/Core/BuildEngineTest.cpp
+++ b/unittests/Core/BuildEngineTest.cpp
@@ -45,6 +45,11 @@
std::transform(items.begin(), items.end(), std::back_inserter(cycle),
[](auto rule) { return std::string(rule->key); });
}
+
+ virtual void error(const Twine& message) override {
+ fprintf(stderr, "error: %s\n", message.str().c_str());
+ abort();
+ }
};
static int32_t intFromValue(const core::ValueType& value) {
diff --git a/unittests/Core/DependencyInfoParserTest.cpp b/unittests/Core/DependencyInfoParserTest.cpp
index b44f370..a629be1 100644
--- a/unittests/Core/DependencyInfoParserTest.cpp
+++ b/unittests/Core/DependencyInfoParserTest.cpp
@@ -50,8 +50,9 @@
}
};
-#define INPUT(str) ({ \
- assert(sizeof(str) != 0); StringRef(str, sizeof(str) - 1); })
+#define INPUT(str) \
+ StringRef(str, sizeof(str) - 1); \
+ assert(sizeof(str) != 0);
// Check missing terminator diagnose (on empty file).
{
diff --git a/unittests/Core/DepsBuildEngineTest.cpp b/unittests/Core/DepsBuildEngineTest.cpp
index 77b40a1..2d10445 100644
--- a/unittests/Core/DepsBuildEngineTest.cpp
+++ b/unittests/Core/DepsBuildEngineTest.cpp
@@ -43,6 +43,11 @@
fprintf(stderr, "error: cycle\n");
abort();
}
+
+ virtual void error(const Twine& message) override {
+ fprintf(stderr, "error: %s\n", message.str().c_str());
+ abort();
+ }
};
static int32_t intFromValue(const core::ValueType& value) {