Merge "trace_processor: Parse process and trace packets"
diff --git a/include/perfetto/base/BUILD.gn b/include/perfetto/base/BUILD.gn
index 41f075d..908baf4 100644
--- a/include/perfetto/base/BUILD.gn
+++ b/include/perfetto/base/BUILD.gn
@@ -24,6 +24,7 @@
"string_splitter.h",
"string_utils.h",
"task_runner.h",
+ "temp_file.h",
"thread_checker.h",
"time.h",
"unix_task_runner.h",
diff --git a/src/base/watchdog_posix.cc b/src/base/watchdog_posix.cc
index 9864e7b..5f8755f 100644
--- a/src/base/watchdog_posix.cc
+++ b/src/base/watchdog_posix.cc
@@ -247,7 +247,7 @@
}
}
-Watchdog::Timer::Timer(Timer&& other) {
+Watchdog::Timer::Timer(Timer&& other) noexcept {
timerid_ = other.timerid_;
other.timerid_ = nullptr;
}
diff --git a/src/trace_processor/sched_slice_table.cc b/src/trace_processor/sched_slice_table.cc
index 3a5af21..6d90d0b 100644
--- a/src/trace_processor/sched_slice_table.cc
+++ b/src/trace_processor/sched_slice_table.cc
@@ -17,6 +17,9 @@
#include "src/trace_processor/sched_slice_table.h"
#include <string.h>
+#include <algorithm>
+#include <bitset>
+#include <numeric>
#include "perfetto/base/logging.h"
@@ -51,6 +54,109 @@
inline SchedSliceTable::Cursor* AsCursor(sqlite3_vtab_cursor* cursor) {
return reinterpret_cast<SchedSliceTable::Cursor*>(cursor);
}
+
+template <size_t N = TraceStorage::kMaxCpus>
+bool PopulateFilterBitmap(int op,
+ sqlite3_value* value,
+ std::bitset<N>* filter) {
+ bool constraint_implemented = true;
+ int64_t int_value = sqlite3_value_int64(value);
+ if (IsOpGe(op) || IsOpGt(op)) {
+ // If the operator is gt, then add one to the upper bound.
+ int_value = IsOpGt(op) ? int_value + 1 : int_value;
+
+ // Set to false all values less than |int_value|.
+ size_t ub = static_cast<size_t>(std::max(0l, int_value));
+ ub = std::min(ub, filter->size());
+ for (size_t i = 0; i < ub; i++) {
+ filter->set(i, false);
+ }
+ } else if (IsOpLe(op) || IsOpLt(op)) {
+ // If the operator is lt, then minus one to the lower bound.
+ int_value = IsOpLt(op) ? int_value - 1 : int_value;
+
+ // Set to false all values greater than |int_value|.
+ size_t lb = static_cast<size_t>(std::max(0l, int_value));
+ lb = std::min(lb, filter->size());
+ for (size_t i = lb; i < filter->size(); i++) {
+ filter->set(i, false);
+ }
+ } else if (IsOpEq(op)) {
+ if (int_value >= 0 && static_cast<size_t>(int_value) < filter->size()) {
+ // If the value is in bounds, set all bits to false and restore the value
+ // of the bit at the specified index.
+ bool existing = filter->test(static_cast<size_t>(int_value));
+ filter->reset();
+ filter->set(static_cast<size_t>(int_value), existing);
+ } else {
+ // If the index is out of bounds, nothing should match.
+ filter->reset();
+ }
+ } else {
+ constraint_implemented = false;
+ }
+ return constraint_implemented;
+}
+
+template <class T>
+inline int Compare(T first, T second, bool desc) {
+ if (first < second) {
+ return desc ? 1 : -1;
+ } else if (first > second) {
+ return desc ? -1 : 1;
+ }
+ return 0;
+}
+
+// Compares the slice at index |f| in |f_slices| for CPU |f_cpu| with the
+// slice at index |s| in |s_slices| for CPU |s_cpu| on |column| in either
+// ascending or descending mode depending on |desc|
+// Returns -1 if the first slice is before the second in the ordering, 1 if
+// the first slice is after the second and 0 if they are equal.
+inline int CompareValuesForColumn(uint32_t f_cpu,
+ const TraceStorage::SlicesPerCpu& f_slices,
+ size_t f,
+ uint32_t s_cpu,
+ const TraceStorage::SlicesPerCpu& s_slices,
+ size_t s,
+ SchedSliceTable::Column column,
+ bool desc) {
+ switch (column) {
+ case SchedSliceTable::Column::kTimestamp:
+ return Compare(f_slices.start_ns()[f], s_slices.start_ns()[s], desc);
+ case SchedSliceTable::Column::kDuration:
+ return Compare(f_slices.durations()[f], s_slices.durations()[s], desc);
+ case SchedSliceTable::Column::kCpu:
+ return Compare(f_cpu, s_cpu, desc);
+ }
+}
+
+// Creates a vector of indices into the given |slices| sorted by the ordering
+// criteria given by |order_by|.
+std::vector<uint32_t> CreateSortedIndexVector(
+ uint32_t cpu,
+ const TraceStorage::SlicesPerCpu& slices,
+ const std::vector<SchedSliceTable::OrderBy>& order_by) {
+ PERFETTO_CHECK(slices.slice_count() <= std::numeric_limits<uint32_t>::max());
+
+ std::vector<uint32_t> indices;
+ indices.resize(slices.slice_count());
+ std::iota(indices.begin(), indices.end(), 0u);
+ auto callback = [cpu, &order_by, &slices](uint32_t f, uint32_t s) {
+ for (const auto& ob : order_by) {
+ int value = CompareValuesForColumn(cpu, slices, f, cpu, slices, s,
+ ob.column, ob.desc);
+ if (value < 0)
+ return true;
+ else if (value > 0)
+ return false;
+ }
+ return false;
+ };
+ std::sort(indices.begin(), indices.end(), callback);
+ return indices;
+}
+
} // namespace
SchedSliceTable::SchedSliceTable(const TraceStorage* storage)
@@ -113,29 +219,29 @@
// Called at least once but possibly many times before filtering things and is
// the best time to keep track of constriants.
int SchedSliceTable::BestIndex(sqlite3_index_info* idx) {
- bool external_ordering_required = false;
- for (int i = 0; i < idx->nOrderBy; i++) {
- if (idx->aOrderBy[i].iColumn != Column::kTimestamp ||
- idx->aOrderBy[i].desc) {
- // TODO(lalitm): support ordering by other fields.
- external_ordering_required = true;
- break;
- }
- }
- idx->orderByConsumed = !external_ordering_required;
-
indexes_.emplace_back();
- idx->idxNum = static_cast<int>(indexes_.size() - 1);
- std::vector<Constraint>* constraints = &indexes_.back();
+ IndexInfo* index = &indexes_.back();
+ for (int i = 0; i < idx->nOrderBy; i++) {
+ index->order_by.emplace_back();
+
+ OrderBy* order = &index->order_by.back();
+ order->column = static_cast<Column>(idx->aOrderBy[i].iColumn);
+ order->desc = idx->aOrderBy[i].desc;
+ }
+ idx->orderByConsumed = true;
+
for (int i = 0; i < idx->nConstraint; i++) {
const auto& cs = idx->aConstraint[i];
if (!cs.usable)
continue;
- constraints->emplace_back(cs);
+ index->constraints.emplace_back(cs);
// argvIndex is 1-based so use the current size of the vector.
- idx->aConstraintUsage[i].argvIndex = static_cast<int>(constraints->size());
+ int argv_index = static_cast<int>(index->constraints.size());
+ idx->aConstraintUsage[i].argvIndex = argv_index;
}
+ idx->idxNum = static_cast<int>(indexes_.size() - 1);
+
return SQLITE_OK;
}
@@ -154,34 +260,31 @@
// Reset the filter state.
filter_state_ = {};
- const auto& constraints = table_->indexes_[static_cast<size_t>(idxNum)];
- PERFETTO_CHECK(constraints.size() == static_cast<size_t>(argc));
- for (size_t i = 0; i < constraints.size(); i++) {
- const auto& cs = constraints[i];
+ std::bitset<TraceStorage::kMaxCpus> cpu_filter;
+ const auto& index = table_->indexes_[static_cast<size_t>(idxNum)];
+ PERFETTO_CHECK(index.constraints.size() == static_cast<size_t>(argc));
+ for (size_t i = 0; i < index.constraints.size(); i++) {
+ const auto& cs = index.constraints[i];
switch (cs.iColumn) {
- case Column::kTimestamp:
- filter_state_.timestamp_constraints.Initialize(cs, argv[i]);
- break;
case Column::kCpu:
- filter_state_.cpu_constraints.Initialize(cs, argv[i]);
+ PopulateFilterBitmap(cs.op, argv[i], &cpu_filter);
break;
}
}
+ // Update the filter state with the order by info.
+ *filter_state_.order_by() = std::move(index.order_by);
+
// First setup CPU filtering because the trace storage is indexed by CPU.
for (uint32_t cpu = 0; cpu < TraceStorage::kMaxCpus; cpu++) {
- const auto& slices = storage_->SlicesForCpu(cpu);
-
- // Start by setting index out of bounds if filtering below doesn't
- // yield any results.
- PerCpuState* state = &filter_state_.per_cpu_state[cpu];
- state->index = slices.slice_count();
-
- if (!filter_state_.cpu_constraints.Matches(cpu))
+ if (!cpu_filter.test(cpu))
continue;
- // Filter on other constraints now.
- FindNextSliceForCpu(cpu, 0ul /* start_index */);
+ PerCpuState* state = filter_state_.StateForCpu(cpu);
+
+ // Create a sorted index vector based on the order by requirements.
+ *state->sorted_row_ids() = CreateSortedIndexVector(
+ cpu, storage_->SlicesForCpu(cpu), *filter_state_.order_by());
}
// Set the cpu index to be the first item to look at.
@@ -192,37 +295,40 @@
}
int SchedSliceTable::Cursor::Next() {
- uint32_t cpu = static_cast<uint32_t>(filter_state_.next_slice_cpu);
- FindNextSliceForCpu(cpu, filter_state_.per_cpu_state[cpu].index + 1);
+ uint32_t cpu = filter_state_.next_cpu();
+ auto* state = filter_state_.StateForCpu(cpu);
+
+ // TODO(lalitm): maybe one day we may want to filter more efficiently. If so
+ // update this method with filter logic.
+ state->set_next_row_id_index(state->next_row_id_index() + 1);
+
FindNextSliceAmongCpus();
return SQLITE_OK;
}
int SchedSliceTable::Cursor::Eof() {
- return filter_state_.next_slice_cpu >= filter_state_.per_cpu_state.size();
+ return !filter_state_.IsNextCpuValid();
}
int SchedSliceTable::Cursor::Column(sqlite3_context* context, int N) {
- if (filter_state_.next_slice_cpu >= filter_state_.per_cpu_state.size()) {
+ if (!filter_state_.IsNextCpuValid())
return SQLITE_ERROR;
- }
- uint32_t cpu_index = static_cast<uint32_t>(filter_state_.next_slice_cpu);
- const auto& state = filter_state_.per_cpu_state[cpu_index];
- const auto& slices = storage_->SlicesForCpu(cpu_index);
+
+ uint32_t cpu = filter_state_.next_cpu();
+ size_t row = filter_state_.StateForCpu(cpu)->next_row_id();
+ const auto& slices = storage_->SlicesForCpu(cpu);
switch (N) {
case Column::kTimestamp: {
- auto timestamp =
- static_cast<sqlite3_int64>(slices.start_ns()[state.index]);
+ auto timestamp = static_cast<sqlite3_int64>(slices.start_ns()[row]);
sqlite3_result_int64(context, timestamp);
break;
}
case Column::kCpu: {
- sqlite3_result_int(context, static_cast<int>(cpu_index));
+ sqlite3_result_int(context, static_cast<int>(cpu));
break;
}
case Column::kDuration: {
- auto duration =
- static_cast<sqlite3_int64>(slices.durations()[state.index]);
+ auto duration = static_cast<sqlite3_int64>(slices.durations()[row]);
sqlite3_result_int64(context, duration);
break;
}
@@ -234,68 +340,40 @@
return SQLITE_ERROR;
}
-void SchedSliceTable::Cursor::FindNextSliceForCpu(uint32_t cpu,
- size_t start_index) {
- auto* state = &filter_state_.per_cpu_state[cpu];
- const auto& slices = storage_->SlicesForCpu(cpu);
-
- // Store the position we should start filtering from before setting
- // the index out of bounds in case the loop doesn't match anything.
- state->index = slices.slice_count();
-
- for (size_t i = start_index; i < slices.slice_count(); i++) {
- if (filter_state_.timestamp_constraints.Matches(slices.start_ns()[i])) {
- state->index = i;
- break;
- }
- }
-}
-
void SchedSliceTable::Cursor::FindNextSliceAmongCpus() {
- filter_state_.next_slice_cpu = filter_state_.per_cpu_state.size();
+ filter_state_.InvalidateNextCpu();
- uint64_t min_timestamp = std::numeric_limits<uint64_t>::max();
- for (uint32_t i = 0; i < filter_state_.per_cpu_state.size(); i++) {
- const auto& cpu_state = filter_state_.per_cpu_state[i];
- const auto& slices = storage_->SlicesForCpu(i);
- if (cpu_state.index >= slices.slice_count())
+ for (uint32_t cpu = 0; cpu < TraceStorage::kMaxCpus; cpu++) {
+ const auto& cpu_state = *filter_state_.StateForCpu(cpu);
+ if (!cpu_state.IsNextRowIdIndexValid())
continue;
- // TODO(lalitm): handle sorting by things other than timestamp.
- uint64_t cur_timestamp = slices.start_ns()[cpu_state.index];
- if (cur_timestamp < min_timestamp) {
- min_timestamp = cur_timestamp;
- filter_state_.next_slice_cpu = i;
+ // The first CPU with a valid slice can be set to the next CPU.
+ if (!filter_state_.IsNextCpuValid()) {
+ filter_state_.set_next_cpu(cpu);
+ continue;
+ }
+
+ uint32_t cur_cpu = filter_state_.next_cpu();
+ const auto& cur_slices = storage_->SlicesForCpu(cur_cpu);
+ size_t cur_row = filter_state_.StateForCpu(cur_cpu)->next_row_id();
+
+ const auto& slices = storage_->SlicesForCpu(cpu);
+ size_t row = cpu_state.next_row_id();
+ for (const auto& ob : *filter_state_.order_by()) {
+ int ret = CompareValuesForColumn(cpu, slices, row, cur_cpu, cur_slices,
+ cur_row, ob.column, ob.desc);
+ if (ret < 0) {
+ filter_state_.set_next_cpu(cpu);
+ break;
+ } else if (ret > 0) {
+ // If the cpu we are iterating over is not ordered before the current
+ // lowest CPU, then exit the loop.
+ break;
+ }
}
}
}
-template <typename T>
-bool SchedSliceTable::Cursor::NumericConstraints<T>::Initialize(
- const Constraint& cs,
- sqlite3_value* value) {
- bool is_integral = std::is_integral<T>::value;
- PERFETTO_DCHECK(is_integral ? sqlite3_value_type(value) == SQLITE_INTEGER
- : sqlite3_value_type(value) == SQLITE_FLOAT);
- bool constraint_implemented = true;
- T const_value = static_cast<T>(is_integral ? sqlite3_value_int64(value)
- : sqlite3_value_double(value));
- if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
- min_value = const_value;
- min_equals = IsOpGt(cs.op);
- } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
- max_value = const_value;
- max_equals = IsOpLt(cs.op);
- } else if (IsOpEq(cs.op)) {
- max_value = const_value;
- max_equals = true;
- min_value = const_value;
- min_equals = true;
- } else {
- constraint_implemented = false;
- }
- return constraint_implemented;
-}
-
} // namespace trace_processor
} // namespace perfetto
diff --git a/src/trace_processor/sched_slice_table.h b/src/trace_processor/sched_slice_table.h
index 612f911..ecdb252 100644
--- a/src/trace_processor/sched_slice_table.h
+++ b/src/trace_processor/sched_slice_table.h
@@ -29,6 +29,17 @@
public:
using Constraint = sqlite3_index_info::sqlite3_index_constraint;
+ enum Column { kTimestamp = 0, kCpu = 1, kDuration = 2 };
+ struct OrderBy {
+ Column column = kTimestamp;
+ bool desc = false;
+ };
+
+ struct IndexInfo {
+ std::vector<OrderBy> order_by;
+ std::vector<Constraint> constraints;
+ };
+
class Cursor {
public:
Cursor(SchedSliceTable* table, const TraceStorage* storage);
@@ -41,41 +52,56 @@
int RowId(sqlite_int64* pRowid);
private:
- template <class T>
- class NumericConstraints {
+ class PerCpuState {
public:
- bool Initialize(const Constraint& cs, sqlite3_value* value);
- bool Matches(T value) {
- if (value < min_value || (value == min_value && !min_equals)) {
- return false;
- } else if (value > max_value || (value == max_value && !max_equals)) {
- return false;
- }
- return true;
+ bool IsNextRowIdIndexValid() const {
+ return next_row_id_index_ < sorted_row_ids_.size();
}
+ uint32_t next_row_id_index() const { return next_row_id_index_; }
+
+ void set_next_row_id_index(uint32_t index) {
+ PERFETTO_DCHECK(next_row_id_index_ < sorted_row_ids_.size());
+ next_row_id_index_ = index;
+ }
+
+ std::vector<uint32_t>* sorted_row_ids() { return &sorted_row_ids_; }
+
+ size_t next_row_id() const { return sorted_row_ids_[next_row_id_index_]; }
+
private:
- T min_value = std::numeric_limits<T>::min();
- bool min_equals = true;
- T max_value = std::numeric_limits<T>::max();
- bool max_equals = true;
+ // Vector of row ids sorted by the the given order by constraints.
+ std::vector<uint32_t> sorted_row_ids_;
+
+ // An offset into |sorted_row_ids_| indicating the next row to return.
+ uint32_t next_row_id_index_ = 0;
};
- struct PerCpuState {
- size_t index = 0;
- };
+ class FilterState {
+ public:
+ PerCpuState* StateForCpu(uint32_t cpu) { return &per_cpu_state_[cpu]; }
- struct FilterState {
+ void InvalidateNextCpu() { next_cpu_ = per_cpu_state_.size(); }
+
+ bool IsNextCpuValid() const { return next_cpu_ < per_cpu_state_.size(); }
+
+ uint32_t next_cpu() const { return static_cast<uint32_t>(next_cpu_); }
+
+ void set_next_cpu(uint32_t cpu) {
+ PERFETTO_DCHECK(cpu < per_cpu_state_.size());
+ next_cpu_ = cpu;
+ }
+
+ std::vector<OrderBy>* order_by() { return &order_by_; }
+
+ private:
// One entry for each cpu which is used in filtering.
- std::array<PerCpuState, TraceStorage::kMaxCpus> per_cpu_state;
- size_t next_slice_cpu = 0;
+ std::array<PerCpuState, TraceStorage::kMaxCpus> per_cpu_state_;
+ size_t next_cpu_ = 0;
- NumericConstraints<uint64_t> timestamp_constraints;
- NumericConstraints<uint32_t> cpu_constraints;
+ std::vector<OrderBy> order_by_;
};
- void FindNextSliceForCpu(uint32_t cpu, size_t start_index);
-
void FindNextSliceAmongCpus();
sqlite3_vtab_cursor base_; // Must be first.
@@ -90,18 +116,14 @@
static sqlite3_module CreateModule();
int BestIndex(sqlite3_index_info* index_info);
-
int Open(sqlite3_vtab_cursor** ppCursor);
private:
- enum Column { kTimestamp = 0, kCpu = 1, kDuration = 2 };
-
sqlite3_vtab base_; // Must be first.
const TraceStorage* const storage_;
- // This vector contains one outer entry for each xBestIndex call and one
- // inner entry for each constraint provided by that xBestIndex call.
- std::vector<std::vector<Constraint>> indexes_;
+ // One entry for each BestIndex call.
+ std::vector<IndexInfo> indexes_;
};
} // namespace trace_processor
diff --git a/src/traced/probes/ftrace/ftrace_procfs.cc b/src/traced/probes/ftrace/ftrace_procfs.cc
index 145d0df..87095cf 100644
--- a/src/traced/probes/ftrace/ftrace_procfs.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs.cc
@@ -189,6 +189,8 @@
end = s.find(' ', start);
if (end == std::string::npos)
end = s.size();
+ while (end > start && s[end - 1] == '\n')
+ end--;
if (start == end)
break;
diff --git a/src/traced/probes/ftrace/ftrace_procfs_unittest.cc b/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
index 053a87d..cac3360 100644
--- a/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
+++ b/src/traced/probes/ftrace/ftrace_procfs_unittest.cc
@@ -56,8 +56,44 @@
EXPECT_THAT(ftrace.GetClock(), "global");
EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("local global [boot]"));
+ EXPECT_THAT(ftrace.GetClock(), "boot");
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
.WillOnce(Return(""));
EXPECT_THAT(ftrace.AvailableClocks(), IsEmpty());
+
+ // trace_clock text may end in a new line:
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("[local] global boot\n"));
+ EXPECT_THAT(ftrace.AvailableClocks(),
+ UnorderedElementsAre("local", "global", "boot"));
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("local global [boot]\n"));
+ EXPECT_THAT(ftrace.AvailableClocks(),
+ UnorderedElementsAre("local", "global", "boot"));
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("local global [boot]\n"));
+ EXPECT_THAT(ftrace.GetClock(), "boot");
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("\n"));
+ EXPECT_THAT(ftrace.AvailableClocks(), IsEmpty());
+
+ // We should handle many newlines (just in case):
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("local global [boot]\n\n\n"));
+ EXPECT_THAT(ftrace.GetClock(), "boot");
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("local global [boot]\n\n"));
+ EXPECT_THAT(ftrace.GetClock(), "boot");
+
+ EXPECT_CALL(ftrace, ReadFileIntoString("/root/trace_clock"))
+ .WillOnce(Return("\n\n\n\n"));
+ EXPECT_THAT(ftrace.AvailableClocks(), IsEmpty());
}
} // namespace
diff --git a/src/traced/probes/ftrace/proto_translation_table_unittest.cc b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
index b2b07dd..fe296d0 100644
--- a/src/traced/probes/ftrace/proto_translation_table_unittest.cc
+++ b/src/traced/probes/ftrace/proto_translation_table_unittest.cc
@@ -178,6 +178,7 @@
print fmt: "some format")"));
;
+ EXPECT_CALL(ftrace, ReadPageHeaderFormat()).Times(AnyNumber());
EXPECT_CALL(ftrace, ReadEventFormat(_, _)).Times(AnyNumber());
{
diff --git a/ui/BUILD.gn b/ui/BUILD.gn
index e50fa60..3a98f45 100644
--- a/ui/BUILD.gn
+++ b/ui/BUILD.gn
@@ -66,60 +66,82 @@
}
# +----------------------------------------------------------------------------+
+# | Template for "sorcery" the source map resolver. |
+# +----------------------------------------------------------------------------+
+template("sorcery") {
+ node_bin(target_name) {
+ assert(defined(invoker.input))
+ assert(defined(invoker.output))
+ forward_variables_from(invoker, [ "deps" ])
+ inputs = [
+ invoker.input,
+ ]
+ outputs = [
+ invoker.output,
+ invoker.output + ".map",
+ ]
+ node_cmd = "sorcery"
+ args = [
+ "-i",
+ rebase_path(invoker.input, root_build_dir),
+ "-o",
+ rebase_path(invoker.output, root_build_dir),
+ ]
+ }
+}
+
+# +----------------------------------------------------------------------------+
+# | Template for bundling js |
+# +----------------------------------------------------------------------------+
+template("bundle") {
+ node_bin(target_name) {
+ assert(defined(invoker.input))
+ assert(defined(invoker.output))
+ forward_variables_from(invoker, [ "deps" ])
+ inputs = [
+ invoker.input,
+ "rollup.config.js",
+ ]
+ outputs = [
+ invoker.output,
+ invoker.output + ".map",
+ ]
+ node_cmd = "rollup"
+ args = [
+ "-c",
+ rebase_path("rollup.config.js", root_build_dir),
+ rebase_path(invoker.input, root_build_dir),
+ "-o",
+ rebase_path(invoker.output, root_build_dir),
+ "-f",
+ "iife",
+ "-m",
+ "--silent",
+ ]
+ }
+}
+
+# +----------------------------------------------------------------------------+
# | Bundles all *.js files together resolving CommonJS require() deps. |
# +----------------------------------------------------------------------------+
# Bundle together all js sources into a bundle.js file, that will ultimately be
# included by the .html files.
-node_bin("main_bundle") {
+bundle("main_bundle") {
deps = [
":transpile_all_ts",
]
- node_cmd = "rollup"
- inputs = [
- "$target_out_dir/main.js",
- "rollup.config.js",
- ]
- outputs = [
- "$target_out_dir/main_bundle.js",
- ]
- args = [
- "-c",
- rebase_path("rollup.config.js", root_build_dir),
- rebase_path(inputs[0], root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- "-f",
- "iife",
- "-m",
- "--silent",
- ]
+ input = "$target_out_dir/main.js"
+ output = "$target_out_dir/main_bundle.js"
}
-node_bin("worker_bundle") {
+bundle("worker_bundle") {
deps = [
":transpile_all_ts",
]
- node_cmd = "rollup"
- inputs = [
- "$target_out_dir/worker.js",
- "rollup.config.js",
- ]
- outputs = [
- "$target_out_dir/worker_bundle.js",
- ]
- args = [
- "-c",
- rebase_path("rollup.config.js", root_build_dir),
- rebase_path(inputs[0], root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- "-f",
- "iife",
- "-m",
- "--silent",
- ]
+ input = "$target_out_dir/worker.js"
+ output = "$target_out_dir/worker_bundle.js"
}
# +----------------------------------------------------------------------------+
@@ -226,42 +248,20 @@
]
}
-node_bin("main_bundle_release") {
+sorcery("main_bundle_release") {
deps = [
":main_bundle",
]
- inputs = [
- "$target_out_dir/main_bundle.js",
- ]
- outputs = [
- "$ui_dir/main_bundle.js",
- ]
- node_cmd = "sorcery"
- args = [
- "-i",
- rebase_path(inputs[0], root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- ]
+ input = "$target_out_dir/main_bundle.js"
+ output = "$ui_dir/main_bundle.js"
}
-node_bin("worker_bundle_release") {
+sorcery("worker_bundle_release") {
deps = [
":worker_bundle",
]
- inputs = [
- "$target_out_dir/worker_bundle.js",
- ]
- outputs = [
- "$ui_dir/worker_bundle.js",
- ]
- node_cmd = "sorcery"
- args = [
- "-i",
- rebase_path(inputs[0], root_build_dir),
- "-o",
- rebase_path(outputs[0], root_build_dir),
- ]
+ input = "$target_out_dir/worker_bundle.js"
+ output = "$ui_dir/worker_bundle.js"
}
copy("wasm_release") {