Make zlib optional
Allow embedders to build perfetto without having to support zlib
Bug: 147789115
Change-Id: Idbb989d269efca7c294bd2e7c61505412b189d5c
diff --git a/gn/BUILD.gn b/gn/BUILD.gn
index cb35cd0..3440b62 100644
--- a/gn/BUILD.gn
+++ b/gn/BUILD.gn
@@ -85,6 +85,7 @@
"PERFETTO_TP_JSON_IMPORT=$enable_perfetto_trace_processor_json_import",
"PERFETTO_TP_FUCHSIA=$enable_perfetto_trace_processor_fuchsia",
"PERFETTO_LOCAL_SYMBOLIZER=$perfetto_local_symbolizer",
+ "PERFETTO_ZLIB=$enable_perfetto_zlib",
]
rel_out_path = rebase_path(gen_header_path, "$root_build_dir")
@@ -306,7 +307,7 @@
}
# Zlib is used both by trace_processor and by perfetto_cmd.
-if (enable_perfetto_trace_processor || enable_perfetto_platform_services) {
+if (enable_perfetto_zlib) {
group("zlib") {
if (perfetto_root_path == "//") {
public_configs = [ "//buildtools:zlib_config" ]
diff --git a/gn/perfetto.gni b/gn/perfetto.gni
index b479435..563db03 100644
--- a/gn/perfetto.gni
+++ b/gn/perfetto.gni
@@ -223,6 +223,11 @@
# Further per-OS conditionals are applied in gn/BUILD.gn.
enable_perfetto_trace_processor_httpd =
enable_perfetto_trace_processor && perfetto_build_standalone
+
+ # Enables Zlib support. This is used both by the "perfetto" cmdline client
+ # (for compressing traces) and by trace processor (for compressed traces).
+ enable_perfetto_zlib =
+ enable_perfetto_trace_processor || enable_perfetto_platform_services
}
declare_args() {
diff --git a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
index 259721b..dbc68b7 100644
--- a/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/android_tree/perfetto_build_flags.h
@@ -39,6 +39,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (0)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
index 7919b4d..ce91468 100644
--- a/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
+++ b/include/perfetto/base/build_configs/bazel/perfetto_build_flags.h
@@ -39,6 +39,7 @@
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_JSON_IMPORT() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_TP_FUCHSIA() (1)
#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_LOCAL_SYMBOLIZER() (PERFETTO_BUILDFLAG_DEFINE_PERFETTO_OS_LINUX())
+#define PERFETTO_BUILDFLAG_DEFINE_PERFETTO_ZLIB() (1)
// clang-format on
#endif // GEN_BUILD_CONFIG_PERFETTO_BUILD_FLAGS_H_
diff --git a/src/perfetto_cmd/BUILD.gn b/src/perfetto_cmd/BUILD.gn
index 969b732..6e920a9 100644
--- a/src/perfetto_cmd/BUILD.gn
+++ b/src/perfetto_cmd/BUILD.gn
@@ -61,7 +61,6 @@
":perfetto_atoms",
":trigger_producer",
"../../gn:default_deps",
- "../../gn:zlib",
"../../protos/perfetto/common:cpp",
"../../protos/perfetto/config:cpp",
"../../protos/perfetto/config/ftrace:cpp",
@@ -70,6 +69,9 @@
"../protozero",
"../tracing:ipc",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"config.cc",
"config.h",
@@ -131,7 +133,6 @@
":perfetto_cmd",
"../../gn:default_deps",
"../../gn:gtest_and_gmock",
- "../../gn:zlib",
"../../include/perfetto/base",
"../../include/perfetto/ext/base",
"../../protos/perfetto/config:cpp",
@@ -139,6 +140,9 @@
"../../protos/perfetto/trace:cpp",
"../tracing",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"config_unittest.cc",
"packet_writer_unittest.cc",
diff --git a/src/perfetto_cmd/packet_writer.cc b/src/perfetto_cmd/packet_writer.cc
index 9d5a8d6..2fb0562 100644
--- a/src/perfetto_cmd/packet_writer.cc
+++ b/src/perfetto_cmd/packet_writer.cc
@@ -24,13 +24,17 @@
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <zlib.h>
+#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/ext/base/utils.h"
#include "perfetto/ext/tracing/core/trace_packet.h"
#include "perfetto/protozero/proto_utils.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace {
@@ -43,14 +47,20 @@
// ID of the |packet| field in trace.proto. Hardcoded as this we don't
// want to depend on protos/trace:lite for binary size saving reasons.
constexpr uint32_t kPacketId = 1;
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
// ID of |compressed_packets| in trace_packet.proto.
constexpr uint32_t kCompressedPacketsId = 50;
// Maximum allowable size for a single packet.
const size_t kMaxPacketSize = 500 * 1024;
+
// After every kPendingBytesLimit we do a Z_SYNC_FLUSH in the zlib stream.
const size_t kPendingBytesLimit = 32 * 1024;
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
template <uint32_t id>
size_t GetPreamble(size_t sz, Preamble* preamble) {
uint8_t* ptr = reinterpret_cast<uint8_t*>(preamble->data());
@@ -73,6 +83,31 @@
FILE* fd_;
};
+FilePacketWriter::FilePacketWriter(FILE* fd) : fd_(fd) {}
+
+FilePacketWriter::~FilePacketWriter() {
+ fflush(fd_);
+}
+
+bool FilePacketWriter::WritePackets(const std::vector<TracePacket>& packets) {
+ for (const TracePacket& packet : packets) {
+ Preamble preamble;
+ size_t size = GetPreamble<kPacketId>(packet.size(), &preamble);
+ if (fwrite(preamble.data(), 1, size, fd_) != size)
+ return false;
+ for (const Slice& slice : packet.slices()) {
+ if (fwrite(reinterpret_cast<const char*>(slice.start), 1, slice.size,
+ fd_) != slice.size) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
class ZipPacketWriter : public PacketWriter {
public:
ZipPacketWriter(std::unique_ptr<PacketWriter>);
@@ -102,29 +137,6 @@
size_t pending_bytes_ = 0;
};
-FilePacketWriter::FilePacketWriter(FILE* fd) : fd_(fd) {}
-
-FilePacketWriter::~FilePacketWriter() {
- fflush(fd_);
-}
-
-bool FilePacketWriter::WritePackets(const std::vector<TracePacket>& packets) {
- for (const TracePacket& packet : packets) {
- Preamble preamble;
- size_t size = GetPreamble<kPacketId>(packet.size(), &preamble);
- if (fwrite(preamble.data(), 1, size, fd_) != size)
- return false;
- for (const Slice& slice : packet.slices()) {
- if (fwrite(reinterpret_cast<const char*>(slice.start), 1, slice.size,
- fd_) != slice.size) {
- return false;
- }
- }
- }
-
- return true;
-}
-
ZipPacketWriter::ZipPacketWriter(std::unique_ptr<PacketWriter> writer)
: writer_(std::move(writer)),
buf_(base::PagedMemory::Allocate(kMaxPacketSize)),
@@ -237,6 +249,8 @@
pending_bytes_ += size;
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace
PacketWriter::PacketWriter() {}
@@ -247,9 +261,11 @@
return std::unique_ptr<PacketWriter>(new FilePacketWriter(fd));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
std::unique_ptr<PacketWriter> CreateZipPacketWriter(
std::unique_ptr<PacketWriter> writer) {
return std::unique_ptr<PacketWriter>(new ZipPacketWriter(std::move(writer)));
}
+#endif
} // namespace perfetto
diff --git a/src/perfetto_cmd/packet_writer_unittest.cc b/src/perfetto_cmd/packet_writer_unittest.cc
index c1fab21..fbf9603 100644
--- a/src/perfetto_cmd/packet_writer_unittest.cc
+++ b/src/perfetto_cmd/packet_writer_unittest.cc
@@ -21,8 +21,7 @@
#include <random>
-#include <zlib.h>
-
+#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/temp_file.h"
@@ -34,6 +33,10 @@
#include "protos/perfetto/trace/trace.gen.h"
#include "protos/perfetto/trace/trace_packet.gen.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace {
@@ -51,6 +54,7 @@
return packet;
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
std::string Decompress(const std::string& data) {
uint8_t out[1024];
@@ -76,6 +80,7 @@
inflateEnd(&stream);
return s;
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TEST(PacketWriterTest, FilePacketWriter) {
base::TempFile tmp = base::TempFile::Create();
@@ -105,6 +110,8 @@
EXPECT_EQ(trace.packet()[0].for_testing().str(), "abc");
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
TEST(PacketWriterTest, ZipPacketWriter) {
base::TempFile tmp = base::TempFile::Create();
base::ScopedResource<FILE*, fclose, nullptr> f(
@@ -281,5 +288,7 @@
EXPECT_EQ(packet_count, 1000u);
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace
} // namespace perfetto
diff --git a/src/perfetto_cmd/perfetto_cmd.cc b/src/perfetto_cmd/perfetto_cmd.cc
index 638112f..bb48f6f 100644
--- a/src/perfetto_cmd/perfetto_cmd.cc
+++ b/src/perfetto_cmd/perfetto_cmd.cc
@@ -603,7 +603,11 @@
if (trace_config_->compression_type() ==
TraceConfig::COMPRESSION_TYPE_DEFLATE) {
if (packet_writer_) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
packet_writer_ = CreateZipPacketWriter(std::move(packet_writer_));
+#else
+ PERFETTO_ELOG("Cannot compress. Zlib not enabled in the build config");
+#endif
} else {
PERFETTO_ELOG("Cannot compress when tracing directly to file.");
}
diff --git a/src/trace_processor/BUILD.gn b/src/trace_processor/BUILD.gn
index 0455917..ebabeb3 100644
--- a/src/trace_processor/BUILD.gn
+++ b/src/trace_processor/BUILD.gn
@@ -88,8 +88,6 @@
"ftrace_utils.h",
"global_args_tracker.cc",
"global_args_tracker.h",
- "gzip_trace_parser.cc",
- "gzip_trace_parser.h",
"heap_profile_tracker.cc",
"heap_profile_tracker.h",
"importers/ftrace/ftrace_module.cc",
@@ -140,11 +138,9 @@
"track_tracker.h",
"virtual_destructors.cc",
]
-
deps = [
":descriptors",
"../../gn:default_deps",
- "../../gn:zlib",
"../base",
"../protozero",
"containers",
@@ -167,6 +163,13 @@
"../../protos/perfetto/trace/sys_stats:zero",
"../../protos/perfetto/trace/track_event:zero",
]
+ if (enable_perfetto_zlib) {
+ sources += [
+ "gzip_trace_parser.cc",
+ "gzip_trace_parser.h",
+ ]
+ deps += [ "../../gn:zlib" ]
+ }
if (enable_perfetto_trace_processor_json_import) {
sources += [
"importers/json/json_trace_parser.cc",
diff --git a/src/trace_processor/forwarding_trace_parser.cc b/src/trace_processor/forwarding_trace_parser.cc
index ea63b8e..89798f2 100644
--- a/src/trace_processor/forwarding_trace_parser.cc
+++ b/src/trace_processor/forwarding_trace_parser.cc
@@ -39,6 +39,11 @@
namespace trace_processor {
namespace {
+#if !PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+const char kNoZlibErr[] =
+ "Cannot open compressed trace. zlib not enabled in the build config";
+#endif
+
inline bool isspace(unsigned char c) {
return ::isspace(c);
}
@@ -119,12 +124,20 @@
}
case kGzipTraceType:
PERFETTO_DLOG("gzip trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
reader_.reset(new GzipTraceParser(context_));
break;
+#else
+ return util::ErrStatus(kNoZlibErr);
+#endif
case kCtraceTraceType:
PERFETTO_DLOG("ctrace trace detected");
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
reader_.reset(new GzipTraceParser(context_));
break;
+#else
+ return util::ErrStatus(kNoZlibErr);
+#endif
case kUnknownTraceType:
return util::ErrStatus("Unknown trace type provided");
}
diff --git a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
index b964a2c..ca746b7 100644
--- a/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
+++ b/src/trace_processor/importers/proto/proto_trace_tokenizer.cc
@@ -18,8 +18,7 @@
#include <string>
-#include <zlib.h>
-
+#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_view.h"
@@ -42,6 +41,10 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_processor {
@@ -53,6 +56,7 @@
constexpr uint8_t kTracePacketTag =
MakeTagLengthDelimited(protos::pbzero::Trace::kPacketFieldNumber);
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
TraceBlobView Decompress(TraceBlobView input) {
uint8_t out[4096];
std::string s;
@@ -81,6 +85,7 @@
memcpy(output.get(), s.data(), s.size());
return TraceBlobView(std::move(output), 0, s.size());
}
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
} // namespace
@@ -309,6 +314,7 @@
}
if (decoder.has_compressed_packets()) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
protozero::ConstBytes field = decoder.compressed_packets();
const size_t field_off = packet.offset_of(field.data);
TraceBlobView compressed_packets = packet.slice(field_off, field.size);
@@ -334,6 +340,9 @@
}
return util::OkStatus();
+#else
+ return util::Status("Cannot decode compressed packets. Zlib not enabled");
+#endif
}
// If we're not forcing a full sort and this is a write_into_file trace, then
diff --git a/tools/trace_to_text/BUILD.gn b/tools/trace_to_text/BUILD.gn
index 41c844d..6892d1a 100644
--- a/tools/trace_to_text/BUILD.gn
+++ b/tools/trace_to_text/BUILD.gn
@@ -50,10 +50,12 @@
"../../src/profiling/symbolizer:symbolize_database",
]
public_deps = [
- "../../gn:zlib",
"../../include/perfetto/ext/base",
"../../include/perfetto/profiling:deobfuscator",
]
+ if (enable_perfetto_zlib) {
+ public_deps += [ "../../gn:zlib" ]
+ }
sources = [
"utils.cc",
"utils.h",
@@ -144,9 +146,11 @@
":utils",
"../../gn:default_deps",
"../../gn:protobuf_full",
- "../../gn:zlib",
"../../protos/perfetto/trace:zero",
]
+ if (enable_perfetto_zlib) {
+ deps += [ "../../gn:zlib" ]
+ }
sources = [
"proto_full_utils.cc",
"proto_full_utils.h",
diff --git a/tools/trace_to_text/trace_to_text.cc b/tools/trace_to_text/trace_to_text.cc
index 3fb86d8..1616a2d 100644
--- a/tools/trace_to_text/trace_to_text.cc
+++ b/tools/trace_to_text/trace_to_text.cc
@@ -16,8 +16,6 @@
#include "tools/trace_to_text/trace_to_text.h"
-#include <zlib.h>
-
#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
@@ -31,6 +29,10 @@
#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_to_text {
@@ -78,6 +80,7 @@
void PrintCompressedPackets(const std::string& packets,
Message* compressed_msg_scratch,
ZeroCopyOutputStream* output) {
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
uint8_t out[4096];
std::vector<uint8_t> data;
@@ -120,6 +123,24 @@
}
WriteToZeroCopyOutput(output, kCompressedPacketsSuffix,
sizeof(kCompressedPacketsSuffix) - 1);
+#else
+ base::ignore_result(packets);
+ base::ignore_result(compressed_msg_scratch);
+ base::ignore_result(kIndentedPacketPrefix);
+ base::ignore_result(kIndentedPacketSuffix);
+ WriteToZeroCopyOutput(output, kCompressedPacketsPrefix,
+ sizeof(kCompressedPacketsPrefix) - 1);
+ static const char kErrMsg[] =
+ "Cannot decode compressed packets. zlib not enabled in the build config";
+ WriteToZeroCopyOutput(output, kErrMsg, sizeof(kErrMsg) - 1);
+ WriteToZeroCopyOutput(output, kCompressedPacketsSuffix,
+ sizeof(kCompressedPacketsSuffix) - 1);
+ static bool log_once = [] {
+ PERFETTO_ELOG("%s", kErrMsg);
+ return true;
+ }();
+ base::ignore_result(log_once);
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
}
} // namespace
diff --git a/tools/trace_to_text/utils.cc b/tools/trace_to_text/utils.cc
index 73645f6..e655b38 100644
--- a/tools/trace_to_text/utils.cc
+++ b/tools/trace_to_text/utils.cc
@@ -39,8 +39,9 @@
using Iterator = trace_processor::TraceProcessor::Iterator;
-
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
constexpr size_t kCompressionBufferSize = 500 * 1024;
+#endif
std::map<std::string, std::set<std::string>> GetHeapGraphClasses(
trace_processor::TraceProcessor* tp) {
@@ -179,7 +180,6 @@
return true;
}
-
void DeobfuscateDatabase(
trace_processor::TraceProcessor* tp,
const std::map<std::string, profiling::ObfuscatedClass>& mapping,
@@ -229,6 +229,8 @@
output_->write(data, static_cast<std::streamsize>(sz));
}
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
DeflateTraceWriter::DeflateTraceWriter(std::ostream* output)
: TraceWriter(output),
buf_(base::PagedMemory::Allocate(kCompressionBufferSize)),
@@ -270,6 +272,15 @@
PERFETTO_FATAL("Expected %d got %d: %s", actual_code, expected_code,
stream_.msg);
}
+#else
+
+DeflateTraceWriter::DeflateTraceWriter(std::ostream* output)
+ : TraceWriter(output) {
+ PERFETTO_ELOG("Cannot compress. Zlib is not enabled in the build config");
+}
+DeflateTraceWriter::~DeflateTraceWriter() = default;
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
} // namespace trace_to_text
} // namespace perfetto
diff --git a/tools/trace_to_text/utils.h b/tools/trace_to_text/utils.h
index 19bd3ca..d708e04 100644
--- a/tools/trace_to_text/utils.h
+++ b/tools/trace_to_text/utils.h
@@ -26,13 +26,15 @@
#include <memory>
#include <vector>
-#include <zlib.h>
-
#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/paged_memory.h"
#include "perfetto/profiling/deobfuscator.h"
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+#include <zlib.h>
+#endif
+
namespace perfetto {
namespace trace_processor {
@@ -83,6 +85,7 @@
std::ostream* output_;
};
+#if PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
class DeflateTraceWriter : public TraceWriter {
public:
DeflateTraceWriter(std::ostream* output);
@@ -100,6 +103,17 @@
uint8_t* const end_;
};
+#else
+
+// Fallback implementation. Will print an error and write uncompressed.
+class DeflateTraceWriter : public TraceWriter {
+ public:
+ DeflateTraceWriter(std::ostream* output);
+ ~DeflateTraceWriter() override;
+};
+
+#endif // PERFETTO_BUILDFLAG(PERFETTO_ZLIB)
+
} // namespace trace_to_text
} // namespace perfetto