Move over to ABSL logging and flags.

Removes gperftools too since that wants gflags.

Here come the fireworks.

Change-Id: I79cb7bcf60f1047fbfa28bfffc21a0fd692e4b1c
Signed-off-by: Austin Schuh <austin.linux@gmail.com>
diff --git a/aos/BUILD b/aos/BUILD
index 83adcd6..64c6587 100644
--- a/aos/BUILD
+++ b/aos/BUILD
@@ -100,7 +100,8 @@
     deps = [
         "//aos/ipc_lib:aos_sync",
         "//aos/mutex",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -163,7 +164,8 @@
         "//aos/events:shm_event_loop",
         "//aos/time",
         "//aos/util:top",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -182,6 +184,14 @@
         ":uuid",
         "//aos:die",
         "//aos/logging",
+        "@com_google_absl//absl/debugging:failure_signal_handler",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/flags:parse",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
+        "@com_google_absl//absl/log:flags",
+        "@com_google_absl//absl/log:globals",
+        "@com_google_absl//absl/log:initialize",
     ],
 )
 
@@ -197,7 +207,8 @@
         ":for_rust",
         ":init",
         "//aos/logging",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log:flags",
         "@crate_index//:cxx_cc",
     ],
 )
@@ -246,7 +257,8 @@
     visibility = ["//visibility:public"],
     deps = [
         ":uuid",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -317,8 +329,9 @@
         "//aos/ipc_lib:index",
         "//aos/network:team_number",
         "//aos/util:file",
-        "@com_github_google_glog//:glog",
         "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -392,7 +405,8 @@
     visibility = ["//visibility:public"],
     deps = [
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -403,7 +417,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -425,7 +440,8 @@
         "//aos/flatbuffers:builder",
         "//aos/util:file",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -512,7 +528,8 @@
         "//aos/ipc_lib:data_alignment",
         "//aos/util:file",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:span",
     ],
@@ -564,7 +581,8 @@
         ":configuration",
         ":init",
         "//aos/util:file",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -583,7 +601,8 @@
         "//aos:init",
         "//aos/events:shm_event_loop",
         "//aos/events:simulated_event_loop",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -599,7 +618,8 @@
         ":configuration",
         ":json_to_flatbuffer",
         "//aos:init",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -616,7 +636,8 @@
         ":init",
         ":json_to_flatbuffer",
         ":realtime",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -632,8 +653,9 @@
         ":configuration",
         ":init",
         ":json_to_flatbuffer",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -649,7 +671,8 @@
         ":json_to_flatbuffer",
         "//aos:init",
         "//aos/events:shm_event_loop",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -664,7 +687,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -680,7 +704,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/strings:str_format",
     ],
@@ -696,8 +721,9 @@
     deps = [
         ":init",
         ":realtime",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -729,9 +755,10 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_gflags_gflags//:gflags",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -794,8 +821,9 @@
         "//aos/events:simulated_event_loop",
         "//aos/events/logging:log_reader",
         "//aos/time",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/actions/action_test.cc b/aos/actions/action_test.cc
index fca60a3..3d6a199 100644
--- a/aos/actions/action_test.cc
+++ b/aos/actions/action_test.cc
@@ -6,8 +6,9 @@
 #include <ostream>
 #include <string>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/actions/actions.h"
diff --git a/aos/actions/actions.h b/aos/actions/actions.h
index 1aae62f..1245f55 100644
--- a/aos/actions/actions.h
+++ b/aos/actions/actions.h
@@ -10,7 +10,8 @@
 #include <string>
 #include <type_traits>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/actions/actions_generated.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/actions/actor.h b/aos/actions/actor.h
index b0b6bd4..2d4294a 100644
--- a/aos/actions/actor.h
+++ b/aos/actions/actor.h
@@ -9,8 +9,9 @@
 #include <string>
 #include <type_traits>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/string.h"
-#include "glog/logging.h"
 
 #include "aos/actions/actions_generated.h"
 #include "aos/configuration_generated.h"
diff --git a/aos/analysis/BUILD b/aos/analysis/BUILD
index 85f8783..7f1f038 100644
--- a/aos/analysis/BUILD
+++ b/aos/analysis/BUILD
@@ -18,7 +18,8 @@
         "//aos/events:simulated_event_loop",
         "//aos/events/logging:log_reader",
         "//third_party/python",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/analysis/in_process_plotter.cc b/aos/analysis/in_process_plotter.cc
index 6c45389..437c71e 100644
--- a/aos/analysis/in_process_plotter.cc
+++ b/aos/analysis/in_process_plotter.cc
@@ -3,9 +3,10 @@
 #include <algorithm>
 #include <ostream>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 
diff --git a/aos/analysis/local_foxglove.cc b/aos/analysis/local_foxglove.cc
index b07a628..e30f150 100644
--- a/aos/analysis/local_foxglove.cc
+++ b/aos/analysis/local_foxglove.cc
@@ -1,6 +1,6 @@
 #include <memory>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/init.h"
 #include "aos/seasocks/seasocks_logger.h"
@@ -8,9 +8,9 @@
 #include "seasocks/Logger.h"
 #include "seasocks/Server.h"
 
-DEFINE_string(data_path, "external/foxglove_studio",
-              "Path to foxglove studio files to serve.");
-DEFINE_uint32(port, 8000, "Port to serve files at.");
+ABSL_FLAG(std::string, data_path, "external/foxglove_studio",
+          "Path to foxglove studio files to serve.");
+ABSL_FLAG(uint32_t, port, 8000, "Port to serve files at.");
 
 int main(int argc, char *argv[]) {
   aos::InitGoogle(&argc, &argv);
@@ -18,5 +18,6 @@
   findEmbeddedContent("");
   ::seasocks::Server server(std::make_shared<aos::seasocks::SeasocksLogger>(
       ::seasocks::Logger::Level::Info));
-  server.serve(FLAGS_data_path.c_str(), FLAGS_port);
+  server.serve(absl::GetFlag(FLAGS_data_path).c_str(),
+               absl::GetFlag(FLAGS_port));
 }
diff --git a/aos/analysis/py_log_reader.cc b/aos/analysis/py_log_reader.cc
index c190acb..19b0855 100644
--- a/aos/analysis/py_log_reader.cc
+++ b/aos/analysis/py_log_reader.cc
@@ -26,8 +26,9 @@
 #include <string>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/context.h"
diff --git a/aos/aos_cli_utils.cc b/aos/aos_cli_utils.cc
index 9a2c738..1a9e1d6 100644
--- a/aos/aos_cli_utils.cc
+++ b/aos/aos_cli_utils.cc
@@ -17,25 +17,26 @@
 #include "aos/events/simulated_event_loop.h"
 #include "aos/time/time.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
 
-DEFINE_bool(
-    _bash_autocomplete, false,
+ABSL_FLAG(
+    bool, _bash_autocomplete, false,
     "Internal use: Outputs channel list for use with autocomplete script.");
 
-DEFINE_bool(_zsh_compatability, false,
-            "Internal use: Force completion to complete either channels or "
-            "message_types, zsh doesn't handle spaces well.");
+ABSL_FLAG(bool, _zsh_compatability, false,
+          "Internal use: Force completion to complete either channels or "
+          "message_types, zsh doesn't handle spaces well.");
 
-DEFINE_string(_bash_autocomplete_word, "",
-              "Internal use: Current word being autocompleted");
+ABSL_FLAG(std::string, _bash_autocomplete_word, "",
+          "Internal use: Current word being autocompleted");
 
-DEFINE_bool(all, false,
-            "If true, print out the channels for all nodes, not just the "
-            "channels which are visible on this node.");
+ABSL_FLAG(bool, all, false,
+          "If true, print out the channels for all nodes, not just the "
+          "channels which are visible on this node.");
 
-DEFINE_bool(
-    canonical, false,
+ABSL_FLAG(
+    bool, canonical, false,
     "If true, print out the canonical channel names instead of the aliases.");
 
 namespace aos {
@@ -79,14 +80,15 @@
     std::string_view channel_filter_description, bool expect_args) {
   // Don't generate failure output if the config doesn't exist while attempting
   // to autocomplete.
-  if (FLAGS__bash_autocomplete &&
-      (!(EndsWith(FLAGS_config, ".json") || EndsWith(FLAGS_config, ".bfbs")))) {
+  if (absl::GetFlag(FLAGS__bash_autocomplete) &&
+      (!(EndsWith(absl::GetFlag(FLAGS_config), ".json") ||
+         EndsWith(absl::GetFlag(FLAGS_config), ".bfbs")))) {
     std::cout << "COMPREPLY=()";
     return true;
   }
 
-  config = aos::configuration::MaybeReadConfig(FLAGS_config);
-  if (FLAGS__bash_autocomplete && !config.has_value()) {
+  config = aos::configuration::MaybeReadConfig(absl::GetFlag(FLAGS_config));
+  if (absl::GetFlag(FLAGS__bash_autocomplete) && !config.has_value()) {
     std::cout << "COMPREPLY=()";
     return true;
   }
@@ -111,7 +113,7 @@
       ShiftArgs(argc, argv);
     }
 
-    if (FLAGS__bash_autocomplete) {
+    if (absl::GetFlag(FLAGS__bash_autocomplete)) {
       Autocomplete(channel_name, message_type, channel_filter);
       return true;
     }
@@ -122,8 +124,8 @@
       std::cout << "Channels:\n";
       std::set<std::pair<std::string, std::string>> channels_to_print;
       for (const aos::Channel *channel : *channels) {
-        if (FLAGS_all || channel_filter(channel)) {
-          if (FLAGS_canonical) {
+        if (absl::GetFlag(FLAGS_all) || channel_filter(channel)) {
+          if (absl::GetFlag(FLAGS_canonical)) {
             channels_to_print.emplace(channel->name()->c_str(),
                                       channel->type()->c_str());
           } else {
@@ -187,7 +189,7 @@
         continue;
       }
 
-      if (!FLAGS_all && !channel_filter(channel)) {
+      if (!absl::GetFlag(FLAGS_all) && !channel_filter(channel)) {
         LOG(FATAL) << "matched channel does not pass the channel filter: \""
                    << channel_filter_description
                    << "\" [matched channel info]: "
@@ -226,9 +228,11 @@
                     }) == 1;
 
   const bool editing_message =
-      !channel_name.empty() && FLAGS__bash_autocomplete_word == message_type;
+      !channel_name.empty() &&
+      absl::GetFlag(FLAGS__bash_autocomplete_word) == message_type;
   const bool editing_channel =
-      !editing_message && FLAGS__bash_autocomplete_word == channel_name;
+      !editing_message &&
+      absl::GetFlag(FLAGS__bash_autocomplete_word) == channel_name;
 
   std::cout << "COMPREPLY=(";
 
@@ -236,7 +240,7 @@
   // that were're editing one of the two positional arguments.
   if (!unique_match && (editing_message || editing_channel)) {
     for (const aos::Channel *channel : *config_msg->channels()) {
-      if (FLAGS_all || channel_filter(channel)) {
+      if (absl::GetFlag(FLAGS_all) || channel_filter(channel)) {
         const std::set<std::string> aliases =
             aos::configuration::GetChannelAliases(
                 config_msg, channel->name()->string_view(),
@@ -260,7 +264,8 @@
           // Otherwise, since the message type is poulated yet not being edited,
           // the user must be editing the channel name alone, in which case only
           // suggest channel names, not pairs.
-          if (!FLAGS__zsh_compatability && message_type.empty()) {
+          if (!absl::GetFlag(FLAGS__zsh_compatability) &&
+              message_type.empty()) {
             std::cout << '\'' << *it << ' ' << channel->type()->c_str() << "' ";
           } else {
             std::cout << '\'' << *it << "' ";
diff --git a/aos/aos_cli_utils.h b/aos/aos_cli_utils.h
index 199c490..980f94f 100644
--- a/aos/aos_cli_utils.h
+++ b/aos/aos_cli_utils.h
@@ -1,7 +1,7 @@
 #ifndef AOS_AOS_CLI_UTILS_H_
 #define AOS_AOS_CLI_UTILS_H_
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/configuration.h"
 #include "aos/events/shm_event_loop.h"
diff --git a/aos/aos_dump.cc b/aos/aos_dump.cc
index 18d2ce1..ecf4add 100644
--- a/aos/aos_dump.cc
+++ b/aos/aos_dump.cc
@@ -2,37 +2,38 @@
 
 #include <iostream>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/aos_cli_utils.h"
 #include "aos/configuration.h"
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_int64(max_vector_size, 100,
-             "If positive, vectors longer than this will not be printed");
-DEFINE_bool(json, false, "If true, print fully valid JSON");
-DEFINE_bool(fetch, false,
-            "If true, fetch the current message on the channel first");
-DEFINE_bool(pretty, false,
-            "If true, pretty print the messages on multiple lines");
-DEFINE_bool(
-    pretty_max, false,
+ABSL_FLAG(int64_t, max_vector_size, 100,
+          "If positive, vectors longer than this will not be printed");
+ABSL_FLAG(bool, json, false, "If true, print fully valid JSON");
+ABSL_FLAG(bool, fetch, false,
+          "If true, fetch the current message on the channel first");
+ABSL_FLAG(bool, pretty, false,
+          "If true, pretty print the messages on multiple lines");
+ABSL_FLAG(
+    bool, pretty_max, false,
     "If true, expand every field to its own line (expands more than -pretty)");
-DEFINE_bool(print_timestamps, true, "If true, timestamps are printed.");
-DEFINE_uint64(count, 0,
-              "If >0, aos_dump will exit after printing this many messages.");
-DEFINE_int32(rate_limit, 0,
-             "The minimum amount of time to wait in milliseconds before "
-             "sending another message");
-DEFINE_int32(timeout, -1,
-             "The max time in milliseconds to wait for messages before "
-             "exiting.  -1 means forever, 0 means don't wait.");
-DEFINE_bool(hex, false,
-            "Are integers in the messages printed in hex notation.");
+ABSL_FLAG(bool, print_timestamps, true, "If true, timestamps are printed.");
+ABSL_FLAG(uint64_t, count, 0,
+          "If >0, aos_dump will exit after printing this many messages.");
+ABSL_FLAG(int32_t, rate_limit, 0,
+          "The minimum amount of time to wait in milliseconds before "
+          "sending another message");
+ABSL_FLAG(int32_t, timeout, -1,
+          "The max time in milliseconds to wait for messages before "
+          "exiting.  -1 means forever, 0 means don't wait.");
+ABSL_FLAG(bool, hex, false,
+          "Are integers in the messages printed in hex notation.");
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Prints messages from arbitrary channels as they are received given a "
       "configuration file describing the channels to listen on.\nTypical "
       "Usage: aos_dump [--config path_to_config.json] channel_name "
@@ -56,18 +57,19 @@
 
   aos::Printer printer(
       {
-          .pretty = FLAGS_pretty,
-          .max_vector_size = static_cast<size_t>(FLAGS_max_vector_size),
-          .pretty_max = FLAGS_pretty_max,
-          .print_timestamps = FLAGS_print_timestamps,
-          .json = FLAGS_json,
+          .pretty = absl::GetFlag(FLAGS_pretty),
+          .max_vector_size =
+              static_cast<size_t>(absl::GetFlag(FLAGS_max_vector_size)),
+          .pretty_max = absl::GetFlag(FLAGS_pretty_max),
+          .print_timestamps = absl::GetFlag(FLAGS_print_timestamps),
+          .json = absl::GetFlag(FLAGS_json),
           .distributed_clock = false,
-          .hex = FLAGS_hex,
+          .hex = absl::GetFlag(FLAGS_hex),
       },
       /*flush*/ true);
 
   for (const aos::Channel *channel : cli_info.found_channels) {
-    if (FLAGS_fetch) {
+    if (absl::GetFlag(FLAGS_fetch)) {
       const std::unique_ptr<aos::RawFetcher> fetcher =
           cli_info.event_loop->MakeRawFetcher(channel);
       if (fetcher->Fetch()) {
@@ -75,11 +77,12 @@
       }
     }
 
-    if (FLAGS_count > 0 && printer.message_count() >= FLAGS_count) {
+    if (absl::GetFlag(FLAGS_count) > 0 &&
+        printer.message_count() >= absl::GetFlag(FLAGS_count)) {
       return 0;
     }
 
-    if (FLAGS_timeout == 0) {
+    if (absl::GetFlag(FLAGS_timeout) == 0) {
       continue;
     }
 
@@ -87,33 +90,36 @@
         channel, [channel, &printer, &cli_info, &next_send_time](
                      const aos::Context &context, const void * /*message*/) {
           if (context.monotonic_event_time > next_send_time) {
-            if (FLAGS_count > 0 && printer.message_count() >= FLAGS_count) {
+            if (absl::GetFlag(FLAGS_count) > 0 &&
+                printer.message_count() >= absl::GetFlag(FLAGS_count)) {
               return;
             }
 
             printer.PrintMessage(channel, context);
-            next_send_time = context.monotonic_event_time +
-                             std::chrono::milliseconds(FLAGS_rate_limit);
-            if (FLAGS_count > 0 && printer.message_count() >= FLAGS_count) {
+            next_send_time =
+                context.monotonic_event_time +
+                std::chrono::milliseconds(absl::GetFlag(FLAGS_rate_limit));
+            if (absl::GetFlag(FLAGS_count) > 0 &&
+                printer.message_count() >= absl::GetFlag(FLAGS_count)) {
               cli_info.event_loop->Exit();
             }
           }
         });
   }
 
-  if (FLAGS_timeout == 0) {
+  if (absl::GetFlag(FLAGS_timeout) == 0) {
     return 0;
   }
 
-  if (FLAGS_timeout > 0) {
+  if (absl::GetFlag(FLAGS_timeout) > 0) {
     aos::TimerHandler *handle = cli_info.event_loop->AddTimer(
         [event_loop = &cli_info.event_loop.value()]() { event_loop->Exit(); });
 
-    cli_info.event_loop->OnRun(
-        [handle, event_loop = &cli_info.event_loop.value()]() {
-          handle->Schedule(event_loop->monotonic_now() +
-                           std::chrono::milliseconds(FLAGS_timeout));
-        });
+    cli_info.event_loop->OnRun([handle,
+                                event_loop = &cli_info.event_loop.value()]() {
+      handle->Schedule(event_loop->monotonic_now() +
+                       std::chrono::milliseconds(absl::GetFlag(FLAGS_timeout)));
+    });
   }
 
   cli_info.event_loop->Run();
diff --git a/aos/aos_graph_channels.cc b/aos/aos_graph_channels.cc
index 1a89223..c03dc36 100644
--- a/aos/aos_graph_channels.cc
+++ b/aos/aos_graph_channels.cc
@@ -1,9 +1,10 @@
 #include <iomanip>
 #include <iostream>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_split.h"
-#include "gflags/gflags.h"
 
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/simulated_event_loop.h"
@@ -11,7 +12,7 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/time/time.h"
 
-DEFINE_string(skip, "", "Applications to skip, seperated by ;");
+ABSL_FLAG(std::string, skip, "", "Applications to skip, seperated by ;");
 
 struct ChannelState {
   const aos::Channel *channel = nullptr;
@@ -34,7 +35,7 @@
 };
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Usage: \n"
       "  aos_graph_channels [args] logfile1 logfile2 ...\n"
       "\n"
@@ -49,7 +50,8 @@
     LOG(FATAL) << "Expected at least 1 logfile as an argument.";
   }
 
-  const std::vector<std::string> skip_list = absl::StrSplit(FLAGS_skip, ";");
+  const std::vector<std::string> skip_list =
+      absl::StrSplit(absl::GetFlag(FLAGS_skip), ";");
   aos::logger::LogReader reader(
       aos::logger::SortParts(aos::logger::FindLogs(argc, argv)));
 
diff --git a/aos/aos_graph_nodes.cc b/aos/aos_graph_nodes.cc
index 4ed9866..87b8671 100644
--- a/aos/aos_graph_nodes.cc
+++ b/aos/aos_graph_nodes.cc
@@ -1,22 +1,24 @@
 #include <iostream>
 #include <map>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/configuration.h"
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_bool(all, false,
-            "If true, print out the channels for all nodes in the config file, "
-            "not just the channels which are visible on this node.");
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
-DEFINE_bool(short_types, true,
-            "Whether to show a shortened version of the type name");
+ABSL_FLAG(bool, all, false,
+          "If true, print out the channels for all nodes in the config file, "
+          "not just the channels which are visible on this node.");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
+ABSL_FLAG(bool, short_types, true,
+          "Whether to show a shortened version of the type name");
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "\nCreates graph of nodes and message channels based on the robot config "
       "file.  \n\n"
       "To save to file, run as: \n"
@@ -38,13 +40,12 @@
   std::map<std::string, std::string> color_map;
 
   if (argc > 1) {
-    LOG(ERROR) << "ERROR: Got unexpected arguments\n\n";
-    gflags::ShowUsageWithFlagsRestrict(argv[0], "aos/aos_graph_nodes.cc");
+    LOG(ERROR) << "ERROR: Got unexpected arguments";
     return -1;
   }
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   const aos::Configuration *config_msg = &config.message();
   aos::ShmEventLoop event_loop(config_msg);
@@ -57,10 +58,10 @@
 
   for (const aos::Channel *channel : *config_msg->channels()) {
     VLOG(1) << "Found channel " << channel->type()->string_view();
-    if (FLAGS_all || aos::configuration::ChannelIsReadableOnNode(
-                         channel, event_loop.node())) {
+    if (absl::GetFlag(FLAGS_all) || aos::configuration::ChannelIsReadableOnNode(
+                                        channel, event_loop.node())) {
       flatbuffers::string_view type_name = channel->type()->string_view();
-      if (FLAGS_short_types) {
+      if (absl::GetFlag(FLAGS_short_types)) {
         // Strip down to just the top level of the message type
         type_name = channel->type()->string_view().substr(
             channel->type()->string_view().rfind(".") + 1, std::string::npos);
diff --git a/aos/aos_jitter.cc b/aos/aos_jitter.cc
index 5f23935..82a79ea 100644
--- a/aos/aos_jitter.cc
+++ b/aos/aos_jitter.cc
@@ -3,7 +3,8 @@
 #include <iomanip>
 #include <iostream>  // IWYU pragma: keep
 
-#include "gflags/gflags.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
 
 #include "aos/aos_cli_utils.h"
 #include "aos/configuration.h"
@@ -12,15 +13,15 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/realtime.h"
 
-DEFINE_int32(priority, -1, "If set, the RT priority to run at.");
-DEFINE_double(max_jitter, 0.01,
-              "The max time in milliseconds between messages before marking it "
-              "as too late.");
-DEFINE_bool(print_jitter, true,
-            "If true, print jitter events.  These will impact RT performance.");
-DECLARE_bool(enable_ftrace);
-DEFINE_bool(print_latency_stats, false,
-            "If true, print latency stats.  These will impact RT performance.");
+ABSL_FLAG(int32_t, priority, -1, "If set, the RT priority to run at.");
+ABSL_FLAG(double, max_jitter, 0.01,
+          "The max time in milliseconds between messages before marking it "
+          "as too late.");
+ABSL_FLAG(bool, print_jitter, true,
+          "If true, print jitter events.  These will impact RT performance.");
+ABSL_DECLARE_FLAG(bool, enable_ftrace);
+ABSL_FLAG(bool, print_latency_stats, false,
+          "If true, print latency stats.  These will impact RT performance.");
 
 namespace aos {
 
@@ -37,7 +38,7 @@
           HandleMessage(context, message);
         });
 
-    if (FLAGS_print_latency_stats) {
+    if (absl::GetFlag(FLAGS_print_latency_stats)) {
       timer_handle_ = event_loop->AddTimer([this]() { PrintLatencyStats(); });
       timer_handle_->set_name("jitter");
       event_loop->OnRun([this, event_loop]() {
@@ -54,8 +55,9 @@
                              .count());
       if (context.monotonic_event_time >
           last_time_ + std::chrono::duration_cast<std::chrono::nanoseconds>(
-                           std::chrono::duration<double>(FLAGS_max_jitter))) {
-        if (FLAGS_enable_ftrace) {
+                           std::chrono::duration<double>(
+                               absl::GetFlag(FLAGS_max_jitter)))) {
+        if (absl::GetFlag(FLAGS_enable_ftrace)) {
           ftrace_->FormatMessage(
               "Got high latency event on %s -> %.9f between messages",
               channel_name_.c_str(),
@@ -65,7 +67,7 @@
           ftrace_->TurnOffOrDie();
         }
 
-        if (FLAGS_print_jitter) {
+        if (absl::GetFlag(FLAGS_print_jitter)) {
           // Printing isn't realtime, but if someone wants to run as RT, they
           // should know this.  Bypass the warning.
           ScopedNotRealtime nrt;
@@ -138,8 +140,9 @@
         &ftrace, &(cli_info.event_loop.value()), channel));
   }
 
-  if (FLAGS_priority > 0) {
-    cli_info.event_loop->SetRuntimeRealtimePriority(FLAGS_priority);
+  if (absl::GetFlag(FLAGS_priority) > 0) {
+    cli_info.event_loop->SetRuntimeRealtimePriority(
+        absl::GetFlag(FLAGS_priority));
   }
 
   cli_info.event_loop->Run();
diff --git a/aos/aos_send.cc b/aos/aos_send.cc
index 8533f47..d95768f 100644
--- a/aos/aos_send.cc
+++ b/aos/aos_send.cc
@@ -3,18 +3,20 @@
 
 #include <iostream>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
+#include "absl/log/log.h"
 
 #include "aos/aos_cli_utils.h"
 #include "aos/configuration.h"
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_double(rate, -1, "Rate at which to send the message (-1 to send once).");
+ABSL_FLAG(double, rate, -1,
+          "Rate at which to send the message (-1 to send once).");
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Sends messages on arbitrary channels.\n"
       "Typical Usage: aos_send [--config path_to_config.json]"
       " channel_name message_type '{\"foo\": \"bar\"}'\n"
@@ -67,7 +69,7 @@
 
   fbb.Finish(msg_offset);
 
-  if (FLAGS_rate < 0) {
+  if (absl::GetFlag(FLAGS_rate) < 0) {
     sender->CheckOk(sender->Send(fbb.GetSize()));
   } else {
     cli_info.event_loop
@@ -76,7 +78,8 @@
         })
         ->Schedule(cli_info.event_loop->monotonic_now(),
                    std::chrono::duration_cast<std::chrono::nanoseconds>(
-                       std::chrono::duration<double>(1.0 / FLAGS_rate)));
+                       std::chrono::duration<double>(
+                           1.0 / absl::GetFlag(FLAGS_rate))));
     cli_info.event_loop->Run();
   }
 
diff --git a/aos/condition.cc b/aos/condition.cc
index f7860be..b293cb4 100644
--- a/aos/condition.cc
+++ b/aos/condition.cc
@@ -4,7 +4,8 @@
 #include <cinttypes>
 #include <ctime>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/mutex/mutex.h"
 #include "aos/type_traits/type_traits.h"
diff --git a/aos/config_flattener.cc b/aos/config_flattener.cc
index b623426..2685076 100644
--- a/aos/config_flattener.cc
+++ b/aos/config_flattener.cc
@@ -1,21 +1,21 @@
 #include <string>
 #include <vector>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 #include "aos/util/file.h"
 
-DEFINE_string(full_output, "",
-              "If provided, the path to write the full json configuration to.");
-DEFINE_string(
-    stripped_output, "",
-    "If provided, the path to write the stripped json configuration to.");
-DEFINE_string(
-    binary_output, "",
+ABSL_FLAG(std::string, full_output, "",
+          "If provided, the path to write the full json configuration to.");
+ABSL_FLAG(std::string, stripped_output, "",
+          "If provided, the path to write the stripped json configuration to.");
+ABSL_FLAG(
+    std::string, binary_output, "",
     "If provided, the path to write the binary flatbuffer configuration to.");
 
 namespace aos {
@@ -67,16 +67,18 @@
   // TODO(austin): Figure out how to squash the schemas onto 1 line so it is
   // easier to read?
   VLOG(1) << "Flattened config is " << merged_config_json;
-  if (!FLAGS_full_output.empty()) {
-    util::WriteStringToFileOrDie(FLAGS_full_output, merged_config_json);
+  if (!absl::GetFlag(FLAGS_full_output).empty()) {
+    util::WriteStringToFileOrDie(absl::GetFlag(FLAGS_full_output),
+                                 merged_config_json);
   }
-  if (!FLAGS_stripped_output.empty()) {
+  if (!absl::GetFlag(FLAGS_stripped_output).empty()) {
     util::WriteStringToFileOrDie(
-        FLAGS_stripped_output,
+        absl::GetFlag(FLAGS_stripped_output),
         FlatbufferToJson(&config.message(), {.multi_line = true}));
   }
-  if (!FLAGS_binary_output.empty()) {
-    aos::WriteFlatbufferToFile(FLAGS_binary_output, merged_config);
+  if (!absl::GetFlag(FLAGS_binary_output).empty()) {
+    aos::WriteFlatbufferToFile(absl::GetFlag(FLAGS_binary_output),
+                               merged_config);
   }
   return 0;
 }
diff --git a/aos/configuration.cc b/aos/configuration.cc
index 3b52e0c..fd446c2 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -16,11 +16,12 @@
 
 #include "absl/container/btree_map.h"
 #include "absl/container/btree_set.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/str_split.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration_generated.h"
 #include "aos/flatbuffer_merge.h"
@@ -30,11 +31,11 @@
 #include "aos/unique_malloc_ptr.h"
 #include "aos/util/file.h"
 
-DEFINE_uint32(max_queue_size_override, 0,
-              "If nonzero, this is the max number of elements in a queue to "
-              "enforce.  If zero, use the number that the processor that this "
-              "application is compiled for can support.  This is mostly useful "
-              "for config validation, and shouldn't be touched.");
+ABSL_FLAG(uint32_t, max_queue_size_override, 0,
+          "If nonzero, this is the max number of elements in a queue to "
+          "enforce.  If zero, use the number that the processor that this "
+          "application is compiled for can support.  This is mostly useful "
+          "for config validation, and shouldn't be touched.");
 
 namespace aos {
 namespace configuration {
@@ -1007,8 +1008,8 @@
       }
 
       CHECK_LT(QueueSize(&config.message(), c) + QueueScratchBufferSize(c),
-               FLAGS_max_queue_size_override != 0
-                   ? FLAGS_max_queue_size_override
+               absl::GetFlag(FLAGS_max_queue_size_override) != 0
+                   ? absl::GetFlag(FLAGS_max_queue_size_override)
                    : std::numeric_limits<
                          ipc_lib::QueueIndex::PackedIndexType>::max())
           << ": More messages/second configured than the queue can hold on "
@@ -1535,9 +1536,10 @@
 }
 
 const Node *GetMyNode(const Configuration *config) {
-  const std::string hostname = (FLAGS_override_hostname.size() > 0)
-                                   ? FLAGS_override_hostname
-                                   : network::GetHostname();
+  const std::string hostname =
+      (absl::GetFlag(FLAGS_override_hostname).size() > 0)
+          ? absl::GetFlag(FLAGS_override_hostname)
+          : network::GetHostname();
   const Node *node = GetNodeFromHostname(config, hostname);
   if (node != nullptr) return node;
 
diff --git a/aos/configuration_test.cc b/aos/configuration_test.cc
index d980dad..556fea9 100644
--- a/aos/configuration_test.cc
+++ b/aos/configuration_test.cc
@@ -1,8 +1,9 @@
 #include "aos/configuration.h"
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/strip.h"
 #include "flatbuffers/reflection.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
diff --git a/aos/containers/BUILD b/aos/containers/BUILD
index c0b365c..8da9218 100644
--- a/aos/containers/BUILD
+++ b/aos/containers/BUILD
@@ -17,7 +17,8 @@
     deps = [
         ":ring_buffer",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -61,6 +62,7 @@
         ":inlined_vector",
         "//aos:realtime",
         "//aos/testing:googletest",
+        "@com_google_absl//absl/flags:reflection",
     ],
 )
 
@@ -117,7 +119,8 @@
     ],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/containers/inlined_vector_test.cc b/aos/containers/inlined_vector_test.cc
index b8aab6b..d2d9af6 100644
--- a/aos/containers/inlined_vector_test.cc
+++ b/aos/containers/inlined_vector_test.cc
@@ -1,19 +1,21 @@
 #include "aos/containers/inlined_vector.h"
 
-#include "gflags/gflags.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
 #include "gtest/gtest.h"
 
 #include "aos/realtime.h"
 
-DECLARE_bool(die_on_malloc);
+ABSL_DECLARE_FLAG(bool, die_on_malloc);
 
 namespace aos::testing {
 
 // Checks that we don't malloc until/unless we need to increase the size of the
 // vector.
 TEST(SizedArrayTest, NoUnnecessaryMalloc) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_die_on_malloc = true;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_die_on_malloc, true);
   RegisterMallocHook();
   InlinedVector<int, 5> a;
   {
diff --git a/aos/containers/resizeable_buffer.h b/aos/containers/resizeable_buffer.h
index 1af888d..db4a102 100644
--- a/aos/containers/resizeable_buffer.h
+++ b/aos/containers/resizeable_buffer.h
@@ -8,7 +8,8 @@
 #include <cstdlib>
 #include <memory>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 
diff --git a/aos/containers/ring_buffer_test.cc b/aos/containers/ring_buffer_test.cc
index b7b0f17..ed388f3 100644
--- a/aos/containers/ring_buffer_test.cc
+++ b/aos/containers/ring_buffer_test.cc
@@ -3,7 +3,8 @@
 #include <memory>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 namespace aos::testing {
diff --git a/aos/containers/sized_array_test.cc b/aos/containers/sized_array_test.cc
index 5fc4b38..8813370 100644
--- a/aos/containers/sized_array_test.cc
+++ b/aos/containers/sized_array_test.cc
@@ -174,7 +174,7 @@
   // Verify that we didn't reallocate
   EXPECT_EQ(pre_front, a.data());
 
-  EXPECT_DEATH(a.emplace_back(5), "Aborted at");
+  EXPECT_DEATH(a.emplace_back(5), "SIGILL received at");
 }
 
 // Tests inserting at various positions in the array.
diff --git a/aos/dump_rtprio.cc b/aos/dump_rtprio.cc
index 74ade74..4ea540d 100644
--- a/aos/dump_rtprio.cc
+++ b/aos/dump_rtprio.cc
@@ -19,14 +19,17 @@
 #include <set>
 #include <string>
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/time/time.h"
 #include "aos/util/top.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
 
 namespace {
 
@@ -253,7 +256,7 @@
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
   event_loop.SkipTimingReport();
diff --git a/aos/events/BUILD b/aos/events/BUILD
index c61b3e5..c49655a 100644
--- a/aos/events/BUILD
+++ b/aos/events/BUILD
@@ -65,7 +65,8 @@
     visibility = ["//visibility:public"],
     deps = [
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -76,7 +77,8 @@
     deps = [
         ":epoll",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -196,7 +198,8 @@
         ":simulated_event_loop",
         "//aos/testing:googletest",
         "//aos/testing:path",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -214,7 +217,8 @@
         ":ping_fbs",
         ":pong_fbs",
         "//aos:json_to_flatbuffer",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -231,7 +235,8 @@
         "//aos:configuration",
         "//aos:init",
         "//aos:json_to_flatbuffer",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -379,7 +384,8 @@
         ":event_loop",
         ":ping_fbs",
         ":pong_fbs",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -398,7 +404,8 @@
         "//aos:configuration",
         "//aos:init",
         "//aos:json_to_flatbuffer",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -430,7 +437,8 @@
         ":event_loop_fbs",
         "//aos:configuration",
         "//aos/util:error_counter",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -535,7 +543,8 @@
     deps = [
         "//aos:configuration_fbs",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -664,7 +673,8 @@
         ":simulated_event_loop",
         "//aos/network:testing_time_converter",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -707,7 +717,8 @@
     deps = [
         "//aos/events:shm_event_loop",
         "//third_party:gstreamer",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -726,7 +737,8 @@
         "//aos/testing:googletest",
         "//aos/testing:path",
         "//third_party:gstreamer",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/events/aos_timing_report_streamer.cc b/aos/events/aos_timing_report_streamer.cc
index 58b44e6..fdf468d 100644
--- a/aos/events/aos_timing_report_streamer.cc
+++ b/aos/events/aos_timing_report_streamer.cc
@@ -1,4 +1,4 @@
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/configuration.h"
 #include "aos/events/shm_event_loop.h"
@@ -6,27 +6,30 @@
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_string(config, "aos_config.json", "The path to the config to use.");
-DEFINE_string(application, "",
-              "Application filter to use. Empty for no filter.");
-DEFINE_bool(stream, true, "Stream out all the timing reports that we receive.");
-DEFINE_bool(accumulate, true,
-            "Display accumulation of all timing reports that we've seen when "
-            "the process is terminated.");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "The path to the config to use.");
+ABSL_FLAG(std::string, application, "",
+          "Application filter to use. Empty for no filter.");
+ABSL_FLAG(bool, stream, true,
+          "Stream out all the timing reports that we receive.");
+ABSL_FLAG(bool, accumulate, true,
+          "Display accumulation of all timing reports that we've seen when "
+          "the process is terminated.");
 
 namespace aos {
 int Main() {
   aos::FlatbufferVector<aos::Configuration> config(
-      aos::configuration::ReadConfig(FLAGS_config));
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config)));
   ShmEventLoop event_loop(&config.message());
   TimingReportDump dumper(&event_loop,
-                          FLAGS_accumulate
+                          absl::GetFlag(FLAGS_accumulate)
                               ? TimingReportDump::AccumulateStatistics::kYes
                               : TimingReportDump::AccumulateStatistics::kNo,
-                          FLAGS_stream ? TimingReportDump::StreamResults::kYes
-                                       : TimingReportDump::StreamResults::kNo);
-  if (!FLAGS_application.empty()) {
-    dumper.ApplicationFilter(FLAGS_application);
+                          absl::GetFlag(FLAGS_stream)
+                              ? TimingReportDump::StreamResults::kYes
+                              : TimingReportDump::StreamResults::kNo);
+  if (!absl::GetFlag(FLAGS_application).empty()) {
+    dumper.ApplicationFilter(absl::GetFlag(FLAGS_application));
   }
   event_loop.Run();
   return EXIT_SUCCESS;
diff --git a/aos/events/epoll.cc b/aos/events/epoll.cc
index d5f5162..2a266d6 100644
--- a/aos/events/epoll.cc
+++ b/aos/events/epoll.cc
@@ -17,7 +17,8 @@
 #include <utility>
 #include <vector>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/time/time.h"
 
diff --git a/aos/events/epoll_test.cc b/aos/events/epoll_test.cc
index e1be563..83139f0 100644
--- a/aos/events/epoll_test.cc
+++ b/aos/events/epoll_test.cc
@@ -3,7 +3,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 namespace aos::internal::testing {
diff --git a/aos/events/event_loop.cc b/aos/events/event_loop.cc
index 424971d..212bc45 100644
--- a/aos/events/event_loop.cc
+++ b/aos/events/event_loop.cc
@@ -1,15 +1,17 @@
 #include "aos/events/event_loop.h"
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/configuration_generated.h"
 #include "aos/logging/implementations.h"
 #include "aos/realtime.h"
 
-DEFINE_bool(timing_reports, true, "Publish timing reports.");
-DEFINE_int32(timing_report_ms, 1000,
-             "Period in milliseconds to publish timing reports at.");
+ABSL_FLAG(bool, timing_reports, true, "Publish timing reports.");
+ABSL_FLAG(int32_t, timing_report_ms, 1000,
+          "Period in milliseconds to publish timing reports at.");
 
 namespace aos {
 namespace {
@@ -157,7 +159,9 @@
 EventLoop::EventLoop(const Configuration *configuration)
     : version_string_(default_version_string_),
       timing_report_(flatbuffers::DetachedBuffer()),
-      configuration_(configuration) {}
+      configuration_(configuration) {
+  CHECK(configuration != nullptr);
+}
 
 EventLoop::~EventLoop() {
   if (!senders_.empty()) {
@@ -545,7 +549,7 @@
 }
 
 void EventLoop::MaybeScheduleTimingReports() {
-  if (FLAGS_timing_reports && !skip_timing_report_) {
+  if (absl::GetFlag(FLAGS_timing_reports) && !skip_timing_report_) {
     CHECK(!timing_report_sender_) << ": Timing reports already scheduled.";
     // Make a raw sender for the report.
     const Channel *channel = configuration::GetChannel(
@@ -578,8 +582,9 @@
     timing_reports_timer->set_name("timing_reports");
     OnRun([this, timing_reports_timer]() {
       timing_reports_timer->Schedule(
-          monotonic_now() + std::chrono::milliseconds(FLAGS_timing_report_ms),
-          std::chrono::milliseconds(FLAGS_timing_report_ms));
+          monotonic_now() +
+              std::chrono::milliseconds(absl::GetFlag(FLAGS_timing_report_ms)),
+          std::chrono::milliseconds(absl::GetFlag(FLAGS_timing_report_ms)));
     });
 
     UpdateTimingReport();
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index c8cf487..891d5c8 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -8,8 +8,10 @@
 #include <string_view>
 
 #include "absl/container/btree_set.h"
+#include "absl/flags/declare.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 #include "tl/expected.hpp"
 
 #include "aos/configuration.h"
@@ -30,8 +32,8 @@
 #include "aos/util/status.h"
 #include "aos/uuid.h"
 
-DECLARE_bool(timing_reports);
-DECLARE_int32(timing_report_ms);
+ABSL_DECLARE_FLAG(bool, timing_reports);
+ABSL_DECLARE_FLAG(int32_t, timing_report_ms);
 
 namespace aos {
 
diff --git a/aos/events/event_loop_event.h b/aos/events/event_loop_event.h
index 4d1ff07..6e823f0 100644
--- a/aos/events/event_loop_event.h
+++ b/aos/events/event_loop_event.h
@@ -5,7 +5,8 @@
 
 #include <chrono>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/time/time.h"
 
diff --git a/aos/events/event_loop_param_test.cc b/aos/events/event_loop_param_test.cc
index 4975540..1e6b3a4 100644
--- a/aos/events/event_loop_param_test.cc
+++ b/aos/events/event_loop_param_test.cc
@@ -5,7 +5,10 @@
 #include <unordered_map>
 #include <unordered_set>
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -1458,7 +1461,8 @@
 // Verify that timer intervals and duration function properly.
 TEST_P(AbstractEventLoopTest, TimerIntervalAndDuration) {
   // Force a slower rate so we are guaranteed to have reports for our timer.
-  FLAGS_timing_report_ms = 2000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 2000);
 
   const int kCount = 5;
 
@@ -1586,8 +1590,8 @@
 // Test that setting a default version string results in it getting populated
 // correctly.
 TEST_P(AbstractEventLoopTest, DefaultVersionStringInTimingReport) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_timing_report_ms = 1000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
 
   EventLoop::SetDefaultVersionString("default_version_string");
 
@@ -1625,8 +1629,8 @@
 // Test that overriding the default version string results in it getting
 // populated correctly.
 TEST_P(AbstractEventLoopTest, OverrideDersionStringInTimingReport) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_timing_report_ms = 1000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
 
   EventLoop::SetDefaultVersionString("default_version_string");
 
@@ -2101,7 +2105,8 @@
 TEST_P(AbstractEventLoopTest, PhasedLoopTest) {
   // Force a slower rate so we are guaranteed to have reports for our phased
   // loop.
-  FLAGS_timing_report_ms = 2000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 2000);
 
   const chrono::milliseconds kOffset = chrono::milliseconds(400);
   const int kCount = 5;
@@ -2237,7 +2242,8 @@
 TEST_P(AbstractEventLoopTest, PhasedLoopChangingOffsetTest) {
   // Force a slower rate so we are guaranteed to have reports for our phased
   // loop.
-  FLAGS_timing_report_ms = 2000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 2000);
 
   const chrono::milliseconds kOffset = chrono::milliseconds(400);
   const chrono::milliseconds kInterval = chrono::milliseconds(1000);
@@ -2624,7 +2630,8 @@
 
 // Tests that senders count correctly in the timing report.
 TEST_P(AbstractEventLoopTest, SenderTimingReport) {
-  FLAGS_timing_report_ms = 1000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = MakePrimary();
 
   auto loop2 = Make("watcher_loop");
@@ -2745,8 +2752,8 @@
 // Tests that the RawSender::Send(void*, size_t) overload tracks things properly
 // in its timing report.
 TEST_P(AbstractEventLoopTest, CopySenderTimingReport) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_timing_report_ms = 1000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = Make();
   auto loop2 = MakePrimary();
 
@@ -2801,8 +2808,8 @@
 
 // Tests that the RawSender::Send(SharedSpan) overload works.
 TEST_P(AbstractEventLoopTest, SharedSenderTimingReport) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_timing_report_ms = 1000;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = Make();
   auto loop2 = MakePrimary();
 
@@ -2863,7 +2870,7 @@
 
 // Tests that senders count correctly in the timing report.
 TEST_P(AbstractEventLoopTest, WatcherTimingReport) {
-  FLAGS_timing_report_ms = 1000;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = MakePrimary();
   loop1->MakeWatcher("/test", [](const TestMessage &) {});
 
@@ -2930,7 +2937,7 @@
 
 // Tests that fetchers count correctly in the timing report.
 TEST_P(AbstractEventLoopTest, FetcherTimingReport) {
-  FLAGS_timing_report_ms = 1000;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = MakePrimary();
   auto loop2 = Make("sender_loop");
 
diff --git a/aos/events/event_loop_runtime_test.cc b/aos/events/event_loop_runtime_test.cc
index 6bd4c70..a1c20eb 100644
--- a/aos/events/event_loop_runtime_test.cc
+++ b/aos/events/event_loop_runtime_test.cc
@@ -1,4 +1,5 @@
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/event_loop_runtime_test_lib_rs_cxxgen.h"
diff --git a/aos/events/event_loop_tmpl.h b/aos/events/event_loop_tmpl.h
index 25aa36c..a112b36 100644
--- a/aos/events/event_loop_tmpl.h
+++ b/aos/events/event_loop_tmpl.h
@@ -5,7 +5,8 @@
 #include <cstdint>
 #include <type_traits>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/event_loop.h"
 
diff --git a/aos/events/event_scheduler.h b/aos/events/event_scheduler.h
index 68fcf28..a9226df 100644
--- a/aos/events/event_scheduler.h
+++ b/aos/events/event_scheduler.h
@@ -8,7 +8,8 @@
 #include <utility>
 #include <vector>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/epoll.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/events/glib_main_loop.cc b/aos/events/glib_main_loop.cc
index bee8a81..b3bd2b3 100644
--- a/aos/events/glib_main_loop.cc
+++ b/aos/events/glib_main_loop.cc
@@ -1,6 +1,7 @@
 #include "aos/events/glib_main_loop.h"
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 namespace {
diff --git a/aos/events/glib_main_loop.h b/aos/events/glib_main_loop.h
index 080bc57..782043b 100644
--- a/aos/events/glib_main_loop.h
+++ b/aos/events/glib_main_loop.h
@@ -247,7 +247,7 @@
       signal_handler_id_(g_signal_connect(
           instance, detailed_signal,
           G_CALLBACK(&GlibSignalCallback::InvokeSignal), user_data())) {
-  CHECK_GT(signal_handler_id_, 0);
+  CHECK_GT(signal_handler_id_, 0u);
   VLOG(1) << this << " connected glib signal with " << user_data() << " as "
           << signal_handler_id_ << " on " << instance << ": "
           << detailed_signal;
diff --git a/aos/events/glib_main_loop_test.cc b/aos/events/glib_main_loop_test.cc
index 6fced6d..cd5c109 100644
--- a/aos/events/glib_main_loop_test.cc
+++ b/aos/events/glib_main_loop_test.cc
@@ -2,8 +2,9 @@
 
 #include <thread>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "glib-2.0/glib.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/configuration.h"
diff --git a/aos/events/logging/BUILD b/aos/events/logging/BUILD
index 2bb87b6..7df8823 100644
--- a/aos/events/logging/BUILD
+++ b/aos/events/logging/BUILD
@@ -81,9 +81,10 @@
         "//aos:init",
         "//aos:json_to_flatbuffer",
         "//aos/events:shm_event_loop",
-        "@com_github_gflags_gflags//:gflags",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -93,7 +94,8 @@
     hdrs = ["file_operations.h"],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -119,7 +121,9 @@
         ":file_operations",
         "//aos/time",
         "//aos/util:file",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:span",
     ],
@@ -135,7 +139,8 @@
         "//aos/containers:resizeable_buffer",
         "//aos/testing:googletest",
         "//aos/testing:tmpdir",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -195,9 +200,10 @@
         "//aos/events:event_loop",
         "//aos/network:remote_message_fbs",
         "//aos/util:file",
-        "@com_github_gflags_gflags//:gflags",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ] + select({
         "//tools:cpu_k8": [
@@ -220,8 +226,9 @@
     deps = [
         ":logfile_utils",
         "//aos:init",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -265,7 +272,8 @@
         "//aos/containers:resizeable_buffer",
         "//aos/time",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -281,7 +289,8 @@
         ":buffer_encoder",
         ":buffer_encoder_param_test",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -302,7 +311,8 @@
         "//aos/containers:resizeable_buffer",
         "//aos/util:crc32",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
         "@snappy",
     ],
@@ -319,7 +329,8 @@
         ":buffer_encoder_param_test",
         ":snappy_encoder",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -340,7 +351,9 @@
         "//aos/containers:resizeable_buffer",
         "//third_party:lzma",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -363,7 +376,8 @@
         "//aos/containers:resizeable_buffer",
         "@aws_sdk//:core",
         "@aws_sdk//:s3",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:span",
     ],
@@ -380,7 +394,9 @@
         ":buffer_encoder_param_test",
         ":lzma_encoder",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -399,7 +415,8 @@
         ":logger_fbs",
         "//aos/testing:googletest",
         "//aos/testing:random_seed",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -418,7 +435,8 @@
         "//aos/containers:error_list",
         "//aos/containers:sized_array",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -546,8 +564,9 @@
         "//aos:json_to_flatbuffer",
         "//aos:sha256",
         "//aos/events:simulated_event_loop",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -564,8 +583,9 @@
         "//aos:configuration",
         "//aos/events:simulated_event_loop",
         "//aos/network:multinode_timestamp_filter",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -583,8 +603,9 @@
         "//aos:init",
         "//aos/events:simulated_event_loop",
         "//aos/network:multinode_timestamp_filter",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -601,8 +622,9 @@
         "//aos:init",
         "//aos/events:simulated_event_loop",
         "//aos/network:multinode_timestamp_filter",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -618,8 +640,9 @@
         "//aos:init",
         "//aos:json_to_flatbuffer",
         "//aos/util:file",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -636,8 +659,9 @@
         "//aos:json_to_flatbuffer",
         "//aos/events:simulated_event_loop",
         "//aos/time",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -660,8 +684,9 @@
         "//aos:init",
         "//aos/events:shm_event_loop",
         "//aos/logging:log_namer",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -1009,8 +1034,9 @@
         "//aos:init",
         "//aos:json_to_flatbuffer",
         "//aos/events/logging:log_reader",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -1025,7 +1051,8 @@
         "//aos:init",
         "//aos/containers:resizeable_buffer",
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/events/logging/boot_timestamp.h b/aos/events/logging/boot_timestamp.h
index dc5967c..0440ea7 100644
--- a/aos/events/logging/boot_timestamp.h
+++ b/aos/events/logging/boot_timestamp.h
@@ -9,7 +9,8 @@
 #include <iostream>
 #include <limits>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/time/time.h"
 
diff --git a/aos/events/logging/buffer_encoder.cc b/aos/events/logging/buffer_encoder.cc
index b352d5d..b6350a5 100644
--- a/aos/events/logging/buffer_encoder.cc
+++ b/aos/events/logging/buffer_encoder.cc
@@ -4,7 +4,8 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/flatbuffers.h"
 
diff --git a/aos/events/logging/buffer_encoder.h b/aos/events/logging/buffer_encoder.h
index db09d32..5235d7b 100644
--- a/aos/events/logging/buffer_encoder.h
+++ b/aos/events/logging/buffer_encoder.h
@@ -1,9 +1,10 @@
 #ifndef AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_
 #define AOS_EVENTS_LOGGING_BUFFER_ENCODER_H_
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
 #include "aos/containers/resizeable_buffer.h"
 #include "aos/events/logging/logger_generated.h"
diff --git a/aos/events/logging/buffer_encoder_param_test.h b/aos/events/logging/buffer_encoder_param_test.h
index 8b6648d..7a05e98 100644
--- a/aos/events/logging/buffer_encoder_param_test.h
+++ b/aos/events/logging/buffer_encoder_param_test.h
@@ -6,7 +6,8 @@
 #include <random>
 #include <vector>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/logging/logfile_utils.h"
diff --git a/aos/events/logging/buffer_encoder_test.cc b/aos/events/logging/buffer_encoder_test.cc
index 127fb4f..69dd7de 100644
--- a/aos/events/logging/buffer_encoder_test.cc
+++ b/aos/events/logging/buffer_encoder_test.cc
@@ -4,7 +4,8 @@
 #include <fstream>
 #include <string>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
diff --git a/aos/events/logging/config_remapper.cc b/aos/events/logging/config_remapper.cc
index 088d393..763cbc3 100644
--- a/aos/events/logging/config_remapper.cc
+++ b/aos/events/logging/config_remapper.cc
@@ -2,6 +2,8 @@
 
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/escaping.h"
 #include "flatbuffers/flatbuffers.h"
 
diff --git a/aos/events/logging/file_operations.cc b/aos/events/logging/file_operations.cc
index d54c8b6..abd9942 100644
--- a/aos/events/logging/file_operations.cc
+++ b/aos/events/logging/file_operations.cc
@@ -3,8 +3,9 @@
 #include <algorithm>
 #include <ostream>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/match.h"
-#include "glog/logging.h"
 
 namespace aos::logger::internal {
 
diff --git a/aos/events/logging/log_backend.cc b/aos/events/logging/log_backend.cc
index f8a6846..d2f0d77 100644
--- a/aos/events/logging/log_backend.cc
+++ b/aos/events/logging/log_backend.cc
@@ -4,19 +4,21 @@
 
 #include <filesystem>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
-#include "glog/logging.h"
 
 #include "aos/events/logging/file_operations.h"
 #include "aos/util/file.h"
 
-DEFINE_bool(
-    sync, false,
+ABSL_FLAG(
+    bool, sync, false,
     "If true, sync data to disk as we go so we don't get too far ahead.  Also "
     "fadvise that we are done with the memory once it hits disk.");
 
-DEFINE_uint32(queue_reserve, 32, "Pre-reserved size of write queue.");
+ABSL_FLAG(uint32_t, queue_reserve, 32, "Pre-reserved size of write queue.");
 
 namespace aos::logger {
 namespace {
@@ -42,7 +44,7 @@
 }  // namespace
 
 logger::QueueAligner::QueueAligner() {
-  aligned_queue_.reserve(FLAGS_queue_reserve);
+  aligned_queue_.reserve(absl::GetFlag(FLAGS_queue_reserve));
 }
 
 void logger::QueueAligner::FillAlignedQueue(
@@ -285,7 +287,7 @@
     return WriteCode::kOutOfSpace;
   }
 
-  if (FLAGS_sync) {
+  if (absl::GetFlag(FLAGS_sync)) {
     // Flush asynchronously and force the data out of the cache.
     sync_file_range(fd_, total_write_bytes_, written, SYNC_FILE_RANGE_WRITE);
     if (last_synced_bytes_ != 0) {
diff --git a/aos/events/logging/log_backend_test.cc b/aos/events/logging/log_backend_test.cc
index 0603b33..fc29979 100644
--- a/aos/events/logging/log_backend_test.cc
+++ b/aos/events/logging/log_backend_test.cc
@@ -5,9 +5,10 @@
 #include <fstream>
 #include <random>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
diff --git a/aos/events/logging/log_cat.cc b/aos/events/logging/log_cat.cc
index d7347be..38a9136 100644
--- a/aos/events/logging/log_cat.cc
+++ b/aos/events/logging/log_cat.cc
@@ -6,8 +6,9 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 #include "absl/strings/escaping.h"
-#include "gflags/gflags.h"
 
 #include "aos/aos_cli_utils.h"
 #include "aos/configuration.h"
@@ -17,52 +18,52 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/sha256.h"
 
-DEFINE_string(
-    name, "",
+ABSL_FLAG(
+    std::string, name, "",
     "Name to match for printing out channels. Empty means no name filter.");
-DEFINE_string(type, "",
-              "Channel type to match for printing out channels. Empty means no "
-              "type filter.");
-DEFINE_bool(json, false, "If true, print fully valid JSON");
-DEFINE_bool(fetch, false,
-            "If true, also print out the messages from before the start of the "
-            "log file");
-DEFINE_bool(raw, false,
-            "If true, just print the data out unsorted and unparsed");
-DEFINE_string(raw_header, "",
-              "If set, the file to read the header from in raw mode");
-DEFINE_bool(distributed_clock, false,
-            "If true, print out the distributed time");
-DEFINE_bool(format_raw, true,
-            "If true and --raw is specified, print out raw data, but use the "
-            "schema to format the data.");
-DEFINE_int64(max_vector_size, 100,
-             "If positive, vectors longer than this will not be printed");
-DEFINE_bool(pretty, false,
-            "If true, pretty print the messages on multiple lines");
-DEFINE_bool(
-    pretty_max, false,
+ABSL_FLAG(std::string, type, "",
+          "Channel type to match for printing out channels. Empty means no "
+          "type filter.");
+ABSL_FLAG(bool, json, false, "If true, print fully valid JSON");
+ABSL_FLAG(bool, fetch, false,
+          "If true, also print out the messages from before the start of the "
+          "log file");
+ABSL_FLAG(bool, raw, false,
+          "If true, just print the data out unsorted and unparsed");
+ABSL_FLAG(std::string, raw_header, "",
+          "If set, the file to read the header from in raw mode");
+ABSL_FLAG(bool, distributed_clock, false,
+          "If true, print out the distributed time");
+ABSL_FLAG(bool, format_raw, true,
+          "If true and --raw is specified, print out raw data, but use the "
+          "schema to format the data.");
+ABSL_FLAG(int64_t, max_vector_size, 100,
+          "If positive, vectors longer than this will not be printed");
+ABSL_FLAG(bool, pretty, false,
+          "If true, pretty print the messages on multiple lines");
+ABSL_FLAG(
+    bool, pretty_max, false,
     "If true, expand every field to its own line (expands more than -pretty)");
-DEFINE_bool(print_timestamps, true, "If true, timestamps are printed.");
-DEFINE_bool(print, true,
-            "If true, actually print the messages.  If false, discard them, "
-            "confirming they can be parsed.");
-DEFINE_uint64(
-    count, 0,
+ABSL_FLAG(bool, print_timestamps, true, "If true, timestamps are printed.");
+ABSL_FLAG(bool, print, true,
+          "If true, actually print the messages.  If false, discard them, "
+          "confirming they can be parsed.");
+ABSL_FLAG(
+    uint64_t, count, 0,
     "If >0, log_cat will exit after printing this many messages.  This "
     "includes messages from before the start of the log if --fetch is set.");
-DEFINE_bool(print_parts_only, false,
-            "If true, only print out the results of logfile sorting.");
-DEFINE_bool(channels, false,
-            "If true, print out all the configured channels for this log.");
-DEFINE_double(monotonic_start_time, 0.0,
-              "If set, only print messages sent at or after this many seconds "
-              "after epoch.");
-DEFINE_double(monotonic_end_time, 0.0,
-              "If set, only print messages sent at or before this many seconds "
-              "after epoch.");
-DEFINE_bool(hex, false,
-            "Are integers in the messages printed in hex notation.");
+ABSL_FLAG(bool, print_parts_only, false,
+          "If true, only print out the results of logfile sorting.");
+ABSL_FLAG(bool, channels, false,
+          "If true, print out all the configured channels for this log.");
+ABSL_FLAG(double, monotonic_start_time, 0.0,
+          "If set, only print messages sent at or after this many seconds "
+          "after epoch.");
+ABSL_FLAG(double, monotonic_end_time, 0.0,
+          "If set, only print messages sent at or before this many seconds "
+          "after epoch.");
+ABSL_FLAG(bool, hex, false,
+          "Are integers in the messages printed in hex notation.");
 
 using aos::monotonic_clock;
 namespace chrono = std::chrono;
@@ -70,12 +71,14 @@
 // Prints out raw log parts to stdout.
 int PrintRaw(int argc, char **argv) {
   if (argc == 1) {
-    CHECK(!FLAGS_raw_header.empty());
-    aos::logger::MessageReader raw_header_reader(FLAGS_raw_header);
-    std::cout << aos::FlatbufferToJson(raw_header_reader.raw_log_file_header(),
-                                       {.multi_line = FLAGS_pretty,
-                                        .max_vector_size = static_cast<size_t>(
-                                            FLAGS_max_vector_size)})
+    CHECK(!absl::GetFlag(FLAGS_raw_header).empty());
+    aos::logger::MessageReader raw_header_reader(
+        absl::GetFlag(FLAGS_raw_header));
+    std::cout << aos::FlatbufferToJson(
+                     raw_header_reader.raw_log_file_header(),
+                     {.multi_line = absl::GetFlag(FLAGS_pretty),
+                      .max_vector_size = static_cast<size_t>(
+                          absl::GetFlag(FLAGS_max_vector_size))})
               << std::endl;
     return 0;
   }
@@ -108,9 +111,10 @@
         maybe_header_data);
     if (maybe_header.Verify()) {
       std::cout << aos::FlatbufferToJson(
-                       log_file_header, {.multi_line = FLAGS_pretty,
-                                         .max_vector_size = static_cast<size_t>(
-                                             FLAGS_max_vector_size)})
+                       log_file_header,
+                       {.multi_line = absl::GetFlag(FLAGS_pretty),
+                        .max_vector_size = static_cast<size_t>(
+                            absl::GetFlag(FLAGS_max_vector_size))})
                 << std::endl;
       LOG(WARNING) << "Found duplicate LogFileHeader in " << reader.filename();
       log_file_header =
@@ -126,26 +130,26 @@
   // And now use the final sha256 to match the raw_header.
   std::optional<aos::logger::MessageReader> raw_header_reader;
   const aos::logger::LogFileHeader *full_header = &log_file_header.message();
-  if (!FLAGS_raw_header.empty()) {
-    raw_header_reader.emplace(FLAGS_raw_header);
-    std::cout << aos::FlatbufferToJson(full_header,
-                                       {.multi_line = FLAGS_pretty,
-                                        .max_vector_size = static_cast<size_t>(
-                                            FLAGS_max_vector_size)})
+  if (!absl::GetFlag(FLAGS_raw_header).empty()) {
+    raw_header_reader.emplace(absl::GetFlag(FLAGS_raw_header));
+    std::cout << aos::FlatbufferToJson(
+                     full_header, {.multi_line = absl::GetFlag(FLAGS_pretty),
+                                   .max_vector_size = static_cast<size_t>(
+                                       absl::GetFlag(FLAGS_max_vector_size))})
               << std::endl;
     CHECK_EQ(full_header->configuration_sha256()->string_view(),
              aos::Sha256(raw_header_reader->raw_log_file_header().span()));
     full_header = raw_header_reader->log_file_header();
   }
 
-  if (!FLAGS_print) {
+  if (!absl::GetFlag(FLAGS_print)) {
     return 0;
   }
 
-  std::cout << aos::FlatbufferToJson(full_header,
-                                     {.multi_line = FLAGS_pretty,
-                                      .max_vector_size = static_cast<size_t>(
-                                          FLAGS_max_vector_size)})
+  std::cout << aos::FlatbufferToJson(
+                   full_header, {.multi_line = absl::GetFlag(FLAGS_pretty),
+                                 .max_vector_size = static_cast<size_t>(
+                                     absl::GetFlag(FLAGS_max_vector_size))})
             << std::endl;
   CHECK(full_header->has_configuration())
       << ": Missing configuration! You may want to provide the path to the "
@@ -178,21 +182,25 @@
           << channel->type()->c_str();
     }
 
-    if (FLAGS_format_raw && message.message().data() != nullptr) {
+    if (absl::GetFlag(FLAGS_format_raw) &&
+        message.message().data() != nullptr) {
       std::cout << aos::configuration::StrippedChannelToString(channel) << " "
-                << aos::FlatbufferToJson(message, {.multi_line = FLAGS_pretty,
-                                                   .max_vector_size = 4})
+                << aos::FlatbufferToJson(
+                       message, {.multi_line = absl::GetFlag(FLAGS_pretty),
+                                 .max_vector_size = 4})
                 << ": "
                 << aos::FlatbufferToJson(
                        channel->schema(), message.message().data()->data(),
-                       {FLAGS_pretty,
-                        static_cast<size_t>(FLAGS_max_vector_size)})
+                       {absl::GetFlag(FLAGS_pretty),
+                        static_cast<size_t>(
+                            absl::GetFlag(FLAGS_max_vector_size))})
                 << std::endl;
     } else {
       std::cout << aos::configuration::StrippedChannelToString(channel) << " "
                 << aos::FlatbufferToJson(
-                       message, {FLAGS_pretty,
-                                 static_cast<size_t>(FLAGS_max_vector_size)})
+                       message, {absl::GetFlag(FLAGS_pretty),
+                                 static_cast<size_t>(
+                                     absl::GetFlag(FLAGS_max_vector_size))})
                 << std::endl;
     }
   }
@@ -219,26 +227,26 @@
         event_loop_->configuration()->channels();
 
     const monotonic_clock::time_point start_time =
-        (FLAGS_monotonic_start_time == 0.0
+        (absl::GetFlag(FLAGS_monotonic_start_time) == 0.0
              ? monotonic_clock::min_time
              : monotonic_clock::time_point(
                    std::chrono::duration_cast<monotonic_clock::duration>(
                        std::chrono::duration<double>(
-                           FLAGS_monotonic_start_time))));
+                           absl::GetFlag(FLAGS_monotonic_start_time)))));
     const monotonic_clock::time_point end_time =
-        (FLAGS_monotonic_end_time == 0.0
+        (absl::GetFlag(FLAGS_monotonic_end_time) == 0.0
              ? monotonic_clock::max_time
              : monotonic_clock::time_point(
                    std::chrono::duration_cast<monotonic_clock::duration>(
                        std::chrono::duration<double>(
-                           FLAGS_monotonic_end_time))));
+                           absl::GetFlag(FLAGS_monotonic_end_time)))));
 
     for (flatbuffers::uoffset_t i = 0; i < channels->size(); i++) {
       const aos::Channel *channel = channels->Get(i);
       const flatbuffers::string_view name = channel->name()->string_view();
       const flatbuffers::string_view type = channel->type()->string_view();
-      if (name.find(FLAGS_name) != std::string::npos &&
-          type.find(FLAGS_type) != std::string::npos) {
+      if (name.find(absl::GetFlag(FLAGS_name)) != std::string::npos &&
+          type.find(absl::GetFlag(FLAGS_type)) != std::string::npos) {
         if (!aos::configuration::ChannelIsReadableOnNode(channel,
                                                          event_loop_->node())) {
           continue;
@@ -250,14 +258,15 @@
                                               end_time](
                                                  const aos::Context &context,
                                                  const void * /*message*/) {
-          if (!FLAGS_print) {
+          if (!absl::GetFlag(FLAGS_print)) {
             return;
           }
-          if (FLAGS_count > 0 && printer_->message_count() >= FLAGS_count) {
+          if (absl::GetFlag(FLAGS_count) > 0 &&
+              printer_->message_count() >= absl::GetFlag(FLAGS_count)) {
             return;
           }
 
-          if (!FLAGS_fetch && !started_) {
+          if (!absl::GetFlag(FLAGS_fetch) && !started_) {
             return;
           }
 
@@ -267,7 +276,8 @@
           }
 
           printer_->PrintMessage(node_name_, node_factory_, channel, context);
-          if (FLAGS_count > 0 && printer_->message_count() >= FLAGS_count) {
+          if (absl::GetFlag(FLAGS_count) > 0 &&
+              printer_->message_count() >= absl::GetFlag(FLAGS_count)) {
             factory_->Exit();
           }
         });
@@ -278,7 +288,7 @@
   void SetStarted(bool started, aos::monotonic_clock::time_point monotonic_now,
                   aos::realtime_clock::time_point realtime_now) {
     started_ = started;
-    if (FLAGS_json) {
+    if (absl::GetFlag(FLAGS_json)) {
       return;
     }
     if (started_) {
@@ -318,7 +328,7 @@
 };
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Usage:\n"
       "  log_cat [args] logfile1 logfile2 ...\n"
       "\n"
@@ -332,7 +342,7 @@
       "the logged data.");
   aos::InitGoogle(&argc, &argv);
 
-  if (FLAGS_raw) {
+  if (absl::GetFlag(FLAGS_raw)) {
     return PrintRaw(argc, argv);
   }
 
@@ -345,17 +355,17 @@
 
   for (auto &it : logfiles) {
     VLOG(1) << it;
-    if (FLAGS_print_parts_only) {
+    if (absl::GetFlag(FLAGS_print_parts_only)) {
       std::cout << it << std::endl;
     }
   }
-  if (FLAGS_print_parts_only) {
+  if (absl::GetFlag(FLAGS_print_parts_only)) {
     return 0;
   }
 
   aos::logger::LogReader reader(logfiles);
 
-  if (FLAGS_channels) {
+  if (absl::GetFlag(FLAGS_channels)) {
     const aos::Configuration *config = reader.configuration();
     for (const aos::Channel *channel : *config->channels()) {
       std::cout << channel->name()->c_str() << " " << channel->type()->c_str()
@@ -373,8 +383,8 @@
       const aos::Channel *channel = channels->Get(i);
       const flatbuffers::string_view name = channel->name()->string_view();
       const flatbuffers::string_view type = channel->type()->string_view();
-      if (name.find(FLAGS_name) != std::string::npos &&
-          type.find(FLAGS_type) != std::string::npos) {
+      if (name.find(absl::GetFlag(FLAGS_name)) != std::string::npos &&
+          type.find(absl::GetFlag(FLAGS_type)) != std::string::npos) {
         found_channel = true;
       }
     }
@@ -385,13 +395,14 @@
 
   aos::Printer printer(
       {
-          .pretty = FLAGS_pretty,
-          .max_vector_size = static_cast<size_t>(FLAGS_max_vector_size),
-          .pretty_max = FLAGS_pretty_max,
-          .print_timestamps = FLAGS_print_timestamps,
-          .json = FLAGS_json,
-          .distributed_clock = FLAGS_distributed_clock,
-          .hex = FLAGS_hex,
+          .pretty = absl::GetFlag(FLAGS_pretty),
+          .max_vector_size =
+              static_cast<size_t>(absl::GetFlag(FLAGS_max_vector_size)),
+          .pretty_max = absl::GetFlag(FLAGS_pretty_max),
+          .print_timestamps = absl::GetFlag(FLAGS_print_timestamps),
+          .json = absl::GetFlag(FLAGS_json),
+          .distributed_clock = absl::GetFlag(FLAGS_distributed_clock),
+          .hex = absl::GetFlag(FLAGS_hex),
       },
       false);
 
diff --git a/aos/events/logging/log_config_extractor.cc b/aos/events/logging/log_config_extractor.cc
index f2df5b3..628bf72 100644
--- a/aos/events/logging/log_config_extractor.cc
+++ b/aos/events/logging/log_config_extractor.cc
@@ -2,9 +2,11 @@
 #include <iostream>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration_generated.h"
 #include "aos/events/logging/log_reader.h"
@@ -13,19 +15,20 @@
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_string(output_path, "/tmp/",
-              "Destination folder for output files. If this flag is not used, "
-              "it stores the files in /tmp/.");
-DEFINE_bool(convert_to_json, false,
-            "If true, can be used to convert bfbs to json.");
-DEFINE_bool(bfbs, false,
-            "If true, write as a binary flatbuffer inside the output_path.");
-DEFINE_bool(json, false, "If true, write as a json inside the output_path.");
-DEFINE_bool(stripped, false,
-            "If true, write as a stripped json inside the output_path.");
-DEFINE_bool(quiet, false,
-            "If true, do not print configuration to stdout. If false, print "
-            "stripped json");
+ABSL_FLAG(std::string, output_path, "/tmp/",
+          "Destination folder for output files. If this flag is not used, "
+          "it stores the files in /tmp/.");
+ABSL_FLAG(bool, convert_to_json, false,
+          "If true, can be used to convert bfbs to json.");
+ABSL_FLAG(bool, bfbs, false,
+          "If true, write as a binary flatbuffer inside the output_path.");
+ABSL_FLAG(bool, json, false,
+          "If true, write as a json inside the output_path.");
+ABSL_FLAG(bool, stripped, false,
+          "If true, write as a stripped json inside the output_path.");
+ABSL_FLAG(bool, quiet, false,
+          "If true, do not print configuration to stdout. If false, print "
+          "stripped json");
 
 namespace aos {
 
@@ -43,27 +46,27 @@
   auto config_flatbuffer = configuration::MergeConfiguration(
       RecursiveCopyFlatBuffer(config), schemas);
 
-  if (FLAGS_bfbs) {
+  if (absl::GetFlag(FLAGS_bfbs)) {
     WriteFlatbufferToFile(output_path + ".bfbs", config_flatbuffer);
     LOG(INFO) << "Done writing bfbs to " << output_path << ".bfbs";
   }
 
-  if (FLAGS_json) {
+  if (absl::GetFlag(FLAGS_json)) {
     WriteFlatbufferToJson(output_path + ".json", config_flatbuffer);
     LOG(INFO) << "Done writing json to " << output_path << ".json";
   }
 
-  if (FLAGS_stripped || !FLAGS_quiet) {
+  if (absl::GetFlag(FLAGS_stripped) || !absl::GetFlag(FLAGS_quiet)) {
     auto *channels = config_flatbuffer.mutable_message()->mutable_channels();
     for (size_t i = 0; i < channels->size(); i++) {
       channels->GetMutableObject(i)->clear_schema();
     }
-    if (FLAGS_stripped) {
+    if (absl::GetFlag(FLAGS_stripped)) {
       WriteFlatbufferToJson(output_path + ".stripped.json", config_flatbuffer);
       LOG(INFO) << "Done writing stripped json to " << output_path
                 << ".stripped.json";
     }
-    if (!FLAGS_quiet) {
+    if (!absl::GetFlag(FLAGS_quiet)) {
       std::cout << FlatbufferToJson(config_flatbuffer) << std::endl;
     }
   }
@@ -72,7 +75,7 @@
 int Main(int argc, char *argv[]) {
   CHECK(argc > 1) << "Must provide an argument";
 
-  std::string output_path = FLAGS_output_path;
+  std::string output_path = absl::GetFlag(FLAGS_output_path);
   if (output_path.back() != '/') {
     output_path += "/";
   }
@@ -93,7 +96,7 @@
     aos::FlatbufferDetachedBuffer<aos::Configuration> buffer(
         aos::JsonToFlatbuffer(stdin_data, aos::ConfigurationTypeTable()));
     WriteConfig(&buffer.message(), output_path);
-  } else if (FLAGS_convert_to_json) {
+  } else if (absl::GetFlag(FLAGS_convert_to_json)) {
     aos::FlatbufferDetachedBuffer config = aos::configuration::ReadConfig(arg);
     WriteFlatbufferToJson(output_path + ".json", config);
     LOG(INFO) << "Done writing json to " << output_path << ".json";
@@ -109,7 +112,7 @@
 }  // namespace aos
 
 int main(int argc, char *argv[]) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Binary to output the configuration of a log.\n"
       "# print config as stripped json to stdout\n"
       "# path to log should always be absolute path.\n"
diff --git a/aos/events/logging/log_edit.cc b/aos/events/logging/log_edit.cc
index 4585ab7..33cd120 100644
--- a/aos/events/logging/log_edit.cc
+++ b/aos/events/logging/log_edit.cc
@@ -1,6 +1,7 @@
 #include <iostream>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/log_reader.h"
@@ -9,32 +10,32 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/util/file.h"
 
-DEFINE_string(logfile, "/tmp/logfile.bfbs",
-              "Name of the logfile to read from.");
-DEFINE_bool(
-    replace, false,
-    "If true, replace the header on the log file with the JSON header.");
-DEFINE_string(
-    header, "",
+ABSL_FLAG(std::string, logfile, "/tmp/logfile.bfbs",
+          "Name of the logfile to read from.");
+ABSL_FLAG(bool, replace, false,
+          "If true, replace the header on the log file with the JSON header.");
+ABSL_FLAG(
+    std::string, header, "",
     "If provided, this is the path to the JSON with the log file header.  If "
     "not provided, _header.json will be appended to --logfile.");
 
-DEFINE_int32(
-    max_message_size, 128 * 1024 * 1024,
-    "Max size of a message to be written.  This sets the buffers inside "
-    "the encoders.");
+ABSL_FLAG(int32_t, max_message_size, 128 * 1024 * 1024,
+          "Max size of a message to be written.  This sets the buffers inside "
+          "the encoders.");
+ABSL_FLAG(bool, direct, false,
+          "If true, write using O_DIRECT and write 512 byte aligned blocks "
+          "whenever possible.");
 
-DEFINE_bool(direct, false,
-            "If true, write using O_DIRECT and write 512 byte aligned blocks "
-            "whenever possible.");
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(R"(This tool lets us manipulate log files.)");
+  absl::SetProgramUsageMessage(R"(This tool lets us manipulate log files.)");
   aos::InitGoogle(&argc, &argv);
 
   std::string header_json_path =
-      FLAGS_header.empty() ? (FLAGS_logfile + "_header.json") : FLAGS_header;
+      absl::GetFlag(FLAGS_header).empty()
+          ? (absl::GetFlag(FLAGS_logfile) + "_header.json")
+          : absl::GetFlag(FLAGS_header);
 
-  if (FLAGS_replace) {
+  if (absl::GetFlag(FLAGS_replace)) {
     const ::std::string header_json =
         aos::util::ReadFileToStringOrDie(header_json_path);
     flatbuffers::FlatBufferBuilder fbb;
@@ -46,16 +47,18 @@
     aos::SizePrefixedFlatbufferDetachedBuffer<aos::logger::LogFileHeader>
         header(fbb.Release());
 
-    const std::string orig_path = FLAGS_logfile + ".orig";
-    PCHECK(rename(FLAGS_logfile.c_str(), orig_path.c_str()) == 0);
+    const std::string orig_path = absl::GetFlag(FLAGS_logfile) + ".orig";
+    PCHECK(rename(absl::GetFlag(FLAGS_logfile).c_str(), orig_path.c_str()) ==
+           0);
 
     aos::logger::SpanReader span_reader(orig_path);
     CHECK(!span_reader.ReadMessage().empty()) << ": Empty header, aborting";
 
-    aos::logger::FileBackend file_backend("/", FLAGS_direct);
+    aos::logger::FileBackend file_backend("/", absl::GetFlag(FLAGS_direct));
     aos::logger::DetachedBufferWriter buffer_writer(
-        file_backend.RequestFile(FLAGS_logfile),
-        std::make_unique<aos::logger::DummyEncoder>(FLAGS_max_message_size));
+        file_backend.RequestFile(absl::GetFlag(FLAGS_logfile)),
+        std::make_unique<aos::logger::DummyEncoder>(
+            absl::GetFlag(FLAGS_max_message_size)));
     {
       aos::logger::DataEncoder::SpanCopier copier(header.span());
       buffer_writer.CopyMessage(&copier, aos::monotonic_clock::min_time);
@@ -73,7 +76,7 @@
       }
     }
   } else {
-    aos::logger::MessageReader reader(FLAGS_logfile);
+    aos::logger::MessageReader reader(absl::GetFlag(FLAGS_logfile));
     aos::util::WriteStringToFileOrDie(
         header_json_path,
         aos::FlatbufferToJson(reader.log_file_header(), {.multi_line = true}));
diff --git a/aos/events/logging/log_namer.cc b/aos/events/logging/log_namer.cc
index c065f68..e8fb524 100644
--- a/aos/events/logging/log_namer.cc
+++ b/aos/events/logging/log_namer.cc
@@ -6,9 +6,11 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
 #include "aos/containers/error_list.h"
 #include "aos/containers/sized_array.h"
@@ -17,7 +19,7 @@
 #include "aos/flatbuffer_merge.h"
 #include "aos/uuid.h"
 
-DECLARE_int32(flush_size);
+ABSL_DECLARE_FLAG(int32_t, flush_size);
 
 namespace aos::logger {
 
@@ -762,7 +764,7 @@
       encoder_factory_([](size_t max_message_size) {
         // TODO(austin): For slow channels, can we allocate less memory?
         return std::make_unique<DummyEncoder>(max_message_size,
-                                              FLAGS_flush_size);
+                                              absl::GetFlag(FLAGS_flush_size));
       }) {}
 
 MultiNodeLogNamer::~MultiNodeLogNamer() {
diff --git a/aos/events/logging/log_namer.h b/aos/events/logging/log_namer.h
index 2c0982a..dcacd1b 100644
--- a/aos/events/logging/log_namer.h
+++ b/aos/events/logging/log_namer.h
@@ -8,8 +8,9 @@
 #include <vector>
 
 #include "absl/container/btree_map.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
 #include "aos/events/logging/logfile_utils.h"
 #include "aos/events/logging/logger_generated.h"
diff --git a/aos/events/logging/log_reader.cc b/aos/events/logging/log_reader.cc
index 81f8466..ae5f0ef 100644
--- a/aos/events/logging/log_reader.cc
+++ b/aos/events/logging/log_reader.cc
@@ -10,6 +10,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/flags/flag.h"
 #include "absl/strings/escaping.h"
 #include "absl/types/span.h"
 #include "flatbuffers/flatbuffers.h"
@@ -30,47 +31,47 @@
 #include "aos/util/file.h"
 #include "aos/uuid.h"
 
-DEFINE_bool(skip_missing_forwarding_entries, false,
-            "If true, drop any forwarding entries with missing data.  If "
-            "false, CHECK.");
+ABSL_FLAG(bool, skip_missing_forwarding_entries, false,
+          "If true, drop any forwarding entries with missing data.  If "
+          "false, CHECK.");
 
-DECLARE_bool(timestamps_to_csv);
-DEFINE_bool(
-    enable_timestamp_loading, true,
+ABSL_DECLARE_FLAG(bool, timestamps_to_csv);
+ABSL_FLAG(
+    bool, enable_timestamp_loading, true,
     "Enable loading all the timestamps into RAM at startup if they are in "
     "separate files.  This fixes any timestamp queueing problems for the cost "
     "of storing timestamps in RAM only on logs with timestamps logged in "
     "separate files from data.  Only disable this if you are reading a really "
     "long log file and are experiencing memory problems due to loading all the "
     "timestamps into RAM.");
-DEFINE_bool(
-    force_timestamp_loading, false,
+ABSL_FLAG(
+    bool, force_timestamp_loading, false,
     "Force loading all the timestamps into RAM at startup.  This fixes any "
     "timestamp queueing problems for the cost of storing timestamps in RAM and "
     "potentially reading each log twice.");
 
-DEFINE_bool(skip_order_validation, false,
-            "If true, ignore any out of orderness in replay");
+ABSL_FLAG(bool, skip_order_validation, false,
+          "If true, ignore any out of orderness in replay");
 
-DEFINE_double(
-    time_estimation_buffer_seconds, 2.0,
+ABSL_FLAG(
+    double, time_estimation_buffer_seconds, 2.0,
     "The time to buffer ahead in the log file to accurately reconstruct time.");
 
-DEFINE_string(
-    start_time, "",
+ABSL_FLAG(
+    std::string, start_time, "",
     "If set, start at this point in time in the log on the realtime clock.");
-DEFINE_string(
-    end_time, "",
+ABSL_FLAG(
+    std::string, end_time, "",
     "If set, end at this point in time in the log on the realtime clock.");
 
-DEFINE_bool(drop_realtime_messages_before_start, false,
-            "If set, will drop any messages sent before the start of the "
-            "logfile in realtime replay. Setting this guarantees consistency "
-            "in timing with the original logfile, but means that you lose "
-            "access to fetched low-frequency messages.");
+ABSL_FLAG(bool, drop_realtime_messages_before_start, false,
+          "If set, will drop any messages sent before the start of the "
+          "logfile in realtime replay. Setting this guarantees consistency "
+          "in timing with the original logfile, but means that you lose "
+          "access to fetched low-frequency messages.");
 
-DEFINE_double(
-    threaded_look_ahead_seconds, 2.0,
+ABSL_FLAG(
+    double, threaded_look_ahead_seconds, 2.0,
     "Time, in seconds, to add to look-ahead when using multi-threaded replay. "
     "Can validly be zero, but higher values are encouraged for realtime replay "
     "in order to prevent the replay from ever having to block on waiting for "
@@ -190,8 +191,8 @@
       replay_channels_(replay_channels),
       config_remapper_(log_files_.config().get(), replay_configuration_,
                        replay_channels_) {
-  SetStartTime(FLAGS_start_time);
-  SetEndTime(FLAGS_end_time);
+  SetStartTime(absl::GetFlag(FLAGS_start_time));
+  SetEndTime(absl::GetFlag(FLAGS_end_time));
 
   {
     // Log files container validates that log files shared the same config.
@@ -442,13 +443,13 @@
   filters_ =
       std::make_unique<message_bridge::MultiNodeNoncausalOffsetEstimator>(
           event_loop_factory_->configuration(), logged_configuration(),
-          log_files_.boots(), FLAGS_skip_order_validation,
+          log_files_.boots(), absl::GetFlag(FLAGS_skip_order_validation),
           timestamp_queue_strategy ==
                   TimestampQueueStrategy::kQueueTimestampsAtStartup
               ? chrono::seconds(0)
               : chrono::duration_cast<chrono::nanoseconds>(
                     chrono::duration<double>(
-                        FLAGS_time_estimation_buffer_seconds)));
+                        absl::GetFlag(FLAGS_time_estimation_buffer_seconds))));
 
   std::vector<TimestampMapper *> timestamp_mappers;
   for (const Node *node : configuration::GetNodes(configuration())) {
@@ -625,7 +626,7 @@
                                                : monotonic_clock::min_time);
   }
 
-  if (FLAGS_timestamps_to_csv) {
+  if (absl::GetFlag(FLAGS_timestamps_to_csv)) {
     filters_->Start(event_loop_factory);
   }
 }
@@ -640,8 +641,8 @@
 
 TimestampQueueStrategy LogReader::ComputeTimestampQueueStrategy() const {
   if ((log_files_.TimestampsStoredSeparately() &&
-       FLAGS_enable_timestamp_loading) ||
-      FLAGS_force_timestamp_loading) {
+       absl::GetFlag(FLAGS_enable_timestamp_loading)) ||
+      absl::GetFlag(FLAGS_force_timestamp_loading)) {
     return TimestampQueueStrategy::kQueueTimestampsAtStartup;
   } else {
     return TimestampQueueStrategy::kQueueTogether;
@@ -658,13 +659,13 @@
   filters_ =
       std::make_unique<message_bridge::MultiNodeNoncausalOffsetEstimator>(
           event_loop->configuration(), logged_configuration(),
-          log_files_.boots(), FLAGS_skip_order_validation,
+          log_files_.boots(), absl::GetFlag(FLAGS_skip_order_validation),
           timestamp_queue_strategy ==
                   TimestampQueueStrategy::kQueueTimestampsAtStartup
               ? chrono::seconds(0)
               : chrono::duration_cast<chrono::nanoseconds>(
                     chrono::duration<double>(
-                        FLAGS_time_estimation_buffer_seconds)));
+                        absl::GetFlag(FLAGS_time_estimation_buffer_seconds))));
 
   std::vector<TimestampMapper *> timestamp_mappers;
   for (const Node *node : configuration::GetNodes(configuration())) {
@@ -860,7 +861,7 @@
         state->event_loop()->context().monotonic_event_time;
     if (event_loop_factory_ != nullptr) {
       // Only enforce exact timing in simulation.
-      if (!FLAGS_skip_order_validation) {
+      if (!absl::GetFlag(FLAGS_skip_order_validation)) {
         CHECK(monotonic_now == timestamped_message.monotonic_event_time.time)
             << ": " << FlatbufferToJson(state->event_loop()->node()) << " Now "
             << monotonic_now << " trying to send "
@@ -884,11 +885,12 @@
             state->monotonic_start_time(
                 timestamped_message.monotonic_event_time.boot) ||
         event_loop_factory_ != nullptr ||
-        !FLAGS_drop_realtime_messages_before_start) {
+        !absl::GetFlag(FLAGS_drop_realtime_messages_before_start)) {
       if (timestamped_message.data != nullptr && !state->found_last_message()) {
         if (timestamped_message.monotonic_remote_time !=
                 BootTimestamp::min_time() &&
-            !FLAGS_skip_order_validation && event_loop_factory_ != nullptr) {
+            !absl::GetFlag(FLAGS_skip_order_validation) &&
+            event_loop_factory_ != nullptr) {
           // Confirm that the message was sent on the sending node before the
           // destination node (this node).  As a proxy, do this by making sure
           // that time on the source node is past when the message was sent.
@@ -899,7 +901,7 @@
           // fix that.
           BootTimestamp monotonic_remote_now =
               state->monotonic_remote_now(timestamped_message.channel_index);
-          if (!FLAGS_skip_order_validation) {
+          if (!absl::GetFlag(FLAGS_skip_order_validation)) {
             CHECK_EQ(timestamped_message.monotonic_remote_time.boot,
                      monotonic_remote_now.boot)
                 << state->event_loop()->node()->name()->string_view() << " to "
@@ -974,7 +976,7 @@
                       state->monotonic_remote_start_time(
                           timestamped_message.monotonic_remote_time.boot,
                           timestamped_message.channel_index) &&
-                  !FLAGS_skip_missing_forwarding_entries)) {
+                  !absl::GetFlag(FLAGS_skip_missing_forwarding_entries))) {
         if (!state->found_last_message()) {
           // We've found a timestamp without data that we expect to have data
           // for. This likely means that we are at the end of the log file.
@@ -1130,8 +1132,8 @@
       // primed).
       state->QueueThreadUntil(
           next_time + std::chrono::duration_cast<std::chrono::nanoseconds>(
-                          std::chrono::duration<double>(
-                              FLAGS_threaded_look_ahead_seconds)));
+                          std::chrono::duration<double>(absl::GetFlag(
+                              FLAGS_threaded_look_ahead_seconds))));
       state->MaybeSetClockOffset();
       state->Schedule(next_time.time);
       state->SetUpStartupTimer();
@@ -1787,7 +1789,8 @@
     message_queuer_->SetState(
         message.value().monotonic_event_time +
         std::chrono::duration_cast<std::chrono::nanoseconds>(
-            std::chrono::duration<double>(FLAGS_threaded_look_ahead_seconds)));
+            std::chrono::duration<double>(
+                absl::GetFlag(FLAGS_threaded_look_ahead_seconds))));
     VLOG(1) << "Popped " << message.value()
             << configuration::CleanedChannelToString(
                    event_loop_->configuration()->channels()->Get(
@@ -1872,8 +1875,9 @@
       TimestampQueueStrategy::kQueueTimestampsAtStartup)
     return;
 
-  timestamp_mapper_->QueueFor(chrono::duration_cast<chrono::seconds>(
-      chrono::duration<double>(FLAGS_time_estimation_buffer_seconds)));
+  timestamp_mapper_->QueueFor(
+      chrono::duration_cast<chrono::seconds>(chrono::duration<double>(
+          absl::GetFlag(FLAGS_time_estimation_buffer_seconds))));
 }
 
 void LogReader::State::Deregister() {
diff --git a/aos/events/logging/log_reader.h b/aos/events/logging/log_reader.h
index 85d4d2c..1334b86 100644
--- a/aos/events/logging/log_reader.h
+++ b/aos/events/logging/log_reader.h
@@ -8,9 +8,10 @@
 #include <tuple>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/condition.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/events/logging/log_replayer.cc b/aos/events/logging/log_replayer.cc
index 22d8b39..970b828 100644
--- a/aos/events/logging/log_replayer.cc
+++ b/aos/events/logging/log_replayer.cc
@@ -7,9 +7,11 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration_generated.h"
 #include "aos/events/event_loop.h"
@@ -28,30 +30,31 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/util/file.h"
 
-DEFINE_string(config, "", "If specified, overrides logged configuration.");
-DEFINE_bool(
-    plot_timing, true,
+ABSL_FLAG(std::string, config, "",
+          "If specified, overrides logged configuration.");
+ABSL_FLAG(
+    bool, plot_timing, true,
     "If set, generates a plot of the replay timing--namely, the errors between "
     "when we "
     "should've sent messages and when we actually sent replayed messages.");
-DEFINE_bool(skip_sender_channels, true,
-            "If set, skips replay of the channels applications replay on");
-DEFINE_bool(skip_replay, false,
-            "If set, skips actually running the replay. Useful for writing a "
-            "config without running replay");
-DEFINE_bool(
-    print_config, false,
+ABSL_FLAG(bool, skip_sender_channels, true,
+          "If set, skips replay of the channels applications replay on");
+ABSL_FLAG(bool, skip_replay, false,
+          "If set, skips actually running the replay. Useful for writing a "
+          "config without running replay");
+ABSL_FLAG(
+    bool, print_config, false,
     "If set, prints the config that will be used for replay to stdout as json");
-DEFINE_string(
-    replay_config, "",
+ABSL_FLAG(
+    std::string, replay_config, "",
     "Path to the configuration used for log replay which includes items such "
     "as channels to remap, and applications to target for replay. If not set, "
     "log_reader will run on shm event loop. ");
-DEFINE_string(merge_with_config, "",
-              "A valid json string to be merged with config. This is used to "
-              "add extra applications needed to run only for log_replayer");
-DEFINE_bool(print_stats, true,
-            "if set, prints the LogReplayerStats message as JSON to stdout");
+ABSL_FLAG(std::string, merge_with_config, "",
+          "A valid json string to be merged with config. This is used to "
+          "add extra applications needed to run only for log_replayer");
+ABSL_FLAG(bool, print_stats, true,
+          "if set, prints the LogReplayerStats message as JSON to stdout");
 
 namespace aos::logger {
 
@@ -61,11 +64,11 @@
 
   aos::logger::LogReader config_reader(logfiles);
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      FLAGS_config.empty()
+      absl::GetFlag(FLAGS_config).empty()
           ? CopyFlatBuffer<aos::Configuration>(config_reader.configuration())
-          : aos::configuration::ReadConfig(FLAGS_config);
+          : aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
-  if (FLAGS_plot_timing) {
+  if (absl::GetFlag(FLAGS_plot_timing)) {
     // Go through the effort to add a ReplayTiming channel to ensure that we
     // can capture timing information from the replay.
     const aos::Configuration *raw_config = &config.message();
@@ -89,18 +92,19 @@
       aos::FlatbufferSpan<reflection::Schema>(aos::LogReplayerStatsSchema()),
       aos::configuration::GetMyNode(raw_config), channel_overrides);
 
-  if (!FLAGS_merge_with_config.empty()) {
-    config = aos::configuration::MergeWithConfig(&config.message(),
-                                                 FLAGS_merge_with_config);
+  if (!absl::GetFlag(FLAGS_merge_with_config).empty()) {
+    config = aos::configuration::MergeWithConfig(
+        &config.message(), absl::GetFlag(FLAGS_merge_with_config));
   }
 
   std::optional<aos::FlatbufferDetachedBuffer<ReplayConfig>> replay_config =
-      FLAGS_replay_config.empty()
+      absl::GetFlag(FLAGS_replay_config).empty()
           ? std::nullopt
           : std::make_optional(aos::JsonToFlatbuffer<ReplayConfig>(
-                aos::util::ReadFileToStringOrDie(FLAGS_replay_config.data())));
+                aos::util::ReadFileToStringOrDie(
+                    absl::GetFlag(FLAGS_replay_config).data())));
   std::vector<std::pair<std::string, std::string>> message_filter;
-  if (FLAGS_skip_sender_channels && replay_config.has_value()) {
+  if (absl::GetFlag(FLAGS_skip_sender_channels) && replay_config.has_value()) {
     CHECK(replay_config.value().message().has_active_nodes());
     std::vector<const Node *> active_nodes;
     for (const auto &node : *replay_config.value().message().active_nodes()) {
@@ -142,12 +146,12 @@
     }
   }
 
-  if (FLAGS_print_config) {
+  if (absl::GetFlag(FLAGS_print_config)) {
     // TODO(Naman): Replace with config writer if it will be cleaner
     std::cout << FlatbufferToJson(reader.configuration()) << std::endl;
   }
 
-  if (!FLAGS_skip_replay) {
+  if (!absl::GetFlag(FLAGS_skip_replay)) {
     aos::ShmEventLoop event_loop(reader.configuration());
 
     event_loop.SkipAosLog();
@@ -198,7 +202,7 @@
 
     reader.OnEnd(event_loop.node(), [&event_loop]() { event_loop.Exit(); });
 
-    if (FLAGS_plot_timing) {
+    if (absl::GetFlag(FLAGS_plot_timing)) {
       aos::Sender<aos::timing::ReplayTiming> replay_timing_sender =
           event_loop.MakeSender<aos::timing::ReplayTiming>("/timing");
       reader.set_timing_accuracy_sender(event_loop.node(),
@@ -209,7 +213,7 @@
 
     reader.Deregister();
 
-    if (FLAGS_print_stats) {
+    if (absl::GetFlag(FLAGS_print_stats)) {
       aos::Fetcher<aos::LogReplayerStats> stats_fetcher =
           event_loop.MakeFetcher<aos::LogReplayerStats>("/replay");
       CHECK(stats_fetcher.Fetch()) << "Failed to fetch LogReplayerStats!";
@@ -223,7 +227,7 @@
 }  // namespace aos::logger
 
 int main(int argc, char *argv[]) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       R"message(Binary to replay the full contents of a logfile into shared memory.
                 #replay_config should be set in order to replay a set of nodes, applications and channels
                 #print config and skip replay, if you only want to print the config and not do log replay
diff --git a/aos/events/logging/log_stats.cc b/aos/events/logging/log_stats.cc
index a45a167..6e6efc9 100644
--- a/aos/events/logging/log_stats.cc
+++ b/aos/events/logging/log_stats.cc
@@ -2,8 +2,9 @@
 #include <iostream>
 #include <queue>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 #include "absl/strings/str_format.h"
-#include "gflags/gflags.h"
 
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/simulated_event_loop.h"
@@ -11,23 +12,23 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/time/time.h"
 
-DEFINE_string(
-    name, "",
+ABSL_FLAG(
+    std::string, name, "",
     "Name to match for printing out channels. Empty means no name filter.");
 
-DEFINE_string(node, "", "Node to print stats out for.");
+ABSL_FLAG(std::string, node, "", "Node to print stats out for.");
 
-DEFINE_bool(excessive_size_only, false,
-            "Only print channels that have a set max message size that is more "
-            "than double of the max message size.");
+ABSL_FLAG(bool, excessive_size_only, false,
+          "Only print channels that have a set max message size that is more "
+          "than double of the max message size.");
 
-DEFINE_double(
-    run_for, 0.0,
+ABSL_FLAG(
+    double, run_for, 0.0,
     "If set to a positive value, only process the log for this many seconds. "
     "Otherwise, process the log until the end of the log.");
 
-DEFINE_bool(
-    print_repack_size_diffs, false,
+ABSL_FLAG(
+    bool, print_repack_size_diffs, false,
     "Analyze how many bytes could be saved in each message when converted to "
     "JSON and back. This can be helpful to identify code that is generating "
     "inefficiently packed flatbuffer messages.");
@@ -340,7 +341,7 @@
         continue;
       }
 
-      if (channel->name()->string_view().find(FLAGS_name) ==
+      if (channel->name()->string_view().find(absl::GetFlag(FLAGS_name)) ==
           std::string::npos) {
         continue;
       }
@@ -354,7 +355,7 @@
       auto watcher = [this, channel_stats_index](const aos::Context &context) {
         this->UpdateStats(context, channel_stats_index);
       };
-      if (FLAGS_print_repack_size_diffs) {
+      if (absl::GetFlag(FLAGS_print_repack_size_diffs)) {
         event_loop_->MakeRawWatcher(
             channel, std::bind(watcher, ::std::placeholders::_1));
       } else {
@@ -376,7 +377,7 @@
   void PrintStats() {
     // Print out the stats per channel and for the logfile.
     for (size_t i = 0; i != channel_stats_.size(); i++) {
-      if (!FLAGS_excessive_size_only ||
+      if (!absl::GetFlag(FLAGS_excessive_size_only) ||
           (channel_stats_[i].max_message_size() * 2) <
               static_cast<size_t>(channel_stats_[i].channel()->max_size())) {
         if (channel_stats_[i].total_num_messages() > 0) {
@@ -390,7 +391,7 @@
               std::max(logfile_stats_.logfile_end_time,
                        channel_stats_[i].channel_end_time());
 
-          if (!FLAGS_excessive_size_only) {
+          if (!absl::GetFlag(FLAGS_excessive_size_only)) {
             std::cout << "   " << channel_stats_[i].total_num_messages()
                       << " msgs, " << channel_stats_[i].avg_messages_per_sec()
                       << "hz avg, " << channel_stats_[i].max_messages_per_sec()
@@ -406,7 +407,7 @@
                     << channel_stats_[i].Percentile() << ", "
                     << channel_stats_[i].AvgLatency();
           std::cout << std::endl;
-          if (FLAGS_print_repack_size_diffs) {
+          if (absl::GetFlag(FLAGS_print_repack_size_diffs)) {
             std::cout << "   " << channel_stats_[i].avg_packed_size_reduction()
                       << " bytes packed reduction avg, "
                       << channel_stats_[i].max_packed_size_reduction()
@@ -441,7 +442,7 @@
 };
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Usage: \n"
       "  log_stats [args] logfile1 logfile2 ...\n"
       "This program provides statistics on a given log file. Supported "
@@ -470,7 +471,7 @@
   const aos::Node *node = nullptr;
 
   if (aos::configuration::MultiNode(reader.configuration())) {
-    if (FLAGS_node.empty()) {
+    if (absl::GetFlag(FLAGS_node).empty()) {
       LOG(INFO) << "Need a --node specified.  The log file has:";
       for (const aos::Node *node : reader.LoggedNodes()) {
         LOG(INFO) << "  " << node->name()->string_view();
@@ -478,7 +479,8 @@
       reader.Deregister();
       return 1;
     } else {
-      node = aos::configuration::GetNode(reader.configuration(), FLAGS_node);
+      node = aos::configuration::GetNode(reader.configuration(),
+                                         absl::GetFlag(FLAGS_node));
     }
   }
 
@@ -498,10 +500,10 @@
     log_stats_application = nullptr;
   });
 
-  if (FLAGS_run_for > 0.0) {
+  if (absl::GetFlag(FLAGS_run_for) > 0.0) {
     event_loop_factory.RunFor(
         std::chrono::duration_cast<std::chrono::nanoseconds>(
-            std::chrono::duration<double>(FLAGS_run_for)));
+            std::chrono::duration<double>(absl::GetFlag(FLAGS_run_for))));
   } else {
     event_loop_factory.Run();
   }
diff --git a/aos/events/logging/logfile_sorting.cc b/aos/events/logging/logfile_sorting.cc
index fdb4eab..756138c 100644
--- a/aos/events/logging/logfile_sorting.cc
+++ b/aos/events/logging/logfile_sorting.cc
@@ -9,6 +9,9 @@
 #include <vector>
 
 #include "absl/container/btree_map.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_join.h"
 
 #include "aos/containers/error_list.h"
@@ -24,8 +27,8 @@
 #include "aos/events/logging/s3_file_operations.h"
 #endif
 
-DEFINE_bool(quiet_sorting, false,
-            "If true, sort with minimal messages about truncated files.");
+ABSL_FLAG(bool, quiet_sorting, false,
+          "If true, sort with minimal messages about truncated files.");
 
 namespace aos::logger {
 namespace {
@@ -388,7 +391,7 @@
     std::optional<SizePrefixedFlatbufferVector<LogFileHeader>> log_header =
         ReadHeader(reader);
     if (!log_header) {
-      if (!FLAGS_quiet_sorting) {
+      if (!absl::GetFlag(FLAGS_quiet_sorting)) {
         LOG(WARNING) << "Skipping " << part.name << " without a header";
       }
       corrupted.emplace_back(part.name);
@@ -519,7 +522,7 @@
       std::optional<SizePrefixedFlatbufferVector<MessageHeader>> first_message =
           ReadNthMessage(part.name, 0);
       if (!first_message) {
-        if (!FLAGS_quiet_sorting) {
+        if (!absl::GetFlag(FLAGS_quiet_sorting)) {
           LOG(WARNING) << "Skipping " << part.name << " without any messages";
         }
         corrupted.emplace_back(part.name);
diff --git a/aos/events/logging/logfile_utils.cc b/aos/events/logging/logfile_utils.cc
index 0d10a99..f920681 100644
--- a/aos/events/logging/logfile_utils.cc
+++ b/aos/events/logging/logfile_utils.cc
@@ -9,10 +9,11 @@
 #include <climits>
 #include <filesystem>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/escaping.h"
 #include "flatbuffers/flatbuffers.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/snappy_encoder.h"
@@ -34,39 +35,38 @@
 #include "aos/events/logging/s3_fetcher.h"
 #endif
 
-DEFINE_int32(flush_size, 128 * 1024,
-             "Number of outstanding bytes to allow before flushing to disk.");
-DEFINE_double(
-    flush_period, 5.0,
-    "Max time to let data sit in the queue before flushing in seconds.");
+ABSL_FLAG(int32_t, flush_size, 128 * 1024,
+          "Number of outstanding bytes to allow before flushing to disk.");
+ABSL_FLAG(double, flush_period, 5.0,
+          "Max time to let data sit in the queue before flushing in seconds.");
 
-DEFINE_double(
-    max_network_delay, 1.0,
+ABSL_FLAG(
+    double, max_network_delay, 1.0,
     "Max time to assume a message takes to cross the network before we are "
     "willing to drop it from our buffers and assume it didn't make it.  "
     "Increasing this number can increase memory usage depending on the packet "
     "loss of your network or if the timestamps aren't logged for a message.");
 
-DEFINE_double(
-    max_out_of_order, -1,
+ABSL_FLAG(
+    double, max_out_of_order, -1,
     "If set, this overrides the max out of order duration for a log file.");
 
-DEFINE_bool(workaround_double_headers, true,
-            "Some old log files have two headers at the beginning.  Use the "
-            "last header as the actual header.");
+ABSL_FLAG(bool, workaround_double_headers, true,
+          "Some old log files have two headers at the beginning.  Use the "
+          "last header as the actual header.");
 
-DEFINE_bool(crash_on_corrupt_message, true,
-            "When true, MessageReader will crash the first time a message "
-            "with corrupted format is found. When false, the crash will be "
-            "suppressed, and any remaining readable messages will be "
-            "evaluated to present verified vs corrupted stats.");
+ABSL_FLAG(bool, crash_on_corrupt_message, true,
+          "When true, MessageReader will crash the first time a message "
+          "with corrupted format is found. When false, the crash will be "
+          "suppressed, and any remaining readable messages will be "
+          "evaluated to present verified vs corrupted stats.");
 
-DEFINE_bool(ignore_corrupt_messages, false,
-            "When true, and crash_on_corrupt_message is false, then any "
-            "corrupt message found by MessageReader be silently ignored, "
-            "providing access to all uncorrupted messages in a logfile.");
+ABSL_FLAG(bool, ignore_corrupt_messages, false,
+          "When true, and crash_on_corrupt_message is false, then any "
+          "corrupt message found by MessageReader be silently ignored, "
+          "providing access to all uncorrupted messages in a logfile.");
 
-DECLARE_bool(quiet_sorting);
+ABSL_DECLARE_FLAG(bool, quiet_sorting);
 
 namespace aos::logger {
 namespace {
@@ -280,11 +280,12 @@
   // point queueing up any more data in memory. Also flush once we have enough
   // data queued up or if it has been long enough.
   while (encoder_->space() == 0 ||
-         encoder_->queued_bytes() > static_cast<size_t>(FLAGS_flush_size) ||
+         encoder_->queued_bytes() >
+             static_cast<size_t>(absl::GetFlag(FLAGS_flush_size)) ||
          encoder_->queue_size() >= IOV_MAX ||
-         (now > last_flush_time_ +
-                    chrono::duration_cast<chrono::nanoseconds>(
-                        chrono::duration<double>(FLAGS_flush_period)) &&
+         (now > last_flush_time_ + chrono::duration_cast<chrono::nanoseconds>(
+                                       chrono::duration<double>(absl::GetFlag(
+                                           FLAGS_flush_period))) &&
           encoder_->queued_bytes() != 0)) {
     VLOG(1) << "Chose to flush at " << now << ", last " << last_flush_time_
             << " queued bytes " << encoder_->queued_bytes();
@@ -1140,7 +1141,7 @@
     part_readers_.clear();
   }
   if (log_source_ == nullptr) {
-    part_readers_.emplace_back(id, FLAGS_quiet_sorting);
+    part_readers_.emplace_back(id, absl::GetFlag(FLAGS_quiet_sorting));
   } else {
     part_readers_.emplace_back(id, log_source_->GetDecoder(id));
   }
@@ -1168,7 +1169,8 @@
   // way that it can't happen anymore.  We've seen some logs where the body
   // parses as a header recently, so the simple solution of always looking is
   // failing us.
-  if (FLAGS_workaround_double_headers && !result.message().has_logger_sha1()) {
+  if (absl::GetFlag(FLAGS_workaround_double_headers) &&
+      !result.message().has_logger_sha1()) {
     while (true) {
       absl::Span<const uint8_t> maybe_header_data = span_reader->PeekMessage();
       if (maybe_header_data.empty()) {
@@ -1227,8 +1229,10 @@
     : span_reader_(std::move(span_reader)),
       raw_log_file_header_(
           SizePrefixedFlatbufferVector<LogFileHeader>::Empty()) {
-  set_crash_on_corrupt_message_flag(FLAGS_crash_on_corrupt_message);
-  set_ignore_corrupt_messages_flag(FLAGS_ignore_corrupt_messages);
+  set_crash_on_corrupt_message_flag(
+      absl::GetFlag(FLAGS_crash_on_corrupt_message));
+  set_ignore_corrupt_messages_flag(
+      absl::GetFlag(FLAGS_ignore_corrupt_messages));
 
   std::optional<SizePrefixedFlatbufferVector<LogFileHeader>>
       raw_log_file_header = ReadHeader(&span_reader_);
@@ -1244,9 +1248,9 @@
   total_verified_before_ = span_reader_.TotalConsumed();
 
   max_out_of_order_duration_ =
-      FLAGS_max_out_of_order > 0
+      absl::GetFlag(FLAGS_max_out_of_order) > 0
           ? chrono::duration_cast<chrono::nanoseconds>(
-                chrono::duration<double>(FLAGS_max_out_of_order))
+                chrono::duration<double>(absl::GetFlag(FLAGS_max_out_of_order)))
           : chrono::nanoseconds(log_file_header()->max_out_of_order_duration());
 
   VLOG(1) << "Opened " << span_reader_.filename() << " as node "
@@ -2622,7 +2626,8 @@
                messages.begin()->timestamp +
                        node_data.channels[msg->channel_index].time_to_live +
                        chrono::duration_cast<chrono::nanoseconds>(
-                           chrono::duration<double>(FLAGS_max_network_delay)) <
+                           chrono::duration<double>(
+                               absl::GetFlag(FLAGS_max_network_delay))) <
                    last_popped_message_time_) {
           messages.pop_front();
         }
diff --git a/aos/events/logging/logfile_utils_out_of_space_test_runner.cc b/aos/events/logging/logfile_utils_out_of_space_test_runner.cc
index f6fb499..4247c12 100644
--- a/aos/events/logging/logfile_utils_out_of_space_test_runner.cc
+++ b/aos/events/logging/logfile_utils_out_of_space_test_runner.cc
@@ -2,19 +2,21 @@
 
 #include <array>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/logging/logfile_utils.h"
 #include "aos/init.h"
 
-DECLARE_int32(flush_size);
-DEFINE_string(tmpfs, "", "tmpfs with the desired size");
+ABSL_DECLARE_FLAG(int32_t, flush_size);
+ABSL_FLAG(std::string, tmpfs, "", "tmpfs with the desired size");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
-  FLAGS_flush_size = 1;
-  CHECK(!FLAGS_tmpfs.empty()) << ": Must specify a tmpfs location";
+  absl::SetFlag(&FLAGS_flush_size, 1);
+  CHECK(!absl::GetFlag(FLAGS_tmpfs).empty())
+      << ": Must specify a tmpfs location";
 
   std::array<uint8_t, 10240> data;
   data.fill(0);
@@ -22,7 +24,7 @@
   // Don't use odirect
   aos::logger::FileBackend file_backend("/", false);
   aos::logger::DetachedBufferWriter writer(
-      file_backend.RequestFile(FLAGS_tmpfs + "/file"),
+      file_backend.RequestFile(absl::GetFlag(FLAGS_tmpfs) + "/file"),
       std::make_unique<aos::logger::DummyEncoder>(data.size()));
   for (int i = 0; i < 8; ++i) {
     aos::logger::DataEncoder::SpanCopier coppier(data);
diff --git a/aos/events/logging/logfile_utils_test.cc b/aos/events/logging/logfile_utils_test.cc
index 87c6f5d..b97579a 100644
--- a/aos/events/logging/logfile_utils_test.cc
+++ b/aos/events/logging/logfile_utils_test.cc
@@ -5,11 +5,12 @@
 #include <random>
 #include <string>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/escaping.h"
 #include "external/com_github_google_flatbuffers/src/annotated_binary_text_gen.h"
 #include "external/com_github_google_flatbuffers/src/binary_annotator.h"
 #include "flatbuffers/reflection_generated.h"
-#include "gflags/gflags.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/logging/logfile_sorting.h"
@@ -3094,7 +3095,7 @@
   }
 
   {
-    gflags::FlagSaver fs;
+    absl::FlagSaver fs;
 
     MessageReader reader(logfile);
     reader.set_crash_on_corrupt_message_flag(false);
@@ -3116,7 +3117,7 @@
   }
 
   {
-    gflags::FlagSaver fs;
+    absl::FlagSaver fs;
 
     MessageReader reader(logfile);
     reader.set_crash_on_corrupt_message_flag(false);
@@ -3239,6 +3240,30 @@
       std::mt19937(::aos::testing::RandomSeed())};
 
   std::vector<uint8_t> data_;
+
+  const aos::FlatbufferDetachedBuffer<Configuration> config_{
+      JsonToFlatbuffer<Configuration>(
+          R"({
+  "channels": [
+    {
+      "name": "/a",
+      "type": "aos.logger.testing.TestMessage"
+    },
+    {
+      "name": "/b",
+      "type": "aos.logger.testing.TestMessage"
+    },
+    {
+      "name": "/c",
+      "type": "aos.logger.testing.TestMessage"
+    },
+    {
+      "name": "/d",
+      "type": "aos.logger.testing.TestMessage"
+    }
+  ]
+}
+)")};
 };
 
 // Uses the binary schema to annotate a provided flatbuffer.  Returns the
@@ -3268,7 +3293,7 @@
 // tested below.
 class TimeEventLoop : public EventLoop {
  public:
-  TimeEventLoop() : EventLoop(nullptr) {}
+  TimeEventLoop(const aos::Configuration *config) : EventLoop(config) {}
 
   aos::monotonic_clock::time_point monotonic_now() const final {
     return aos::monotonic_clock::min_time;
@@ -3403,7 +3428,7 @@
 
       // Ok, now we want to confirm that we can build up arbitrary pieces of
       // said flatbuffer.  Try all of them since it is cheap.
-      TimeEventLoop event_loop;
+      TimeEventLoop event_loop(&config_.message());
       for (size_t i = 0; i < repacked_message.size(); i += 8) {
         for (size_t j = i; j < repacked_message.size(); j += 8) {
           std::vector<uint8_t> destination(repacked_message.size(), 67u);
@@ -3475,7 +3500,7 @@
 
     // Ok, now we want to confirm that we can build up arbitrary pieces of said
     // flatbuffer.  Try all of them since it is cheap.
-    TimeEventLoop event_loop;
+    TimeEventLoop event_loop(&config_.message());
     for (size_t i = 0; i < repacked_message.size(); i += 8) {
       for (size_t j = i; j < repacked_message.size(); j += 8) {
         std::vector<uint8_t> destination(repacked_message.size(), 67u);
diff --git a/aos/events/logging/logger_main.cc b/aos/events/logging/logger_main.cc
index f99fe4c..73b6694 100644
--- a/aos/events/logging/logger_main.cc
+++ b/aos/events/logging/logger_main.cc
@@ -6,41 +6,45 @@
 #ifdef LZMA
 #include "aos/events/logging/lzma_encoder.h"
 #endif
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/logging/snappy_encoder.h"
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/logging/log_namer.h"
 
-DEFINE_bool(direct, false,
-            "If true, write using O_DIRECT and write 512 byte aligned blocks "
-            "whenever possible.");
+ABSL_FLAG(bool, direct, false,
+          "If true, write using O_DIRECT and write 512 byte aligned blocks "
+          "whenever possible.");
 
-DEFINE_string(config, "aos_config.json", "Config file to use.");
+ABSL_FLAG(std::string, config, "aos_config.json", "Config file to use.");
 
-DEFINE_bool(skip_renicing, false,
-            "If true, skip renicing the logger.  This leaves it lower priority "
-            "and increases the likelihood of dropping messages and crashing.");
+ABSL_FLAG(bool, skip_renicing, false,
+          "If true, skip renicing the logger.  This leaves it lower priority "
+          "and increases the likelihood of dropping messages and crashing.");
 
-DEFINE_bool(snappy_compress, false, "If true, compress log data using snappy.");
+ABSL_FLAG(bool, snappy_compress, false,
+          "If true, compress log data using snappy.");
 
 #ifdef LZMA
-DEFINE_bool(xz_compress, false, "If true, compress log data using xz.");
+ABSL_FLAG(bool, xz_compress, false, "If true, compress log data using xz.");
 #endif
 
-DEFINE_double(rotate_every, 0.0,
-              "If set, rotate the logger after this many seconds");
+ABSL_FLAG(double, rotate_every, 0.0,
+          "If set, rotate the logger after this many seconds");
 
 #ifdef LZMA
-DEFINE_int32(xz_compression_level, 9, "Compression level for the LZMA Encoder");
+ABSL_FLAG(int32_t, xz_compression_level, 9,
+          "Compression level for the LZMA Encoder");
 #endif
 
-DECLARE_int32(flush_size);
+ABSL_DECLARE_FLAG(int32_t, flush_size);
 
 int main(int argc, char *argv[]) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "This program provides a simple logger binary that logs all SHMEM data "
       "directly to a file specified at the command line. It does not manage "
       "filenames, so it will just crash if you attempt to overwrite an "
@@ -49,27 +53,28 @@
   aos::InitGoogle(&argc, &argv);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
 
   auto log_namer = std::make_unique<aos::logger::MultiNodeFilesLogNamer>(
       &event_loop, std::make_unique<aos::logger::RenamableFileBackend>(
                        absl::StrCat(aos::logging::GetLogName("fbs_log"), "/"),
-                       FLAGS_direct));
+                       absl::GetFlag(FLAGS_direct)));
 
-  if (FLAGS_snappy_compress) {
+  if (absl::GetFlag(FLAGS_snappy_compress)) {
     log_namer->set_extension(aos::logger::SnappyDecoder::kExtension);
     log_namer->set_encoder_factory([](size_t max_message_size) {
-      return std::make_unique<aos::logger::SnappyEncoder>(max_message_size,
-                                                          FLAGS_flush_size);
+      return std::make_unique<aos::logger::SnappyEncoder>(
+          max_message_size, absl::GetFlag(FLAGS_flush_size));
     });
 #ifdef LZMA
-  } else if (FLAGS_xz_compress) {
+  } else if (absl::GetFlag(FLAGS_xz_compress)) {
     log_namer->set_extension(aos::logger::LzmaEncoder::kExtension);
     log_namer->set_encoder_factory([](size_t max_message_size) {
       return std::make_unique<aos::logger::LzmaEncoder>(
-          max_message_size, FLAGS_xz_compression_level, FLAGS_flush_size);
+          max_message_size, absl::GetFlag(FLAGS_xz_compression_level),
+          absl::GetFlag(FLAGS_flush_size));
     });
 #endif
   }
@@ -78,10 +83,10 @@
       event_loop.monotonic_now();
   aos::logger::Logger logger(&event_loop);
 
-  if (FLAGS_rotate_every != 0.0) {
+  if (absl::GetFlag(FLAGS_rotate_every) != 0.0) {
     logger.set_on_logged_period([&](aos::monotonic_clock::time_point t) {
-      if (t > last_rotation_time +
-                  std::chrono::duration<double>(FLAGS_rotate_every)) {
+      if (t > last_rotation_time + std::chrono::duration<double>(
+                                       absl::GetFlag(FLAGS_rotate_every))) {
         logger.Rotate();
         last_rotation_time = t;
       }
@@ -89,7 +94,7 @@
   }
 
   event_loop.OnRun([&log_namer, &logger]() {
-    if (FLAGS_skip_renicing) {
+    if (absl::GetFlag(FLAGS_skip_renicing)) {
       LOG(WARNING) << "Ignoring request to renice to -20 due to "
                       "--skip_renicing.";
     } else {
diff --git a/aos/events/logging/logger_test.cc b/aos/events/logging/logger_test.cc
index c810203..bf5e414 100644
--- a/aos/events/logging/logger_test.cc
+++ b/aos/events/logging/logger_test.cc
@@ -2,8 +2,9 @@
 
 #include <filesystem>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_format.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
diff --git a/aos/events/logging/lzma_encoder.cc b/aos/events/logging/lzma_encoder.cc
index 5e9fa7a..f4a075a 100644
--- a/aos/events/logging/lzma_encoder.cc
+++ b/aos/events/logging/lzma_encoder.cc
@@ -1,8 +1,10 @@
 #include "aos/events/logging/lzma_encoder.h"
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
-DEFINE_int32(lzma_threads, 1, "Number of threads to use for encoding");
+ABSL_FLAG(int32_t, lzma_threads, 1, "Number of threads to use for encoding");
 
 namespace aos::logger {
 namespace {
@@ -58,14 +60,14 @@
   CHECK_LE(compression_preset_, 9u)
       << ": Compression preset must be in the range [0, 9].";
 
-  if (FLAGS_lzma_threads <= 1) {
+  if (absl::GetFlag(FLAGS_lzma_threads) <= 1) {
     lzma_ret status =
         lzma_easy_encoder(&stream_, compression_preset_, LZMA_CHECK_CRC64);
     CHECK(LzmaCodeIsOk(status));
   } else {
     lzma_mt mt_options;
     memset(&mt_options, 0, sizeof(mt_options));
-    mt_options.threads = FLAGS_lzma_threads;
+    mt_options.threads = absl::GetFlag(FLAGS_lzma_threads);
     mt_options.block_size = block_size;
     // Compress for at most 100 ms before relinquishing control back to the main
     // thread.
diff --git a/aos/events/logging/lzma_encoder_test.cc b/aos/events/logging/lzma_encoder_test.cc
index 92b4f54..2eb1281 100644
--- a/aos/events/logging/lzma_encoder_test.cc
+++ b/aos/events/logging/lzma_encoder_test.cc
@@ -1,5 +1,7 @@
 #include "aos/events/logging/lzma_encoder.h"
 
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -7,14 +9,14 @@
 #include "aos/testing/tmpdir.h"
 #include "aos/util/file.h"
 
-DECLARE_int32(lzma_threads);
+ABSL_DECLARE_FLAG(int32_t, lzma_threads);
 
 namespace aos::logger::testing {
 
 INSTANTIATE_TEST_SUITE_P(
     MtLzma, BufferEncoderTest,
     ::testing::Combine(::testing::Values([](size_t max_message_size) {
-                         FLAGS_lzma_threads = 3;
+                         absl::SetFlag(&FLAGS_lzma_threads, 3);
                          return std::make_unique<LzmaEncoder>(max_message_size,
                                                               2, 4096);
                        }),
@@ -26,7 +28,7 @@
 INSTANTIATE_TEST_SUITE_P(
     MtLzmaThreaded, BufferEncoderTest,
     ::testing::Combine(::testing::Values([](size_t max_message_size) {
-                         FLAGS_lzma_threads = 3;
+                         absl::SetFlag(&FLAGS_lzma_threads, 3);
                          return std::make_unique<LzmaEncoder>(max_message_size,
                                                               5, 4096);
                        }),
@@ -38,7 +40,7 @@
 INSTANTIATE_TEST_SUITE_P(
     Lzma, BufferEncoderTest,
     ::testing::Combine(::testing::Values([](size_t max_message_size) {
-                         FLAGS_lzma_threads = 1;
+                         absl::SetFlag(&FLAGS_lzma_threads, 1);
                          return std::make_unique<LzmaEncoder>(max_message_size,
                                                               2, 4096);
                        }),
@@ -50,7 +52,7 @@
 INSTANTIATE_TEST_SUITE_P(
     LzmaThreaded, BufferEncoderTest,
     ::testing::Combine(::testing::Values([](size_t max_message_size) {
-                         FLAGS_lzma_threads = 1;
+                         absl::SetFlag(&FLAGS_lzma_threads, 1);
                          return std::make_unique<LzmaEncoder>(max_message_size,
                                                               5, 4096);
                        }),
diff --git a/aos/events/logging/multinode_logger_test_lib.cc b/aos/events/logging/multinode_logger_test_lib.cc
index 3bf6207..b48f78a 100644
--- a/aos/events/logging/multinode_logger_test_lib.cc
+++ b/aos/events/logging/multinode_logger_test_lib.cc
@@ -1,5 +1,9 @@
 #include "aos/events/logging/multinode_logger_test_lib.h"
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
+
 #include "aos/events/event_loop.h"
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/logging/logfile_utils.h"
@@ -9,7 +13,7 @@
 #include "aos/events/simulated_event_loop.h"
 #include "aos/testing/tmpdir.h"
 
-DECLARE_bool(force_timestamp_loading);
+ABSL_DECLARE_FLAG(bool, force_timestamp_loading);
 
 namespace aos::logger::testing {
 
@@ -111,9 +115,9 @@
       pi1_reboot_logfiles_(MakePi1RebootLogfiles()),
       logfiles_(MakeLogFiles(logfile_base1_, logfile_base2_)),
       structured_logfiles_(StructureLogFiles()) {
-  FLAGS_force_timestamp_loading =
-      std::get<0>(GetParam()).timestamp_buffering ==
-      ForceTimestampBuffering::kForceBufferTimestamps;
+  absl::SetFlag(&FLAGS_force_timestamp_loading,
+                std::get<0>(GetParam()).timestamp_buffering ==
+                    ForceTimestampBuffering::kForceBufferTimestamps);
 
   util::UnlinkRecursive(tmp_dir_ + "/logs");
   std::filesystem::create_directory(tmp_dir_ + "/logs");
diff --git a/aos/events/logging/multinode_logger_test_lib.h b/aos/events/logging/multinode_logger_test_lib.h
index 3c71632..386339d 100644
--- a/aos/events/logging/multinode_logger_test_lib.h
+++ b/aos/events/logging/multinode_logger_test_lib.h
@@ -1,8 +1,8 @@
 #ifndef AOS_EVENTS_LOGGING_MULTINODE_LOGGER_TEST_LIB_H
 #define AOS_EVENTS_LOGGING_MULTINODE_LOGGER_TEST_LIB_H
 
+#include "absl/flags/reflection.h"
 #include "absl/strings/str_format.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 
 #include "aos/events/event_loop.h"
@@ -172,7 +172,7 @@
 
   void AddExtension(std::string_view extension);
 
-  gflags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 
   // Config and factory.
   aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
diff --git a/aos/events/logging/realtime_replay_test.cc b/aos/events/logging/realtime_replay_test.cc
index dd4aaf0..7db9442 100644
--- a/aos/events/logging/realtime_replay_test.cc
+++ b/aos/events/logging/realtime_replay_test.cc
@@ -9,15 +9,14 @@
 #include "aos/testing/path.h"
 #include "aos/testing/tmpdir.h"
 
-DECLARE_string(override_hostname);
+ABSL_DECLARE_FLAG(std::string, override_hostname);
 
 namespace aos::logger::testing {
 
 class RealtimeLoggerTest : public ::testing::Test {
  protected:
   RealtimeLoggerTest()
-      : shm_dir_(aos::testing::TestTmpDir() + "/aos"),
-        config_file_(
+      : config_file_(
             aos::testing::ArtifactPath("aos/events/pingpong_config.json")),
         config_(aos::configuration::ReadConfig(config_file_)),
         event_loop_factory_(&config_.message()),
@@ -27,17 +26,12 @@
         pong_(pong_event_loop_.get()),
         tmpdir_(aos::testing::TestTmpDir()),
         base_name_(tmpdir_ + "/logfile/") {
-    FLAGS_shm_base = shm_dir_;
-
     // Nuke the shm and log dirs, to ensure we aren't being affected by any
     // preexisting tests.
-    aos::util::UnlinkRecursive(shm_dir_);
+    aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
     aos::util::UnlinkRecursive(base_name_);
   }
 
-  gflags::FlagSaver flag_saver_;
-  std::string shm_dir_;
-
   const std::string config_file_;
   const aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
 
@@ -54,8 +48,7 @@
 class RealtimeMultiNodeLoggerTest : public ::testing::Test {
  protected:
   RealtimeMultiNodeLoggerTest()
-      : shm_dir_(aos::testing::TestTmpDir() + "/aos"),
-        config_file_(aos::testing::ArtifactPath(
+      : config_file_(aos::testing::ArtifactPath(
             "aos/events/logging/multinode_pingpong_combined_config.json")),
         config_(aos::configuration::ReadConfig(config_file_)),
         event_loop_factory_(&config_.message()),
@@ -64,17 +57,12 @@
         ping_(ping_event_loop_.get()),
         tmpdir_(aos::testing::TestTmpDir()),
         base_name_(tmpdir_ + "/logfile/") {
-    FLAGS_shm_base = shm_dir_;
-
     // Nuke the shm and log dirs, to ensure we aren't being affected by any
     // preexisting tests.
-    aos::util::UnlinkRecursive(shm_dir_);
+    aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
     aos::util::UnlinkRecursive(base_name_);
   }
 
-  gflags::FlagSaver flag_saver_;
-  std::string shm_dir_;
-
   const std::string config_file_;
   const aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
 
@@ -178,7 +166,7 @@
 // Tests that ReplayChannels causes no messages to be replayed other than what
 // is included on a multi node config
 TEST_F(RealtimeMultiNodeLoggerTest, ReplayChannelsPingTest) {
-  FLAGS_override_hostname = "raspberrypi";
+  absl::SetFlag(&FLAGS_override_hostname, "raspberrypi");
   {
     std::unique_ptr<EventLoop> logger_event_loop =
         event_loop_factory_.MakeEventLoop(
@@ -223,7 +211,7 @@
 // Tests that when remapping a channel included in ReplayChannels messages are
 // sent on the remapped channel
 TEST_F(RealtimeMultiNodeLoggerTest, RemappedReplayChannelsTest) {
-  FLAGS_override_hostname = "raspberrypi";
+  absl::SetFlag(&FLAGS_override_hostname, "raspberrypi");
   {
     std::unique_ptr<EventLoop> logger_event_loop =
         event_loop_factory_.MakeEventLoop(
@@ -275,7 +263,7 @@
 // exist in the log being replayed, and there's no messages on those
 // channels as well.
 TEST_F(RealtimeMultiNodeLoggerTest, DoesNotExistInReplayChannelsTest) {
-  FLAGS_override_hostname = "raspberrypi";
+  absl::SetFlag(&FLAGS_override_hostname, "raspberrypi");
   {
     std::unique_ptr<EventLoop> logger_event_loop =
         event_loop_factory_.MakeEventLoop(
@@ -335,7 +323,7 @@
 // the channel being remapped.
 TEST_F(RealtimeMultiNodeLoggerDeathTest,
        RemapLoggedChannelNotIncludedInReplayChannels) {
-  FLAGS_override_hostname = "raspberrypi";
+  absl::SetFlag(&FLAGS_override_hostname, "raspberrypi");
   {
     std::unique_ptr<EventLoop> logger_event_loop =
         event_loop_factory_.MakeEventLoop(
diff --git a/aos/events/logging/s3_fetcher.cc b/aos/events/logging/s3_fetcher.cc
index 4207286..557c3da 100644
--- a/aos/events/logging/s3_fetcher.cc
+++ b/aos/events/logging/s3_fetcher.cc
@@ -3,8 +3,9 @@
 #include <aws/core/Aws.h>
 #include <aws/s3/model/ListObjectsV2Request.h>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
-#include "glog/logging.h"
 
 // When we first start reading a log folder, we end up reading the first part of
 // each file twice. We could speed this up by restructuring the API so all the
diff --git a/aos/events/logging/single_node_merge.cc b/aos/events/logging/single_node_merge.cc
index a34e4c2..01eeb6b 100644
--- a/aos/events/logging/single_node_merge.cc
+++ b/aos/events/logging/single_node_merge.cc
@@ -2,7 +2,7 @@
 #include <string>
 #include <vector>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/events/logging/logfile_sorting.h"
 #include "aos/events/logging/logfile_utils.h"
@@ -13,7 +13,7 @@
 // log.  It doesn't solve the timestamp problem, but is still quite useful for
 // debugging what happened in a log.
 
-DEFINE_string(node, "", "The node to dump sorted messages for");
+ABSL_FLAG(std::string, node, "", "The node to dump sorted messages for");
 
 namespace aos::logger {
 
@@ -39,7 +39,7 @@
       // Filter the parts relevant to each node when building the mapper.
       mappers.emplace_back(std::make_unique<TimestampMapper>(
           node_name, log_files, TimestampQueueStrategy::kQueueTogether));
-      if (node_name == FLAGS_node) {
+      if (node_name == absl::GetFlag(FLAGS_node)) {
         node_mapper = mappers.back().get();
       }
     } else {
@@ -47,7 +47,8 @@
     }
   }
 
-  CHECK(node_mapper != nullptr) << ": Failed to find node " << FLAGS_node;
+  CHECK(node_mapper != nullptr)
+      << ": Failed to find node " << absl::GetFlag(FLAGS_node);
 
   // Hook the peers up so data gets matched.
   for (std::unique_ptr<TimestampMapper> &mapper1 : mappers) {
@@ -61,7 +62,7 @@
   // Now, read all the timestamps for each node.  This is simpler than the
   // logger on purpose.  It loads in *all* the timestamps in 1 go per node,
   // ignoring memory usage.
-  const Node *node = configuration::GetNode(config, FLAGS_node);
+  const Node *node = configuration::GetNode(config, absl::GetFlag(FLAGS_node));
 
   LOG(INFO) << "Reading all data for " << node->name()->string_view();
   const size_t node_index = configuration::GetNodeIndex(config, node);
@@ -74,7 +75,7 @@
     if (m == nullptr) {
       break;
     }
-    std::cout << "on " << FLAGS_node << " from "
+    std::cout << "on " << absl::GetFlag(FLAGS_node) << " from "
               << config->nodes()
                      ->Get(configuration::GetNodeIndex(
                          config, config->channels()
diff --git a/aos/events/logging/ssd_profiler.cc b/aos/events/logging/ssd_profiler.cc
index 093e17b..034ac28 100644
--- a/aos/events/logging/ssd_profiler.cc
+++ b/aos/events/logging/ssd_profiler.cc
@@ -8,8 +8,9 @@
 #include <csignal>
 #include <filesystem>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/containers/resizeable_buffer.h"
 #include "aos/events/logging/log_backend.h"
@@ -19,33 +20,34 @@
 
 namespace chrono = std::chrono;
 
-DEFINE_string(file, "/media/sda1/foo", "File to write to.");
+ABSL_FLAG(std::string, file, "/media/sda1/foo", "File to write to.");
 
-DEFINE_uint32(write_size, 4096, "Size of hunk to write");
-DEFINE_bool(cleanup, true, "If true, delete the created file");
-DEFINE_int32(nice, -20,
-             "Priority to nice to. Set to 0 to not change the priority.");
-DEFINE_bool(sync, false, "If true, sync the file after each written block.");
-DEFINE_bool(writev, false, "If true, use writev.");
-DEFINE_bool(direct, false, "If true, O_DIRECT.");
-DEFINE_uint32(chunks, 1, "Chunks to write using writev.");
-DEFINE_uint32(chunk_size, 512, "Chunk size to write using writev.");
-DEFINE_uint64(overall_size, 0,
-              "If nonzero, write this many bytes and then stop.  Must be a "
-              "multiple of --write_size");
-DEFINE_bool(rate_limit, false,
-            "If true, kick off writes every 100ms to mimic logger write "
-            "patterns more correctly.");
-DEFINE_double(write_bandwidth, 120.0,
-              "Write speed in MB/s to simulate. This is only used when "
-              "--rate_limit is specified.");
+ABSL_FLAG(uint32_t, write_size, 4096, "Size of hunk to write");
+ABSL_FLAG(bool, cleanup, true, "If true, delete the created file");
+ABSL_FLAG(int32_t, nice, -20,
+          "Priority to nice to. Set to 0 to not change the priority.");
+ABSL_FLAG(bool, sync, false,
+          "If true, sync the file after each written block.");
+ABSL_FLAG(bool, writev, false, "If true, use writev.");
+ABSL_FLAG(bool, direct, false, "If true, O_DIRECT.");
+ABSL_FLAG(uint32_t, chunks, 1, "Chunks to write using writev.");
+ABSL_FLAG(uint32_t, chunk_size, 512, "Chunk size to write using writev.");
+ABSL_FLAG(uint64_t, overall_size, 0,
+          "If nonzero, write this many bytes and then stop.  Must be a "
+          "multiple of --write_size");
+ABSL_FLAG(bool, rate_limit, false,
+          "If true, kick off writes every 100ms to mimic logger write "
+          "patterns more correctly.");
+ABSL_FLAG(double, write_bandwidth, 120.0,
+          "Write speed in MB/s to simulate. This is only used when "
+          "--rate_limit is specified.");
 
 void trap_sig(int signum) { exit(signum); }
 
 aos::monotonic_clock::time_point start_time = aos::monotonic_clock::min_time;
 std::atomic<size_t> written_data = 0;
 
-void cleanup() {
+void Cleanup() {
   LOG(INFO) << "Overall average write speed: "
             << ((written_data) /
                 chrono::duration<double>(aos::monotonic_clock::now() -
@@ -56,19 +58,20 @@
             << "MB";
 
   // Delete FLAGS_file at shutdown
-  PCHECK(std::filesystem::remove(FLAGS_file) != 0) << "Failed to cleanup file";
+  PCHECK(std::filesystem::remove(absl::GetFlag(FLAGS_file)) != 0)
+      << "Failed to cleanup file";
 }
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
   // c++ needs bash's trap <fcn> EXIT
   // instead we get this mess :(
-  if (FLAGS_cleanup) {
+  if (absl::GetFlag(FLAGS_cleanup)) {
     std::signal(SIGINT, trap_sig);
     std::signal(SIGTERM, trap_sig);
     std::signal(SIGKILL, trap_sig);
     std::signal(SIGHUP, trap_sig);
-    std::atexit(cleanup);
+    std::atexit(Cleanup);
   }
   aos::AllocatorResizeableBuffer<
       aos::AlignedReallocator<aos::logger::FileHandler::kSector>>
@@ -79,7 +82,7 @@
     // good sized block from /dev/random, and then reuse it.
     int random_fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
     PCHECK(random_fd != -1) << ": Failed to open /dev/random";
-    data.resize(FLAGS_write_size);
+    data.resize(absl::GetFlag(FLAGS_write_size));
     size_t written = 0;
     while (written < data.size()) {
       const size_t result =
@@ -92,23 +95,24 @@
   }
 
   std::vector<struct iovec> iovec;
-  if (FLAGS_writev) {
-    iovec.resize(FLAGS_chunks);
-    CHECK_LE(FLAGS_chunks * FLAGS_chunk_size, FLAGS_write_size);
+  if (absl::GetFlag(FLAGS_writev)) {
+    const size_t chunks = absl::GetFlag(FLAGS_chunks);
+    const size_t chunk_size = absl::GetFlag(FLAGS_chunk_size);
+    iovec.resize(chunks);
+    CHECK_LE(chunks * chunk_size, absl::GetFlag(FLAGS_write_size));
 
-    for (size_t i = 0; i < FLAGS_chunks; ++i) {
-      iovec[i].iov_base = &data.at(i * FLAGS_chunk_size);
-      iovec[i].iov_len = FLAGS_chunk_size;
+    for (size_t i = 0; i < chunks; ++i) {
+      iovec[i].iov_base = &data.at(i * chunk_size);
+      iovec[i].iov_len = chunk_size;
     }
-    iovec[FLAGS_chunks - 1].iov_base =
-        &data.at((FLAGS_chunks - 1) * FLAGS_chunk_size);
-    iovec[FLAGS_chunks - 1].iov_len =
-        data.size() - (FLAGS_chunks - 1) * FLAGS_chunk_size;
+    iovec[chunks - 1].iov_base = &data.at((chunks - 1) * chunk_size);
+    iovec[chunks - 1].iov_len = data.size() - (chunks - 1) * chunk_size;
   }
 
-  int fd =
-      open(FLAGS_file.c_str(),
-           O_RDWR | O_CLOEXEC | O_CREAT | (FLAGS_direct ? O_DIRECT : 0), 0774);
+  int fd = open(absl::GetFlag(FLAGS_file).c_str(),
+                O_RDWR | O_CLOEXEC | O_CREAT |
+                    (absl::GetFlag(FLAGS_direct) ? O_DIRECT : 0),
+                0774);
   PCHECK(fd != -1);
 
   start_time = aos::monotonic_clock::now();
@@ -121,23 +125,24 @@
   // want to write it in cycles of 100ms to simulate the logger.
   size_t cycle_written_data = 0;
   size_t data_per_cycle = std::numeric_limits<size_t>::max();
-  if (FLAGS_rate_limit) {
-    data_per_cycle =
-        static_cast<size_t>((FLAGS_write_bandwidth * 1024 * 1024) / 10);
+  if (absl::GetFlag(FLAGS_rate_limit)) {
+    data_per_cycle = static_cast<size_t>(
+        (absl::GetFlag(FLAGS_write_bandwidth) * 1024 * 1024) / 10);
   }
 
-  if (FLAGS_nice != 0) {
-    PCHECK(-1 != setpriority(PRIO_PROCESS, 0, FLAGS_nice))
-        << ": Renicing to " << FLAGS_nice << " failed";
+  if (absl::GetFlag(FLAGS_nice) != 0) {
+    PCHECK(-1 != setpriority(PRIO_PROCESS, 0, absl::GetFlag(FLAGS_nice)))
+        << ": Renicing to " << absl::GetFlag(FLAGS_nice) << " failed";
   }
 
   while (true) {
     // Bail if we have written our limit.
-    if (written_data >= FLAGS_overall_size && FLAGS_overall_size != 0) {
+    if (written_data >= absl::GetFlag(FLAGS_overall_size) &&
+        absl::GetFlag(FLAGS_overall_size) != 0) {
       break;
     }
 
-    if (FLAGS_writev) {
+    if (absl::GetFlag(FLAGS_writev)) {
       PCHECK(writev(fd, iovec.data(), iovec.size()) ==
              static_cast<ssize_t>(data.size()))
           << ": Failed after "
@@ -152,7 +157,7 @@
     }
 
     // Trigger a flush if asked.
-    if (FLAGS_sync) {
+    if (absl::GetFlag(FLAGS_sync)) {
       const aos::monotonic_clock::time_point monotonic_now =
           aos::monotonic_clock::now();
       sync_file_range(fd, written_data, data.size(), SYNC_FILE_RANGE_WRITE);
@@ -178,11 +183,12 @@
     // Simulate the logger by writing the specified amount of data in periods of
     // 100ms.
     bool reset_cycle = false;
-    if (cycle_written_data > data_per_cycle && FLAGS_rate_limit) {
+    if (cycle_written_data > data_per_cycle &&
+        absl::GetFlag(FLAGS_rate_limit)) {
       // Check how much data we should have already written based on
       // --write_bandwidth.
       const size_t current_target =
-          FLAGS_write_bandwidth * 1024 * 1024 *
+          absl::GetFlag(FLAGS_write_bandwidth) * 1024 * 1024 *
           chrono::duration<double>(aos::monotonic_clock::now() - start_time)
               .count();
       const bool caught_up = written_data > current_target;
diff --git a/aos/events/logging/timestamp_extractor.cc b/aos/events/logging/timestamp_extractor.cc
index 3cf96f6..00555d8 100644
--- a/aos/events/logging/timestamp_extractor.cc
+++ b/aos/events/logging/timestamp_extractor.cc
@@ -2,30 +2,32 @@
 #include <string>
 #include <vector>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/events/logging/logfile_sorting.h"
 #include "aos/events/logging/logfile_utils.h"
 #include "aos/events/logging/logfile_validator.h"
 #include "aos/init.h"
 
-DECLARE_bool(timestamps_to_csv);
-DEFINE_bool(skip_order_validation, false,
-            "If true, ignore any out of orderness in replay");
+ABSL_DECLARE_FLAG(bool, timestamps_to_csv);
+ABSL_FLAG(bool, skip_order_validation, false,
+          "If true, ignore any out of orderness in replay");
 
 namespace aos::logger {
 
 int Main(int argc, char **argv) {
   const LogFilesContainer log_files(SortParts(FindLogs(argc, argv)));
-  CHECK(MultiNodeLogIsReadable(log_files, FLAGS_skip_order_validation));
+  CHECK(MultiNodeLogIsReadable(log_files,
+                               absl::GetFlag(FLAGS_skip_order_validation)));
   return 0;
 }
 
 }  // namespace aos::logger
 
 int main(int argc, char **argv) {
-  FLAGS_timestamps_to_csv = true;
-  gflags::SetUsageMessage(
+  absl::SetFlag(&FLAGS_timestamps_to_csv, true);
+  absl::SetProgramUsageMessage(
       "Usage:\n"
       "  timestamp_extractor [args] logfile1 logfile2 ...\n\nThis program "
       "dumps out all the timestamps from a set of log files for plotting.  Use "
diff --git a/aos/events/logging/timestamp_plot.cc b/aos/events/logging/timestamp_plot.cc
index 5b5cdc2..82e8031 100644
--- a/aos/events/logging/timestamp_plot.cc
+++ b/aos/events/logging/timestamp_plot.cc
@@ -1,3 +1,4 @@
+#include "absl/flags/flag.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 
@@ -7,13 +8,13 @@
 
 using aos::analysis::Plotter;
 
-DEFINE_bool(all, false, "If true, plot *all* the nodes at once");
-DEFINE_bool(bounds, false, "If true, plot the noncausal bounds too.");
-DEFINE_bool(samples, true, "If true, plot the samples too.");
+ABSL_FLAG(bool, all, false, "If true, plot *all* the nodes at once");
+ABSL_FLAG(bool, bounds, false, "If true, plot the noncausal bounds too.");
+ABSL_FLAG(bool, samples, true, "If true, plot the samples too.");
 
-DEFINE_string(offsets, "",
-              "Offsets to add to the monotonic clock for each node.  Use the "
-              "format of node=offset,node=offest");
+ABSL_FLAG(std::string, offsets, "",
+          "Offsets to add to the monotonic clock for each node.  Use the "
+          "format of node=offset,node=offest");
 
 // Simple C++ application to read the CSV files and use the in process plotter
 // to plot them.  This smokes the pants off gnuplot in terms of interactivity.
@@ -112,8 +113,9 @@
  public:
   NodePlotter() : nodes_(Nodes()) {
     plotter_.AddFigure("Time");
-    if (!FLAGS_offsets.empty()) {
-      for (std::string_view nodeoffset : absl::StrSplit(FLAGS_offsets, ',')) {
+    if (!absl::GetFlag(FLAGS_offsets).empty()) {
+      for (std::string_view nodeoffset :
+           absl::StrSplit(absl::GetFlag(FLAGS_offsets), ',')) {
         std::vector<std::string_view> node_offset =
             absl::StrSplit(nodeoffset, '=');
         CHECK_EQ(node_offset.size(), 2u);
@@ -284,7 +286,7 @@
                        .color = "yellow",
                        .point_size = 2.0});
 
-  if (FLAGS_samples) {
+  if (absl::GetFlag(FLAGS_samples)) {
     plotter_.AddLine(samplefile12.first, samplefile12.second,
                      Plotter::LineOptions{
                          .label = absl::StrCat("sample ", node1, " ", node2),
@@ -299,7 +301,7 @@
                      });
   }
 
-  if (FLAGS_bounds) {
+  if (absl::GetFlag(FLAGS_bounds)) {
     plotter_.AddLine(
         noncausalfile12.first, noncausalfile12.second,
         Plotter::LineOptions{.label = absl::StrCat("nc ", node1, " ", node2),
@@ -316,7 +318,7 @@
 int Main(int argc, const char *const *argv) {
   NodePlotter plotter;
 
-  if (FLAGS_all) {
+  if (absl::GetFlag(FLAGS_all)) {
     const std::vector<std::pair<std::string, std::string>> connections =
         NodeConnections();
     for (std::pair<std::string, std::string> ab : connections) {
diff --git a/aos/events/ping.cc b/aos/events/ping.cc
index 975f2e4..5ed85c7 100644
--- a/aos/events/ping.cc
+++ b/aos/events/ping.cc
@@ -1,20 +1,18 @@
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
 
 #include "aos/configuration.h"
 #include "aos/events/ping_lib.h"
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
-#include "aos/json_to_flatbuffer.h"
 
-DEFINE_string(config, "pingpong_config.json", "Path to the config.");
+ABSL_FLAG(std::string, config, "pingpong_config.json", "Path to the config.");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
   aos::EventLoop::SetDefaultVersionString("ping_version");
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
 
diff --git a/aos/events/ping_lib.cc b/aos/events/ping_lib.cc
index cd36378..8a65c84 100644
--- a/aos/events/ping_lib.cc
+++ b/aos/events/ping_lib.cc
@@ -1,13 +1,13 @@
 #include "aos/events/ping_lib.h"
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/log.h"
 
 #include "aos/events/ping_static.h"
 #include "aos/events/pong_static.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_int32(sleep_us, 10000, "Time to sleep between pings");
+ABSL_FLAG(int32_t, sleep_us, 10000, "Time to sleep between pings");
 
 namespace aos {
 
@@ -25,8 +25,9 @@
   }
 
   event_loop_->OnRun([this]() {
-    timer_handle_->Schedule(event_loop_->monotonic_now(),
-                            chrono::microseconds(FLAGS_sleep_us));
+    timer_handle_->Schedule(
+        event_loop_->monotonic_now(),
+        chrono::microseconds(absl::GetFlag(FLAGS_sleep_us)));
   });
 
   event_loop_->SetRuntimeRealtimePriority(5);
@@ -35,7 +36,7 @@
 void Ping::SendPing() {
   if (last_pong_value_ != count_ && (!quiet_ || VLOG_IS_ON(1))) {
     LOG(WARNING) << "Did not receive response to " << count_ << " within "
-                 << FLAGS_sleep_us << "us.";
+                 << absl::GetFlag(FLAGS_sleep_us) << "us.";
   }
   ++count_;
   aos::Sender<examples::PingStatic>::StaticBuilder builder =
diff --git a/aos/events/pingpong_test.cc b/aos/events/pingpong_test.cc
index c52e8eb..5905b73 100644
--- a/aos/events/pingpong_test.cc
+++ b/aos/events/pingpong_test.cc
@@ -1,4 +1,5 @@
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/ping_lib.h"
diff --git a/aos/events/pong.cc b/aos/events/pong.cc
index 9162567..ed09e70 100644
--- a/aos/events/pong.cc
+++ b/aos/events/pong.cc
@@ -1,4 +1,6 @@
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/ping_generated.h"
@@ -7,14 +9,14 @@
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 
-DEFINE_string(config, "pingpong_config.json", "Path to the config.");
+ABSL_FLAG(std::string, config, "pingpong_config.json", "Path to the config.");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
   aos::EventLoop::SetDefaultVersionString("pong_version");
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   ::aos::ShmEventLoop event_loop(&config.message());
 
diff --git a/aos/events/pong_lib.cc b/aos/events/pong_lib.cc
index 8fc3f62..52bcd38 100644
--- a/aos/events/pong_lib.cc
+++ b/aos/events/pong_lib.cc
@@ -1,13 +1,15 @@
 #include "aos/events/pong_lib.h"
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/log.h"
 
 #include "aos/events/event_loop.h"
 #include "aos/events/ping_static.h"
 #include "aos/events/pong_static.h"
 
-DEFINE_bool(fetch, false, "Poll & fetch messages instead of using a watcher.");
-DEFINE_uint32(fetch_period_ms, 10, "Frequency at which to fetch.");
+ABSL_FLAG(bool, fetch, false,
+          "Poll & fetch messages instead of using a watcher.");
+ABSL_FLAG(uint32_t, fetch_period_ms, 10, "Frequency at which to fetch.");
 
 namespace aos {
 
@@ -15,7 +17,7 @@
     : event_loop_(event_loop),
       fetcher_(event_loop_->MakeFetcher<examples::Ping>("/test")),
       sender_(event_loop_->MakeSender<examples::PongStatic>("/test")) {
-  if (FLAGS_fetch) {
+  if (absl::GetFlag(FLAGS_fetch)) {
     event_loop_
         ->AddPhasedLoop(
             [this](int) {
@@ -23,7 +25,7 @@
                 HandlePing(*fetcher_.get());
               }
             },
-            std::chrono::milliseconds(FLAGS_fetch_period_ms))
+            std::chrono::milliseconds(absl::GetFlag(FLAGS_fetch_period_ms)))
         ->set_name("pong");
   } else {
     event_loop_->MakeWatcher(
diff --git a/aos/events/shm_event_loop.cc b/aos/events/shm_event_loop.cc
index 8035235..e038498 100644
--- a/aos/events/shm_event_loop.cc
+++ b/aos/events/shm_event_loop.cc
@@ -10,7 +10,9 @@
 #include <iterator>
 #include <stdexcept>
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/aos_logging.h"
 #include "aos/events/epoll.h"
@@ -46,12 +48,12 @@
 // groups or others).
 // See https://man7.org/linux/man-pages/man2/umask.2.html for more details.
 // WITH THE DEFAULT UMASK YOU WONT ACTUALLY GET THESE PERMISSIONS :)
-DEFINE_uint32(permissions, 0770,
-              "Permissions to make shared memory files and folders, "
-              "affected by the process's umask. "
-              "See shm_event_loop.cc for more details.");
-DEFINE_string(application_name, Filename(program_invocation_name),
-              "The application name");
+ABSL_FLAG(uint32_t, permissions, 0770,
+          "Permissions to make shared memory files and folders, "
+          "affected by the process's umask. "
+          "See shm_event_loop.cc for more details.");
+ABSL_FLAG(std::string, application_name, Filename(program_invocation_name),
+          "The application name");
 
 namespace aos {
 
@@ -80,8 +82,8 @@
 ShmEventLoop::ShmEventLoop(const Configuration *configuration)
     : EventLoop(configuration),
       boot_uuid_(UUID::BootUUID()),
-      shm_base_(FLAGS_shm_base),
-      name_(FLAGS_application_name),
+      shm_base_(absl::GetFlag(FLAGS_shm_base)),
+      name_(absl::GetFlag(FLAGS_application_name)),
       node_(MaybeMyNode(configuration)) {
   // Ignore the wakeup signal by default. Otherwise, we have race conditions on
   // shutdown where a wakeup signal will uncleanly terminate the process.
@@ -103,7 +105,7 @@
                             const Channel *channel)
       : event_loop_(event_loop),
         channel_(channel),
-        lockless_queue_memory_(shm_base, FLAGS_permissions,
+        lockless_queue_memory_(shm_base, absl::GetFlag(FLAGS_permissions),
                                event_loop->configuration(), channel),
         reader_(lockless_queue_memory_.queue()) {
     context_.data = nullptr;
@@ -430,7 +432,7 @@
   explicit ShmSender(std::string_view shm_base, EventLoop *event_loop,
                      const Channel *channel)
       : RawSender(event_loop, channel),
-        lockless_queue_memory_(shm_base, FLAGS_permissions,
+        lockless_queue_memory_(shm_base, absl::GetFlag(FLAGS_permissions),
                                event_loop->configuration(), channel),
         lockless_queue_sender_(
             VerifySender(ipc_lib::LocklessQueueSender::Make(
diff --git a/aos/events/shm_event_loop.h b/aos/events/shm_event_loop.h
index 5da1632..5de4423 100644
--- a/aos/events/shm_event_loop.h
+++ b/aos/events/shm_event_loop.h
@@ -12,7 +12,7 @@
 #include "aos/ipc_lib/signalfd.h"
 #include "aos/stl_mutex/stl_mutex.h"
 
-DECLARE_string(application_name);
+ABSL_DECLARE_FLAG(std::string, application_name);
 
 namespace aos {
 namespace shm_event_loop_internal {
diff --git a/aos/events/shm_event_loop_test.cc b/aos/events/shm_event_loop_test.cc
index aae8f15..9665478 100644
--- a/aos/events/shm_event_loop_test.cc
+++ b/aos/events/shm_event_loop_test.cc
@@ -2,7 +2,9 @@
 
 #include <string_view>
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/event_loop_param_test.h"
@@ -18,20 +20,26 @@
  public:
   ShmEventLoopTestFactory() {
     // Clean up anything left there before.
-    unlink((FLAGS_shm_base + "/test/aos.TestMessage.v7").c_str());
-    unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v7").c_str());
-    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v7").c_str());
-    unlink((FLAGS_shm_base + "/test2/aos.TestMessage.v7").c_str());
-    unlink((FLAGS_shm_base + "/aos/aos.timing.Report.v7").c_str());
-    unlink((FLAGS_shm_base + "/aos/aos.logging.LogMessageFbs.v7").c_str());
+    unlink(
+        (absl::GetFlag(FLAGS_shm_base) + "/test/aos.TestMessage.v7").c_str());
+    unlink(
+        (absl::GetFlag(FLAGS_shm_base) + "/test1/aos.TestMessage.v7").c_str());
+    unlink(
+        (absl::GetFlag(FLAGS_shm_base) + "/test2/aos.TestMessage.v7").c_str());
+    unlink(
+        (absl::GetFlag(FLAGS_shm_base) + "/test2/aos.TestMessage.v7").c_str());
+    unlink(
+        (absl::GetFlag(FLAGS_shm_base) + "/aos/aos.timing.Report.v7").c_str());
+    unlink((absl::GetFlag(FLAGS_shm_base) + "/aos/aos.logging.LogMessageFbs.v7")
+               .c_str());
   }
 
-  ~ShmEventLoopTestFactory() { FLAGS_override_hostname = ""; }
+  ~ShmEventLoopTestFactory() { absl::SetFlag(&FLAGS_override_hostname, ""); }
 
   ::std::unique_ptr<EventLoop> Make(std::string_view name) override {
     if (configuration()->has_nodes()) {
-      FLAGS_override_hostname =
-          std::string(my_node()->hostname()->string_view());
+      absl::SetFlag(&FLAGS_override_hostname,
+                    std::string(my_node()->hostname()->string_view()));
     }
     ::std::unique_ptr<ShmEventLoop> loop(new ShmEventLoop(configuration()));
     loop->set_name(name);
@@ -40,8 +48,8 @@
 
   ::std::unique_ptr<EventLoop> MakePrimary(std::string_view name) override {
     if (configuration()->has_nodes()) {
-      FLAGS_override_hostname =
-          std::string(my_node()->hostname()->string_view());
+      absl::SetFlag(&FLAGS_override_hostname,
+                    std::string(my_node()->hostname()->string_view()));
     }
     ::std::unique_ptr<ShmEventLoop> loop =
         ::std::unique_ptr<ShmEventLoop>(new ShmEventLoop(configuration()));
diff --git a/aos/events/simple_channel.cc b/aos/events/simple_channel.cc
index 51d9ef6..72621bc 100644
--- a/aos/events/simple_channel.cc
+++ b/aos/events/simple_channel.cc
@@ -1,7 +1,7 @@
 #include "aos/events/simple_channel.h"
 
+#include "absl/log/check.h"
 #include "absl/strings/str_cat.h"
-#include "glog/logging.h"
 
 namespace aos {
 
diff --git a/aos/events/simulated_event_loop.h b/aos/events/simulated_event_loop.h
index 3bcd639..449ab71 100644
--- a/aos/events/simulated_event_loop.h
+++ b/aos/events/simulated_event_loop.h
@@ -11,7 +11,8 @@
 #include <vector>
 
 #include "absl/container/btree_map.h"
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/event_loop.h"
 #include "aos/events/event_scheduler.h"
diff --git a/aos/events/simulated_event_loop_test.cc b/aos/events/simulated_event_loop_test.cc
index 1588ede..9a1b9cc 100644
--- a/aos/events/simulated_event_loop_test.cc
+++ b/aos/events/simulated_event_loop_test.cc
@@ -4,6 +4,8 @@
 #include <functional>
 #include <string_view>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/event_loop_param_test.h"
@@ -479,10 +481,11 @@
 
 // Tests that watchers have latency in simulation.
 TEST(SimulatedEventLoopTest, WatcherTimingReport) {
+  absl::FlagSaver flag_saver;
   SimulatedEventLoopTestFactory factory;
   factory.set_send_delay(std::chrono::microseconds(50));
 
-  FLAGS_timing_report_ms = 1000;
+  absl::SetFlag(&FLAGS_timing_report_ms, 1000);
   auto loop1 = factory.MakePrimary("primary");
   loop1->MakeWatcher("/test", [](const TestMessage &) {});
 
diff --git a/aos/events/simulated_network_bridge.cc b/aos/events/simulated_network_bridge.cc
index fd2dead..af5c800 100644
--- a/aos/events/simulated_network_bridge.cc
+++ b/aos/events/simulated_network_bridge.cc
@@ -1,7 +1,8 @@
 #include "aos/events/simulated_network_bridge.h"
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/events/timing_report_dump.cc b/aos/events/timing_report_dump.cc
index bd80a04..b519f8d 100644
--- a/aos/events/timing_report_dump.cc
+++ b/aos/events/timing_report_dump.cc
@@ -1,5 +1,6 @@
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/log_reader.h"
@@ -7,11 +8,11 @@
 #include "aos/init.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_string(application, "",
-              "Application filter to use. Empty for no filter.");
-DEFINE_bool(stream, false, "Stream out all the timing reports in the log.");
-DEFINE_bool(accumulate, true,
-            "Display accumulation of all timing reports at end of log.");
+ABSL_FLAG(std::string, application, "",
+          "Application filter to use. Empty for no filter.");
+ABSL_FLAG(bool, stream, false, "Stream out all the timing reports in the log.");
+ABSL_FLAG(bool, accumulate, true,
+          "Display accumulation of all timing reports at end of log.");
 
 namespace aos {
 struct DumperState {
@@ -37,12 +38,14 @@
       std::unique_ptr<TimingReportDump> dumper =
           std::make_unique<TimingReportDump>(
               event_loop.get(),
-              FLAGS_accumulate ? TimingReportDump::AccumulateStatistics::kYes
-                               : TimingReportDump::AccumulateStatistics::kNo,
-              FLAGS_stream ? TimingReportDump::StreamResults::kYes
-                           : TimingReportDump::StreamResults::kNo);
-      if (!FLAGS_application.empty()) {
-        dumper->ApplicationFilter(FLAGS_application);
+              absl::GetFlag(FLAGS_accumulate)
+                  ? TimingReportDump::AccumulateStatistics::kYes
+                  : TimingReportDump::AccumulateStatistics::kNo,
+              absl::GetFlag(FLAGS_stream)
+                  ? TimingReportDump::StreamResults::kYes
+                  : TimingReportDump::StreamResults::kNo);
+      if (!absl::GetFlag(FLAGS_application).empty()) {
+        dumper->ApplicationFilter(absl::GetFlag(FLAGS_application));
       }
       dumpers.push_back({std::move(event_loop), std::move(dumper)});
     }
diff --git a/aos/events/timing_report_dump_lib.h b/aos/events/timing_report_dump_lib.h
index 02bfb54..0a2896c 100644
--- a/aos/events/timing_report_dump_lib.h
+++ b/aos/events/timing_report_dump_lib.h
@@ -3,8 +3,9 @@
 #include <map>
 #include <string>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/events/timing_statistics.cc b/aos/events/timing_statistics.cc
index ea3f2d2..5aff823 100644
--- a/aos/events/timing_statistics.cc
+++ b/aos/events/timing_statistics.cc
@@ -1,6 +1,7 @@
 #include "aos/events/timing_statistics.h"
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/event_loop_generated.h"
 
diff --git a/aos/fast_string_builder.h b/aos/fast_string_builder.h
index e9a4f27..b27ead1 100644
--- a/aos/fast_string_builder.h
+++ b/aos/fast_string_builder.h
@@ -5,9 +5,10 @@
 #include <string>
 #include <type_traits>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_format.h"
-#include "glog/logging.h"
 
 namespace aos {
 
diff --git a/aos/flatbuffer_utils.cc b/aos/flatbuffer_utils.cc
index afa1cb4..9021c78 100644
--- a/aos/flatbuffer_utils.cc
+++ b/aos/flatbuffer_utils.cc
@@ -1,8 +1,9 @@
 #include "aos/flatbuffer_utils.h"
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/minireflect.h"
 #include "flatbuffers/reflection_generated.h"
-#include "glog/logging.h"
 
 namespace aos {
 
diff --git a/aos/flatbuffer_utils.h b/aos/flatbuffer_utils.h
index 003f141..90a4c86 100644
--- a/aos/flatbuffer_utils.h
+++ b/aos/flatbuffer_utils.h
@@ -6,7 +6,6 @@
 
 #include "flatbuffers/flatbuffers.h"
 #include "flatbuffers/reflection_generated.h"
-#include "glog/logging.h"
 
 namespace aos {
 
diff --git a/aos/flatbuffers.cc b/aos/flatbuffers.cc
index 4f6497e..9fead13 100644
--- a/aos/flatbuffers.cc
+++ b/aos/flatbuffers.cc
@@ -1,6 +1,7 @@
 #include "aos/flatbuffers.h"
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 
diff --git a/aos/flatbuffers.h b/aos/flatbuffers.h
index f1ed626..4549e19 100644
--- a/aos/flatbuffers.h
+++ b/aos/flatbuffers.h
@@ -4,9 +4,10 @@
 #include <array>
 #include <string_view>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
 #include "flatbuffers/flatbuffers.h"  // IWYU pragma: export
-#include "glog/logging.h"
 
 #include "aos/containers/resizeable_buffer.h"
 #include "aos/ipc_lib/data_alignment.h"
diff --git a/aos/flatbuffers/BUILD b/aos/flatbuffers/BUILD
index e4f7d1d..f7e4670 100644
--- a/aos/flatbuffers/BUILD
+++ b/aos/flatbuffers/BUILD
@@ -11,7 +11,8 @@
         ":static_vector",
         "//aos:json_to_flatbuffer",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/strings:str_format",
     ],
@@ -32,8 +33,9 @@
         "//aos/containers:resizeable_buffer",
         "//aos/ipc_lib:data_alignment",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
         "@com_google_absl//absl/base",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -54,7 +56,8 @@
     deps = [
         ":base",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -67,7 +70,8 @@
         "//aos/containers:inlined_vector",
         "//aos/containers:sized_array",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/flatbuffers/base.cc b/aos/flatbuffers/base.cc
index f0e7a8b..77988da 100644
--- a/aos/flatbuffers/base.cc
+++ b/aos/flatbuffers/base.cc
@@ -4,6 +4,9 @@
 
 #include <iomanip>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
+
 namespace aos::fbs {
 
 namespace {
diff --git a/aos/flatbuffers/base.h b/aos/flatbuffers/base.h
index 6e93f93..a0d3810 100644
--- a/aos/flatbuffers/base.h
+++ b/aos/flatbuffers/base.h
@@ -12,9 +12,10 @@
 #include <utility>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
 #include "flatbuffers/base.h"
-#include "glog/logging.h"
 
 #include "aos/containers/resizeable_buffer.h"
 #include "aos/ipc_lib/data_alignment.h"
diff --git a/aos/flatbuffers/generate.cc b/aos/flatbuffers/generate.cc
index 9a2e5fd..4c76785 100644
--- a/aos/flatbuffers/generate.cc
+++ b/aos/flatbuffers/generate.cc
@@ -1,7 +1,7 @@
 #include <stdlib.h>
 
+#include "absl/flags/flag.h"
 #include "flatbuffers/reflection_generated.h"
-#include "gflags/gflags.h"
 
 #include "aos/flatbuffers.h"
 #include "aos/flatbuffers/static_flatbuffers.h"
@@ -9,19 +9,22 @@
 #include "aos/json_to_flatbuffer.h"
 #include "aos/util/file.h"
 
-DEFINE_string(reflection_bfbs, "", "Path to the .bfbs reflection file.");
-DEFINE_string(output_file, "", "Path to the output header to write.");
-DEFINE_string(base_file_name, "",
-              "Name of the base file to generate code for as used by the "
-              "reflection::Schema object.");
+ABSL_FLAG(std::string, reflection_bfbs, "",
+          "Path to the .bfbs reflection file.");
+ABSL_FLAG(std::string, output_file, "", "Path to the output header to write.");
+ABSL_FLAG(std::string, base_file_name, "",
+          "Name of the base file to generate code for as used by the "
+          "reflection::Schema object.");
 
 namespace aos::fbs {
 int Main() {
   aos::FlatbufferVector<reflection::Schema> schema =
-      aos::FileToFlatbuffer<reflection::Schema>(FLAGS_reflection_bfbs);
+      aos::FileToFlatbuffer<reflection::Schema>(
+          absl::GetFlag(FLAGS_reflection_bfbs));
   aos::util::WriteStringToFileOrDie(
-      FLAGS_output_file,
-      GenerateCodeForRootTableFile(&schema.message(), FLAGS_base_file_name));
+      absl::GetFlag(FLAGS_output_file),
+      GenerateCodeForRootTableFile(&schema.message(),
+                                   absl::GetFlag(FLAGS_base_file_name)));
   return EXIT_SUCCESS;
 }
 }  // namespace aos::fbs
diff --git a/aos/flatbuffers/static_flatbuffers.cc b/aos/flatbuffers/static_flatbuffers.cc
index 449bcbc..e3130bb 100644
--- a/aos/flatbuffers/static_flatbuffers.cc
+++ b/aos/flatbuffers/static_flatbuffers.cc
@@ -10,6 +10,8 @@
 #include <utility>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
@@ -19,7 +21,6 @@
 #include "flatbuffers/base.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #include "aos/flatbuffers/base.h"
 #include "aos/json_to_flatbuffer.h"
diff --git a/aos/flatbuffers/static_flatbuffers_test.cc b/aos/flatbuffers/static_flatbuffers_test.cc
index 187c72a..aee8067 100644
--- a/aos/flatbuffers/static_flatbuffers_test.cc
+++ b/aos/flatbuffers/static_flatbuffers_test.cc
@@ -12,6 +12,8 @@
 #include <utility>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 #include "absl/types/span.h"
@@ -23,7 +25,6 @@
 #include "flatbuffers/stl_emulation.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/flatbuffers.h"
diff --git a/aos/flatbuffers/static_table.h b/aos/flatbuffers/static_table.h
index a7f96d1..cd3ae5c 100644
--- a/aos/flatbuffers/static_table.h
+++ b/aos/flatbuffers/static_table.h
@@ -3,8 +3,9 @@
 #include <algorithm>
 #include <span>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/base.h"
-#include "glog/logging.h"
 
 #include "aos/flatbuffers/base.h"
 namespace aos::fbs {
diff --git a/aos/flatbuffers/static_vector.h b/aos/flatbuffers/static_vector.h
index f0c48cd..c835864 100644
--- a/aos/flatbuffers/static_vector.h
+++ b/aos/flatbuffers/static_vector.h
@@ -2,9 +2,10 @@
 #define AOS_FLATBUFFERS_STATIC_VECTOR_H_
 #include <span>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/base.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #include "aos/containers/inlined_vector.h"
 #include "aos/containers/sized_array.h"
diff --git a/aos/ftrace.cc b/aos/ftrace.cc
index 37dc147..c731264 100644
--- a/aos/ftrace.cc
+++ b/aos/ftrace.cc
@@ -3,16 +3,18 @@
 #include <cstdarg>
 #include <cstdio>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
 #include "absl/strings/str_cat.h"
 
-DEFINE_bool(enable_ftrace, false,
-            "If false, disable logging to /sys/kernel/tracing/trace_marker");
+ABSL_FLAG(bool, enable_ftrace, false,
+          "If false, disable logging to /sys/kernel/tracing/trace_marker");
 
 namespace aos {
 
 namespace {
 int MaybeCheckOpen(const char *file) {
-  if (!FLAGS_enable_ftrace) return -1;
+  if (!absl::GetFlag(FLAGS_enable_ftrace)) return -1;
   int result =
       open(absl::StrCat("/sys/kernel/tracing/", file).c_str(), O_WRONLY);
   if (result == -1) {
@@ -42,6 +44,13 @@
   }
 }
 
+void Ftrace::TurnOffOrDie() {
+  CHECK(on_fd_ != -1)
+      << ": Failed to open tracing_on earlier, cannot turn off tracing";
+  char zero = '0';
+  CHECK_EQ(write(on_fd_, &zero, 1), 1) << ": Failed to turn tracing off";
+}
+
 void Ftrace::FormatMessage(const char *format, ...) {
   if (message_fd_ == -1) {
     return;
diff --git a/aos/ftrace.h b/aos/ftrace.h
index 3b5326f..e454838 100644
--- a/aos/ftrace.h
+++ b/aos/ftrace.h
@@ -8,8 +8,6 @@
 
 #include <string_view>
 
-#include "glog/logging.h"
-
 namespace aos {
 
 // Manages interacting with ftrace. Silently hides many errors, because they are
@@ -33,12 +31,7 @@
 
   // Turns tracing off, or CHECK-fails if tracing is inaccessible. Does nothing
   // if tracing is currently available but off.
-  void TurnOffOrDie() {
-    CHECK(on_fd_ != -1)
-        << ": Failed to open tracing_on earlier, cannot turn off tracing";
-    char zero = '0';
-    CHECK_EQ(write(on_fd_, &zero, 1), 1) << ": Failed to turn tracing off";
-  }
+  void TurnOffOrDie();
 
  private:
   int message_fd_, on_fd_;
diff --git a/aos/init.cc b/aos/init.cc
index 579ad33..b51dc1c 100644
--- a/aos/init.cc
+++ b/aos/init.cc
@@ -11,29 +11,61 @@
 #include <cstdlib>
 #include <cstring>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/debugging/failure_signal_handler.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/parse.h"
+#include "absl/log/check.h"
+#include "absl/log/flags.h"
+#include "absl/log/globals.h"
+#include "absl/log/initialize.h"
+#include "absl/log/log.h"
 
 #include "aos/realtime.h"
 #include "aos/uuid.h"
 
-DEFINE_bool(coredump, false, "If true, write core dumps on failure.");
+ABSL_FLAG(bool, coredump, false, "If true, write core dumps on failure.");
+ABSL_FLAG(bool, backtrace, true, "If true, print backtraces out on crashes.");
 
 namespace aos {
 namespace {
-bool initialized = false;
+std::atomic<bool> initialized{false};
 }  // namespace
 
 bool IsInitialized() { return initialized; }
 
 void InitGoogle(int *argc, char ***argv) {
   CHECK(!IsInitialized()) << "Only initialize once.";
-  FLAGS_logtostderr = true;
-  google::InitGoogleLogging((*argv)[0]);
-  gflags::ParseCommandLineFlags(argc, argv, true);
-  google::InstallFailureSignalHandler();
+  absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+  std::vector<char *> positional_arguments =
+      absl::ParseCommandLine(*argc, *argv);
 
-  if (FLAGS_coredump) {
+  {
+    const std::vector<absl::UnrecognizedFlag> unrecognized_flags;
+    absl::ReportUnrecognizedFlags(unrecognized_flags);
+    if (!unrecognized_flags.empty()) {
+      for (const absl::UnrecognizedFlag &flag : unrecognized_flags) {
+        LOG(ERROR) << "Unrecognized flag " << flag.flag_name;
+      }
+      LOG(FATAL) << "Found unrecognized flags, aborting";
+    }
+  }
+
+  CHECK_LE(positional_arguments.size(), static_cast<size_t>(*argc));
+  for (size_t i = 0; i < positional_arguments.size(); ++i) {
+    (*argv)[i] = positional_arguments[i];
+  }
+  *argc = positional_arguments.size();
+
+  absl::InitializeLog();
+
+  if (absl::GetFlag(FLAGS_backtrace)) {
+    absl::InitializeSymbolizer((*argv)[0]);
+    absl::FailureSignalHandlerOptions options;
+    absl::InstallFailureSignalHandler(options);
+  }
+
+  if (absl::GetFlag(FLAGS_coredump)) {
     WriteCoreDumps();
   }
 
diff --git a/aos/init.rs b/aos/init.rs
index 8fdb3d1..27b1046 100644
--- a/aos/init.rs
+++ b/aos/init.rs
@@ -262,14 +262,9 @@
     #[test]
     fn set_cxx_flag() {
         let _guard = MUTEX.lock();
-        let app = App::parse_with_cpp_flags_from(&[
-            "mytest",
-            "--alsologtostderr",
-            "true",
-            "--myarg",
-            "23",
-        ]);
+        let app =
+            App::parse_with_cpp_flags_from(&["mytest", "--stderrthreshold", "1", "--myarg", "23"]);
         assert_eq!(app.myarg, 23);
-        assert_eq!(CxxFlag::get_option("alsologtostderr"), "true");
+        assert_eq!(CxxFlag::get_option("stderrthreshold"), "1");
     }
 }
diff --git a/aos/init_for_rust.cc b/aos/init_for_rust.cc
index 9af4d83..1ede457 100644
--- a/aos/init_for_rust.cc
+++ b/aos/init_for_rust.cc
@@ -1,16 +1,19 @@
 #include "aos/init_for_rust.h"
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#include "absl/log/check.h"
+#include "absl/log/initialize.h"
+#include "absl/log/log.h"
 
 #include "aos/init.h"
 
 namespace aos {
 
-void InitFromRust(const char *argv0) {
-  CHECK(!IsInitialized()) << "Only initialize once.";
+void InitFromRust(const char * /*argv0*/) {
+  CHECK(!aos::IsInitialized()) << "Only initialize once.";
 
-  google::InitGoogleLogging(argv0);
+  absl::InitializeLog();
 
   // TODO(Brian): Where should Rust binaries be configured to write coredumps?
 
@@ -20,16 +23,50 @@
 }
 
 std::vector<FlagInfo> GetCppFlags() {
-  std::vector<gflags::CommandLineFlagInfo> info;
-  gflags::GetAllFlags(&info);
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag *> info =
+      absl::GetAllFlags();
   std::vector<FlagInfo> out;
   for (const auto &flag : info) {
+    std::string type;
+    if (flag.second->IsOfType<float>()) {
+      type = "float";
+    } else if (flag.second->IsOfType<double>()) {
+      type = "double";
+    } else if (flag.second->IsOfType<bool>()) {
+      type = "bool";
+    } else if (flag.second->IsOfType<uint8_t>()) {
+      type = "uint8_t";
+    } else if (flag.second->IsOfType<int8_t>()) {
+      type = "int8_t";
+    } else if (flag.second->IsOfType<uint16_t>()) {
+      type = "uint16_t";
+    } else if (flag.second->IsOfType<int16_t>()) {
+      type = "int16_t";
+    } else if (flag.second->IsOfType<uint32_t>()) {
+      type = "uint32_t";
+    } else if (flag.second->IsOfType<int32_t>()) {
+      type = "int32_t";
+    } else if (flag.second->IsOfType<uint64_t>()) {
+      type = "uint64_t";
+    } else if (flag.second->IsOfType<int64_t>()) {
+      type = "int64_t";
+    } else if (flag.second->IsOfType<std::string>()) {
+      type = "string";
+    } else if (flag.second->IsOfType<std::vector<std::string>>()) {
+      type = "vector<string>";
+    } else {
+      LOG(FATAL) << "Unknown type for flag " << flag.second->Name()
+                 << " in file " << flag.second->Filename();
+    }
+
+    LOG(INFO) << "Reporting flag " << flag.second->Name() << " " << type << " "
+              << flag.second->DefaultValue();
     FlagInfo out_flag = {
-        .name_ = flag.name,
-        .type_ = flag.type,
-        .description_ = flag.description,
-        .default_value_ = flag.default_value,
-        .filename_ = flag.filename,
+        .name_ = std::string(flag.second->Name()),
+        .type_ = type,
+        .description_ = flag.second->Help(),
+        .default_value_ = flag.second->DefaultValue(),
+        .filename_ = flag.second->Filename(),
     };
     out.push_back(out_flag);
   }
@@ -37,13 +74,21 @@
 }
 
 bool SetCommandLineOption(const char *name, const char *value) {
-  return !gflags::SetCommandLineOption(name, value).empty();
+  absl::CommandLineFlag *flag = absl::FindCommandLineFlag(name);
+  if (flag == nullptr) {
+    return false;
+  }
+
+  std::string error;
+  bool result = flag->ParseFrom(value, &error);
+  return result;
 }
 
 std::string GetCommandLineOption(const char *name) {
-  std::string out;
-  CHECK(gflags::GetCommandLineOption(name, &out)) << "Unknown flag " << name;
-  return out;
+  absl::CommandLineFlag *flag = absl::FindCommandLineFlag(name);
+  CHECK(flag != nullptr) << "Unknown flag " << name;
+
+  return flag->CurrentValue();
 }
 
 }  // namespace aos
diff --git a/aos/ipc_lib/BUILD b/aos/ipc_lib/BUILD
index bae23b8..2ecd167 100644
--- a/aos/ipc_lib/BUILD
+++ b/aos/ipc_lib/BUILD
@@ -15,8 +15,9 @@
         ":shm_observers",
         "//aos:macros",
         "//aos/util:compiler_memory_barrier",
-        "@com_github_google_glog//:glog",
         "@com_google_absl//absl/base",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -53,7 +54,8 @@
         ":aos_sync",
         ":core_lib",
         ":shared_mem_types",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -105,7 +107,7 @@
         "//aos:init",
         "//aos/logging",
         "//aos/mutex",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -120,7 +122,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -134,7 +137,8 @@
         ":signalfd",
         "//aos/testing:googletest",
         "//aos/testing:test_logging",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -149,7 +153,8 @@
     visibility = ["//visibility:public"],
     deps = [
         ":shm_observers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -160,7 +165,8 @@
     deps = [
         ":index32",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -172,7 +178,8 @@
     visibility = ["//visibility:public"],
     deps = [
         ":shm_observers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -183,7 +190,8 @@
     deps = [
         ":index",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -213,7 +221,8 @@
         "//aos/time",
         "//aos/util:compiler_memory_barrier",
         "//aos/util:top",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:span",
     ],
@@ -266,6 +275,8 @@
     name = "lockless_queue_test",
     timeout = "eternal",
     srcs = ["lockless_queue_test.cc"],
+    # We don't want all the signal handlers registered, otherwise we can't fork.
+    args = ["--nobacktrace"],
     shard_count = 10,
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
@@ -283,6 +294,8 @@
 cc_test(
     name = "lockless_queue_death_test",
     srcs = ["lockless_queue_death_test.cc"],
+    # We don't want all the signal handlers registered, otherwise we can't fork.
+    args = ["--nobacktrace"],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         ":event",
@@ -307,7 +320,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -320,7 +334,8 @@
         "//aos:realtime",
         "//aos/logging",
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -334,7 +349,7 @@
         ":latency_lib",
         "//aos:init",
         "//aos/events:epoll",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -349,7 +364,7 @@
         "//aos:condition",
         "//aos:init",
         "//aos/mutex",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -363,7 +378,7 @@
         ":latency_lib",
         "//aos:init",
         "//aos/events:epoll",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -377,7 +392,7 @@
         ":latency_lib",
         "//aos:init",
         "//aos/events:epoll",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -407,7 +422,8 @@
         "//aos/ipc_lib:aos_sync",
         "//aos/time",
         "//aos/type_traits",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -442,7 +458,7 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
diff --git a/aos/ipc_lib/aos_sync.cc b/aos/ipc_lib/aos_sync.cc
index 78c6b2c..5642434 100644
--- a/aos/ipc_lib/aos_sync.cc
+++ b/aos/ipc_lib/aos_sync.cc
@@ -25,7 +25,8 @@
 #endif
 
 #include "absl/base/call_once.h"
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/macros.h"
 #include "aos/util/compiler_memory_barrier.h"
diff --git a/aos/ipc_lib/data_alignment.h b/aos/ipc_lib/data_alignment.h
index 3bf38ce..9cbfa23 100644
--- a/aos/ipc_lib/data_alignment.h
+++ b/aos/ipc_lib/data_alignment.h
@@ -1,7 +1,8 @@
 #ifndef AOS_IPC_LIB_DATA_ALIGNMENT_H_
 #define AOS_IPC_LIB_DATA_ALIGNMENT_H_
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 
diff --git a/aos/ipc_lib/event.cc b/aos/ipc_lib/event.cc
index fd5bcaf..b62bdb2 100644
--- a/aos/ipc_lib/event.cc
+++ b/aos/ipc_lib/event.cc
@@ -6,7 +6,8 @@
 #include <ostream>
 #include <ratio>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/type_traits/type_traits.h"
 
diff --git a/aos/ipc_lib/eventfd_latency.cc b/aos/ipc_lib/eventfd_latency.cc
index 4a5616f..e35f8fc 100644
--- a/aos/ipc_lib/eventfd_latency.cc
+++ b/aos/ipc_lib/eventfd_latency.cc
@@ -10,10 +10,12 @@
 #include <ratio>
 #include <thread>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/epoll.h"
+#include "aos/init.h"
 #include "aos/ipc_lib/latency_lib.h"
 #include "aos/logging/implementations.h"
 #include "aos/realtime.h"
@@ -23,16 +25,16 @@
 // It measures both latency of a random timer thread, and latency of the
 // pipe.
 
-DEFINE_int32(seconds, 10, "Duration of the test to run");
-DEFINE_int32(
-    latency_threshold, 1000,
+ABSL_FLAG(int32_t, seconds, 10, "Duration of the test to run");
+ABSL_FLAG(
+    int32_t, latency_threshold, 1000,
     "Disable tracing when anything takes more than this many microseoncds");
-DEFINE_int32(core, 7, "Core to pin to");
-DEFINE_int32(sender_priority, 53, "RT priority to send at");
-DEFINE_int32(receiver_priority, 52, "RT priority to receive at");
-DEFINE_int32(timer_priority, 51, "RT priority to spin the timer at");
+ABSL_FLAG(int32_t, core, 7, "Core to pin to");
+ABSL_FLAG(int32_t, sender_priority, 53, "RT priority to send at");
+ABSL_FLAG(int32_t, receiver_priority, 52, "RT priority to receive at");
+ABSL_FLAG(int32_t, timer_priority, 51, "RT priority to spin the timer at");
 
-DEFINE_bool(log_latency, false, "If true, log the latency");
+ABSL_FLAG(bool, log_latency, false, "If true, log the latency");
 
 namespace chrono = ::std::chrono;
 
@@ -40,15 +42,15 @@
 
 void SenderThread(int fd) {
   const monotonic_clock::time_point end_time =
-      monotonic_clock::now() + chrono::seconds(FLAGS_seconds);
+      monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds));
   // Standard mersenne_twister_engine seeded with 0
   ::std::mt19937 generator(0);
 
   // Sleep between 1 and 15 ms.
   ::std::uniform_int_distribution<> distribution(1000, 15000);
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_sender_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_sender_priority));
   while (true) {
     const monotonic_clock::time_point wakeup_time =
         monotonic_clock::now() + chrono::microseconds(distribution(generator));
@@ -108,21 +110,22 @@
 
     max_wakeup_latency = ::std::max(wakeup_latency, max_wakeup_latency);
 
-    if (wakeup_latency > chrono::microseconds(FLAGS_latency_threshold)) {
+    if (wakeup_latency >
+        chrono::microseconds(absl::GetFlag(FLAGS_latency_threshold))) {
       t.Stop();
       AOS_LOG(INFO, "Stopped tracing, latency %" PRId64 "\n",
               static_cast<int64_t>(wakeup_latency.count()));
     }
 
-    if (FLAGS_log_latency) {
+    if (absl::GetFlag(FLAGS_log_latency)) {
       AOS_LOG(INFO, "dt: %8d.%03d\n",
               static_cast<int>(wakeup_latency.count() / 1000),
               static_cast<int>(wakeup_latency.count() % 1000));
     }
   });
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_receiver_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_receiver_priority));
   epoll.Run();
   UnsetCurrentThreadRealtimePriority();
   epoll.DeleteFd(fd);
@@ -141,8 +144,9 @@
 int Main(int /*argc*/, char ** /*argv*/) {
   AOS_LOG(INFO, "Main!\n");
   ::std::thread t([]() {
-    TimerThread(monotonic_clock::now() + chrono::seconds(FLAGS_seconds),
-                FLAGS_timer_priority);
+    TimerThread(
+        monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds)),
+        absl::GetFlag(FLAGS_timer_priority));
   });
 
   int fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
@@ -162,7 +166,7 @@
 }  // namespace aos
 
 int main(int argc, char **argv) {
-  ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+  aos::InitGoogle(&argc, &argv);
 
   return ::aos::Main(argc, argv);
 }
diff --git a/aos/ipc_lib/futex_latency.cc b/aos/ipc_lib/futex_latency.cc
index eee015e..f6264aa 100644
--- a/aos/ipc_lib/futex_latency.cc
+++ b/aos/ipc_lib/futex_latency.cc
@@ -8,26 +8,28 @@
 #include <ratio>
 #include <thread>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/condition.h"
+#include "aos/init.h"
 #include "aos/ipc_lib/latency_lib.h"
 #include "aos/logging/implementations.h"
 #include "aos/mutex/mutex.h"
 #include "aos/realtime.h"
 #include "aos/time/time.h"
 
-DEFINE_int32(seconds, 10, "Duration of the test to run");
-DEFINE_int32(
-    latency_threshold, 1000,
+ABSL_FLAG(int32_t, seconds, 10, "Duration of the test to run");
+ABSL_FLAG(
+    int32_t, latency_threshold, 1000,
     "Disable tracing when anything takes more than this many microseoncds");
-DEFINE_int32(core, 7, "Core to pin to");
-DEFINE_int32(sender_priority, 53, "RT priority to send at");
-DEFINE_int32(receiver_priority, 52, "RT priority to receive at");
-DEFINE_int32(timer_priority, 51, "RT priority to spin the timer at");
+ABSL_FLAG(int32_t, core, 7, "Core to pin to");
+ABSL_FLAG(int32_t, sender_priority, 53, "RT priority to send at");
+ABSL_FLAG(int32_t, receiver_priority, 52, "RT priority to receive at");
+ABSL_FLAG(int32_t, timer_priority, 51, "RT priority to spin the timer at");
 
-DEFINE_bool(log_latency, false, "If true, log the latency");
+ABSL_FLAG(bool, log_latency, false, "If true, log the latency");
 
 const uint32_t kSignalNumber = SIGRTMIN + 1;
 const uint32_t kQuitSignalNumber = SIGRTMIN + 2;
@@ -49,15 +51,15 @@
 
 void SenderThread(WakeupData *data) {
   const monotonic_clock::time_point end_time =
-      monotonic_clock::now() + chrono::seconds(FLAGS_seconds);
+      monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds));
   // Standard mersenne_twister_engine seeded with 0
   ::std::mt19937 generator(0);
 
   // Sleep between 1 and 15 ms.
   ::std::uniform_int_distribution<> distribution(1000, 15000);
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_sender_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_sender_priority));
   while (true) {
     const monotonic_clock::time_point wakeup_time =
         monotonic_clock::now() + chrono::microseconds(distribution(generator));
@@ -93,8 +95,8 @@
   chrono::nanoseconds sum_latency = chrono::nanoseconds(0);
   int latency_count = 0;
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_receiver_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_receiver_priority));
   while (true) {
     chrono::nanoseconds wakeup_latency;
     {
@@ -118,13 +120,14 @@
 
     max_wakeup_latency = ::std::max(wakeup_latency, max_wakeup_latency);
 
-    if (wakeup_latency > chrono::microseconds(FLAGS_latency_threshold)) {
+    if (wakeup_latency >
+        chrono::microseconds(absl::GetFlag(FLAGS_latency_threshold))) {
       t.Stop();
       AOS_LOG(INFO, "Stopped tracing, latency %" PRId64 "\n",
               static_cast<int64_t>(wakeup_latency.count()));
     }
 
-    if (FLAGS_log_latency) {
+    if (absl::GetFlag(FLAGS_log_latency)) {
       AOS_LOG(INFO, "dt: %8d.%03d\n",
               static_cast<int>(wakeup_latency.count() / 1000),
               static_cast<int>(wakeup_latency.count() % 1000));
@@ -148,8 +151,9 @@
 
   AOS_LOG(INFO, "Main!\n");
   ::std::thread t([]() {
-    TimerThread(monotonic_clock::now() + chrono::seconds(FLAGS_seconds),
-                FLAGS_timer_priority);
+    TimerThread(
+        monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds)),
+        absl::GetFlag(FLAGS_timer_priority));
   });
 
   ::std::thread st([&data]() { SenderThread(&data); });
@@ -164,7 +168,7 @@
 }  // namespace aos
 
 int main(int argc, char **argv) {
-  ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+  aos::InitGoogle(&argc, &argv);
 
   return ::aos::Main(argc, argv);
 }
diff --git a/aos/ipc_lib/index.h b/aos/ipc_lib/index.h
index c4cc64a..575d113 100644
--- a/aos/ipc_lib/index.h
+++ b/aos/ipc_lib/index.h
@@ -5,7 +5,8 @@
 
 #include <limits>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/shm_observers.h"
 
diff --git a/aos/ipc_lib/index_test.cc b/aos/ipc_lib/index_test.cc
index 334696e..a7f0c85 100644
--- a/aos/ipc_lib/index_test.cc
+++ b/aos/ipc_lib/index_test.cc
@@ -2,7 +2,8 @@
 
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 namespace aos::ipc_lib::testing {
diff --git a/aos/ipc_lib/ipc_comparison.cc b/aos/ipc_lib/ipc_comparison.cc
index 8bb78d7..e5905ac 100644
--- a/aos/ipc_lib/ipc_comparison.cc
+++ b/aos/ipc_lib/ipc_comparison.cc
@@ -26,7 +26,8 @@
 #include <thread>
 #include <utility>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/condition.h"
 #include "aos/init.h"
@@ -36,14 +37,15 @@
 #include "aos/realtime.h"
 #include "aos/time/time.h"
 
-DEFINE_string(method, "", "Which IPC method to use");
-DEFINE_int32(messages, 1000000, "How many messages to send back and forth");
-DEFINE_int32(client_cpu, 0, "CPU to pin client to");
-DEFINE_int32(server_cpu, 0, "CPU to pin server to");
-DEFINE_int32(client_priority, 1,
-             "Realtime priority for client. Negative for don't change");
-DEFINE_int32(server_priority, 1,
-             "Realtime priority for server. Negative for don't change");
+ABSL_FLAG(std::string, method, "", "Which IPC method to use");
+ABSL_FLAG(int32_t, messages, 1000000,
+          "How many messages to send back and forth");
+ABSL_FLAG(int32_t, client_cpu, 0, "CPU to pin client to");
+ABSL_FLAG(int32_t, server_cpu, 0, "CPU to pin server to");
+ABSL_FLAG(int32_t, client_priority, 1,
+          "Realtime priority for client. Negative for don't change");
+ABSL_FLAG(int32_t, server_priority, 1,
+          "Realtime priority for server. Negative for don't change");
 
 namespace aos {
 
@@ -761,63 +763,65 @@
   sem_t *ping_sem_, *pong_sem_;
 };
 
-int Main(int /*argc*/, char **argv) {
+int Main() {
   ::std::unique_ptr<PingPongerInterface> ping_ponger;
-  if (FLAGS_method == "pipe") {
+  if (absl::GetFlag(FLAGS_method) == "pipe") {
     ping_ponger.reset(new PipePingPonger());
-  } else if (FLAGS_method == "named_pipe") {
+  } else if (absl::GetFlag(FLAGS_method) == "named_pipe") {
     ping_ponger.reset(new NamedPipePingPonger());
-  } else if (FLAGS_method == "aos_mutex") {
+  } else if (absl::GetFlag(FLAGS_method) == "aos_mutex") {
     ping_ponger.reset(new AOSMutexPingPonger());
-  } else if (FLAGS_method == "aos_event") {
+  } else if (absl::GetFlag(FLAGS_method) == "aos_event") {
     ping_ponger.reset(new AOSEventPingPonger());
-  } else if (FLAGS_method == "pthread_mutex") {
+  } else if (absl::GetFlag(FLAGS_method) == "pthread_mutex") {
     ping_ponger.reset(new PthreadMutexPingPonger(false, false));
-  } else if (FLAGS_method == "pthread_mutex_pshared") {
+  } else if (absl::GetFlag(FLAGS_method) == "pthread_mutex_pshared") {
     ping_ponger.reset(new PthreadMutexPingPonger(true, false));
-  } else if (FLAGS_method == "pthread_mutex_pshared_pi") {
+  } else if (absl::GetFlag(FLAGS_method) == "pthread_mutex_pshared_pi") {
     ping_ponger.reset(new PthreadMutexPingPonger(true, true));
-  } else if (FLAGS_method == "pthread_mutex_pi") {
+  } else if (absl::GetFlag(FLAGS_method) == "pthread_mutex_pi") {
     ping_ponger.reset(new PthreadMutexPingPonger(false, true));
-  } else if (FLAGS_method == "eventfd") {
+  } else if (absl::GetFlag(FLAGS_method) == "eventfd") {
     ping_ponger.reset(new EventFDPingPonger());
-  } else if (FLAGS_method == "sysv_semaphore") {
+  } else if (absl::GetFlag(FLAGS_method) == "sysv_semaphore") {
     ping_ponger.reset(new SysvSemaphorePingPonger());
-  } else if (FLAGS_method == "sysv_queue") {
+  } else if (absl::GetFlag(FLAGS_method) == "sysv_queue") {
     ping_ponger.reset(new SysvQueuePingPonger());
-  } else if (FLAGS_method == "posix_semaphore_unnamed_shared") {
+  } else if (absl::GetFlag(FLAGS_method) == "posix_semaphore_unnamed_shared") {
     ping_ponger.reset(new PosixUnnamedSemaphorePingPonger(1));
-  } else if (FLAGS_method == "posix_semaphore_unnamed_unshared") {
+  } else if (absl::GetFlag(FLAGS_method) ==
+             "posix_semaphore_unnamed_unshared") {
     ping_ponger.reset(new PosixUnnamedSemaphorePingPonger(0));
-  } else if (FLAGS_method == "posix_semaphore_named") {
+  } else if (absl::GetFlag(FLAGS_method) == "posix_semaphore_named") {
     ping_ponger.reset(new PosixNamedSemaphorePingPonger());
-  } else if (FLAGS_method == "posix_queue") {
+  } else if (absl::GetFlag(FLAGS_method) == "posix_queue") {
     ping_ponger.reset(new PosixQueuePingPonger());
-  } else if (FLAGS_method == "unix_stream") {
+  } else if (absl::GetFlag(FLAGS_method) == "unix_stream") {
     ping_ponger.reset(new UnixPingPonger(SOCK_STREAM));
-  } else if (FLAGS_method == "unix_datagram") {
+  } else if (absl::GetFlag(FLAGS_method) == "unix_datagram") {
     ping_ponger.reset(new UnixPingPonger(SOCK_DGRAM));
-  } else if (FLAGS_method == "unix_seqpacket") {
+  } else if (absl::GetFlag(FLAGS_method) == "unix_seqpacket") {
     ping_ponger.reset(new UnixPingPonger(SOCK_SEQPACKET));
-  } else if (FLAGS_method == "tcp") {
+  } else if (absl::GetFlag(FLAGS_method) == "tcp") {
     ping_ponger.reset(new TCPPingPonger(false));
-  } else if (FLAGS_method == "tcp_nodelay") {
+  } else if (absl::GetFlag(FLAGS_method) == "tcp_nodelay") {
     ping_ponger.reset(new TCPPingPonger(true));
-  } else if (FLAGS_method == "udp") {
+  } else if (absl::GetFlag(FLAGS_method) == "udp") {
     ping_ponger.reset(new UDPPingPonger());
   } else {
-    fprintf(stderr, "Unknown IPC method to test '%s'\n", FLAGS_method.c_str());
-    ::gflags::ShowUsageWithFlags(argv[0]);
+    fprintf(stderr, "Unknown IPC method to test '%s'\n",
+            absl::GetFlag(FLAGS_method).c_str());
     return 1;
   }
 
   ::std::atomic<bool> done{false};
 
   ::std::thread server([&ping_ponger, &done]() {
-    if (FLAGS_server_priority > 0) {
-      SetCurrentThreadRealtimePriority(FLAGS_server_priority);
+    if (absl::GetFlag(FLAGS_server_priority) > 0) {
+      SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_server_priority));
     }
-    SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_server_cpu}));
+    SetCurrentThreadAffinity(
+        MakeCpusetFromCpus({absl::GetFlag(FLAGS_server_cpu)}));
 
     while (!done) {
       const PingPongerInterface::Data *data = ping_ponger->Wait();
@@ -829,10 +833,11 @@
     }
   });
 
-  if (FLAGS_client_priority > 0) {
-    SetCurrentThreadRealtimePriority(FLAGS_client_priority);
+  if (absl::GetFlag(FLAGS_client_priority) > 0) {
+    SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_client_priority));
   }
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_client_cpu}));
+  SetCurrentThreadAffinity(
+      MakeCpusetFromCpus({absl::GetFlag(FLAGS_client_cpu)}));
 
   // Warm everything up.
   for (int i = 0; i < 1000; ++i) {
@@ -843,7 +848,7 @@
 
   const monotonic_clock::time_point start = monotonic_clock::now();
 
-  for (int32_t i = 0; i < FLAGS_messages; ++i) {
+  for (int32_t i = 0; i < absl::GetFlag(FLAGS_messages); ++i) {
     PingPongerInterface::Data *to_send = ping_ponger->PingData();
     memset(*to_send, i % 123, sizeof(*to_send));
     const PingPongerInterface::Data *received = ping_ponger->Ping();
@@ -865,8 +870,10 @@
   server.join();
 
   AOS_LOG(INFO, "Took %f seconds to send %" PRId32 " messages\n",
-          ::aos::time::DurationInSeconds(end - start), FLAGS_messages);
-  const chrono::nanoseconds per_message = (end - start) / FLAGS_messages;
+          ::aos::time::DurationInSeconds(end - start),
+          absl::GetFlag(FLAGS_messages));
+  const chrono::nanoseconds per_message =
+      (end - start) / absl::GetFlag(FLAGS_messages);
   if (per_message >= chrono::seconds(1)) {
     AOS_LOG(INFO, "More than 1 second per message ?!?\n");
   } else {
@@ -880,7 +887,7 @@
 }  // namespace aos
 
 int main(int argc, char **argv) {
-  ::gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       ::std::string("Compares various forms of IPC. Usage:\n") + argv[0] +
       " --method=METHOD\n"
       "METHOD can be one of the following:\n"
@@ -905,7 +912,7 @@
       "\ttcp\n"
       "\ttcp_nodelay\n"
       "\tudp\n");
-  ::aos::InitGoogle(&argc, &argv);
+  aos::InitGoogle(&argc, &argv);
 
-  return ::aos::Main(argc, argv);
+  return ::aos::Main();
 }
diff --git a/aos/ipc_lib/latency_lib.h b/aos/ipc_lib/latency_lib.h
index 8206f3e..fe68941 100644
--- a/aos/ipc_lib/latency_lib.h
+++ b/aos/ipc_lib/latency_lib.h
@@ -5,7 +5,8 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/time/time.h"
 
diff --git a/aos/ipc_lib/lockless_queue.cc b/aos/ipc_lib/lockless_queue.cc
index ae3a493..986ca62 100644
--- a/aos/ipc_lib/lockless_queue.cc
+++ b/aos/ipc_lib/lockless_queue.cc
@@ -16,16 +16,17 @@
 #include <string>
 #include <string_view>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/escaping.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/ipc_lib/lockless_queue_memory.h"
 #include "aos/util/compiler_memory_barrier.h"
 
-DEFINE_bool(dump_lockless_queue_data, false,
-            "If true, print the data out when dumping the queue.");
-DECLARE_bool(skip_realtime_scheduler);
+ABSL_FLAG(bool, dump_lockless_queue_data, false,
+          "If true, print the data out when dumping the queue.");
+ABSL_DECLARE_FLAG(bool, skip_realtime_scheduler);
 
 namespace aos::ipc_lib {
 namespace {
@@ -821,7 +822,7 @@
       // Inline the setscheduler call rather than using aos/realtime.h.  This is
       // quite performance sensitive, and halves the time needed to send a
       // message when pi boosting is in effect.
-      if (!FLAGS_skip_realtime_scheduler) {
+      if (!absl::GetFlag(FLAGS_skip_realtime_scheduler)) {
         // TODO(austin): Do we need to boost the soft limit here too like we
         // were before?
         struct sched_param param;
@@ -859,7 +860,7 @@
 
     // Drop back down if we were boosted.
     if (max_priority > current_priority && current_priority > 0) {
-      if (!FLAGS_skip_realtime_scheduler) {
+      if (!absl::GetFlag(FLAGS_skip_realtime_scheduler)) {
         struct sched_param param;
         param.sched_priority = current_priority;
         PCHECK(sched_setscheduler(0, SCHED_FIFO, &param) == 0)
@@ -1643,7 +1644,7 @@
     }
     ::std::cout << "      data: {";
 
-    if (FLAGS_dump_lockless_queue_data) {
+    if (absl::GetFlag(FLAGS_dump_lockless_queue_data)) {
       const char *const m_data = m->data(memory->message_data_size());
       std::cout << absl::BytesToHexString(std::string_view(
           m_data, corrupt ? memory->message_data_size() : m->header.length));
diff --git a/aos/ipc_lib/lockless_queue.h b/aos/ipc_lib/lockless_queue.h
index ce067e6..1fdbb39 100644
--- a/aos/ipc_lib/lockless_queue.h
+++ b/aos/ipc_lib/lockless_queue.h
@@ -11,8 +11,9 @@
 #include <utility>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/events/context.h"
 #include "aos/ipc_lib/aos_sync.h"
diff --git a/aos/ipc_lib/lockless_queue_death_test.cc b/aos/ipc_lib/lockless_queue_death_test.cc
index c61c62c..fa2bdf6 100644
--- a/aos/ipc_lib/lockless_queue_death_test.cc
+++ b/aos/ipc_lib/lockless_queue_death_test.cc
@@ -8,7 +8,8 @@
 #include <optional>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/context.h"
diff --git a/aos/ipc_lib/lockless_queue_stepping.cc b/aos/ipc_lib/lockless_queue_stepping.cc
index a7bd233..8608ad5 100644
--- a/aos/ipc_lib/lockless_queue_stepping.cc
+++ b/aos/ipc_lib/lockless_queue_stepping.cc
@@ -21,7 +21,8 @@
 #include <thread>
 #include <utility>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/ipc_lib/aos_sync.h"
diff --git a/aos/ipc_lib/lockless_queue_test.cc b/aos/ipc_lib/lockless_queue_test.cc
index 4169c93..bdb9755 100644
--- a/aos/ipc_lib/lockless_queue_test.cc
+++ b/aos/ipc_lib/lockless_queue_test.cc
@@ -17,7 +17,7 @@
 #include <thread>
 #include <type_traits>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/epoll.h"
@@ -29,20 +29,20 @@
 #include "aos/realtime.h"
 #include "aos/util/phased_loop.h"
 
-DEFINE_int32(min_iterations, 100,
-             "Minimum number of stress test iterations to run");
-DEFINE_int32(duration, 5, "Number of seconds to test for");
-DEFINE_int32(print_rate, 60, "Number of seconds between status prints");
+ABSL_FLAG(int32_t, min_iterations, 100,
+          "Minimum number of stress test iterations to run");
+ABSL_FLAG(int32_t, duration, 5, "Number of seconds to test for");
+ABSL_FLAG(int32_t, print_rate, 60, "Number of seconds between status prints");
 
 // The roboRIO can only handle 10 threads before exploding.  Set the default for
 // ARM to 10.
-DEFINE_int32(thread_count,
+ABSL_FLAG(int32_t, thread_count,
 #if defined(__ARM_EABI__)
-             10,
+          10,
 #else
-             100,
+          100,
 #endif
-             "Number of threads to race");
+          "Number of threads to race");
 
 namespace aos::ipc_lib::testing {
 
@@ -299,7 +299,7 @@
 
 // Races a bunch of sending threads to see if it all works.
 TEST_F(LocklessQueueTest, SendRace) {
-  const size_t kNumMessages = 10000 / FLAGS_thread_count;
+  const size_t kNumMessages = 10000 / absl::GetFlag(FLAGS_thread_count);
 
   ::std::mt19937 generator(0);
   ::std::uniform_int_distribution<> write_wrap_count_distribution(0, 10);
@@ -308,17 +308,19 @@
   ::std::bernoulli_distribution should_read_result_distribution;
   ::std::bernoulli_distribution wrap_writes_distribution;
 
-  const chrono::seconds print_frequency(FLAGS_print_rate);
+  const chrono::seconds print_frequency(absl::GetFlag(FLAGS_print_rate));
 
-  QueueRacer racer(queue(), FLAGS_thread_count, kNumMessages);
+  QueueRacer racer(queue(), absl::GetFlag(FLAGS_thread_count), kNumMessages);
   const monotonic_clock::time_point start_time = monotonic_clock::now();
   const monotonic_clock::time_point end_time =
-      start_time + chrono::seconds(FLAGS_duration);
+      start_time + chrono::seconds(absl::GetFlag(FLAGS_duration));
 
   monotonic_clock::time_point monotonic_now = start_time;
   monotonic_clock::time_point next_print_time = start_time + print_frequency;
   uint64_t messages = 0;
-  for (int i = 0; i < FLAGS_min_iterations || monotonic_now < end_time; ++i) {
+  for (int i = 0;
+       i < absl::GetFlag(FLAGS_min_iterations) || monotonic_now < end_time;
+       ++i) {
     const bool race_reads = race_reads_distribution(generator);
     const bool set_should_read = set_should_read_distribution(generator);
     const bool should_read_result = should_read_result_distribution(generator);
@@ -402,7 +404,7 @@
   PinForTest pin_cpu;
   uint64_t kNumMessages = 1000000;
   QueueRacer racer(queue(),
-                   {FLAGS_thread_count,
+                   {absl::GetFlag(FLAGS_thread_count),
                     kNumMessages,
                     {LocklessQueueSender::Result::GOOD,
                      LocklessQueueSender::Result::MESSAGES_SENT_TOO_FAST},
diff --git a/aos/ipc_lib/memory_mapped_queue.cc b/aos/ipc_lib/memory_mapped_queue.cc
index 8daf5a1..9ba21a9 100644
--- a/aos/ipc_lib/memory_mapped_queue.cc
+++ b/aos/ipc_lib/memory_mapped_queue.cc
@@ -11,9 +11,10 @@
 #include <ostream>
 #include <thread>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "flatbuffers/string.h"
-#include "glog/logging.h"
 
 #include "aos/ipc_lib/index.h"
 #include "aos/util/file.h"
diff --git a/aos/ipc_lib/named_pipe_latency.cc b/aos/ipc_lib/named_pipe_latency.cc
index 023853d..240bf78 100644
--- a/aos/ipc_lib/named_pipe_latency.cc
+++ b/aos/ipc_lib/named_pipe_latency.cc
@@ -11,10 +11,12 @@
 #include <ratio>
 #include <thread>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/epoll.h"
+#include "aos/init.h"
 #include "aos/ipc_lib/latency_lib.h"
 #include "aos/logging/implementations.h"
 #include "aos/realtime.h"
@@ -24,37 +26,37 @@
 // It measures both latency of a random timer thread, and latency of the
 // pipe.
 
-DEFINE_bool(sender, true, "If true, send signals to the other process.");
-DEFINE_string(fifo, "/dev/shm/aos/named_pipe_latency",
-              "FIFO to use for the test.");
-DEFINE_int32(seconds, 10, "Duration of the test to run");
-DEFINE_int32(
-    latency_threshold, 1000,
+ABSL_FLAG(bool, sender, true, "If true, send signals to the other process.");
+ABSL_FLAG(std::string, fifo, "/dev/shm/aos/named_pipe_latency",
+          "FIFO to use for the test.");
+ABSL_FLAG(int32_t, seconds, 10, "Duration of the test to run");
+ABSL_FLAG(
+    int32_t, latency_threshold, 1000,
     "Disable tracing when anything takes more than this many microseoncds");
-DEFINE_int32(core, 7, "Core to pin to");
-DEFINE_int32(sender_priority, 53, "RT priority to send at");
-DEFINE_int32(receiver_priority, 52, "RT priority to receive at");
-DEFINE_int32(timer_priority, 51, "RT priority to spin the timer at");
+ABSL_FLAG(int32_t, core, 7, "Core to pin to");
+ABSL_FLAG(int32_t, sender_priority, 53, "RT priority to send at");
+ABSL_FLAG(int32_t, receiver_priority, 52, "RT priority to receive at");
+ABSL_FLAG(int32_t, timer_priority, 51, "RT priority to spin the timer at");
 
-DEFINE_bool(log_latency, false, "If true, log the latency");
+ABSL_FLAG(bool, log_latency, false, "If true, log the latency");
 
 namespace chrono = ::std::chrono;
 
 namespace aos {
 
 void SenderThread() {
-  int pipefd =
-      open(FLAGS_fifo.c_str(), FD_CLOEXEC | O_NONBLOCK | O_WRONLY | O_NOATIME);
+  int pipefd = open(absl::GetFlag(FLAGS_fifo).c_str(),
+                    FD_CLOEXEC | O_NONBLOCK | O_WRONLY | O_NOATIME);
   const monotonic_clock::time_point end_time =
-      monotonic_clock::now() + chrono::seconds(FLAGS_seconds);
+      monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds));
   // Standard mersenne_twister_engine seeded with 0
   ::std::mt19937 generator(0);
 
   // Sleep between 1 and 15 ms.
   ::std::uniform_int_distribution<> distribution(1000, 15000);
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_sender_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_sender_priority));
   while (true) {
     const monotonic_clock::time_point wakeup_time =
         monotonic_clock::now() + chrono::microseconds(distribution(generator));
@@ -83,8 +85,8 @@
 }
 
 void ReceiverThread() {
-  int pipefd =
-      open(FLAGS_fifo.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY | O_NOATIME);
+  int pipefd = open(absl::GetFlag(FLAGS_fifo).c_str(),
+                    O_CLOEXEC | O_NONBLOCK | O_RDONLY | O_NOATIME);
   Tracing t;
   t.Start();
 
@@ -118,21 +120,22 @@
 
     max_wakeup_latency = ::std::max(wakeup_latency, max_wakeup_latency);
 
-    if (wakeup_latency > chrono::microseconds(FLAGS_latency_threshold)) {
+    if (wakeup_latency >
+        chrono::microseconds(absl::GetFlag(FLAGS_latency_threshold))) {
       t.Stop();
       AOS_LOG(INFO, "Stopped tracing, latency %" PRId64 "\n",
               static_cast<int64_t>(wakeup_latency.count()));
     }
 
-    if (FLAGS_log_latency) {
+    if (absl::GetFlag(FLAGS_log_latency)) {
       AOS_LOG(INFO, "dt: %8d.%03d\n",
               static_cast<int>(wakeup_latency.count() / 1000),
               static_cast<int>(wakeup_latency.count() % 1000));
     }
   });
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_receiver_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_receiver_priority));
   epoll.Run();
   UnsetCurrentThreadRealtimePriority();
   epoll.DeleteFd(pipefd);
@@ -152,12 +155,13 @@
 }
 
 int Main(int /*argc*/, char ** /*argv*/) {
-  mkfifo(FLAGS_fifo.c_str(), 0777);
+  mkfifo(absl::GetFlag(FLAGS_fifo).c_str(), 0777);
 
   AOS_LOG(INFO, "Main!\n");
   ::std::thread t([]() {
-    TimerThread(monotonic_clock::now() + chrono::seconds(FLAGS_seconds),
-                FLAGS_timer_priority);
+    TimerThread(
+        monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds)),
+        absl::GetFlag(FLAGS_timer_priority));
   });
 
   ::std::thread st([]() { SenderThread(); });
@@ -172,7 +176,7 @@
 }  // namespace aos
 
 int main(int argc, char **argv) {
-  ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+  aos::InitGoogle(&argc, &argv);
 
   return ::aos::Main(argc, argv);
 }
diff --git a/aos/ipc_lib/print_lockless_queue_memory.cc b/aos/ipc_lib/print_lockless_queue_memory.cc
index 4bad81c..8c6e18d 100644
--- a/aos/ipc_lib/print_lockless_queue_memory.cc
+++ b/aos/ipc_lib/print_lockless_queue_memory.cc
@@ -5,7 +5,8 @@
 
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/lockless_queue.h"
 
diff --git a/aos/ipc_lib/queue_racer.cc b/aos/ipc_lib/queue_racer.cc
index 67ed6c5..a25d10a 100644
--- a/aos/ipc_lib/queue_racer.cc
+++ b/aos/ipc_lib/queue_racer.cc
@@ -10,8 +10,9 @@
 #include <ostream>
 #include <thread>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/context.h"
diff --git a/aos/ipc_lib/robust_ownership_tracker.h b/aos/ipc_lib/robust_ownership_tracker.h
index 34c8b7a..bc2db17 100644
--- a/aos/ipc_lib/robust_ownership_tracker.h
+++ b/aos/ipc_lib/robust_ownership_tracker.h
@@ -13,7 +13,8 @@
 #include <ostream>
 #include <string>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/aos_sync.h"
 #include "aos/util/top.h"
diff --git a/aos/ipc_lib/shared_mem.cc b/aos/ipc_lib/shared_mem.cc
index 30dd173..861f02e 100644
--- a/aos/ipc_lib/shared_mem.cc
+++ b/aos/ipc_lib/shared_mem.cc
@@ -12,7 +12,8 @@
 #include <cstring>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/aos_sync.h"
 
diff --git a/aos/ipc_lib/shm_base.cc b/aos/ipc_lib/shm_base.cc
index 5db25d3..eebed6f 100644
--- a/aos/ipc_lib/shm_base.cc
+++ b/aos/ipc_lib/shm_base.cc
@@ -2,10 +2,15 @@
 
 #include <string>
 
-DEFINE_string(shm_base, "/dev/shm/aos",
-              "Directory to place queue backing mmaped files in.");
+#include "absl/flags/flag.h"
+
+ABSL_FLAG(std::string, shm_base, "/dev/shm/aos",
+          "Directory to place queue backing mmaped files in.");
+
 namespace aos::testing {
+
 void SetShmBase(const std::string_view base) {
-  FLAGS_shm_base = std::string(base) + "/aos";
+  absl::SetFlag(&FLAGS_shm_base, std::string(base) + "/aos");
 }
+
 }  // namespace aos::testing
diff --git a/aos/ipc_lib/shm_base.h b/aos/ipc_lib/shm_base.h
index 1d06a69..9a56d29 100644
--- a/aos/ipc_lib/shm_base.h
+++ b/aos/ipc_lib/shm_base.h
@@ -3,11 +3,12 @@
 
 #include <string_view>
 
-#include "gflags/gflags.h"
+#include "absl/flags/declare.h"
 
-DECLARE_string(shm_base);
+ABSL_DECLARE_FLAG(std::string, shm_base);
 
 namespace aos::testing {
 void SetShmBase(const std::string_view base);
 }
+
 #endif  // AOS_IPC_LIB_SHM_BASE_H_
diff --git a/aos/ipc_lib/signal_stress.cc b/aos/ipc_lib/signal_stress.cc
index b2749af..d5d1323 100644
--- a/aos/ipc_lib/signal_stress.cc
+++ b/aos/ipc_lib/signal_stress.cc
@@ -10,10 +10,12 @@
 #include <ratio>
 #include <thread>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/epoll.h"
+#include "aos/init.h"
 #include "aos/ipc_lib/latency_lib.h"
 #include "aos/logging/implementations.h"
 #include "aos/realtime.h"
@@ -26,18 +28,18 @@
 // To enable function graph:
 //   echo "function_graph" > current_tracer
 
-DEFINE_bool(sender, true, "If true, send signals to the other process.");
-DEFINE_int32(other_pid, -1, "PID of other process to ping");
-DEFINE_int32(seconds, 10, "Duration of the test to run");
-DEFINE_int32(
-    latency_threshold, 1000,
+ABSL_FLAG(bool, sender, true, "If true, send signals to the other process.");
+ABSL_FLAG(int32_t, other_pid, -1, "PID of other process to ping");
+ABSL_FLAG(int32_t, seconds, 10, "Duration of the test to run");
+ABSL_FLAG(
+    int32_t, latency_threshold, 1000,
     "Disable tracing when anything takes more than this many microseoncds");
-DEFINE_int32(core, 7, "Core to pin to");
-DEFINE_int32(sender_priority, 53, "RT priority to send at");
-DEFINE_int32(receiver_priority, 52, "RT priority to receive at");
-DEFINE_int32(timer_priority, 51, "RT priority to spin the timer at");
+ABSL_FLAG(int32_t, core, 7, "Core to pin to");
+ABSL_FLAG(int32_t, sender_priority, 53, "RT priority to send at");
+ABSL_FLAG(int32_t, receiver_priority, 52, "RT priority to receive at");
+ABSL_FLAG(int32_t, timer_priority, 51, "RT priority to spin the timer at");
 
-DEFINE_bool(log_latency, false, "If true, log the latency");
+ABSL_FLAG(bool, log_latency, false, "If true, log the latency");
 
 const uint32_t kSignalNumber = SIGRTMIN + 1;
 const uint32_t kQuitSignalNumber = SIGRTMIN + 2;
@@ -48,7 +50,7 @@
 
 void SenderThread() {
   const monotonic_clock::time_point end_time =
-      monotonic_clock::now() + chrono::seconds(FLAGS_seconds);
+      monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds));
   // Standard mersenne_twister_engine seeded with 0
   ::std::mt19937 generator(0);
 
@@ -56,13 +58,13 @@
   ::std::uniform_int_distribution<> distribution(1000, 15000);
 
   int pid = getpid();
-  if (FLAGS_other_pid != -1) {
-    pid = FLAGS_other_pid;
+  if (absl::GetFlag(FLAGS_other_pid) != -1) {
+    pid = absl::GetFlag(FLAGS_other_pid);
   }
   AOS_LOG(INFO, "Current PID: %d\n", pid);
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_sender_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_sender_priority));
   while (true) {
     const monotonic_clock::time_point wakeup_time =
         monotonic_clock::now() + chrono::microseconds(distribution(generator));
@@ -137,21 +139,22 @@
 
     max_wakeup_latency = ::std::max(wakeup_latency, max_wakeup_latency);
 
-    if (wakeup_latency > chrono::microseconds(FLAGS_latency_threshold)) {
+    if (wakeup_latency >
+        chrono::microseconds(absl::GetFlag(FLAGS_latency_threshold))) {
       t.Stop();
       AOS_LOG(INFO, "Stopped tracing, latency %" PRId64 "\n",
               static_cast<int64_t>(wakeup_latency.count()));
     }
 
-    if (FLAGS_log_latency) {
+    if (absl::GetFlag(FLAGS_log_latency)) {
       AOS_LOG(INFO, "signo: %d, sending pid: %d, dt: %8d.%03d\n", si.ssi_signo,
               si.ssi_pid, static_cast<int>(wakeup_latency_int64 / 1000),
               static_cast<int>(wakeup_latency_int64 % 1000));
     }
   });
 
-  SetCurrentThreadAffinity(MakeCpusetFromCpus({FLAGS_core}));
-  SetCurrentThreadRealtimePriority(FLAGS_receiver_priority);
+  SetCurrentThreadAffinity(MakeCpusetFromCpus({absl::GetFlag(FLAGS_core)}));
+  SetCurrentThreadRealtimePriority(absl::GetFlag(FLAGS_receiver_priority));
   epoll.Run();
   UnsetCurrentThreadRealtimePriority();
   epoll.DeleteFd(signalfd_fd);
@@ -178,8 +181,9 @@
 
   AOS_LOG(INFO, "Main!\n");
   ::std::thread t([]() {
-    TimerThread(monotonic_clock::now() + chrono::seconds(FLAGS_seconds),
-                FLAGS_timer_priority);
+    TimerThread(
+        monotonic_clock::now() + chrono::seconds(absl::GetFlag(FLAGS_seconds)),
+        absl::GetFlag(FLAGS_timer_priority));
   });
 
   ::std::thread st([]() { SenderThread(); });
@@ -194,7 +198,7 @@
 }  // namespace aos
 
 int main(int argc, char **argv) {
-  ::gflags::ParseCommandLineFlags(&argc, &argv, true);
+  aos::InitGoogle(&argc, &argv);
 
   return ::aos::Main(argc, argv);
 }
diff --git a/aos/ipc_lib/signalfd.cc b/aos/ipc_lib/signalfd.cc
index c9634a5..9f3c972 100644
--- a/aos/ipc_lib/signalfd.cc
+++ b/aos/ipc_lib/signalfd.cc
@@ -12,7 +12,8 @@
 
 #include <initializer_list>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::ipc_lib {
 namespace {
diff --git a/aos/ipc_lib/signalfd_test.cc b/aos/ipc_lib/signalfd_test.cc
index 025d66b..bc6f460 100644
--- a/aos/ipc_lib/signalfd_test.cc
+++ b/aos/ipc_lib/signalfd_test.cc
@@ -3,7 +3,8 @@
 #include <memory>
 #include <thread>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/testing/test_logging.h"
diff --git a/aos/json_to_flatbuffer.cc b/aos/json_to_flatbuffer.cc
index 3f049d7..2a19557 100644
--- a/aos/json_to_flatbuffer.cc
+++ b/aos/json_to_flatbuffer.cc
@@ -4,9 +4,10 @@
 #include <cstdio>
 #include <string_view>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
 #include "flatbuffers/minireflect.h"
-#include "glog/logging.h"
 
 #include "aos/flatbuffer_utils.h"
 #include "aos/json_tokenizer.h"
diff --git a/aos/libc/BUILD b/aos/libc/BUILD
index 9bfd365..8385ebb 100644
--- a/aos/libc/BUILD
+++ b/aos/libc/BUILD
@@ -10,7 +10,8 @@
     ],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/libc/aos_strsignal.cc b/aos/libc/aos_strsignal.cc
index 6a91973..d8dd914 100644
--- a/aos/libc/aos_strsignal.cc
+++ b/aos/libc/aos_strsignal.cc
@@ -6,7 +6,8 @@
 
 #include <csignal>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 const char *aos_strsignal(int signal) {
   thread_local char buffer[512];
diff --git a/aos/logging/BUILD b/aos/logging/BUILD
index b08f465..0ba90a9 100644
--- a/aos/logging/BUILD
+++ b/aos/logging/BUILD
@@ -23,7 +23,8 @@
         "//aos:macros",
         "//aos/libc:aos_strerror",
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -36,7 +37,8 @@
     deps = [
         "//aos:configuration",
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -49,7 +51,8 @@
     deps = [
         ":logging",
         "//aos/testing:googletest",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -83,7 +86,8 @@
     deps = [
         ":dynamic_log_command_fbs",
         "//aos/events:shm_event_loop",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/logging/context.cc b/aos/logging/context.cc
index 00b7f3c..66ece05 100644
--- a/aos/logging/context.cc
+++ b/aos/logging/context.cc
@@ -21,7 +21,8 @@
 extern char *program_invocation_name;
 extern char *program_invocation_short_name;
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::logging::internal {
 namespace {
diff --git a/aos/logging/dynamic_logging.cc b/aos/logging/dynamic_logging.cc
index 48c9dcb..4ed4ea3 100644
--- a/aos/logging/dynamic_logging.cc
+++ b/aos/logging/dynamic_logging.cc
@@ -3,8 +3,10 @@
 #include <ostream>
 #include <string_view>
 
+#include "absl/log/check.h"
+#include "absl/log/globals.h"
+#include "absl/log/log.h"
 #include "flatbuffers/string.h"
-#include "glog/logging.h"
 
 namespace aos::logging {
 
@@ -31,7 +33,7 @@
   if (command.vlog_level() < 0) {
     return;
   }
-  FLAGS_v = command.vlog_level();
+  absl::SetGlobalVLogLevel(command.vlog_level());
 }
 
 }  // namespace aos::logging
diff --git a/aos/logging/dynamic_logging_test.cc b/aos/logging/dynamic_logging_test.cc
index 21e0c36..449d7ac 100644
--- a/aos/logging/dynamic_logging_test.cc
+++ b/aos/logging/dynamic_logging_test.cc
@@ -4,9 +4,10 @@
 #include <memory>
 #include <ostream>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/configuration.h"
diff --git a/aos/logging/implementations_test.cc b/aos/logging/implementations_test.cc
index 08fdc7b..62d5f1e 100644
--- a/aos/logging/implementations_test.cc
+++ b/aos/logging/implementations_test.cc
@@ -7,7 +7,8 @@
 #include <cinttypes>
 #include <string>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/logging/printf_formats.h"
diff --git a/aos/logging/interface.cc b/aos/logging/interface.cc
index 326f28e..a630285 100644
--- a/aos/logging/interface.cc
+++ b/aos/logging/interface.cc
@@ -9,7 +9,8 @@
 #include <string>
 #include <type_traits>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/die.h"
 #include "aos/logging/context.h"
diff --git a/aos/logging/log_namer.cc b/aos/logging/log_namer.cc
index d5005bb..0e68e7b 100644
--- a/aos/logging/log_namer.cc
+++ b/aos/logging/log_namer.cc
@@ -11,8 +11,9 @@
 #include <ostream>
 #include <string>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/time/time.h"
@@ -23,14 +24,14 @@
 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
 #endif
 
-DEFINE_string(logging_folder,
+ABSL_FLAG(std::string, logging_folder,
 #ifdef AOS_ARCHITECTURE_arm_frc
-              "",
+          "",
 #else
-              "./logs",
+          "./logs",
 #endif
-              "The folder to log to.  If empty, search for the /media/sd*1/ "
-              "folder and place logs there.");
+          "The folder to log to.  If empty, search for the /media/sd*1/ "
+          "folder and place logs there.");
 
 namespace aos::logging {
 namespace {
@@ -126,7 +127,7 @@
 }  // namespace
 
 std::optional<std::string> MaybeGetLogName(const char *basename) {
-  if (FLAGS_logging_folder.empty()) {
+  if (absl::GetFlag(FLAGS_logging_folder).empty()) {
     char folder[128];
     {
       char dev_name[8];
@@ -147,23 +148,23 @@
                  << "' does not exist. please create it.";
     }
 
-    FLAGS_logging_folder = folder;
+    absl::SetFlag(&FLAGS_logging_folder, folder);
   }
-  const char *folder = FLAGS_logging_folder.c_str();
-  if (access(folder, R_OK | W_OK) == -1) {
+  const std::string folder = absl::GetFlag(FLAGS_logging_folder);
+  if (access(folder.c_str(), R_OK | W_OK) == -1) {
     LOG(FATAL) << "folder '" << folder << "' does not exist. please create it.";
   }
   LOG(INFO) << "logging to folder '" << folder << "'";
 
   char *tmp;
-  AllocateLogName(&tmp, folder, basename);
+  AllocateLogName(&tmp, folder.c_str(), basename);
 
   std::string log_base_name = tmp;
   std::string log_roborio_name = log_base_name + "/";
   free(tmp);
 
   char *tmp2;
-  if (asprintf(&tmp2, "%s/%s-current", folder, basename) == -1) {
+  if (asprintf(&tmp2, "%s/%s-current", folder.c_str(), basename) == -1) {
     PLOG(WARNING) << "couldn't create current symlink name";
   } else {
     if (unlink(tmp2) == -1 && (errno != EROFS && errno != ENOENT)) {
diff --git a/aos/mutex/BUILD b/aos/mutex/BUILD
index d079a02..d3fea1f 100644
--- a/aos/mutex/BUILD
+++ b/aos/mutex/BUILD
@@ -12,7 +12,8 @@
     deps = [
         "//aos/ipc_lib:aos_sync",
         "//aos/type_traits",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -29,6 +30,7 @@
         "//aos/testing:test_shm",
         "//aos/time",
         "//aos/util:death_test_log_implementation",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
diff --git a/aos/mutex/mutex.cc b/aos/mutex/mutex.cc
index 30a9534..4a3fb25 100644
--- a/aos/mutex/mutex.cc
+++ b/aos/mutex/mutex.cc
@@ -1,6 +1,7 @@
 #include "aos/mutex/mutex.h"
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 
diff --git a/aos/mutex/mutex.h b/aos/mutex/mutex.h
index dfc212a..c40917a 100644
--- a/aos/mutex/mutex.h
+++ b/aos/mutex/mutex.h
@@ -3,7 +3,8 @@
 
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/aos_sync.h"
 #include "aos/macros.h"
diff --git a/aos/network/BUILD b/aos/network/BUILD
index 96f8b50..57dba97 100644
--- a/aos/network/BUILD
+++ b/aos/network/BUILD
@@ -173,7 +173,9 @@
     ],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -203,7 +205,9 @@
     deps = [
         "//aos:unique_malloc_ptr",
         "//aos/util:file",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -290,8 +294,9 @@
         ":remote_message_fbs",
         "//aos:configuration",
         "//aos/events:event_loop",
-        "@com_github_google_glog//:glog",
         "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -353,6 +358,7 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         ":sctp_lib",
+        "@com_google_absl//absl/flags:flag",
     ],
 )
 
@@ -713,8 +719,9 @@
         "//aos/mutex",
         "//aos/seasocks:seasocks_logger",
         "//third_party/seasocks",
-        "@com_github_google_glog//:glog",
         "@com_github_rawrtc_rawrtc//:rawrtc",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -926,5 +933,7 @@
         ":sctp_server",
         "//aos:init",
         "//aos/events:shm_event_loop",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/flags:usage",
     ],
 )
diff --git a/aos/network/log_web_proxy_main.cc b/aos/network/log_web_proxy_main.cc
index 12276c3..dc55ff1 100644
--- a/aos/network/log_web_proxy_main.cc
+++ b/aos/network/log_web_proxy_main.cc
@@ -4,7 +4,8 @@
 // /path/to/logfile And then opening the plotting webpage at
 // http://localhost:8080/graph.html
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/log_reader.h"
@@ -13,13 +14,14 @@
 #include "aos/init.h"
 #include "aos/network/web_proxy.h"
 
-DEFINE_string(data_dir, "www", "Directory to serve data files from");
-DEFINE_string(node, "", "Directory to serve data files from");
-DEFINE_int32(buffer_size, -1, "-1 if infinite, in # of messages / channel.");
-DEFINE_double(monotonic_start_time, -1.0, "Start time (sec)");
-DEFINE_double(monotonic_end_time, -1.0, "End time (sec)");
-DEFINE_double(
-    replay_rate, -1,
+ABSL_FLAG(std::string, data_dir, "www", "Directory to serve data files from");
+ABSL_FLAG(std::string, node, "", "Directory to serve data files from");
+ABSL_FLAG(int32_t, buffer_size, -1,
+          "-1 if infinite, in # of messages / channel.");
+ABSL_FLAG(double, monotonic_start_time, -1.0, "Start time (sec)");
+ABSL_FLAG(double, monotonic_end_time, -1.0, "End time (sec)");
+ABSL_FLAG(
+    double, replay_rate, -1,
     "-1 to replay as fast as possible; 1.0 = realtime, 0.5 = half speed.");
 
 int main(int argc, char **argv) {
@@ -34,44 +36,46 @@
 
   // If going for "as fast as possible" don't actually use infinity, because we
   // don't want the log reading blocking our use of the epoll handlers.
-  reader.SetRealtimeReplayRate(FLAGS_replay_rate == -1.0
+  reader.SetRealtimeReplayRate(absl::GetFlag(FLAGS_replay_rate) == -1.0
                                    ? std::numeric_limits<double>::max()
-                                   : FLAGS_replay_rate);
+                                   : absl::GetFlag(FLAGS_replay_rate));
 
   std::unique_ptr<aos::EventLoop> event_loop;
 
-  if (FLAGS_node.empty()) {
+  if (absl::GetFlag(FLAGS_node).empty()) {
     CHECK(!aos::configuration::MultiNode(reader.configuration()))
         << "If using a multi-node logfile, please specify --node.";
     event_loop = reader.event_loop_factory()->MakeEventLoop("web_proxy");
   } else {
     event_loop = reader.event_loop_factory()->MakeEventLoop(
-        "web_proxy",
-        aos::configuration::GetNode(reader.configuration(), FLAGS_node));
+        "web_proxy", aos::configuration::GetNode(reader.configuration(),
+                                                 absl::GetFlag(FLAGS_node)));
   }
 
   event_loop->SkipTimingReport();
 
-  if (FLAGS_monotonic_start_time > 0) {
+  if (absl::GetFlag(FLAGS_monotonic_start_time) > 0) {
     event_loop->AddTimer([&reader]() { reader.event_loop_factory()->Exit(); })
         ->Schedule(aos::monotonic_clock::time_point(
             std::chrono::duration_cast<std::chrono::nanoseconds>(
-                std::chrono::duration<double>(FLAGS_monotonic_start_time))));
+                std::chrono::duration<double>(
+                    absl::GetFlag(FLAGS_monotonic_start_time)))));
 
     reader.event_loop_factory()->Run();
   }
 
   aos::web_proxy::WebProxy web_proxy(
       event_loop.get(), reader.event_loop_factory()->scheduler_epoll(),
-      aos::web_proxy::StoreHistory::kYes, FLAGS_buffer_size);
+      aos::web_proxy::StoreHistory::kYes, absl::GetFlag(FLAGS_buffer_size));
 
-  web_proxy.SetDataPath(FLAGS_data_dir.c_str());
+  web_proxy.SetDataPath(absl::GetFlag(FLAGS_data_dir).c_str());
 
-  if (FLAGS_monotonic_end_time > 0) {
+  if (absl::GetFlag(FLAGS_monotonic_end_time) > 0) {
     event_loop->AddTimer([&web_proxy]() { web_proxy.StopRecording(); })
         ->Schedule(aos::monotonic_clock::time_point(
             std::chrono::duration_cast<std::chrono::nanoseconds>(
-                std::chrono::duration<double>(FLAGS_monotonic_end_time))));
+                std::chrono::duration<double>(
+                    absl::GetFlag(FLAGS_monotonic_end_time)))));
   }
 
   reader.event_loop_factory()->Run();
diff --git a/aos/network/message_bridge_auth_client_lib.cc b/aos/network/message_bridge_auth_client_lib.cc
index c277b4f..2b520ba 100644
--- a/aos/network/message_bridge_auth_client_lib.cc
+++ b/aos/network/message_bridge_auth_client_lib.cc
@@ -2,7 +2,8 @@
 
 #include <vector>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/event_loop.h"
 #include "aos/network/message_bridge_auth.grpc.pb.h"
diff --git a/aos/network/message_bridge_auth_server_lib.cc b/aos/network/message_bridge_auth_server_lib.cc
index 6a9dc7e..f2a03c8 100644
--- a/aos/network/message_bridge_auth_server_lib.cc
+++ b/aos/network/message_bridge_auth_server_lib.cc
@@ -3,7 +3,8 @@
 #include <cstdio>
 #include <fstream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "grpc/grpc.h"
 #include "grpcpp/server_context.h"
diff --git a/aos/network/message_bridge_client.cc b/aos/network/message_bridge_client.cc
index 4a1992a..e6b71ea 100644
--- a/aos/network/message_bridge_client.cc
+++ b/aos/network/message_bridge_client.cc
@@ -1,3 +1,5 @@
+#include "absl/flags/flag.h"
+
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/logging/dynamic_logging.h"
@@ -6,11 +8,10 @@
 #include "aos/sha256.h"
 #include "aos/util/file.h"
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_int32(rt_priority, -1, "If > 0, run as this RT priority");
-DEFINE_bool(
-    wants_sctp_authentication, false,
-    "When set, try to use SCTP authentication if provided by the kernel");
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(int32_t, rt_priority, -1, "If > 0, run as this RT priority");
+ABSL_FLAG(bool, wants_sctp_authentication, false,
+          "When set, try to use SCTP authentication if provided by the kernel");
 
 namespace aos::message_bridge {
 
@@ -18,15 +19,15 @@
 
 int Main() {
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
-  if (FLAGS_rt_priority > 0) {
-    event_loop.SetRuntimeRealtimePriority(FLAGS_rt_priority);
+  if (absl::GetFlag(FLAGS_rt_priority) > 0) {
+    event_loop.SetRuntimeRealtimePriority(absl::GetFlag(FLAGS_rt_priority));
   }
 
   MessageBridgeClient app(&event_loop, Sha256(config.span()),
-                          FLAGS_wants_sctp_authentication
+                          absl::GetFlag(FLAGS_wants_sctp_authentication)
                               ? SctpAuthMethod::kAuth
                               : SctpAuthMethod::kNoAuth);
 
diff --git a/aos/network/message_bridge_client_lib.cc b/aos/network/message_bridge_client_lib.cc
index cf52a69..d9fa91d 100644
--- a/aos/network/message_bridge_client_lib.cc
+++ b/aos/network/message_bridge_client_lib.cc
@@ -3,8 +3,9 @@
 #include <chrono>
 #include <string_view>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/shm_event_loop.h"
@@ -24,7 +25,7 @@
 #pragma clang diagnostic ignored "-Wcast-align"
 #endif
 
-DECLARE_bool(use_sctp_authentication);
+ABSL_DECLARE_FLAG(bool, use_sctp_authentication);
 
 // This application receives messages from another node and re-publishes them on
 // this node.
diff --git a/aos/network/message_bridge_retry_test.cc b/aos/network/message_bridge_retry_test.cc
index e90bcb0..52ed3c9 100644
--- a/aos/network/message_bridge_retry_test.cc
+++ b/aos/network/message_bridge_retry_test.cc
@@ -1,6 +1,7 @@
 #include <chrono>
 #include <thread>
 
+#include "absl/flags/declare.h"
 #include "absl/strings/str_cat.h"
 #include "gtest/gtest.h"
 
@@ -16,7 +17,7 @@
 #include "aos/testing/path.h"
 #include "aos/util/file.h"
 
-DECLARE_int32(force_wmem_max);
+ABSL_DECLARE_FLAG(int32_t, force_wmem_max);
 
 namespace aos::message_bridge::testing {
 
@@ -37,10 +38,10 @@
 // message_bridge_test, so we kept it separate.
 TEST_P(MessageBridgeParameterizedTest, ReliableRetries) {
   // Set an absurdly small wmem max. This will help to trigger retries.
-  FLAGS_force_wmem_max = 1024;
+  absl::SetFlag(&FLAGS_force_wmem_max, 1024);
   pi1_.OnPi();
 
-  FLAGS_application_name = "sender";
+  absl::SetFlag(&FLAGS_application_name, "sender");
   aos::ShmEventLoop send_event_loop(&config_.message());
   aos::Sender<examples::Ping> ping_sender =
       send_event_loop.MakeSender<examples::Ping>("/test");
diff --git a/aos/network/message_bridge_server.cc b/aos/network/message_bridge_server.cc
index 64c57f5..2df5704 100644
--- a/aos/network/message_bridge_server.cc
+++ b/aos/network/message_bridge_server.cc
@@ -1,5 +1,6 @@
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
@@ -8,11 +9,10 @@
 #include "aos/network/sctp_lib.h"
 #include "aos/sha256.h"
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_int32(rt_priority, -1, "If > 0, run as this RT priority");
-DEFINE_bool(
-    wants_sctp_authentication, false,
-    "When set, try to use SCTP authentication if provided by the kernel");
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(int32_t, rt_priority, -1, "If > 0, run as this RT priority");
+ABSL_FLAG(bool, wants_sctp_authentication, false,
+          "When set, try to use SCTP authentication if provided by the kernel");
 
 namespace aos::message_bridge {
 
@@ -20,15 +20,15 @@
 
 int Main() {
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
-  if (FLAGS_rt_priority > 0) {
-    event_loop.SetRuntimeRealtimePriority(FLAGS_rt_priority);
+  if (absl::GetFlag(FLAGS_rt_priority) > 0) {
+    event_loop.SetRuntimeRealtimePriority(absl::GetFlag(FLAGS_rt_priority));
   }
 
   MessageBridgeServer app(&event_loop, Sha256(config.span()),
-                          FLAGS_wants_sctp_authentication
+                          absl::GetFlag(FLAGS_wants_sctp_authentication)
                               ? SctpAuthMethod::kAuth
                               : SctpAuthMethod::kNoAuth);
 
diff --git a/aos/network/message_bridge_server_lib.cc b/aos/network/message_bridge_server_lib.cc
index a3f429a..7f6ad53 100644
--- a/aos/network/message_bridge_server_lib.cc
+++ b/aos/network/message_bridge_server_lib.cc
@@ -1,9 +1,10 @@
 #include "aos/network/message_bridge_server_lib.h"
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
 
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/logging/logger_generated.h"
@@ -31,31 +32,31 @@
 // that hopefully it is a relatively minor blip for anything that isn't
 // timing-critical (and timing-critical things that hit the retry logic are
 // probably in trouble).
-DEFINE_uint32(min_retry_period_ms, 10,
-              "Maximum retry timer period--the exponential backoff will not "
-              "exceed this period, in milliseconds.");
+ABSL_FLAG(uint32_t, min_retry_period_ms, 10,
+          "Maximum retry timer period--the exponential backoff will not "
+          "exceed this period, in milliseconds.");
 // Amount of backoff to add every time a retry fails. Chosen semi-arbitrarily;
 // 100ms is large enough that the backoff actually does increase at a reasonable
 // rate, while preventing the period from growing so fast that it can readily
 // take multiple seconds for a retry to occur.
-DEFINE_uint32(retry_period_additive_backoff_ms, 100,
-              "Amount of time to add to the retry period every time a retry "
-              "fails, in milliseconds.");
+ABSL_FLAG(uint32_t, retry_period_additive_backoff_ms, 100,
+          "Amount of time to add to the retry period every time a retry "
+          "fails, in milliseconds.");
 // Max out retry period at 10 seconds---this is generally a much longer
 // timescale than anything normally happening on our systems, while still being
 // short enough that the retries will regularly happen (basically, the maximum
 // should be short enough that a human trying to debug issues with the system
 // will still see the retries regularly happening as they debug, rather than
 // having to wait minutes or hours for a retry to occur).
-DEFINE_uint32(max_retry_period_ms, 10000,
-              "Maximum retry timer period--the additive backoff will not "
-              "exceed this period, in milliseconds.");
+ABSL_FLAG(uint32_t, max_retry_period_ms, 10000,
+          "Maximum retry timer period--the additive backoff will not "
+          "exceed this period, in milliseconds.");
 
-DEFINE_int32(force_wmem_max, -1,
-             "If set to a nonnegative numbers, the wmem buffer size to use, in "
-             "bytes. Intended solely for testing purposes.");
+ABSL_FLAG(int32_t, force_wmem_max, -1,
+          "If set to a nonnegative numbers, the wmem buffer size to use, in "
+          "bytes. Intended solely for testing purposes.");
 
-DECLARE_bool(use_sctp_authentication);
+ABSL_DECLARE_FLAG(bool, use_sctp_authentication);
 
 namespace aos::message_bridge {
 namespace chrono = std::chrono;
@@ -115,7 +116,8 @@
       allocator_(allocator),
       last_message_fetcher_(event_loop->MakeRawFetcher(channel)),
       retry_timer_(event_loop->AddTimer([this]() { SendData(); })),
-      retry_period_(std::chrono::milliseconds(FLAGS_min_retry_period_ms)) {
+      retry_period_(
+          std::chrono::milliseconds(absl::GetFlag(FLAGS_min_retry_period_ms))) {
   retry_timer_->set_name(absl::StrFormat("retry%d", channel_index));
 }
 
@@ -164,7 +166,8 @@
   // either (a) we run out of messages to send or (b) sends start to fail.
   do {
     if (ReadyToFetchNext()) {
-      retry_period_ = std::chrono::milliseconds(FLAGS_min_retry_period_ms);
+      retry_period_ =
+          std::chrono::milliseconds(absl::GetFlag(FLAGS_min_retry_period_ms));
       if (!last_message_fetcher_->FetchNext()) {
         return;
       }
@@ -231,9 +234,9 @@
   if (retry_required) {
     retry_timer_->Schedule(event_loop_->monotonic_now() + retry_period_);
     retry_period_ = std::min(
-        retry_period_ +
-            std::chrono::milliseconds(FLAGS_retry_period_additive_backoff_ms),
-        std::chrono::milliseconds(FLAGS_max_retry_period_ms));
+        retry_period_ + std::chrono::milliseconds(absl::GetFlag(
+                            FLAGS_retry_period_additive_backoff_ms)),
+        std::chrono::milliseconds(absl::GetFlag(FLAGS_max_retry_period_ms)));
   }
 
   if (logged_remotely) {
@@ -369,13 +372,13 @@
         reconnected->push_back(peer.sac_assoc_id);
         if (peer.sac_assoc_id == assoc_id) {
           if (VLOG_IS_ON(1)) {
-            LOG_EVERY_T(WARNING, 0.025)
+            LOG_EVERY_N_SEC(WARNING, 0.025)
                 << "Node " << node->name()->string_view() << " reconnecting on "
                 << assoc_id << " with the same ID, something got lost";
           }
         } else {
           if (VLOG_IS_ON(1)) {
-            LOG_EVERY_T(WARNING, 0.025)
+            LOG_EVERY_N_SEC(WARNING, 0.025)
                 << "Node " << node->name()->string_view() << " "
                 << " already connected on " << peer.sac_assoc_id
                 << " aborting old connection and switching to " << assoc_id;
@@ -395,7 +398,8 @@
       if (!AnyNodeConnected()) {
         // If no one else is connected yet, reset the Fetcher.
         last_message_fetcher_->Fetch();
-        retry_period_ = std::chrono::milliseconds(FLAGS_min_retry_period_ms);
+        retry_period_ =
+            std::chrono::milliseconds(absl::GetFlag(FLAGS_min_retry_period_ms));
       }
       // Unreliable channels aren't supposed to send out the latest fetched
       // message.
@@ -581,8 +585,8 @@
   LOG(INFO) << "Reliable buffer size for all clients is "
             << reliable_buffer_size;
   server_.SetMaxReadSize(max_size);
-  if (FLAGS_force_wmem_max >= 0) {
-    server_.SetMaxWriteSize(FLAGS_force_wmem_max);
+  if (absl::GetFlag(FLAGS_force_wmem_max) >= 0) {
+    server_.SetMaxWriteSize(absl::GetFlag(FLAGS_force_wmem_max));
   } else {
     server_.SetMaxWriteSize(
         std::max(max_channel_buffer_size, reliable_buffer_size));
@@ -696,7 +700,7 @@
       flatbuffers::Verifier verifier(message->data(), message->size);
       if (!connect->Verify(verifier)) {
         if (VLOG_IS_ON(1)) {
-          LOG_EVERY_T(WARNING, 1.0)
+          LOG_EVERY_N_SEC(WARNING, 1.0)
               << "Failed to verify message, disconnecting client";
         }
         server_.Abort(message->header.rcvinfo.rcv_assoc_id);
diff --git a/aos/network/message_bridge_server_lib.h b/aos/network/message_bridge_server_lib.h
index 1c3903f..1b20743 100644
--- a/aos/network/message_bridge_server_lib.h
+++ b/aos/network/message_bridge_server_lib.h
@@ -3,8 +3,9 @@
 
 #include <deque>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/events/logging/log_reader.h"
 #include "aos/events/logging/logger_generated.h"
diff --git a/aos/network/message_bridge_test.cc b/aos/network/message_bridge_test.cc
index 350cf26..a923f81 100644
--- a/aos/network/message_bridge_test.cc
+++ b/aos/network/message_bridge_test.cc
@@ -1,6 +1,9 @@
 #include <chrono>
 #include <thread>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "gtest/gtest.h"
 
@@ -54,7 +57,7 @@
   const std::string long_data = std::string(10000, 'a');
 
   // And build the app which sends the pings.
-  FLAGS_application_name = "ping";
+  absl::SetFlag(&FLAGS_application_name, "ping");
   aos::ShmEventLoop ping_event_loop(&config_.message());
   aos::Sender<examples::Ping> ping_sender =
       ping_event_loop.MakeSender<examples::Ping>("/test");
@@ -78,11 +81,11 @@
   pi2_.MakeServer();
 
   // And build the app which sends the pongs.
-  FLAGS_application_name = "pong";
+  absl::SetFlag(&FLAGS_application_name, "pong");
   aos::ShmEventLoop pong_event_loop(&config_.message());
 
   // And build the app for testing.
-  FLAGS_application_name = "test";
+  absl::SetFlag(&FLAGS_application_name, "test");
   aos::ShmEventLoop test_event_loop(&config_.message());
 
   aos::Fetcher<ClientStatistics> client_statistics_fetcher =
@@ -112,7 +115,7 @@
     VLOG(1) << "Got ping back " << FlatbufferToJson(&ping);
   });
 
-  FLAGS_override_hostname = "";
+  absl::SetFlag(&FLAGS_override_hostname, "");
 
   // Wait until we are connected, then send.
   int ping_count = 0;
@@ -805,7 +808,7 @@
 TEST_P(MessageBridgeParameterizedTest, ReliableSentBeforeClientStartup) {
   pi1_.OnPi();
 
-  FLAGS_application_name = "sender";
+  absl::SetFlag(&FLAGS_application_name, "sender");
   aos::ShmEventLoop send_event_loop(&config_.message());
   aos::Sender<examples::Ping> ping_sender =
       send_event_loop.MakeSender<examples::Ping>("/test");
@@ -817,7 +820,7 @@
   pi1_.MakeServer();
   pi1_.MakeClient();
 
-  FLAGS_application_name = "pi1_timestamp";
+  absl::SetFlag(&FLAGS_application_name, "pi1_timestamp");
   aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
 
   // Now do it for "raspberrypi2", the client.
@@ -953,7 +956,7 @@
   // Force ourselves to be "raspberrypi" and allocate everything.
   pi1_.OnPi();
 
-  FLAGS_application_name = "sender";
+  absl::SetFlag(&FLAGS_application_name, "sender");
   aos::ShmEventLoop send_event_loop(&config_.message());
   aos::Sender<examples::Ping> ping_sender =
       send_event_loop.MakeSender<examples::Ping>("/test");
@@ -967,7 +970,7 @@
 
   pi1_.MakeClient();
 
-  FLAGS_application_name = "pi1_timestamp";
+  absl::SetFlag(&FLAGS_application_name, "pi1_timestamp");
   aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
 
   const size_t ping_channel_index = configuration::ChannelIndex(
@@ -1077,7 +1080,7 @@
 TEST_P(MessageBridgeParameterizedTest, ReliableSentDuringClientReboot) {
   pi1_.OnPi();
 
-  FLAGS_application_name = "sender";
+  absl::SetFlag(&FLAGS_application_name, "sender");
   aos::ShmEventLoop send_event_loop(&config_.message());
   aos::Sender<examples::Ping> ping_sender =
       send_event_loop.MakeSender<examples::Ping>("/test");
@@ -1087,7 +1090,7 @@
   pi1_.MakeServer();
   pi1_.MakeClient();
 
-  FLAGS_application_name = "pi1_timestamp";
+  absl::SetFlag(&FLAGS_application_name, "pi1_timestamp");
   aos::ShmEventLoop pi1_remote_timestamp_event_loop(&config_.message());
 
   // Now do it for "raspberrypi2", the client.
@@ -1363,7 +1366,7 @@
     // Now, spin up a SctpClient and send a massive hunk of data.  This should
     // trigger a disconnect, but no crash.
     pi2_.OnPi();
-    FLAGS_application_name = "pi2_message_bridge_client";
+    absl::SetFlag(&FLAGS_application_name, "pi2_message_bridge_client");
     pi2_.client_event_loop_ =
         std::make_unique<aos::ShmEventLoop>(&config_.message());
     pi2_.client_event_loop_->SetRuntimeRealtimePriority(1);
diff --git a/aos/network/message_bridge_test_lib.cc b/aos/network/message_bridge_test_lib.cc
index 6b8b49e..eed1698 100644
--- a/aos/network/message_bridge_test_lib.cc
+++ b/aos/network/message_bridge_test_lib.cc
@@ -1,6 +1,9 @@
 #include "aos/network/message_bridge_test_lib.h"
 
-DECLARE_string(boot_uuid);
+#include "absl/flags/flag.h"
+#include "absl/log/log.h"
+
+ABSL_DECLARE_FLAG(std::string, boot_uuid);
 
 namespace aos::message_bridge::testing {
 
@@ -69,14 +72,14 @@
 
 void PiNode::OnPi() {
   DoSetShmBase(node_name_);
-  FLAGS_override_hostname = host_name_;
-  FLAGS_boot_uuid = boot_uuid_.ToString();
+  absl::SetFlag(&FLAGS_override_hostname, host_name_);
+  absl::SetFlag(&FLAGS_boot_uuid, boot_uuid_.ToString());
 }
 
 void PiNode::MakeServer(const std::string server_config_sha256) {
   OnPi();
   LOG(INFO) << "Making " << node_name_ << " server";
-  FLAGS_application_name = app_name_;
+  absl::SetFlag(&FLAGS_application_name, app_name_);
   server_event_loop_ = std::make_unique<aos::ShmEventLoop>(&config_.message());
   server_event_loop_->SetRuntimeRealtimePriority(1);
   message_bridge_server_ = std::make_unique<MessageBridgeServer>(
@@ -114,7 +117,7 @@
 void PiNode::MakeClient() {
   OnPi();
   LOG(INFO) << "Making " << node_name_ << " client";
-  FLAGS_application_name = app_name_;
+  absl::SetFlag(&FLAGS_application_name, app_name_);
   client_event_loop_ = std::make_unique<aos::ShmEventLoop>(&config_.message());
   client_event_loop_->SetRuntimeRealtimePriority(1);
   message_bridge_client_ = std::make_unique<MessageBridgeClient>(
@@ -138,7 +141,7 @@
                       const PiNode *other_node) {
   OnPi();
   LOG(INFO) << "Making " << node_name_ << " test";
-  FLAGS_application_name = test_app_name;
+  absl::SetFlag(&FLAGS_application_name, test_app_name);
   test_event_loop_ = std::make_unique<aos::ShmEventLoop>(&config_.message());
 
   std::string channel_name = "/" + node_name_ + "/aos";
diff --git a/aos/network/message_bridge_test_lib.h b/aos/network/message_bridge_test_lib.h
index f8c0a3a..613f792 100644
--- a/aos/network/message_bridge_test_lib.h
+++ b/aos/network/message_bridge_test_lib.h
@@ -3,6 +3,7 @@
 #include <chrono>
 #include <thread>
 
+#include "absl/flags/reflection.h"
 #include "absl/strings/str_cat.h"
 #include "gtest/gtest.h"
 
@@ -92,7 +93,7 @@
 
   bool shared() const;
 
-  gflags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 
   PiNode pi1_;
   PiNode pi2_;
diff --git a/aos/network/multinode_timestamp_filter.cc b/aos/network/multinode_timestamp_filter.cc
index 42e4299..263d52b 100644
--- a/aos/network/multinode_timestamp_filter.cc
+++ b/aos/network/multinode_timestamp_filter.cc
@@ -4,8 +4,10 @@
 #include <functional>
 #include <map>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_join.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/boot_timestamp.h"
@@ -13,53 +15,54 @@
 #include "aos/network/timestamp_filter.h"
 #include "aos/time/time.h"
 
-DEFINE_bool(timestamps_to_csv, false,
-            "If true, write all the time synchronization information to a set "
-            "of CSV files in /tmp/.  This should only be needed when debugging "
-            "time synchronization.");
+ABSL_FLAG(bool, timestamps_to_csv, false,
+          "If true, write all the time synchronization information to a set "
+          "of CSV files in /tmp/.  This should only be needed when debugging "
+          "time synchronization.");
 
-DEFINE_string(timestamp_csv_folder, "/tmp", "Folder to drop CSVs in");
+ABSL_FLAG(std::string, timestamp_csv_folder, "/tmp", "Folder to drop CSVs in");
 
-DEFINE_int32(max_invalid_distance_ns, 0,
-             "The max amount of time we will let the solver go backwards.");
+ABSL_FLAG(int32_t, max_invalid_distance_ns, 0,
+          "The max amount of time we will let the solver go backwards.");
 
-DEFINE_int32(debug_solve_number, -1,
-             "If nonzero, print out all the state for the provided solve "
-             "number.  This is typically used by solving once, taking note of "
-             "which solution failed to converge, and then re-running with "
-             "debug turned on for just that problem.");
+ABSL_FLAG(int32_t, debug_solve_number, -1,
+          "If nonzero, print out all the state for the provided solve "
+          "number.  This is typically used by solving once, taking note of "
+          "which solution failed to converge, and then re-running with "
+          "debug turned on for just that problem.");
 
-DEFINE_bool(bounds_offset_error, false,
-            "If true, use the offset to the bounds for solving instead of to "
-            "the interpolation lines.  This seems to make startup a bit "
-            "better, but won't track the middle as well.");
+ABSL_FLAG(bool, bounds_offset_error, false,
+          "If true, use the offset to the bounds for solving instead of to "
+          "the interpolation lines.  This seems to make startup a bit "
+          "better, but won't track the middle as well.");
 
-DEFINE_bool(
-    crash_on_solve_failure, true,
+ABSL_FLAG(
+    bool, crash_on_solve_failure, true,
     "If true, crash when the solver fails to converge.  If false, keep going.  "
     "This should only be set to false when trying to see if future problems "
     "would be solvable.  This won't process a valid log");
 
-DEFINE_bool(attempt_simultaneous_constrained_solve, true,
-            "If true, try the simultaneous, constrained solver.  If false, "
-            "only solve constrained problems sequentially.");
+ABSL_FLAG(bool, attempt_simultaneous_constrained_solve, true,
+          "If true, try the simultaneous, constrained solver.  If false, "
+          "only solve constrained problems sequentially.");
 
-DEFINE_bool(
-    remove_unlikely_constraints, true,
+ABSL_FLAG(
+    bool, remove_unlikely_constraints, true,
     "If true, when solving, try with our best guess at which constraints will "
     "be relevant and resolve if that proves wrong with an updated set.  For "
     "expensive problems, this reduces solve time significantly.");
 
-DEFINE_int32(solve_verbosity, 1, "Verbosity to use when debugging the solver.");
+ABSL_FLAG(int32_t, solve_verbosity, 1,
+          "Verbosity to use when debugging the solver.");
 
-DEFINE_bool(constrained_solve, true,
-            "If true, use the constrained solver.  If false, only solve "
-            "unconstrained.");
+ABSL_FLAG(bool, constrained_solve, true,
+          "If true, use the constrained solver.  If false, only solve "
+          "unconstrained.");
 
-#define SOLVE_VLOG_IS_ON(solve_number, v)                             \
-  (VLOG_IS_ON(v) ||                                                   \
-   (static_cast<int32_t>(solve_number) == FLAGS_debug_solve_number && \
-    v <= FLAGS_solve_verbosity))
+#define SOLVE_VLOG_IS_ON(solve_number, v)                           \
+  (VLOG_IS_ON(v) || (static_cast<int32_t>(solve_number) ==          \
+                         absl::GetFlag(FLAGS_debug_solve_number) && \
+                     v <= absl::GetFlag(FLAGS_solve_verbosity)))
 
 #define SOLVE_VLOG(solve_number, v) \
   LOG_IF(INFO, SOLVE_VLOG_IS_ON(solve_number, v))
@@ -77,7 +80,7 @@
 
 template <class... Args>
 std::string CsvPath(Args &&...args) {
-  return absl::StrCat(FLAGS_timestamp_csv_folder, "/",
+  return absl::StrCat(absl::GetFlag(FLAGS_timestamp_csv_folder), "/",
                       std::forward<Args>(args)...);
 }
 }  // namespace
@@ -329,7 +332,7 @@
       std::pair<NoncausalTimestampFilter::Pointer,
                 std::tuple<chrono::nanoseconds, double, double>>
           offset_error =
-              FLAGS_bounds_offset_error
+              absl::GetFlag(FLAGS_bounds_offset_error)
                   ? filter.filter->BoundsOffsetError(
                         filter.b_filter, std::move(filter.pointer),
                         base_clock_[i], time_offsets(a_solution_index),
@@ -1049,7 +1052,8 @@
             << " Considering constraint " << i << " from before";
         active_constraints.emplace_back(i);
         ++original_constraint_index;
-      } else if (derivatives.f(i) > 0.0 || !FLAGS_remove_unlikely_constraints) {
+      } else if (derivatives.f(i) > 0.0 ||
+                 !absl::GetFlag(FLAGS_remove_unlikely_constraints)) {
         SOLVE_VLOG(my_solve_number_, 1) << " Considering constraint " << i;
         active_constraints.emplace_back(i);
       }
@@ -1306,7 +1310,8 @@
     }
   }
 
-  if (iteration > max_iterations && FLAGS_crash_on_solve_failure) {
+  if (iteration > max_iterations &&
+      absl::GetFlag(FLAGS_crash_on_solve_failure)) {
     LOG(ERROR) << "Failed to converge on solve " << my_solve_number_;
     return std::nullopt;
   }
@@ -1417,7 +1422,7 @@
         // hitting this anymore.  I'm also likely the one who will be debugging
         // it next and would rather spend the time debugging it when I get a bug
         // report.
-        if (FLAGS_bounds_offset_error) {
+        if (absl::GetFlag(FLAGS_bounds_offset_error)) {
           gradients[i].emplace_back(
               std::string("- ") +
               filter.filter->DebugOffsetError(
@@ -1789,7 +1794,7 @@
   CHECK_EQ(boots_->boots.size(), NodesCount());
   filters_per_node_.resize(NodesCount());
   last_monotonics_.resize(NodesCount(), BootTimestamp::epoch());
-  if (FLAGS_timestamps_to_csv && multi_node) {
+  if (absl::GetFlag(FLAGS_timestamps_to_csv) && multi_node) {
     fp_ = fopen(CsvPath("timestamp_noncausal_offsets.csv").c_str(), "w");
     fprintf(fp_, "# distributed");
     for (const Node *node : configuration::GetNodes(logged_configuration)) {
@@ -1925,7 +1930,7 @@
 
 void MultiNodeNoncausalOffsetEstimator::Start(
     std::vector<monotonic_clock::time_point> times) {
-  if (FLAGS_timestamps_to_csv) {
+  if (absl::GetFlag(FLAGS_timestamps_to_csv)) {
     std::fstream s(CsvPath("timestamp_noncausal_starttime.csv").c_str(),
                    s.trunc | s.out);
     CHECK(s.is_open());
@@ -2636,7 +2641,8 @@
                                  SOLVE_VLOG_IS_ON(solver.my_solve_number(), 2),
                              solution_y);
 
-    if (iterations > kMaxIterations && FLAGS_crash_on_solve_failure) {
+    if (iterations > kMaxIterations &&
+        absl::GetFlag(FLAGS_crash_on_solve_failure)) {
       UpdateSolution(std::move(solution));
       if (!FlushAndClose(false)) {
         return std::nullopt;
@@ -2646,7 +2652,7 @@
     }
 
     if (!problem->ValidateSolution(solution, true)) {
-      if (!FLAGS_constrained_solve) {
+      if (!absl::GetFlag(FLAGS_constrained_solve)) {
         problem->ValidateSolution(solution, false);
         LOG(WARNING) << "Invalid solution, constraints not met for problem "
                      << solver.my_solve_number();
@@ -2671,7 +2677,7 @@
           problem->set_base_clock(node_index, solution[node_index]);
         }
 
-        if (!FLAGS_attempt_simultaneous_constrained_solve) {
+        if (!absl::GetFlag(FLAGS_attempt_simultaneous_constrained_solve)) {
           VLOG(1) << "Falling back to sequential constrained Newton.";
           return SequentialSolution(problem, candidate_times, base_times);
         }
@@ -2687,7 +2693,8 @@
         std::tie(std::ignore, std::ignore, solution_index, iterations) =
             *solver_result;
 
-        if (iterations > kMaxIterations && FLAGS_crash_on_solve_failure) {
+        if (iterations > kMaxIterations &&
+            absl::GetFlag(FLAGS_crash_on_solve_failure)) {
           UpdateSolution(std::move(solution));
           if (!FlushAndClose(false)) {
             return std::nullopt;
@@ -2729,7 +2736,8 @@
   // If times are close enough, drop the invalid time.
   const chrono::nanoseconds invalid_distance =
       InvalidDistance(result_times, solution);
-  if (invalid_distance <= chrono::nanoseconds(FLAGS_max_invalid_distance_ns)) {
+  if (invalid_distance <=
+      chrono::nanoseconds(absl::GetFlag(FLAGS_max_invalid_distance_ns))) {
     VLOG(1) << "Times can't be compared by " << invalid_distance.count()
             << "ns";
     for (size_t i = 0; i < result_times.size(); ++i) {
@@ -2867,7 +2875,8 @@
                                  SOLVE_VLOG_IS_ON(solver.my_solve_number(), 2),
                              solution_y);
 
-    if (iterations > kMaxIterations && FLAGS_crash_on_solve_failure) {
+    if (iterations > kMaxIterations &&
+        absl::GetFlag(FLAGS_crash_on_solve_failure)) {
       UpdateSolution(std::move(solution));
       if (!FlushAndClose(false)) {
         return std::nullopt;
@@ -2881,7 +2890,7 @@
     // CSV file so we can view the problem and figure out what to do.  The
     // results won't make sense.
     if (!problem->ValidateSolution(solution, true)) {
-      if (!FLAGS_constrained_solve) {
+      if (!absl::GetFlag(FLAGS_constrained_solve)) {
         // Do it non-quiet now.
         problem->ValidateSolution(solution, false);
 
@@ -2918,7 +2927,8 @@
         std::tie(std::ignore, std::ignore, solution_index, iterations) =
             *solver_result;
 
-        if (iterations > kMaxIterations && FLAGS_crash_on_solve_failure) {
+        if (iterations > kMaxIterations &&
+            absl::GetFlag(FLAGS_crash_on_solve_failure)) {
           UpdateSolution(std::move(solution));
           if (!FlushAndClose(false)) {
             return std::nullopt;
@@ -3238,7 +3248,7 @@
         const chrono::nanoseconds invalid_distance =
             InvalidDistance(last_monotonics_, result_times);
         if (invalid_distance <=
-            chrono::nanoseconds(FLAGS_max_invalid_distance_ns)) {
+            chrono::nanoseconds(absl::GetFlag(FLAGS_max_invalid_distance_ns))) {
           WriteFilter(next_filter, sample);
           return NextTimestamp();
         }
diff --git a/aos/network/multinode_timestamp_filter.h b/aos/network/multinode_timestamp_filter.h
index 66dcbff..8d560b6 100644
--- a/aos/network/multinode_timestamp_filter.h
+++ b/aos/network/multinode_timestamp_filter.h
@@ -8,7 +8,8 @@
 
 #include "Eigen/Dense"
 #include "absl/container/btree_set.h"
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/boot_timestamp.h"
diff --git a/aos/network/ping.cc b/aos/network/ping.cc
index f105133..6aceaee 100644
--- a/aos/network/ping.cc
+++ b/aos/network/ping.cc
@@ -1,17 +1,17 @@
 #include <chrono>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/log.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/network/sctp_server.h"
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_uint32(port, 1323, "Port to pingpong on");
-DEFINE_uint32(size, 1000000, "Size of data to send in bytes");
-DEFINE_uint32(duration, 1000, "Period to send at in milliseconds");
-DEFINE_uint32(ttl, 0, "TTL in milliseconds");
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(uint32_t, port, 1323, "Port to pingpong on");
+ABSL_FLAG(uint32_t, size, 1000000, "Size of data to send in bytes");
+ABSL_FLAG(uint32_t, duration, 1000, "Period to send at in milliseconds");
+ABSL_FLAG(uint32_t, ttl, 0, "TTL in milliseconds");
 
 namespace aos {
 namespace message_bridge {
@@ -21,17 +21,17 @@
 class PingServer {
  public:
   PingServer(aos::ShmEventLoop *event_loop)
-      : event_loop_(event_loop), server_(2, "::", FLAGS_port) {
+      : event_loop_(event_loop), server_(2, "::", absl::GetFlag(FLAGS_port)) {
     event_loop_->epoll()->OnReadable(server_.fd(),
                                      [this]() { MessageReceived(); });
-    server_.SetMaxReadSize(FLAGS_size + 100);
-    server_.SetMaxWriteSize(FLAGS_size + 100);
+    server_.SetMaxReadSize(absl::GetFlag(FLAGS_size) + 100);
+    server_.SetMaxWriteSize(absl::GetFlag(FLAGS_size) + 100);
 
     timer_ = event_loop_->AddTimer([this]() { Timer(); });
 
     event_loop_->OnRun([this]() {
       timer_->Schedule(event_loop_->monotonic_now(),
-                       chrono::milliseconds(FLAGS_duration));
+                       chrono::milliseconds(absl::GetFlag(FLAGS_duration)));
     });
 
     event_loop_->SetRuntimeRealtimePriority(5);
@@ -48,9 +48,9 @@
       return;
     }
 
-    std::string data(FLAGS_size, 'a');
+    std::string data(absl::GetFlag(FLAGS_size), 'a');
 
-    if (server_.Send(data, sac_assoc_id_, 0, FLAGS_ttl)) {
+    if (server_.Send(data, sac_assoc_id_, 0, absl::GetFlag(FLAGS_ttl))) {
       LOG(INFO) << "Sent " << data.size();
     } else {
       PLOG(ERROR) << "Failed to send";
@@ -117,7 +117,7 @@
 
 int Main() {
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
   PingServer server(&event_loop);
diff --git a/aos/network/pong.cc b/aos/network/pong.cc
index 8f08836..29253ec 100644
--- a/aos/network/pong.cc
+++ b/aos/network/pong.cc
@@ -1,19 +1,19 @@
 #include <chrono>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/log.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
 #include "aos/network/sctp_client.h"
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_uint32(port, 1323, "Port to pingpong on");
-DEFINE_string(target, "vpu0-0a", "Host to connect to");
-DEFINE_uint32(rx_size, 1000000,
-              "RX buffer size to set the max size to be in bytes.");
-DEFINE_uint32(size, 1000, "Size of data to send in bytes");
-DEFINE_uint32(ttl, 0, "TTL in milliseconds");
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(uint32_t, port, 1323, "Port to pingpong on");
+ABSL_FLAG(std::string, target, "vpu0-0a", "Host to connect to");
+ABSL_FLAG(uint32_t, rx_size, 1000000,
+          "RX buffer size to set the max size to be in bytes.");
+ABSL_FLAG(uint32_t, size, 1000, "Size of data to send in bytes");
+ABSL_FLAG(uint32_t, ttl, 0, "TTL in milliseconds");
 
 namespace aos {
 namespace message_bridge {
@@ -23,9 +23,15 @@
 class PingClient {
  public:
   PingClient(aos::ShmEventLoop *event_loop)
-      : event_loop_(event_loop), client_(FLAGS_target, FLAGS_port, 2, "::", 0) {
-    client_.SetMaxReadSize(std::max(FLAGS_rx_size, FLAGS_size) + 100);
-    client_.SetMaxWriteSize(std::max(FLAGS_rx_size, FLAGS_size) + 100);
+      : event_loop_(event_loop),
+        client_(absl::GetFlag(FLAGS_target), absl::GetFlag(FLAGS_port), 2,
+                "::", 0) {
+    client_.SetMaxReadSize(
+        std::max(absl::GetFlag(FLAGS_rx_size), absl::GetFlag(FLAGS_size)) +
+        100);
+    client_.SetMaxWriteSize(
+        std::max(absl::GetFlag(FLAGS_rx_size), absl::GetFlag(FLAGS_size)) +
+        100);
 
     timer_ = event_loop_->AddTimer([this]() { Timer(); });
 
@@ -45,9 +51,9 @@
   sctp_assoc_t sac_assoc_id_ = 0;
 
   void Timer() {
-    std::string data(FLAGS_size, 'a');
+    std::string data(absl::GetFlag(FLAGS_size), 'a');
 
-    if (client_.Send(0, data, FLAGS_ttl)) {
+    if (client_.Send(0, data, absl::GetFlag(FLAGS_ttl))) {
       LOG(INFO) << "Sent " << data.size();
     } else {
       PLOG(ERROR) << "Failed to send";
@@ -119,7 +125,7 @@
 
 int Main() {
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
   PingClient server(&event_loop);
diff --git a/aos/network/rawrtc.cc b/aos/network/rawrtc.cc
index 6d9bc3d..eddf696 100644
--- a/aos/network/rawrtc.cc
+++ b/aos/network/rawrtc.cc
@@ -9,13 +9,15 @@
 #include <functional>
 #include <string>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
-DEFINE_int32(min_ice_port, -1,
-             "Minimum port number to use for ICE candidates.");
-DEFINE_int32(max_ice_port, -1,
-             "Maximum port number to use for ICE candidates.");
+ABSL_FLAG(int32_t, min_ice_port, -1,
+          "Minimum port number to use for ICE candidates.");
+ABSL_FLAG(int32_t, max_ice_port, -1,
+          "Maximum port number to use for ICE candidates.");
 
 namespace aos::web_proxy {
 namespace {
@@ -198,11 +200,14 @@
   CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_sctp_buffer_length(
       configuration, TRANSPORT_BUFFER_LENGTH, TRANSPORT_BUFFER_LENGTH));
 
-  if (FLAGS_min_ice_port >= 0 && FLAGS_max_ice_port >= 0) {
-    CHECK_LT(FLAGS_min_ice_port, FLAGS_max_ice_port);
+  if (absl::GetFlag(FLAGS_min_ice_port) >= 0 &&
+      absl::GetFlag(FLAGS_max_ice_port) >= 0) {
+    CHECK_LT(absl::GetFlag(FLAGS_min_ice_port),
+             absl::GetFlag(FLAGS_max_ice_port));
     // Set the port range to use for ICE candidates.
     CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_ice_udp_port_range(
-        configuration, FLAGS_min_ice_port, FLAGS_max_ice_port));
+        configuration, absl::GetFlag(FLAGS_min_ice_port),
+        absl::GetFlag(FLAGS_max_ice_port)));
   }
 
   // Create peer connection
diff --git a/aos/network/rawrtc.h b/aos/network/rawrtc.h
index 57153f0..7b919bf 100644
--- a/aos/network/rawrtc.h
+++ b/aos/network/rawrtc.h
@@ -10,8 +10,9 @@
 #include "rawrtcc/utils.h"
 }
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
 namespace aos::web_proxy {
 
diff --git a/aos/network/sctp_client.cc b/aos/network/sctp_client.cc
index 32347fd..b387e07 100644
--- a/aos/network/sctp_client.cc
+++ b/aos/network/sctp_client.cc
@@ -9,14 +9,16 @@
 #include <cstring>
 #include <string_view>
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/network/sctp_lib.h"
 #include "aos/unique_malloc_ptr.h"
 
-DEFINE_int32(sinit_max_init_timeout, 0,
-             "Timeout in milliseconds for retrying the INIT packet when "
-             "connecting to the message bridge server");
+ABSL_FLAG(int32_t, sinit_max_init_timeout, 0,
+          "Timeout in milliseconds for retrying the INIT packet when "
+          "connecting to the message bridge server");
 
 namespace aos::message_bridge {
 
@@ -35,7 +37,7 @@
     initmsg.sinit_num_ostreams = streams;
     initmsg.sinit_max_instreams = streams;
     // Max timeout in milliseconds for the INIT packet.
-    initmsg.sinit_max_init_timeo = FLAGS_sinit_max_init_timeout;
+    initmsg.sinit_max_init_timeo = absl::GetFlag(FLAGS_sinit_max_init_timeout);
     PCHECK(setsockopt(fd(), IPPROTO_SCTP, SCTP_INITMSG, &initmsg,
                       sizeof(struct sctp_initmsg)) == 0);
   }
diff --git a/aos/network/sctp_client.h b/aos/network/sctp_client.h
index 952d0e9..61e4e9e 100644
--- a/aos/network/sctp_client.h
+++ b/aos/network/sctp_client.h
@@ -5,8 +5,9 @@
 #include <cstdlib>
 #include <string_view>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/network/sctp_lib.h"
 #include "aos/unique_malloc_ptr.h"
diff --git a/aos/network/sctp_lib.cc b/aos/network/sctp_lib.cc
index cf50ad6..1c55293 100644
--- a/aos/network/sctp_lib.cc
+++ b/aos/network/sctp_lib.cc
@@ -16,6 +16,10 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
+
 #include "aos/util/file.h"
 
 // The casts required to read datastructures from sockets trip - Wcast - align.
@@ -23,9 +27,9 @@
 #pragma clang diagnostic ignored "-Wcast-align"
 #endif
 
-DEFINE_string(interface, "", "network interface");
-DEFINE_bool(disable_ipv6, false, "disable ipv6");
-DEFINE_int32(rmem, 0, "If nonzero, set rmem to this size.");
+ABSL_FLAG(std::string, interface, "", "network interface");
+ABSL_FLAG(bool, disable_ipv6, false, "disable ipv6");
+ABSL_FLAG(int32_t, rmem, 0, "If nonzero, set rmem to this size.");
 
 // The Type of Service.
 // https://www.tucny.com/Home/dscp-tos
@@ -39,8 +43,8 @@
 // to zero. Those two bits are the "Explicit Congestion Notification" bits. They
 // are controlled by the IP stack itself (and used by the router). We don't
 // control that via the TOS value we set here.
-DEFINE_int32(
-    sctp_tos, 176,
+ABSL_FLAG(
+    int32_t, sctp_tos, 176,
     "The Type-Of-Service value to use. Defaults to a critical priority. "
     "Always set values here whose two least significant bits are set to zero. "
     "When using tcpdump, the `tos` field may show the least significant two "
@@ -88,7 +92,7 @@
 }  // namespace
 
 bool Ipv6Enabled() {
-  if (FLAGS_disable_ipv6) {
+  if (absl::GetFlag(FLAGS_disable_ipv6)) {
     return false;
   }
   int fd = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);
@@ -151,8 +155,9 @@
       t_addr6->sin6_family = addrinfo_result->ai_family;
       t_addr6->sin6_port = htons(port);
 
-      if (FLAGS_interface.size() > 0) {
-        t_addr6->sin6_scope_id = if_nametoindex(FLAGS_interface.c_str());
+      if (absl::GetFlag(FLAGS_interface).size() > 0) {
+        t_addr6->sin6_scope_id =
+            if_nametoindex(absl::GetFlag(FLAGS_interface).c_str());
       }
 
       break;
@@ -295,7 +300,7 @@
     // Set up Type-Of-Service.
     //
     // See comments for the --sctp_tos flag for more information.
-    int tos = IPTOS_DSCP(FLAGS_sctp_tos);
+    int tos = IPTOS_DSCP(absl::GetFlag(FLAGS_sctp_tos));
     PCHECK(setsockopt(fd_, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == 0);
   }
   {
@@ -683,8 +688,8 @@
   // The SO_RCVBUF option (also controlled by net.core.rmem_default) needs to be
   // decently large but the actual size can be measured by tuning.  The defaults
   // should be fine.  If it isn't big enough, transmission will fail.
-  if (FLAGS_rmem > 0) {
-    size_t rmem = FLAGS_rmem;
+  if (absl::GetFlag(FLAGS_rmem) > 0) {
+    size_t rmem = absl::GetFlag(FLAGS_rmem);
     PCHECK(setsockopt(fd(), SOL_SOCKET, SO_RCVBUF, &rmem, sizeof(rmem)) == 0);
   }
 }
diff --git a/aos/network/sctp_lib.h b/aos/network/sctp_lib.h
index 3430be8..97d9d20 100644
--- a/aos/network/sctp_lib.h
+++ b/aos/network/sctp_lib.h
@@ -11,9 +11,9 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/unique_malloc_ptr.h"
 
diff --git a/aos/network/sctp_lib_test.cc b/aos/network/sctp_lib_test.cc
index f297a82..a822257 100644
--- a/aos/network/sctp_lib_test.cc
+++ b/aos/network/sctp_lib_test.cc
@@ -1,16 +1,17 @@
 #include "aos/network/sctp_lib.h"
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/init.h"
 
-DEFINE_string(host, "", "host to resolve");
-DEFINE_int32(port, 2977, "port to use");
+ABSL_FLAG(std::string, host, "", "host to resolve");
+ABSL_FLAG(int32_t, port, 2977, "port to use");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
   struct sockaddr_storage sockaddr = aos::message_bridge::ResolveSocket(
-      FLAGS_host, FLAGS_port, aos::message_bridge::Ipv6Enabled());
+      absl::GetFlag(FLAGS_host), absl::GetFlag(FLAGS_port),
+      aos::message_bridge::Ipv6Enabled());
   LOG(INFO) << "Family " << aos::message_bridge::Family(sockaddr);
   LOG(INFO) << "Address " << aos::message_bridge::Address(sockaddr);
   return 0;
diff --git a/aos/network/sctp_perf.cc b/aos/network/sctp_perf.cc
index db762de..dae8667 100644
--- a/aos/network/sctp_perf.cc
+++ b/aos/network/sctp_perf.cc
@@ -1,7 +1,9 @@
 #include <chrono>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/init.h"
@@ -14,24 +16,24 @@
 #pragma clang diagnostic ignored "-Wcast-align"
 #endif
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_uint32(port, 1323, "Port to run the sctp test on");
-DEFINE_uint32(payload_size, 1000, "Size of data to send in bytes");
-DEFINE_uint32(ttl, 0, "TTL in milliseconds");
-DEFINE_uint32(rx_size, 1000000,
-              "RX buffer size to set the max size to be in bytes.");
-DEFINE_string(host, "", "Server host (acts as server if unspecified)");
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(uint32_t, port, 1323, "Port to run the sctp test on");
+ABSL_FLAG(uint32_t, payload_size, 1000, "Size of data to send in bytes");
+ABSL_FLAG(uint32_t, ttl, 0, "TTL in milliseconds");
+ABSL_FLAG(uint32_t, rx_size, 1000000,
+          "RX buffer size to set the max size to be in bytes.");
+ABSL_FLAG(std::string, host, "", "Server host (acts as server if unspecified)");
 
-DEFINE_bool(client, false,
-            "If true, then act as a client, otherwise act as a server");
-DEFINE_uint32(skip_first_n, 10,
-              "Skip the first 'n' messages when computing statistics.");
+ABSL_FLAG(bool, client, false,
+          "If true, then act as a client, otherwise act as a server");
+ABSL_FLAG(uint32_t, skip_first_n, 10,
+          "Skip the first 'n' messages when computing statistics.");
 
-DEFINE_string(sctp_auth_key_file, "",
-              "When set, use the provided key for SCTP authentication as "
-              "defined in RFC 4895");
+ABSL_FLAG(std::string, sctp_auth_key_file, "",
+          "When set, use the provided key for SCTP authentication as "
+          "defined in RFC 4895");
 
-DECLARE_bool(die_on_malloc);
+ABSL_DECLARE_FLAG(bool, die_on_malloc);
 
 namespace aos::message_bridge::perf {
 
@@ -40,15 +42,16 @@
 using util::ReadFileToVecOrDie;
 
 SctpAuthMethod SctpAuthMethod() {
-  return FLAGS_sctp_auth_key_file.empty() ? SctpAuthMethod::kNoAuth
-                                          : SctpAuthMethod::kAuth;
+  return absl::GetFlag(FLAGS_sctp_auth_key_file).empty()
+             ? SctpAuthMethod::kNoAuth
+             : SctpAuthMethod::kAuth;
 }
 
 std::vector<uint8_t> GetSctpAuthKey() {
   if (SctpAuthMethod() == SctpAuthMethod::kNoAuth) {
     return {};
   }
-  return ReadFileToVecOrDie(FLAGS_sctp_auth_key_file);
+  return ReadFileToVecOrDie(absl::GetFlag(FLAGS_sctp_auth_key_file));
 }
 
 }  // namespace
@@ -59,12 +62,12 @@
  public:
   Server(aos::ShmEventLoop *event_loop)
       : event_loop_(event_loop),
-        server_(2, "0.0.0.0", FLAGS_port, SctpAuthMethod()) {
+        server_(2, "0.0.0.0", absl::GetFlag(FLAGS_port), SctpAuthMethod()) {
     server_.SetAuthKey(GetSctpAuthKey());
     event_loop_->epoll()->OnReadable(server_.fd(),
                                      [this]() { MessageReceived(); });
-    server_.SetMaxReadSize(FLAGS_rx_size + 100);
-    server_.SetMaxWriteSize(FLAGS_rx_size + 100);
+    server_.SetMaxReadSize(absl::GetFlag(FLAGS_rx_size) + 100);
+    server_.SetMaxWriteSize(absl::GetFlag(FLAGS_rx_size) + 100);
 
     event_loop_->SetRuntimeRealtimePriority(5);
   }
@@ -76,7 +79,7 @@
       LOG(INFO) << "Lost connection to client. Not sending";
       return;
     }
-    if (server_.Send(message, sac_assoc_id_, 0, FLAGS_ttl)) {
+    if (server_.Send(message, sac_assoc_id_, 0, absl::GetFlag(FLAGS_ttl))) {
       LOG(INFO) << "Server reply with " << message.size() << "B";
     } else {
       PLOG(FATAL) << "Failed to send";
@@ -140,11 +143,11 @@
  public:
   Client(aos::ShmEventLoop *event_loop)
       : event_loop_(event_loop),
-        client_(FLAGS_host, FLAGS_port, 2, "0.0.0.0", FLAGS_port,
-                SctpAuthMethod()) {
+        client_(absl::GetFlag(FLAGS_host), absl::GetFlag(FLAGS_port), 2,
+                "0.0.0.0", absl::GetFlag(FLAGS_port), SctpAuthMethod()) {
     client_.SetAuthKey(GetSctpAuthKey());
-    client_.SetMaxReadSize(FLAGS_rx_size + 100);
-    client_.SetMaxWriteSize(FLAGS_rx_size + 100);
+    client_.SetMaxReadSize(absl::GetFlag(FLAGS_rx_size) + 100);
+    client_.SetMaxWriteSize(absl::GetFlag(FLAGS_rx_size) + 100);
 
     timer_ = event_loop_->AddTimer([this]() { Ping(); });
 
@@ -161,9 +164,9 @@
   ~Client() { event_loop_->epoll()->DeleteFd(client_.fd()); }
 
   void Ping() {
-    std::string payload(FLAGS_payload_size, 'a');
+    std::string payload(absl::GetFlag(FLAGS_payload_size), 'a');
     sent_time_ = aos::monotonic_clock::now();
-    if (client_.Send(0, payload, FLAGS_ttl)) {
+    if (client_.Send(0, payload, absl::GetFlag(FLAGS_ttl))) {
       LOG(INFO) << "Sending " << payload.size() << "B";
     } else {
       PLOG(ERROR) << "Failed to send";
@@ -226,8 +229,9 @@
             .count();
     avg_latency_ = (avg_latency_ * (count_ - 1) + elapsed_secs) / count_;
     // average one-way throughput
-    double throughput = FLAGS_payload_size * 2.0 / elapsed_secs;
-    double avg_throughput = FLAGS_payload_size * 2.0 / avg_latency_;
+    double throughput = absl::GetFlag(FLAGS_payload_size) * 2.0 / elapsed_secs;
+    double avg_throughput =
+        absl::GetFlag(FLAGS_payload_size) * 2.0 / avg_latency_;
     printf(
         "Round trip: %.2fms | %.2f KB/s | Avg RTL: %.2fms | %.2f KB/s | "
         "Count: %d\n",
@@ -240,25 +244,27 @@
   SctpClient client_;
   aos::TimerHandler *timer_;
   double avg_latency_ = 0.0;
-  int count_ = -FLAGS_skip_first_n;
+  int count_ = -absl::GetFlag(FLAGS_skip_first_n);
 
   aos::monotonic_clock::time_point sent_time_;
 };
 
 int Main() {
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
-  if (FLAGS_client) {
-    CHECK(!FLAGS_host.empty()) << "Client Usage: `sctp_perf --client --host "
-                                  "abc.com --payload_size [bytes] "
-                                  "[--port PORT] [--config PATH]`";
+  if (absl::GetFlag(FLAGS_client)) {
+    CHECK(!absl::GetFlag(FLAGS_host).empty())
+        << "Client Usage: `sctp_perf --client --host "
+           "abc.com --payload_size [bytes] "
+           "[--port PORT] [--config PATH]`";
 
     Client client(&event_loop);
     event_loop.Run();
   } else {
-    CHECK(FLAGS_host.empty()) << "Server Usage: `sctp_perf [--config PATH]`";
+    CHECK(absl::GetFlag(FLAGS_host).empty())
+        << "Server Usage: `sctp_perf [--config PATH]`";
     Server server(&event_loop);
     event_loop.Run();
   }
@@ -269,12 +275,12 @@
 }  // namespace aos::message_bridge::perf
 
 int main(int argc, char **argv) {
-  gflags::SetUsageMessage(absl::StrCat(
+  absl::SetProgramUsageMessage(absl::StrCat(
       "Measure SCTP performance\n", "  Server Usage: `sctp_perf`\n",
       "  Client Usage: `sctp_perf --client --host abc.com`\n"));
   aos::InitGoogle(&argc, &argv);
 
   // Client and server need to malloc.
-  FLAGS_die_on_malloc = false;
+  absl::SetFlag(&FLAGS_die_on_malloc, false);
   return aos::message_bridge::perf::Main();
 }
diff --git a/aos/network/sctp_server.cc b/aos/network/sctp_server.cc
index 7f7a0ae..c495180 100644
--- a/aos/network/sctp_server.cc
+++ b/aos/network/sctp_server.cc
@@ -13,7 +13,8 @@
 #include <memory>
 #include <thread>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/network/sctp_lib.h"
 #include "aos/unique_malloc_ptr.h"
diff --git a/aos/network/sctp_server.h b/aos/network/sctp_server.h
index 996645e..4dd295d 100644
--- a/aos/network/sctp_server.h
+++ b/aos/network/sctp_server.h
@@ -13,8 +13,9 @@
 #include <cstring>
 #include <memory>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/network/sctp_lib.h"
 #include "aos/unique_malloc_ptr.h"
diff --git a/aos/network/sctp_test.cc b/aos/network/sctp_test.cc
index bce5c19..d202e5d 100644
--- a/aos/network/sctp_test.cc
+++ b/aos/network/sctp_test.cc
@@ -3,7 +3,8 @@
 #include <chrono>
 #include <functional>
 
-#include "gflags/gflags.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
 #include "gmock/gmock-matchers.h"
 #include "gtest/gtest.h"
 
@@ -13,7 +14,7 @@
 #include "aos/network/sctp_server.h"
 #include "sctp_lib.h"
 
-DECLARE_bool(disable_ipv6);
+ABSL_DECLARE_FLAG(bool, disable_ipv6);
 
 namespace aos::message_bridge::testing {
 
@@ -128,7 +129,7 @@
   static void SetUpTestSuite() {
     EnableSctpAuthIfAvailable();
     // Buildkite seems to have issues with ipv6 sctp sockets...
-    FLAGS_disable_ipv6 = true;
+    absl::SetFlag(&FLAGS_disable_ipv6, true);
   }
 
   void SetUp() override { Run(); }
diff --git a/aos/network/team_number.cc b/aos/network/team_number.cc
index cc81e26..175c3a9 100644
--- a/aos/network/team_number.cc
+++ b/aos/network/team_number.cc
@@ -6,12 +6,14 @@
 #include <cinttypes>
 #include <cstdlib>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/numbers.h"
 
-DEFINE_string(
-    override_hostname, "",
-    "If set, this forces the hostname of this node to be the provided "
-    "hostname.");
+ABSL_FLAG(std::string, override_hostname, "",
+          "If set, this forces the hostname of this node to be the provided "
+          "hostname.");
 
 namespace aos::network {
 namespace team_number_internal {
@@ -106,13 +108,13 @@
 }  // namespace
 
 ::std::string GetHostname() {
-  if (FLAGS_override_hostname.empty()) {
+  if (absl::GetFlag(FLAGS_override_hostname).empty()) {
     char buf[256];
     buf[sizeof(buf) - 1] = '\0';
     PCHECK(gethostname(buf, sizeof(buf) - 1) == 0);
     return buf;
   } else {
-    return FLAGS_override_hostname;
+    return absl::GetFlag(FLAGS_override_hostname);
   }
 }
 
diff --git a/aos/network/team_number.h b/aos/network/team_number.h
index 7b9acbb..10f8921 100644
--- a/aos/network/team_number.h
+++ b/aos/network/team_number.h
@@ -5,9 +5,9 @@
 #include <optional>
 #include <string_view>
 
-#include "glog/logging.h"
+#include "absl/flags/declare.h"
 
-DECLARE_string(override_hostname);
+ABSL_DECLARE_FLAG(std::string, override_hostname);
 
 namespace aos {
 namespace network {
diff --git a/aos/network/timestamp_channel.cc b/aos/network/timestamp_channel.cc
index 778c2e7..1a821c5 100644
--- a/aos/network/timestamp_channel.cc
+++ b/aos/network/timestamp_channel.cc
@@ -1,14 +1,15 @@
 #include "aos/network/timestamp_channel.h"
 
+#include "absl/flags/flag.h"
 #include "absl/strings/str_cat.h"
 
-DEFINE_bool(combined_timestamp_channel_fallback, true,
-            "If true, fall back to using the combined timestamp channel if the "
-            "single timestamp channel doesn't exist for a timestamp.");
-DEFINE_bool(check_timestamp_channel_frequencies, true,
-            "If true, include a debug CHECK to ensure that remote timestamp "
-            "channels are configured to have at least as great a frequency as "
-            "the corresponding data channel.");
+ABSL_FLAG(bool, combined_timestamp_channel_fallback, true,
+          "If true, fall back to using the combined timestamp channel if the "
+          "single timestamp channel doesn't exist for a timestamp.");
+ABSL_FLAG(bool, check_timestamp_channel_frequencies, true,
+          "If true, include a debug CHECK to ensure that remote timestamp "
+          "channels are configured to have at least as great a frequency as "
+          "the corresponding data channel.");
 
 namespace aos::message_bridge {
 
@@ -55,7 +56,7 @@
     return split_timestamp_channel;
   }
 
-  if (!FLAGS_combined_timestamp_channel_fallback) {
+  if (!absl::GetFlag(FLAGS_combined_timestamp_channel_fallback)) {
     LOG(FATAL) << "Failed to find new timestamp channel {\"name\": \""
                << split_timestamp_channel_name << "\", \"type\": \""
                << RemoteMessage::GetFullyQualifiedName() << "\"} for "
@@ -112,7 +113,7 @@
 
   const Channel *timestamp_channel = finder.ForChannel(channel, connection);
 
-  if (FLAGS_check_timestamp_channel_frequencies) {
+  if (absl::GetFlag(FLAGS_check_timestamp_channel_frequencies)) {
     // Sanity-check that the timestamp channel can actually support full-rate
     // messages coming through on the source channel.
     CHECK_GE(timestamp_channel->frequency(), channel->frequency())
diff --git a/aos/network/timestamp_channel.h b/aos/network/timestamp_channel.h
index 7e48a00..0d57c82 100644
--- a/aos/network/timestamp_channel.h
+++ b/aos/network/timestamp_channel.h
@@ -5,7 +5,8 @@
 #include <vector>
 
 #include "absl/container/btree_map.h"
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
diff --git a/aos/network/timestamp_channel_test.cc b/aos/network/timestamp_channel_test.cc
index a217a74..9c0f57c 100644
--- a/aos/network/timestamp_channel_test.cc
+++ b/aos/network/timestamp_channel_test.cc
@@ -1,5 +1,7 @@
 #include "aos/network/timestamp_channel.h"
 
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
 #include "gtest/gtest.h"
 
 #include "aos/configuration.h"
@@ -9,16 +11,16 @@
 #include "aos/testing/path.h"
 #include "aos/testing/tmpdir.h"
 
-DECLARE_string(override_hostname);
+ABSL_DECLARE_FLAG(std::string, override_hostname);
 
 namespace aos::message_bridge::testing {
+
 class TimestampChannelTest : public ::testing::Test {
  protected:
   TimestampChannelTest()
       : config_(aos::configuration::ReadConfig(aos::testing::ArtifactPath(
             "aos/network/timestamp_channel_test_config.json"))) {
-    FLAGS_shm_base = aos::testing::TestTmpDir();
-    FLAGS_override_hostname = "pi1";
+    absl::SetFlag(&FLAGS_override_hostname, "pi1");
   }
   aos::FlatbufferDetachedBuffer<aos::Configuration> config_;
 };
diff --git a/aos/network/timestamp_filter.h b/aos/network/timestamp_filter.h
index 04ee605..5b24cd1 100644
--- a/aos/network/timestamp_filter.h
+++ b/aos/network/timestamp_filter.h
@@ -7,8 +7,9 @@
 #include <cstdio>
 #include <deque>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/numeric/int128.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/logging/boot_timestamp.h"
diff --git a/aos/network/web_proxy.cc b/aos/network/web_proxy.cc
index 6b71433..05bb7fa 100644
--- a/aos/network/web_proxy.cc
+++ b/aos/network/web_proxy.cc
@@ -1,6 +1,8 @@
 #include "aos/network/web_proxy.h"
 
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/flatbuffer_merge.h"
 #include "aos/network/connect_generated.h"
@@ -18,21 +20,21 @@
 struct list *tmrl_get(void);
 }
 
-DEFINE_int32(proxy_port, 1180, "Port to use for the web proxy server.");
-DEFINE_int32(pre_send_messages, 10000,
-             "Number of messages / queue to send to a client before waiting on "
-             "confirmation that the initial message was received. If set to "
-             "-1, will not throttle messages at all. This prevents a situation "
-             "where, when run on localhost, the large number of WebRTC packets "
-             "can overwhelm the browser and crash the webpage.");
+ABSL_FLAG(int32_t, proxy_port, 1180, "Port to use for the web proxy server.");
+ABSL_FLAG(int32_t, pre_send_messages, 10000,
+          "Number of messages / queue to send to a client before waiting on "
+          "confirmation that the initial message was received. If set to "
+          "-1, will not throttle messages at all. This prevents a situation "
+          "where, when run on localhost, the large number of WebRTC packets "
+          "can overwhelm the browser and crash the webpage.");
 // Note: sometimes it appears that WebRTC buffer up and stop sending message
 // ack's back from the client page. It is not clear *why* WebRTC is doing this,
 // but since the only reason we use those ack's is to stop ourselves from
 // overloading the client webpage, this setting lets us fall back to just a
 // time-based rate-limit when we stop receiving acks.
-DEFINE_double(max_buffer_pause_sec, 0.1,
-              "If we have not received any ack's in this amount of time, we "
-              "start to continue sending messages.");
+ABSL_FLAG(double, max_buffer_pause_sec, 0.1,
+          "If we have not received any ack's in this amount of time, we "
+          "start to continue sending messages.");
 
 namespace aos::web_proxy {
 WebsocketHandler::WebsocketHandler(::seasocks::Server *server,
@@ -176,7 +178,7 @@
   });
 
   server_.addWebSocketHandler("/ws", websocket_handler_);
-  CHECK(server_.startListening(FLAGS_proxy_port));
+  CHECK(server_.startListening(absl::GetFlag(FLAGS_proxy_port)));
 
   epoll->OnReadable(server_.fd(), [this]() {
     CHECK(::seasocks::Server::PollResult::Continue == server_.poll(0));
@@ -351,17 +353,19 @@
     // We are still waiting on the next message to appear; return.
     return nullptr;
   }
-  if (FLAGS_pre_send_messages > 0) {
+  if (absl::GetFlag(FLAGS_pre_send_messages) > 0) {
     // Note: Uses actual clock to handle simulation time.
     const aos::monotonic_clock::time_point now = aos::monotonic_clock::now();
     if (channel->last_report.has_value() &&
         channel->last_report.value() +
                 std::chrono::duration_cast<std::chrono::nanoseconds>(
-                    std::chrono::duration<double>(FLAGS_max_buffer_pause_sec)) <
+                    std::chrono::duration<double>(
+                        absl::GetFlag(FLAGS_max_buffer_pause_sec))) <
             now) {
       // Increment the number of messages that we will send over to the client
       // webpage.
-      channel->reported_queue_index += FLAGS_pre_send_messages / 10;
+      channel->reported_queue_index +=
+          absl::GetFlag(FLAGS_pre_send_messages) / 10;
       channel->reported_packet_index = 0;
       channel->last_report = now;
     }
@@ -371,7 +375,7 @@
     // browser, not to be ultra precise about anything. It's also not clear that
     // message *size* is necessarily even the determining factor in causing
     // issues.
-    if (channel->reported_queue_index + FLAGS_pre_send_messages <
+    if (channel->reported_queue_index + absl::GetFlag(FLAGS_pre_send_messages) <
         channel->current_queue_index) {
       return nullptr;
     }
diff --git a/aos/network/web_proxy_main.cc b/aos/network/web_proxy_main.cc
index 7684b06..3b1977a 100644
--- a/aos/network/web_proxy_main.cc
+++ b/aos/network/web_proxy_main.cc
@@ -1,27 +1,29 @@
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/events/shm_event_loop.h"
 #include "aos/flatbuffer_merge.h"
 #include "aos/init.h"
 #include "aos/network/web_proxy.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
-DEFINE_string(data_dir, "www", "Directory to serve data files from");
-DEFINE_int32(buffer_size, 1000000,
-             "-1 if infinite, in bytes / channel. If there are no active "
-             "connections, will not store anything.");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
+ABSL_FLAG(std::string, data_dir, "www", "Directory to serve data files from");
+ABSL_FLAG(int32_t, buffer_size, 1000000,
+          "-1 if infinite, in bytes / channel. If there are no active "
+          "connections, will not store anything.");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
 
-  aos::web_proxy::WebProxy web_proxy(
-      &event_loop, aos::web_proxy::StoreHistory::kNo, FLAGS_buffer_size);
-  web_proxy.SetDataPath(FLAGS_data_dir.c_str());
+  aos::web_proxy::WebProxy web_proxy(&event_loop,
+                                     aos::web_proxy::StoreHistory::kNo,
+                                     absl::GetFlag(FLAGS_buffer_size));
+  web_proxy.SetDataPath(absl::GetFlag(FLAGS_data_dir).c_str());
 
   event_loop.Run();
 }
diff --git a/aos/realtime.cc b/aos/realtime.cc
index 1e10457..43f0bb5 100644
--- a/aos/realtime.cc
+++ b/aos/realtime.cc
@@ -15,19 +15,21 @@
 #include <cstdlib>
 #include <cstring>
 
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/uuid.h"
 
-DEFINE_bool(
-    die_on_malloc, true,
+ABSL_FLAG(
+    bool, die_on_malloc, true,
     "If true, die when the application allocates memory in a RT section.");
-DEFINE_bool(skip_realtime_scheduler, false,
-            "If true, skip changing the scheduler.  Pretend that we changed "
-            "the scheduler instead.");
-DEFINE_bool(skip_locking_memory, false,
-            "If true, skip locking memory.  Pretend that we did it instead.");
+ABSL_FLAG(bool, skip_realtime_scheduler, false,
+          "If true, skip changing the scheduler.  Pretend that we changed "
+          "the scheduler instead.");
+ABSL_FLAG(bool, skip_locking_memory, false,
+          "If true, skip locking memory.  Pretend that we did it instead.");
 
 extern "C" {
 typedef void (*MallocHook_NewHook)(const void *ptr, size_t size);
@@ -44,6 +46,8 @@
 
 void *__libc_malloc(size_t size);
 void __libc_free(void *ptr);
+void *__libc_realloc(void *ptr, size_t size);
+void *__libc_calloc(size_t n, size_t elem_size);
 }  // extern "C"
 
 namespace FLAG__namespace_do_not_use_directly_use_DECLARE_double_instead {
@@ -109,6 +113,7 @@
   CHECK_EQ(1, mallopt(M_MMAP_MAX, 0));
 #endif
 
+  // TODO(austin): new tcmalloc does this differently...
   if (&FLAGS_tcmalloc_release_rate) {
     // Tell tcmalloc not to return memory.
     FLAGS_tcmalloc_release_rate = 0.0;
@@ -129,7 +134,7 @@
 }
 
 void InitRT() {
-  if (FLAGS_skip_locking_memory) {
+  if (absl::GetFlag(FLAGS_skip_locking_memory)) {
     LOG(WARNING) << "Ignoring request to lock all memory due to "
                     "--skip_locking_memory.";
     return;
@@ -138,7 +143,7 @@
   CheckNotRealtime();
   LockAllMemory();
 
-  if (FLAGS_skip_realtime_scheduler) {
+  if (absl::GetFlag(FLAGS_skip_realtime_scheduler)) {
     return;
   }
   // Only let rt processes run for 3 seconds straight.
@@ -161,22 +166,6 @@
   MarkRealtime(false);
 }
 
-std::ostream &operator<<(std::ostream &stream, const cpu_set_t &cpuset) {
-  stream << "{CPUs ";
-  bool first_found = false;
-  for (int i = 0; i < CPU_SETSIZE; ++i) {
-    if (CPU_ISSET(i, &cpuset)) {
-      if (first_found) {
-        stream << ", ";
-      }
-      stream << i;
-      first_found = true;
-    }
-  }
-  stream << "}";
-  return stream;
-}
-
 void SetCurrentThreadAffinity(const cpu_set_t &cpuset) {
   PCHECK(sched_setaffinity(0, sizeof(cpuset), &cpuset) == 0) << cpuset;
 }
@@ -203,7 +192,7 @@
   // scheduler is running.
   UUID::Random();
 
-  if (FLAGS_skip_realtime_scheduler) {
+  if (absl::GetFlag(FLAGS_skip_realtime_scheduler)) {
     LOG(WARNING) << "Ignoring request to switch to the RT scheduler due to "
                     "--skip_realtime_scheduler.";
     return;
@@ -271,7 +260,7 @@
 void NewHook(const void *ptr, size_t size) {
   if (is_realtime) {
     is_realtime = false;
-    RAW_LOG(FATAL, "Malloced %p -> %zu bytes", ptr, size);
+    ABSL_RAW_LOG(FATAL, "Malloced %p -> %zu bytes", ptr, size);
   }
 }
 
@@ -281,7 +270,7 @@
   // calls.
   if (is_realtime && ptr != nullptr) {
     is_realtime = false;
-    RAW_LOG(FATAL, "Delete Hook %p", ptr);
+    ABSL_RAW_LOG(FATAL, "Delete Hook %p", ptr);
   }
 }
 
@@ -290,9 +279,9 @@
 // malloc hooks for libc. Tcmalloc will replace everything it finds (malloc,
 // __libc_malloc, etc.), so we need its specific hook above as well.
 void *aos_malloc_hook(size_t size) {
-  if (FLAGS_die_on_malloc && aos::is_realtime) {
+  if (absl::GetFlag(FLAGS_die_on_malloc) && aos::is_realtime) {
     aos::is_realtime = false;
-    RAW_LOG(FATAL, "Malloced %zu bytes", size);
+    ABSL_RAW_LOG(FATAL, "Malloced %zu bytes", size);
     return nullptr;
   } else {
     return __libc_malloc(size);
@@ -300,16 +289,41 @@
 }
 
 void aos_free_hook(void *ptr) {
-  if (FLAGS_die_on_malloc && aos::is_realtime && ptr != nullptr) {
+  if (absl::GetFlag(FLAGS_die_on_malloc) && aos::is_realtime &&
+      ptr != nullptr) {
     aos::is_realtime = false;
-    RAW_LOG(FATAL, "Deleted %p", ptr);
+    ABSL_RAW_LOG(FATAL, "Deleted %p", ptr);
   } else {
     __libc_free(ptr);
   }
 }
 
+void *aos_realloc_hook(void *ptr, size_t size) {
+  if (absl::GetFlag(FLAGS_die_on_malloc) && aos::is_realtime) {
+    aos::is_realtime = false;
+    ABSL_RAW_LOG(FATAL, "Malloced %p -> %zu bytes", ptr, size);
+    return nullptr;
+  } else {
+    return __libc_realloc(ptr, size);
+  }
+}
+
+void *aos_calloc_hook(size_t n, size_t elem_size) {
+  if (absl::GetFlag(FLAGS_die_on_malloc) && aos::is_realtime) {
+    aos::is_realtime = false;
+    ABSL_RAW_LOG(FATAL, "Malloced %zu * %zu bytes", n, elem_size);
+    return nullptr;
+  } else {
+    return __libc_calloc(n, elem_size);
+  }
+}
+
 void *malloc(size_t size) __attribute__((weak, alias("aos_malloc_hook")));
 void free(void *ptr) __attribute__((weak, alias("aos_free_hook")));
+void *realloc(void *ptr, size_t size)
+    __attribute__((weak, alias("aos_realloc_hook")));
+void *calloc(size_t n, size_t elem_size)
+    __attribute__((weak, alias("aos_calloc_hook")));
 }
 
 void FatalUnsetRealtimePriority() {
@@ -342,11 +356,11 @@
 }
 
 void RegisterMallocHook() {
-  if (FLAGS_die_on_malloc) {
+  if (absl::GetFlag(FLAGS_die_on_malloc)) {
     // tcmalloc redefines __libc_malloc, so use this as a feature test.
     if (&__libc_malloc == &tc_malloc) {
       if (VLOG_IS_ON(1)) {
-        RAW_LOG(INFO, "Hooking tcmalloc for die_on_malloc");
+        ABSL_RAW_LOG(INFO, "Hooking tcmalloc for die_on_malloc");
       }
       if (&MallocHook_AddNewHook != nullptr) {
         CHECK(MallocHook_AddNewHook(&NewHook));
@@ -360,7 +374,7 @@
       }
     } else {
       if (VLOG_IS_ON(1)) {
-        RAW_LOG(INFO, "Replacing glibc malloc");
+        ABSL_RAW_LOG(INFO, "Replacing glibc malloc");
       }
       if (&malloc != &aos_malloc_hook) {
         has_malloc_hook = false;
diff --git a/aos/realtime.h b/aos/realtime.h
index 261eb26..e9c76b9 100644
--- a/aos/realtime.h
+++ b/aos/realtime.h
@@ -6,7 +6,26 @@
 #include <ostream>
 #include <string_view>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
+#include "absl/strings/str_format.h"
+
+// Stringifies the cpu_set_t for LOG().
+template <typename Sink>
+void AbslStringify(Sink &sink, const cpu_set_t &cpuset) {
+  sink.Append("{CPUs ");
+  bool first_found = false;
+  for (int i = 0; i < CPU_SETSIZE; ++i) {
+    if (CPU_ISSET(i, &cpuset)) {
+      if (first_found) {
+        sink.Append(", ");
+      }
+      absl::Format(&sink, "%d", i);
+      first_found = true;
+    }
+  }
+  sink.Append("}");
+}
 
 namespace aos {
 
@@ -29,9 +48,6 @@
 // name can have a maximum of 16 characters.
 void SetCurrentThreadName(const std::string_view name);
 
-// Stringifies the cpu_set_t for streams.
-std::ostream &operator<<(std::ostream &stream, const cpu_set_t &cpuset);
-
 // Creates a cpu_set_t from a list of CPUs.
 inline cpu_set_t MakeCpusetFromCpus(std::initializer_list<int> cpus) {
   cpu_set_t result;
diff --git a/aos/realtime_test.cc b/aos/realtime_test.cc
index 1f6e460..feb26b3 100644
--- a/aos/realtime_test.cc
+++ b/aos/realtime_test.cc
@@ -1,12 +1,15 @@
 #include "aos/realtime.h"
 
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/init.h"
 
-DECLARE_bool(die_on_malloc);
+ABSL_DECLARE_FLAG(bool, die_on_malloc);
 
 namespace aos::testing {
 
@@ -129,7 +132,7 @@
         *b = 5;
         EXPECT_EQ(*b, 5);
       },
-      "RAW: Delete");  // realloc free first, then allocates
+      "RAW: Malloced");
 }
 
 TEST(RealtimeDeathTest, Calloc) {
@@ -175,15 +178,15 @@
         int x = reinterpret_cast<const volatile int *>(0)[0];
         LOG(INFO) << x;
       },
-      "\\*\\*\\* Aborted at .*");
+      "\\*\\*\\* SIGSEGV received at .*");
 }
 
-// Tests that RAW_LOG(FATAL) explodes properly.
+// Tests that ABSL_RAW_LOG(FATAL) explodes properly.
 TEST(RealtimeDeathTest, RawFatal) {
   EXPECT_DEATH(
       {
         ScopedRealtime rt;
-        RAW_LOG(FATAL, "Cute message here\n");
+        ABSL_RAW_LOG(FATAL, "Cute message here\n");
       },
       "Cute message here");
 }
@@ -210,10 +213,9 @@
 // we can't test CHECK statements before turning die_on_malloc on globally.
 GTEST_API_ int main(int argc, char **argv) {
   ::testing::InitGoogleTest(&argc, argv);
-  FLAGS_logtostderr = true;
 
 #if !__has_feature(address_sanitizer) && !__has_feature(memory_sanitizer)
-  FLAGS_die_on_malloc = true;
+  absl::SetFlag(&FLAGS_die_on_malloc, true);
 #endif
 
   aos::InitGoogle(&argc, &argv);
diff --git a/aos/scoped/BUILD b/aos/scoped/BUILD
index fb867c6..8c59967 100644
--- a/aos/scoped/BUILD
+++ b/aos/scoped/BUILD
@@ -11,6 +11,7 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "//aos:macros",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
diff --git a/aos/scoped/scoped_fd.cc b/aos/scoped/scoped_fd.cc
index f2375ab..4e9054d 100644
--- a/aos/scoped/scoped_fd.cc
+++ b/aos/scoped/scoped_fd.cc
@@ -4,7 +4,8 @@
 
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos {
 
diff --git a/aos/seasocks/BUILD b/aos/seasocks/BUILD
index 7f5d25a..12d505e 100644
--- a/aos/seasocks/BUILD
+++ b/aos/seasocks/BUILD
@@ -15,6 +15,7 @@
     visibility = ["//visibility:public"],
     deps = [
         "//third_party/seasocks",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
diff --git a/aos/seasocks/seasocks_logger.cc b/aos/seasocks/seasocks_logger.cc
index a9d83bc..bba0482 100644
--- a/aos/seasocks/seasocks_logger.cc
+++ b/aos/seasocks/seasocks_logger.cc
@@ -1,6 +1,6 @@
 #include "aos/seasocks/seasocks_logger.h"
 
-#include "glog/logging.h"
+#include "absl/log/log.h"
 
 #include "seasocks/PrintfLogger.h"
 
@@ -8,17 +8,17 @@
 
 void SeasocksLogger::log(::seasocks::Logger::Level level, const char *message) {
   // Convert Seasocks error codes to glog.
-  int glog_level;
+  absl::LogSeverity log_level;
   switch (level) {
     case ::seasocks::Logger::Level::Info:
-      glog_level = google::INFO;
+      log_level = absl::LogSeverity::kInfo;
       break;
     case ::seasocks::Logger::Level::Warning:
-      glog_level = google::WARNING;
+      log_level = absl::LogSeverity::kWarning;
       break;
     case ::seasocks::Logger::Level::Error:
     case ::seasocks::Logger::Level::Severe:
-      glog_level = google::ERROR;
+      log_level = absl::LogSeverity::kError;
       break;
     case ::seasocks::Logger::Level::Debug:
     case ::seasocks::Logger::Level::Access:
@@ -26,10 +26,10 @@
       if (!VLOG_IS_ON(1)) {
         return;
       }
-      glog_level = google::INFO;
+      log_level = absl::LogSeverity::kInfo;
       break;
   }
-  LOG_AT_LEVEL(glog_level) << "Seasocks: " << message;
+  LOG(LEVEL(log_level)) << "Seasocks: " << message;
 }
 
 }  // namespace aos::seasocks
diff --git a/aos/starter/BUILD b/aos/starter/BUILD
index 9d359d4..13751e0 100644
--- a/aos/starter/BUILD
+++ b/aos/starter/BUILD
@@ -37,7 +37,8 @@
         "//aos/events:shm_event_loop",
         "//aos/util:scoped_pipe",
         "//aos/util:top",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -53,7 +54,8 @@
         "//aos:configuration",
         "//aos:macros",
         "//aos/events:shm_event_loop",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -179,7 +181,8 @@
     deps = [
         ":starter_rpc_lib",
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings:str_format",
     ],
 )
@@ -245,7 +248,8 @@
     hdrs = ["irq_affinity_lib.h"],
     deps = [
         "//aos/scoped:scoped_fd",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
diff --git a/aos/starter/irq_affinity.cc b/aos/starter/irq_affinity.cc
index 94c9c71..0dad287 100644
--- a/aos/starter/irq_affinity.cc
+++ b/aos/starter/irq_affinity.cc
@@ -15,12 +15,13 @@
 #include <utility>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
@@ -33,12 +34,13 @@
 #include "aos/util/file.h"
 #include "aos/util/top.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
 
-DEFINE_string(user, "",
-              "Starter runs as though this user ran a SUID binary if set.");
-DEFINE_string(irq_config, "rockpi_config.json",
-              "File path of rockpi configuration");
+ABSL_FLAG(std::string, user, "",
+          "Starter runs as though this user ran a SUID binary if set.");
+ABSL_FLAG(std::string, irq_config, "rockpi_config.json",
+          "File path of rockpi configuration");
 
 namespace aos {
 
@@ -281,7 +283,7 @@
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
 
-  if (!FLAGS_user.empty()) {
+  if (!absl::GetFlag(FLAGS_user).empty()) {
     // Maintain root permissions as we switch to become the user so we can
     // actually manipulate priorities.
     PCHECK(prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NOROOT) ==
@@ -290,12 +292,12 @@
     uid_t uid;
     uid_t gid;
     {
-      struct passwd *user_data = getpwnam(FLAGS_user.c_str());
+      struct passwd *user_data = getpwnam(absl::GetFlag(FLAGS_user).c_str());
       if (user_data != nullptr) {
         uid = user_data->pw_uid;
         gid = user_data->pw_gid;
       } else {
-        LOG(FATAL) << "Could not find user " << FLAGS_user;
+        LOG(FATAL) << "Could not find user " << absl::GetFlag(FLAGS_user);
         return 1;
       }
     }
@@ -306,22 +308,22 @@
     constexpr int kUnchanged = -1;
     if (setresgid(/* ruid */ gid, /* euid */ gid,
                   /* suid */ kUnchanged) != 0) {
-      PLOG(FATAL) << "Failed to change GID to " << FLAGS_user;
+      PLOG(FATAL) << "Failed to change GID to " << absl::GetFlag(FLAGS_user);
     }
 
     if (setresuid(/* ruid */ uid, /* euid */ uid,
                   /* suid */ kUnchanged) != 0) {
-      PLOG(FATAL) << "Failed to change UID to " << FLAGS_user;
+      PLOG(FATAL) << "Failed to change UID to " << absl::GetFlag(FLAGS_user);
     }
   }
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::FlatbufferDetachedBuffer<aos::starter::IrqAffinityConfig>
       irq_affinity_config =
           aos::JsonFileToFlatbuffer<aos::starter::IrqAffinityConfig>(
-              FLAGS_irq_config);
+              absl::GetFlag(FLAGS_irq_config));
 
   aos::ShmEventLoop shm_event_loop(&config.message());
 
diff --git a/aos/starter/irq_affinity_lib.cc b/aos/starter/irq_affinity_lib.cc
index 7075e31..de58be6 100644
--- a/aos/starter/irq_affinity_lib.cc
+++ b/aos/starter/irq_affinity_lib.cc
@@ -7,12 +7,13 @@
 #include <ostream>
 #include <utility>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/match.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "glog/logging.h"
 
 #include "aos/scoped/scoped_fd.h"
 
diff --git a/aos/starter/mock_starter.cc b/aos/starter/mock_starter.cc
index d52db95..d729833 100644
--- a/aos/starter/mock_starter.cc
+++ b/aos/starter/mock_starter.cc
@@ -5,11 +5,12 @@
 #include <string_view>
 #include <utility>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/starter/starter_rpc_generated.h"
diff --git a/aos/starter/starter_cmd.cc b/aos/starter/starter_cmd.cc
index b79485a..c4d324d 100644
--- a/aos/starter/starter_cmd.cc
+++ b/aos/starter/starter_cmd.cc
@@ -16,12 +16,13 @@
 #include <utility>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/flatbuffers.h"
@@ -31,21 +32,21 @@
 #include "aos/starter/starter_rpc_lib.h"
 #include "aos/time/time.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
 // TODO(james): Bash autocompletion for node names.
-DEFINE_string(
-    node, "",
-    "Node to interact with. If empty, just interact with local node.");
-DEFINE_bool(all_nodes, false, "Interact with all nodes.");
+ABSL_FLAG(std::string, node, "",
+          "Node to interact with. If empty, just interact with local node.");
+ABSL_FLAG(bool, all_nodes, false, "Interact with all nodes.");
 
-DEFINE_bool(_bash_autocomplete, false,
-            "Internal use: Outputs commands or applications for use with "
-            "autocomplete script.");
-DEFINE_string(_bash_autocomplete_word, "",
-              "Internal use: Current word being autocompleted");
-DEFINE_string(sort, "name",
-              "The name of the column to sort processes by.  "
-              "Can be \"name\", \"state\", \"pid\", or \"uptime\".");
+ABSL_FLAG(bool, _bash_autocomplete, false,
+          "Internal use: Outputs commands or applications for use with "
+          "autocomplete script.");
+ABSL_FLAG(std::string, _bash_autocomplete_word, "",
+          "Internal use: Current word being autocompleted");
+ABSL_FLAG(std::string, sort, "name",
+          "The name of the column to sort processes by.  "
+          "Can be \"name\", \"state\", \"pid\", or \"uptime\".");
 
 namespace {
 
@@ -62,12 +63,14 @@
     return {nullptr};
   }
 
-  if (!FLAGS_node.empty()) {
-    CHECK(!FLAGS_all_nodes) << "Can't specify both --node and --all_nodes.";
-    return {aos::configuration::GetNode(configuration, FLAGS_node)};
+  if (!absl::GetFlag(FLAGS_node).empty()) {
+    CHECK(!absl::GetFlag(FLAGS_all_nodes))
+        << "Can't specify both --node and --all_nodes.";
+    return {
+        aos::configuration::GetNode(configuration, absl::GetFlag(FLAGS_node))};
   }
 
-  if (FLAGS_all_nodes) {
+  if (absl::GetFlag(FLAGS_all_nodes)) {
     return aos::configuration::GetNodes(configuration);
   }
 
@@ -114,25 +117,26 @@
     sorted_statuses.push_back(app_status);
   }
   // If --sort flag not set, then return this unsorted vector as is.
-  if (FLAGS_sort.empty()) {
+  if (absl::GetFlag(FLAGS_sort).empty()) {
     return sorted_statuses;
   }
 
   // Convert --sort flag to lowercase for testing below.
-  std::transform(FLAGS_sort.begin(), FLAGS_sort.end(), FLAGS_sort.begin(),
-                 tolower);
+  std::transform(absl::GetFlag(FLAGS_sort).begin(),
+                 absl::GetFlag(FLAGS_sort).end(),
+                 absl::GetFlag(FLAGS_sort).begin(), tolower);
 
   // This function is called once for each node being reported upon, so there is
   // no need to sort on node, it happens implicitly.
 
-  if (FLAGS_sort == "name") {
+  if (absl::GetFlag(FLAGS_sort) == "name") {
     // Sort on name using std::string_view::operator< for lexicographic order.
     std::sort(sorted_statuses.begin(), sorted_statuses.end(),
               [](const aos::starter::ApplicationStatus *lhs,
                  const aos::starter::ApplicationStatus *rhs) {
                 return lhs->name()->string_view() < rhs->name()->string_view();
               });
-  } else if (FLAGS_sort == "state") {
+  } else if (absl::GetFlag(FLAGS_sort) == "state") {
     // Sort on state first, and then name for apps in same state.
     // ApplicationStatus::state is an enum, so need to call EnumNameState()
     // convenience wrapper to convert enum to char*, and then wrap in
@@ -148,7 +152,7 @@
                            : (lhs->name()->string_view() <
                               rhs->name()->string_view());
               });
-  } else if (FLAGS_sort == "pid") {
+  } else if (absl::GetFlag(FLAGS_sort) == "pid") {
     // Sort on pid first, and then name for when both apps are not running.
     // If the app state is STOPPED, then it will not have a pid, so need to test
     // that first. If only one app is STOPPED, then return Boolean state to put
@@ -171,7 +175,7 @@
                   }
                 }
               });
-  } else if (FLAGS_sort == "uptime") {
+  } else if (absl::GetFlag(FLAGS_sort) == "uptime") {
     // Sort on last_start_time first, and then name for when both apps are not
     // running, or have exact same start time. Only use last_start_time when app
     // is not STOPPED. If only one app is STOPPED, then return Boolean state to
@@ -198,7 +202,8 @@
           }
         });
   } else {
-    std::cerr << "Unknown sort criteria \"" << FLAGS_sort << "\"" << std::endl;
+    std::cerr << "Unknown sort criteria \"" << absl::GetFlag(FLAGS_sort) << "\""
+              << std::endl;
     exit(1);
   }
 
@@ -486,7 +491,7 @@
   const std::string_view app_name = (argc >= 3 ? argv[2] : "");
 
   std::cout << "COMPREPLY=(";
-  if (FLAGS__bash_autocomplete_word == command) {
+  if (absl::GetFlag(FLAGS__bash_autocomplete_word) == command) {
     // Autocomplete the starter command
     for (const auto &entry : kCommands) {
       if (std::get<0>(entry).find(command) == 0) {
@@ -515,9 +520,9 @@
   aos::InitGoogle(&argc, &argv);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
-  if (FLAGS__bash_autocomplete) {
+  if (absl::GetFlag(FLAGS__bash_autocomplete)) {
     Autocomplete(argc, argv, &config.message());
     return 0;
   }
diff --git a/aos/starter/starter_rpc_lib.cc b/aos/starter/starter_rpc_lib.cc
index b497792..4a54f71 100644
--- a/aos/starter/starter_rpc_lib.cc
+++ b/aos/starter/starter_rpc_lib.cc
@@ -3,11 +3,12 @@
 #include <algorithm>
 #include <ostream>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #include "aos/events/context.h"
 #include "aos/events/shm_event_loop.h"
diff --git a/aos/starter/starter_test.cc b/aos/starter/starter_test.cc
index 0a074e0..65d43aa 100644
--- a/aos/starter/starter_test.cc
+++ b/aos/starter/starter_test.cc
@@ -8,10 +8,12 @@
 #include <string>
 #include <thread>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_format.h"
 #include "flatbuffers/string.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/configuration.h"
@@ -56,7 +58,7 @@
  public:
   StarterdTest() {
     // Nuke the shm dir:
-    aos::util::UnlinkRecursive(FLAGS_shm_base);
+    aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
   }
 
  protected:
@@ -71,7 +73,7 @@
                    std::chrono::milliseconds(100));
   }
 
-  gflags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
   // Used to track when the test completes so that we can clean up the starter
   // in its thread.
   std::atomic<bool> test_done_{false};
@@ -87,8 +89,8 @@
       public ::testing::WithParamInterface<TestParams> {};
 
 TEST_P(StarterdConfigParamTest, MultiNodeStartStopTest) {
-  gflags::FlagSaver flag_saver;
-  FLAGS_override_hostname = GetParam().hostname;
+  absl::FlagSaver flag_saver;
+  absl::SetFlag(&FLAGS_override_hostname, GetParam().hostname);
   const std::string config_file = ArtifactPath(GetParam().config);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
@@ -111,9 +113,9 @@
                                     "args": ["--shm_base", "%s", "--config", "%s", "--override_hostname", "%s"]
                                   }
                                 ]})",
-          ArtifactPath("aos/events/ping"), FLAGS_shm_base, config_file,
-          GetParam().hostname, ArtifactPath("aos/events/pong"), FLAGS_shm_base,
-          config_file, GetParam().hostname));
+          ArtifactPath("aos/events/ping"), absl::GetFlag(FLAGS_shm_base),
+          config_file, GetParam().hostname, ArtifactPath("aos/events/pong"),
+          absl::GetFlag(FLAGS_shm_base), config_file, GetParam().hostname));
 
   const aos::Configuration *config_msg = &new_config.message();
 
@@ -220,8 +222,9 @@
       aos::configuration::ReadConfig(config_file);
 
   auto new_config = aos::configuration::MergeWithConfig(
-      &config.message(), absl::StrFormat(
-                             R"({"applications": [
+      &config.message(),
+      absl::StrFormat(
+          R"({"applications": [
                                   {
                                     "name": "ping",
                                     "executable_name": "%s",
@@ -233,8 +236,8 @@
                                     "args": ["--shm_base", "%s"]
                                   }
                                 ]})",
-                             ArtifactPath("aos/events/ping"), FLAGS_shm_base,
-                             ArtifactPath("aos/events/pong"), FLAGS_shm_base));
+          ArtifactPath("aos/events/ping"), absl::GetFlag(FLAGS_shm_base),
+          ArtifactPath("aos/events/pong"), absl::GetFlag(FLAGS_shm_base)));
 
   const aos::Configuration *config_msg = &new_config.message();
 
@@ -307,8 +310,9 @@
       aos::configuration::ReadConfig(config_file);
 
   auto new_config = aos::configuration::MergeWithConfig(
-      &config.message(), absl::StrFormat(
-                             R"({"applications": [
+      &config.message(),
+      absl::StrFormat(
+          R"({"applications": [
                                   {
                                     "name": "ping",
                                     "executable_name": "%s",
@@ -321,8 +325,8 @@
                                     "args": ["--shm_base", "%s"]
                                   }
                                 ]})",
-                             ArtifactPath("aos/events/ping"), FLAGS_shm_base,
-                             ArtifactPath("aos/events/pong"), FLAGS_shm_base));
+          ArtifactPath("aos/events/ping"), absl::GetFlag(FLAGS_shm_base),
+          ArtifactPath("aos/events/pong"), absl::GetFlag(FLAGS_shm_base)));
 
   const aos::Configuration *config_msg = &new_config.message();
 
@@ -397,8 +401,9 @@
       aos::configuration::ReadConfig(config_file);
 
   auto new_config = aos::configuration::MergeWithConfig(
-      &config.message(), absl::StrFormat(
-                             R"({"applications": [
+      &config.message(),
+      absl::StrFormat(
+          R"({"applications": [
                                   {
                                     "name": "ping",
                                     "executable_name": "%s",
@@ -411,8 +416,8 @@
                                     "args": ["--shm_base", "%s"]
                                   }
                                 ]})",
-                             ArtifactPath("aos/events/ping"), FLAGS_shm_base,
-                             ArtifactPath("aos/events/pong"), FLAGS_shm_base));
+          ArtifactPath("aos/events/ping"), absl::GetFlag(FLAGS_shm_base),
+          ArtifactPath("aos/events/pong"), absl::GetFlag(FLAGS_shm_base)));
 
   const aos::Configuration *config_msg = &new_config.message();
 
@@ -488,8 +493,9 @@
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
       aos::configuration::ReadConfig(config_file);
   auto new_config = aos::configuration::MergeWithConfig(
-      &config.message(), absl::StrFormat(
-                             R"({"applications": [
+      &config.message(),
+      absl::StrFormat(
+          R"({"applications": [
                                 {
                                   "name": "ping",
                                   "executable_name": "%s",
@@ -502,8 +508,8 @@
                                   "args": ["--shm_base", "%s"]
                                 }
                               ]})",
-                             ArtifactPath("aos/events/ping"), FLAGS_shm_base,
-                             ArtifactPath("aos/events/pong"), FLAGS_shm_base));
+          ArtifactPath("aos/events/ping"), absl::GetFlag(FLAGS_shm_base),
+          ArtifactPath("aos/events/pong"), absl::GetFlag(FLAGS_shm_base)));
 
   const aos::Configuration *config_msg = &new_config.message();
   // Set up starter with config file
diff --git a/aos/starter/starterd.cc b/aos/starter/starterd.cc
index 64858d4..127bf41 100644
--- a/aos/starter/starterd.cc
+++ b/aos/starter/starterd.cc
@@ -4,8 +4,9 @@
 #include <ostream>
 #include <string>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
@@ -14,33 +15,34 @@
 #include "aos/starter/starterd_lib.h"
 #include "aos/util/file.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
-DEFINE_string(user, "",
-              "Starter runs as though this user ran a SUID binary if set.");
-DEFINE_string(version_string, "",
-              "Version to report for starterd and subprocesses.");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
+ABSL_FLAG(std::string, user, "",
+          "Starter runs as though this user ran a SUID binary if set.");
+ABSL_FLAG(std::string, version_string, "",
+          "Version to report for starterd and subprocesses.");
 
-DECLARE_string(shm_base);
-DEFINE_bool(purge_shm_base, false,
-            "If true, delete everything in --shm_base before starting.");
+ABSL_DECLARE_FLAG(std::string, shm_base);
+ABSL_FLAG(bool, purge_shm_base, false,
+          "If true, delete everything in --shm_base before starting.");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
 
-  if (FLAGS_purge_shm_base) {
-    aos::util::UnlinkRecursive(FLAGS_shm_base);
+  if (absl::GetFlag(FLAGS_purge_shm_base)) {
+    aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
   }
 
-  if (!FLAGS_user.empty()) {
+  if (!absl::GetFlag(FLAGS_user).empty()) {
     uid_t uid;
     uid_t gid;
     {
-      struct passwd *user_data = getpwnam(FLAGS_user.c_str());
+      struct passwd *user_data = getpwnam(absl::GetFlag(FLAGS_user).c_str());
       if (user_data != nullptr) {
         uid = user_data->pw_uid;
         gid = user_data->pw_gid;
       } else {
-        LOG(FATAL) << "Could not find user " << FLAGS_user;
+        LOG(FATAL) << "Could not find user " << absl::GetFlag(FLAGS_user);
         return 1;
       }
     }
@@ -51,24 +53,24 @@
     constexpr int kUnchanged = -1;
     if (setresgid(/* ruid */ gid, /* euid */ gid,
                   /* suid */ kUnchanged) != 0) {
-      PLOG(FATAL) << "Failed to change GID to " << FLAGS_user << ", group "
-                  << gid;
+      PLOG(FATAL) << "Failed to change GID to " << absl::GetFlag(FLAGS_user)
+                  << ", group " << gid;
     }
 
     if (setresuid(/* ruid */ uid, /* euid */ uid,
                   /* suid */ kUnchanged) != 0) {
-      PLOG(FATAL) << "Failed to change UID to " << FLAGS_user;
+      PLOG(FATAL) << "Failed to change UID to " << absl::GetFlag(FLAGS_user);
     }
   }
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   const aos::Configuration *config_msg = &config.message();
 
   aos::starter::Starter starter(config_msg);
-  if (!FLAGS_version_string.empty()) {
-    starter.event_loop()->SetVersionString(FLAGS_version_string);
+  if (!absl::GetFlag(FLAGS_version_string).empty()) {
+    starter.event_loop()->SetVersionString(absl::GetFlag(FLAGS_version_string));
   }
 
   starter.Run();
diff --git a/aos/starter/starterd_lib.cc b/aos/starter/starterd_lib.cc
index 79e564e..e507507 100644
--- a/aos/starter/starterd_lib.cc
+++ b/aos/starter/starterd_lib.cc
@@ -11,27 +11,29 @@
 #include <thread>
 #include <utility>
 
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/events/context.h"
 #include "aos/json_to_flatbuffer.h"
 
 // FLAGS_shm_base is defined elsewhere, declare it here so it can be used
 // to override the shared memory folder for unit testing.
-DECLARE_string(shm_base);
+ABSL_DECLARE_FLAG(std::string, shm_base);
 // FLAGS_permissions is defined elsewhere, declare it here so it can be used
 // to set the file permissions on the shared memory block.
-DECLARE_uint32(permissions);
+ABSL_DECLARE_FLAG(uint32_t, permissions);
 
-DEFINE_uint32(queue_initialization_threads, 0,
-              "Number of threads to spin up to initialize the queue.  0 means "
-              "use the main thread.");
-DECLARE_bool(enable_ftrace);
+ABSL_FLAG(uint32_t, queue_initialization_threads, 0,
+          "Number of threads to spin up to initialize the queue.  0 means "
+          "use the main thread.");
+ABSL_DECLARE_FLAG(bool, enable_ftrace);
 
 namespace aos::starter {
 
@@ -64,7 +66,7 @@
           1),
       timing_report_fetcher_(
           event_loop_.MakeFetcher<aos::timing::Report>("/aos")),
-      shm_base_(FLAGS_shm_base),
+      shm_base_(absl::GetFlag(FLAGS_shm_base)),
       listener_(&event_loop_,
                 [this](signalfd_siginfo signal) { OnSignal(signal); }),
       top_(&event_loop_, aos::util::Top::TrackThreadsMode::kDisabled,
@@ -132,7 +134,7 @@
     std::vector<const aos::Channel *> channels_to_construct;
     for (const aos::Channel *channel : *config_msg_->channels()) {
       if (aos::configuration::ChannelIsReadableOnNode(channel, this_node)) {
-        if (FLAGS_queue_initialization_threads == 0) {
+        if (absl::GetFlag(FLAGS_queue_initialization_threads) == 0) {
           AddChannel(channel);
         } else {
           channels_to_construct.push_back(channel);
@@ -140,11 +142,12 @@
       }
     }
 
-    if (FLAGS_queue_initialization_threads != 0) {
+    if (absl::GetFlag(FLAGS_queue_initialization_threads) != 0) {
       std::mutex pool_mutex;
       std::vector<std::thread> threads;
-      threads.reserve(FLAGS_queue_initialization_threads);
-      for (size_t i = 0; i < FLAGS_queue_initialization_threads; ++i) {
+      threads.reserve(absl::GetFlag(FLAGS_queue_initialization_threads));
+      for (size_t i = 0; i < absl::GetFlag(FLAGS_queue_initialization_threads);
+           ++i) {
         threads.emplace_back([this, &pool_mutex, &channels_to_construct]() {
           while (true) {
             const aos::Channel *channel;
@@ -160,7 +163,8 @@
           }
         });
       }
-      for (size_t i = 0; i < FLAGS_queue_initialization_threads; ++i) {
+      for (size_t i = 0; i < absl::GetFlag(FLAGS_queue_initialization_threads);
+           ++i) {
         threads[i].join();
       }
     }
@@ -230,7 +234,7 @@
   if (info.ssi_signo == SIGCHLD) {
     // SIGCHLD messages can be collapsed if multiple are received, so all
     // applications must check their status.
-    if (FLAGS_enable_ftrace) {
+    if (absl::GetFlag(FLAGS_enable_ftrace)) {
       ftrace_.FormatMessage("SIGCHLD");
       ftrace_.TurnOffOrDie();
     }
@@ -324,7 +328,8 @@
   CHECK(channel != nullptr);
   std::unique_ptr<aos::ipc_lib::MemoryMappedQueue> queue =
       std::make_unique<aos::ipc_lib::MemoryMappedQueue>(
-          shm_base_, FLAGS_permissions, event_loop_.configuration(), channel);
+          shm_base_, absl::GetFlag(FLAGS_permissions),
+          event_loop_.configuration(), channel);
 
   {
     std::unique_lock<std::mutex> locker(queue_mutex_);
diff --git a/aos/starter/subprocess.cc b/aos/starter/subprocess.cc
index c36d59b..593945b 100644
--- a/aos/starter/subprocess.cc
+++ b/aos/starter/subprocess.cc
@@ -15,9 +15,11 @@
 #include <ostream>
 #include <ratio>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
-#include "glog/logging.h"
 
 #include "aos/util/file.h"
 #include "aos/util/process_info_generated.h"
@@ -655,7 +657,7 @@
       last_timing_report_ +
           // Leave a bit of margin on the timing report receipt time, to allow
           // for timing errors.
-          3 * std::chrono::milliseconds(FLAGS_timing_report_ms) >
+          3 * std::chrono::milliseconds(absl::GetFlag(FLAGS_timing_report_ms)) >
       event_loop_->monotonic_now());
   status_builder.add_last_stop_reason(stop_reason_);
   if (pid_ != -1) {
diff --git a/aos/starter/subprocess_reliable_test.cc b/aos/starter/subprocess_reliable_test.cc
index a395870..894b6fe 100644
--- a/aos/starter/subprocess_reliable_test.cc
+++ b/aos/starter/subprocess_reliable_test.cc
@@ -9,8 +9,9 @@
 #include <string>
 #include <thread>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
diff --git a/aos/starter/subprocess_test.cc b/aos/starter/subprocess_test.cc
index 2951b2b..d2dc3b0 100644
--- a/aos/starter/subprocess_test.cc
+++ b/aos/starter/subprocess_test.cc
@@ -6,10 +6,11 @@
 
 #include <ostream>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -25,15 +26,10 @@
 
 class SubprocessTest : public ::testing::Test {
  protected:
-  SubprocessTest() : shm_dir_(aos::testing::TestTmpDir() + "/aos") {
-    FLAGS_shm_base = shm_dir_;
-
+  SubprocessTest() {
     // Nuke the shm dir:
-    aos::util::UnlinkRecursive(shm_dir_);
+    aos::util::UnlinkRecursive(absl::GetFlag(FLAGS_shm_base));
   }
-
-  gflags::FlagSaver flag_saver_;
-  std::string shm_dir_;
 };
 
 TEST_F(SubprocessTest, CaptureOutputs) {
diff --git a/aos/stl_mutex/BUILD b/aos/stl_mutex/BUILD
index bc1e428..46c5bb9 100644
--- a/aos/stl_mutex/BUILD
+++ b/aos/stl_mutex/BUILD
@@ -8,7 +8,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "//aos/ipc_lib:aos_sync",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/stl_mutex/stl_mutex.h b/aos/stl_mutex/stl_mutex.h
index c719805..8450e73 100644
--- a/aos/stl_mutex/stl_mutex.h
+++ b/aos/stl_mutex/stl_mutex.h
@@ -4,7 +4,8 @@
 #include <mutex>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/ipc_lib/aos_sync.h"
 #include "aos/macros.h"
diff --git a/aos/testing/BUILD b/aos/testing/BUILD
index 729c978..52fa271 100644
--- a/aos/testing/BUILD
+++ b/aos/testing/BUILD
@@ -12,8 +12,9 @@
     deps = [
         "//aos:init",
         "//aos/testing:tmpdir",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -62,7 +63,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     visibility = ["//visibility:public"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/testing/gtest_main.cc b/aos/testing/gtest_main.cc
index 1940988..ecf2889 100644
--- a/aos/testing/gtest_main.cc
+++ b/aos/testing/gtest_main.cc
@@ -1,14 +1,15 @@
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/init.h"
 #include "aos/testing/tmpdir.h"
 
-DEFINE_bool(print_logs, false,
-            "Print the log messages as they are being generated.");
-DEFINE_string(log_file, "",
-              "Print all log messages to FILE instead of standard output.");
+ABSL_FLAG(bool, print_logs, false,
+          "Print the log messages as they are being generated.");
+ABSL_FLAG(std::string, log_file, "",
+          "Print all log messages to FILE instead of standard output.");
 
 namespace aos::testing {
 
@@ -20,22 +21,20 @@
 
 GTEST_API_ int main(int argc, char **argv) {
   ::testing::InitGoogleTest(&argc, argv);
-  FLAGS_logtostderr = true;
-
   aos::InitGoogle(&argc, &argv);
 
-  if (FLAGS_print_logs) {
+  if (absl::GetFlag(FLAGS_print_logs)) {
     if (::aos::testing::ForcePrintLogsDuringTests) {
       ::aos::testing::ForcePrintLogsDuringTests();
     }
   }
 
-  if (!FLAGS_log_file.empty()) {
+  if (!absl::GetFlag(FLAGS_log_file).empty()) {
     if (::aos::testing::ForcePrintLogsDuringTests) {
       ::aos::testing::ForcePrintLogsDuringTests();
     }
     if (::aos::testing::SetLogFileName) {
-      ::aos::testing::SetLogFileName(FLAGS_log_file.c_str());
+      ::aos::testing::SetLogFileName(absl::GetFlag(FLAGS_log_file).c_str());
     }
   }
 
diff --git a/aos/testing/prevent_exit.cc b/aos/testing/prevent_exit.cc
index 7c8da60..a475e45 100644
--- a/aos/testing/prevent_exit.cc
+++ b/aos/testing/prevent_exit.cc
@@ -4,7 +4,8 @@
 
 #include <cstdlib>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::testing {
 namespace {
diff --git a/aos/testing/tmpdir.cc b/aos/testing/tmpdir.cc
index 0953a21..0aa00ea 100644
--- a/aos/testing/tmpdir.cc
+++ b/aos/testing/tmpdir.cc
@@ -3,6 +3,8 @@
 #include <cstdlib>
 #include <string>
 
+#include "absl/flags/flag.h"
+
 #include "aos/ipc_lib/shm_base.h"
 
 namespace aos::testing {
@@ -19,6 +21,8 @@
 
 std::string TestTmpDir() { return TestTmpDirOr("/tmp"); }
 
-void SetTestShmBase() { SetShmBase(TestTmpDirOr(FLAGS_shm_base)); }
+void SetTestShmBase() {
+  SetShmBase(TestTmpDirOr(absl::GetFlag(FLAGS_shm_base)));
+}
 
 }  // namespace aos::testing
diff --git a/aos/time/BUILD b/aos/time/BUILD
index 04ae38f..ffd7089 100644
--- a/aos/time/BUILD
+++ b/aos/time/BUILD
@@ -9,7 +9,8 @@
     visibility = ["//visibility:public"],
     deps = select({
         "@platforms//os:linux": [
-            "@com_github_google_glog//:glog",
+            "@com_google_absl//absl/log",
+            "@com_google_absl//absl/log:check",
             "@com_google_absl//absl/strings",
         ],
         "//conditions:default": ["//motors/core"],
diff --git a/aos/time/time.cc b/aos/time/time.cc
index 0e02481..3c88931 100644
--- a/aos/time/time.cc
+++ b/aos/time/time.cc
@@ -15,8 +15,9 @@
 
 #ifdef __linux__
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/numbers.h"
-#include "glog/logging.h"
 
 #else  // __linux__
 
diff --git a/aos/util/BUILD b/aos/util/BUILD
index 7e19d4d..814bab6 100644
--- a/aos/util/BUILD
+++ b/aos/util/BUILD
@@ -63,7 +63,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -203,7 +204,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "//aos/time",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
@@ -346,7 +348,8 @@
     deps = [
         "//aos/scoped:scoped_fd",
         "@com_github_google_flatbuffers//:flatbuffers",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
         "@com_google_absl//absl/types:span",
     ],
@@ -390,7 +393,8 @@
         ":process_info_fbs",
         "//aos/containers:ring_buffer",
         "//aos/events:event_loop",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/strings",
     ],
 )
@@ -418,7 +422,8 @@
     hdrs = ["scoped_pipe.h"],
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_absl//absl/types:span",
     ],
 )
@@ -513,8 +518,9 @@
         ":config_validator_lib",
         "//aos:json_to_flatbuffer",
         "//aos/testing:googletest",
-        "@com_github_gflags_gflags//:gflags",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -527,7 +533,8 @@
         ":foxglove_websocket_lib",
         "//aos:init",
         "//aos/events:shm_event_loop",
-        "@com_github_gflags_gflags//:gflags",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/flags:usage",
     ],
 )
 
@@ -561,7 +568,8 @@
         "//aos/events/logging:log_writer",
         "//aos/network:timestamp_channel",
         "//aos/testing:tmpdir",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -616,8 +624,8 @@
     target_compatible_with = ["@platforms//os:linux"],
     deps = [
         "//aos/containers:inlined_vector",
-        "@com_github_google_glog//:glog",
         "@com_github_tartanllama_expected",
+        "@com_google_absl//absl/log",
         "@com_google_absl//absl/strings:str_format",
     ],
 )
diff --git a/aos/util/config_validator.cc b/aos/util/config_validator.cc
index 0ee1018..660a7bd 100644
--- a/aos/util/config_validator.cc
+++ b/aos/util/config_validator.cc
@@ -1,6 +1,6 @@
 #include <memory>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 #include "gtest/gtest.h"
 
 #include "aos/configuration.h"
@@ -9,9 +9,9 @@
 #include "aos/util/config_validator_config_generated.h"
 #include "aos/util/config_validator_lib.h"
 
-DEFINE_string(config, "", "Name of the config file to replay using.");
-DEFINE_string(validation_config, "{}",
-              "JSON config to use to validate the config.");
+ABSL_FLAG(std::string, config, "", "Name of the config file to replay using.");
+ABSL_FLAG(std::string, validation_config, "{}",
+          "JSON config to use to validate the config.");
 /* This binary is used to validate that all of the
    needed remote timestamps channels are in the config
    to log the timestamps.
@@ -23,14 +23,14 @@
    each one
    Reference superstructure_lib_test.cc*/
 TEST(ConfigValidatorTest, ReadConfig) {
-  ASSERT_TRUE(!FLAGS_config.empty());
+  ASSERT_TRUE(!absl::GetFlag(FLAGS_config).empty());
   const aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   const aos::FlatbufferDetachedBuffer<aos::util::ConfigValidatorConfig>
       validator_config =
           aos::JsonToFlatbuffer<aos::util::ConfigValidatorConfig>(
-              FLAGS_validation_config);
+              absl::GetFlag(FLAGS_validation_config));
   aos::util::ConfigIsValid(&config.message(), &validator_config.message());
 }
 
diff --git a/aos/util/config_validator_lib.cc b/aos/util/config_validator_lib.cc
index 4347017..79309b0 100644
--- a/aos/util/config_validator_lib.cc
+++ b/aos/util/config_validator_lib.cc
@@ -13,12 +13,13 @@
 #include <utility>
 #include <vector>
 
+#include "absl/flags/declare.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/detached_buffer.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags_declare.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 
 #include "aos/events/event_loop.h"
@@ -36,7 +37,7 @@
 #include "aos/util/file.h"
 #include "aos/util/simulation_logger.h"
 
-DECLARE_bool(validate_timestamp_logger_nodes);
+ABSL_DECLARE_FLAG(bool, validate_timestamp_logger_nodes);
 
 namespace aos::util {
 
diff --git a/aos/util/error_counter.h b/aos/util/error_counter.h
index 7837f9e..c18c019 100644
--- a/aos/util/error_counter.h
+++ b/aos/util/error_counter.h
@@ -4,10 +4,11 @@
 
 #include <array>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 namespace aos::util {
 // Class to manage simple error counters for flatbuffer status message.
diff --git a/aos/util/file.h b/aos/util/file.h
index d0037fd..881af33 100644
--- a/aos/util/file.h
+++ b/aos/util/file.h
@@ -12,8 +12,9 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
-#include "glog/logging.h"
 
 #include "aos/scoped/scoped_fd.h"
 
diff --git a/aos/util/filesystem_monitor.cc b/aos/util/filesystem_monitor.cc
index df1dd22..be3229b 100644
--- a/aos/util/filesystem_monitor.cc
+++ b/aos/util/filesystem_monitor.cc
@@ -9,13 +9,14 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_split.h"
 #include "flatbuffers/buffer.h"
 #include "flatbuffers/flatbuffer_builder.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
@@ -24,7 +25,8 @@
 #include "aos/init.h"
 #include "aos/util/filesystem_generated.h"
 
-DEFINE_string(config, "aos_config.json", "File path of aos configuration");
+ABSL_FLAG(std::string, config, "aos_config.json",
+          "File path of aos configuration");
 
 namespace aos::util {
 namespace {
@@ -145,7 +147,7 @@
   aos::InitGoogle(&argc, &argv);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop shm_event_loop(&config.message());
 
diff --git a/aos/util/foxglove_websocket.cc b/aos/util/foxglove_websocket.cc
index 57326de..d71ceba 100644
--- a/aos/util/foxglove_websocket.cc
+++ b/aos/util/foxglove_websocket.cc
@@ -1,6 +1,7 @@
 #include <string>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/usage.h"
 
 #include "aos/configuration.h"
 #include "aos/events/shm_event_loop.h"
@@ -8,21 +9,21 @@
 #include "aos/init.h"
 #include "aos/util/foxglove_websocket_lib.h"
 
-DEFINE_string(config, "aos_config.json", "Path to the config.");
-DEFINE_uint32(port, 8765, "Port to use for foxglove websocket server.");
-DEFINE_string(mode, "flatbuffer", "json or flatbuffer serialization.");
-DEFINE_bool(fetch_pinned_channels, true,
-            "Set this to allow foxglove_websocket to make fetchers on channels "
-            "with a read_method of PIN (see aos/configuration.fbs; PIN is an "
-            "enum value). Having this enabled will cause foxglove to  consume "
-            "extra shared memory resources.");
-DEFINE_bool(
-    canonical_channel_names, false,
+ABSL_FLAG(std::string, config, "aos_config.json", "Path to the config.");
+ABSL_FLAG(uint32_t, port, 8765, "Port to use for foxglove websocket server.");
+ABSL_FLAG(std::string, mode, "flatbuffer", "json or flatbuffer serialization.");
+ABSL_FLAG(bool, fetch_pinned_channels, true,
+          "Set this to allow foxglove_websocket to make fetchers on channels "
+          "with a read_method of PIN (see aos/configuration.fbs; PIN is an "
+          "enum value). Having this enabled will cause foxglove to  consume "
+          "extra shared memory resources.");
+ABSL_FLAG(
+    bool, canonical_channel_names, false,
     "If set, use full channel names; by default, will shorten names to be the "
     "shortest possible version of the name (e.g., /aos instead of /pi/aos).");
 
 int main(int argc, char *argv[]) {
-  gflags::SetUsageMessage(
+  absl::SetProgramUsageMessage(
       "Runs a websocket server that a foxglove instance can connect to in "
       "order to view live data on a device.\n\n"
       "Typical Usage: foxglove_websocket [--port 8765]\n"
@@ -51,19 +52,19 @@
   aos::InitGoogle(&argc, &argv);
 
   aos::FlatbufferDetachedBuffer<aos::Configuration> config =
-      aos::configuration::ReadConfig(FLAGS_config);
+      aos::configuration::ReadConfig(absl::GetFlag(FLAGS_config));
 
   aos::ShmEventLoop event_loop(&config.message());
 
   aos::FoxgloveWebsocketServer server(
-      &event_loop, FLAGS_port,
-      FLAGS_mode == "flatbuffer"
+      &event_loop, absl::GetFlag(FLAGS_port),
+      absl::GetFlag(FLAGS_mode) == "flatbuffer"
           ? aos::FoxgloveWebsocketServer::Serialization::kFlatbuffer
           : aos::FoxgloveWebsocketServer::Serialization::kJson,
-      FLAGS_fetch_pinned_channels
+      absl::GetFlag(FLAGS_fetch_pinned_channels)
           ? aos::FoxgloveWebsocketServer::FetchPinnedChannels::kYes
           : aos::FoxgloveWebsocketServer::FetchPinnedChannels::kNo,
-      FLAGS_canonical_channel_names
+      absl::GetFlag(FLAGS_canonical_channel_names)
           ? aos::FoxgloveWebsocketServer::CanonicalChannelNames::kCanonical
           : aos::FoxgloveWebsocketServer::CanonicalChannelNames::kShortened);
 
diff --git a/aos/util/foxglove_websocket_lib.cc b/aos/util/foxglove_websocket_lib.cc
index 7a825e4..de19443 100644
--- a/aos/util/foxglove_websocket_lib.cc
+++ b/aos/util/foxglove_websocket_lib.cc
@@ -6,13 +6,14 @@
 #include <utility>
 
 #include "absl/container/btree_set.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/escaping.h"
 #include "absl/types/span.h"
 #include "flatbuffers/reflection_generated.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 #include "nlohmann/json.hpp"
 #include <foxglove/websocket/server.hpp>
 
@@ -24,9 +25,9 @@
 #include "aos/time/time.h"
 #include "aos/util/mcap_logger.h"
 
-DEFINE_uint32(sorting_buffer_ms, 100,
-              "Amount of time to buffer messages to sort them before sending "
-              "them to foxglove.");
+ABSL_FLAG(uint32_t, sorting_buffer_ms, 100,
+          "Amount of time to buffer messages to sort them before sending "
+          "them to foxglove.");
 
 namespace {
 // Period at which to poll the fetchers for all the channels.
@@ -117,7 +118,7 @@
     // out.
     const aos::monotonic_clock::time_point sort_until =
         event_loop_->monotonic_now() -
-        std::chrono::milliseconds(FLAGS_sorting_buffer_ms);
+        std::chrono::milliseconds(absl::GetFlag(FLAGS_sorting_buffer_ms));
 
     // Pair of <send_time, channel id>.
     absl::btree_set<std::pair<aos::monotonic_clock::time_point, ChannelId>>
diff --git a/aos/util/generate_test_log.cc b/aos/util/generate_test_log.cc
index 106e972..c028df7 100644
--- a/aos/util/generate_test_log.cc
+++ b/aos/util/generate_test_log.cc
@@ -1,7 +1,7 @@
 #include <chrono>
 #include <memory>
 
-#include "gflags/gflags.h"
+#include "absl/flags/flag.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
@@ -13,8 +13,8 @@
 #include "aos/init.h"
 #include "aos/testing/path.h"
 
-DEFINE_string(output_folder, "",
-              "Name of folder to write the generated logfile to.");
+ABSL_FLAG(std::string, output_folder, "",
+          "Name of folder to write the generated logfile to.");
 
 int main(int argc, char **argv) {
   aos::InitGoogle(&argc, &argv);
@@ -38,7 +38,7 @@
   std::unique_ptr<aos::EventLoop> log_writer_event_loop =
       event_loop_factory.MakeEventLoop("log_writer");
   aos::logger::Logger writer(log_writer_event_loop.get());
-  writer.StartLoggingOnRun(FLAGS_output_folder);
+  writer.StartLoggingOnRun(absl::GetFlag(FLAGS_output_folder));
 
   event_loop_factory.RunFor(std::chrono::seconds(10));
   return 0;
diff --git a/aos/util/log_to_mcap.cc b/aos/util/log_to_mcap.cc
index 11b7940..9dc9cdb 100644
--- a/aos/util/log_to_mcap.cc
+++ b/aos/util/log_to_mcap.cc
@@ -6,9 +6,10 @@
 #include <string>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/reflection_generated.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 
 #include "aos/configuration.h"
 #include "aos/events/event_loop.h"
@@ -21,23 +22,23 @@
 #include "aos/util/clock_timepoints_schema.h"
 #include "aos/util/mcap_logger.h"
 
-DEFINE_string(node, "", "Node to replay from the perspective of.");
-DEFINE_string(output_path, "/tmp/log.mcap", "Log to output.");
-DEFINE_string(mode, "flatbuffer", "json or flatbuffer serialization.");
-DEFINE_bool(
-    canonical_channel_names, false,
+ABSL_FLAG(std::string, node, "", "Node to replay from the perspective of.");
+ABSL_FLAG(std::string, output_path, "/tmp/log.mcap", "Log to output.");
+ABSL_FLAG(std::string, mode, "flatbuffer", "json or flatbuffer serialization.");
+ABSL_FLAG(
+    bool, canonical_channel_names, false,
     "If set, use full channel names; by default, will shorten names to be the "
     "shortest possible version of the name (e.g., /aos instead of /pi/aos).");
-DEFINE_bool(compress, true, "Whether to use LZ4 compression in MCAP file.");
-DEFINE_bool(include_clocks, true,
-            "Whether to add a /clocks channel that publishes all nodes' clock "
-            "offsets.");
-DEFINE_bool(include_pre_start_messages, false,
-            "If set, *all* messages in the logfile will be included, including "
-            "any that may have occurred prior to the start of the log. This "
-            "can be used to see additional data, but given that data may be "
-            "incomplete prior to the start of the log, you should be careful "
-            "about interpretting data flow when using this flag.");
+ABSL_FLAG(bool, compress, true, "Whether to use LZ4 compression in MCAP file.");
+ABSL_FLAG(bool, include_clocks, true,
+          "Whether to add a /clocks channel that publishes all nodes' clock "
+          "offsets.");
+ABSL_FLAG(bool, include_pre_start_messages, false,
+          "If set, *all* messages in the logfile will be included, including "
+          "any that may have occurred prior to the start of the log. This "
+          "can be used to see additional data, but given that data may be "
+          "incomplete prior to the start of the log, you should be careful "
+          "about interpretting data flow when using this flag.");
 
 // Converts an AOS log to an MCAP log that can be fed into Foxglove. To try this
 // out, run:
@@ -55,7 +56,7 @@
   const std::set<std::string> logger_nodes = aos::logger::LoggerNodes(logfiles);
   CHECK_LT(0u, logger_nodes.size());
   const std::string logger_node = *logger_nodes.begin();
-  std::string replay_node = FLAGS_node;
+  std::string replay_node = absl::GetFlag(FLAGS_node);
   if (replay_node.empty()) {
     if (logger_nodes.size() == 1u) {
       LOG(INFO) << "Guessing \"" << logger_node
@@ -69,7 +70,7 @@
 
   std::optional<aos::FlatbufferDetachedBuffer<aos::Configuration>> config;
 
-  if (FLAGS_include_clocks) {
+  if (absl::GetFlag(FLAGS_include_clocks)) {
     aos::logger::LogReader config_reader(logfiles);
 
     if (aos::configuration::MultiNode(config_reader.configuration())) {
@@ -103,7 +104,7 @@
   std::unique_ptr<aos::ClockPublisher> clock_publisher;
 
   std::unique_ptr<aos::EventLoop> mcap_event_loop;
-  CHECK(!FLAGS_output_path.empty());
+  CHECK(!absl::GetFlag(FLAGS_output_path).empty());
   std::unique_ptr<aos::McapLogger> relogger;
   auto startup_handler = [&relogger, &mcap_event_loop, &reader,
                           &clock_event_loop, &clock_publisher, &factory,
@@ -112,22 +113,23 @@
                                "files from multi-boot logs.";
     mcap_event_loop = reader.event_loop_factory()->MakeEventLoop("mcap", node);
     relogger = std::make_unique<aos::McapLogger>(
-        mcap_event_loop.get(), FLAGS_output_path,
-        FLAGS_mode == "flatbuffer" ? aos::McapLogger::Serialization::kFlatbuffer
-                                   : aos::McapLogger::Serialization::kJson,
-        FLAGS_canonical_channel_names
+        mcap_event_loop.get(), absl::GetFlag(FLAGS_output_path),
+        absl::GetFlag(FLAGS_mode) == "flatbuffer"
+            ? aos::McapLogger::Serialization::kFlatbuffer
+            : aos::McapLogger::Serialization::kJson,
+        absl::GetFlag(FLAGS_canonical_channel_names)
             ? aos::McapLogger::CanonicalChannelNames::kCanonical
             : aos::McapLogger::CanonicalChannelNames::kShortened,
-        FLAGS_compress ? aos::McapLogger::Compression::kLz4
-                       : aos::McapLogger::Compression::kNone);
-    if (FLAGS_include_clocks) {
+        absl::GetFlag(FLAGS_compress) ? aos::McapLogger::Compression::kLz4
+                                      : aos::McapLogger::Compression::kNone);
+    if (absl::GetFlag(FLAGS_include_clocks)) {
       clock_event_loop =
           reader.event_loop_factory()->MakeEventLoop("clock", node);
       clock_publisher = std::make_unique<aos::ClockPublisher>(
           &factory, clock_event_loop.get());
     }
   };
-  if (FLAGS_include_pre_start_messages) {
+  if (absl::GetFlag(FLAGS_include_pre_start_messages)) {
     // Note: This condition is subtly different from just using --fetch from
     // mcap_logger.cc. Namely, if there is >1 message on a given channel prior
     // to the logfile start, then fetching in the reader OnStart() is
diff --git a/aos/util/mcap_logger.cc b/aos/util/mcap_logger.cc
index a70da62..47f8298 100644
--- a/aos/util/mcap_logger.cc
+++ b/aos/util/mcap_logger.cc
@@ -6,6 +6,9 @@
 #include <ostream>
 #include <set>
 
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/strings/str_cat.h"
 #include "absl/types/span.h"
 #include "flatbuffers/buffer.h"
@@ -15,9 +18,6 @@
 #include "flatbuffers/reflection_generated.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
-#include "glog/vlog_is_on.h"
 #include "lz4/lz4frame.h"
 #include "nlohmann/json.hpp"
 
@@ -26,14 +26,14 @@
 #include "aos/flatbuffer_merge.h"
 #include "aos/json_to_flatbuffer.h"
 
-DEFINE_uint64(mcap_chunk_size, 10'000'000,
-              "Size, in bytes, of individual MCAP chunks");
-DEFINE_bool(fetch, false,
-            "Whether to fetch most recent messages at start of logfile. Turn "
-            "this on if there are, e.g., one-time messages sent before the "
-            "start of the logfile that you need access to. Turn it off if you "
-            "don't want to deal with having messages that have timestamps that "
-            "may be arbitrarily far before any other interesting messages.");
+ABSL_FLAG(uint64_t, mcap_chunk_size, 10'000'000,
+          "Size, in bytes, of individual MCAP chunks");
+ABSL_FLAG(bool, fetch, false,
+          "Whether to fetch most recent messages at start of logfile. Turn "
+          "this on if there are, e.g., one-time messages sent before the "
+          "start of the logfile that you need access to. Turn it off if you "
+          "don't want to deal with having messages that have timestamps that "
+          "may be arbitrarily far before any other interesting messages.");
 
 namespace aos {
 
@@ -246,13 +246,13 @@
             ChunkStatus *chunk = &current_chunks_[id];
             WriteMessage(id, channel, context, chunk);
             if (static_cast<uint64_t>(chunk->data.tellp()) >
-                FLAGS_mcap_chunk_size) {
+                absl::GetFlag(FLAGS_mcap_chunk_size)) {
               WriteChunk(chunk);
             }
           });
       fetchers_[id] = event_loop_->MakeRawFetcher(channel);
       event_loop_->OnRun([this, id, channel]() {
-        if (FLAGS_fetch && fetchers_[id]->Fetch()) {
+        if (absl::GetFlag(FLAGS_fetch) && fetchers_[id]->Fetch()) {
           WriteMessage(id, channel, fetchers_[id]->context(),
                        &current_chunks_[id]);
         }
diff --git a/aos/util/phased_loop.cc b/aos/util/phased_loop.cc
index 5f87bd0..92bda13 100644
--- a/aos/util/phased_loop.cc
+++ b/aos/util/phased_loop.cc
@@ -3,7 +3,8 @@
 #include <compare>
 #include <ratio>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::time {
 
diff --git a/aos/util/scoped_pipe.cc b/aos/util/scoped_pipe.cc
index d178c0d..7983f7b 100644
--- a/aos/util/scoped_pipe.cc
+++ b/aos/util/scoped_pipe.cc
@@ -6,7 +6,8 @@
 
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::util {
 
diff --git a/aos/util/status.cc b/aos/util/status.cc
index dbcd4af..e608ed5 100644
--- a/aos/util/status.cc
+++ b/aos/util/status.cc
@@ -1,5 +1,9 @@
 #include "aos/util/status.h"
 
+#include "absl/log/log.h"
+
+#include "aos/containers/inlined_vector.h"
+
 namespace aos {
 namespace {
 // Constructs a string view from the provided buffer if it has data and
diff --git a/aos/util/status.h b/aos/util/status.h
index fa2f4f0..9880fc7 100644
--- a/aos/util/status.h
+++ b/aos/util/status.h
@@ -4,8 +4,8 @@
 #include <source_location>
 #include <string_view>
 
+#include "absl/log/log.h"
 #include "absl/strings/str_format.h"
-#include "glog/logging.h"
 #include "tl/expected.hpp"
 
 #include "aos/containers/inlined_vector.h"
diff --git a/aos/util/status_test.cc b/aos/util/status_test.cc
index b838636..fe77c61 100644
--- a/aos/util/status_test.cc
+++ b/aos/util/status_test.cc
@@ -8,8 +8,6 @@
 #include "aos/realtime.h"
 #include "aos/testing/path.h"
 
-DECLARE_bool(die_on_malloc);
-
 namespace aos::testing {
 class ErrorTest : public ::testing::Test {
  protected:
diff --git a/aos/util/threaded_consumer.h b/aos/util/threaded_consumer.h
index 471f6e1..05508a8 100644
--- a/aos/util/threaded_consumer.h
+++ b/aos/util/threaded_consumer.h
@@ -5,7 +5,8 @@
 #include <optional>
 #include <thread>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/condition.h"
 #include "aos/containers/ring_buffer.h"
diff --git a/aos/util/top.cc b/aos/util/top.cc
index 8a78609..28b4e69 100644
--- a/aos/util/top.cc
+++ b/aos/util/top.cc
@@ -15,6 +15,8 @@
 #include <string_view>
 #include <vector>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/numeric/int128.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
@@ -22,7 +24,6 @@
 #include "absl/strings/str_split.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "glog/logging.h"
 
 #define PF_KTHREAD 0x00200000
 
@@ -225,9 +226,8 @@
   // Verify we can open the directory.
   DIR *dir = opendir(task_dir.c_str());
   if (dir == nullptr) {
-    LOG_EVERY_T(WARNING, 10) << "Unable to open directory: " << task_dir
-                             << ", error: " << strerror(errno);
-    ;
+    LOG_EVERY_N_SEC(WARNING, 10) << "Unable to open directory: " << task_dir
+                                 << ", error: " << strerror(errno);
     return;
   }
 
diff --git a/aos/util/top_test.cc b/aos/util/top_test.cc
index 7d9d2bb..9dc9c8c 100644
--- a/aos/util/top_test.cc
+++ b/aos/util/top_test.cc
@@ -13,10 +13,12 @@
 #include <thread>
 #include <vector>
 
+#include "absl/flags/flag.h"
+#include "absl/flags/reflection.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "flatbuffers/string.h"
 #include "flatbuffers/vector.h"
-#include "gflags/gflags.h"
-#include "glog/logging.h"
 #include "gtest/gtest.h"
 #include <gmock/gmock.h>
 
@@ -40,7 +42,7 @@
 class TopTest : public ::testing::Test {
  protected:
   TopTest()
-      : shm_dir_(aos::testing::TestTmpDir() + "/aos"),
+      : shm_dir_(aos::testing::TestTmpDir()),
         cpu_consumer_([this]() {
           SetThreadName(std::string(kTestCPUConsumer));
           while (!stop_flag_.load()) {
@@ -50,18 +52,18 @@
             aos::testing::ArtifactPath("aos/events/pingpong_config.json")),
         config_(aos::configuration::ReadConfig(config_file_)),
         event_loop_(&config_.message()) {
-    FLAGS_shm_base = shm_dir_;
+    aos::testing::SetShmBase(shm_dir_);
 
     // Nuke the shm dir, to ensure we aren't being affected by any preexisting
     // tests.
-    aos::util::UnlinkRecursive(shm_dir_);
+    aos::util::UnlinkRecursive(shm_dir_ + "/aos");
   }
   ~TopTest() {
     stop_flag_ = true;
     cpu_consumer_.join();
   }
 
-  gflags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
   std::string shm_dir_;
 
   std::thread cpu_consumer_;
diff --git a/aos/util/trapezoid_profile.cc b/aos/util/trapezoid_profile.cc
index be61889..4bd65fa 100644
--- a/aos/util/trapezoid_profile.cc
+++ b/aos/util/trapezoid_profile.cc
@@ -6,7 +6,8 @@
 #include <cstdlib>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/time/time.h"
 
diff --git a/aos/uuid.cc b/aos/uuid.cc
index f794ec8..8dfaa0c 100644
--- a/aos/uuid.cc
+++ b/aos/uuid.cc
@@ -8,11 +8,12 @@
 #include <random>
 #include <string_view>
 
-#include "gflags/gflags.h"
-#include "glog/logging.h"
+#include "absl/flags/flag.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
-DEFINE_string(boot_uuid, "",
-              "If set, override the boot UUID to have this value instead.");
+ABSL_FLAG(std::string, boot_uuid, "",
+          "If set, override the boot UUID to have this value instead.");
 
 namespace aos {
 namespace {
@@ -184,8 +185,9 @@
 }
 
 UUID UUID::BootUUID() {
-  if (!FLAGS_boot_uuid.empty()) {
-    return UUID::FromString(FLAGS_boot_uuid);
+  auto flag = absl::GetFlag(FLAGS_boot_uuid);
+  if (!flag.empty()) {
+    return UUID::FromString(flag);
   }
 
   int fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY);
diff --git a/aos/uuid.h b/aos/uuid.h
index a2cf8ae..1e5d781 100644
--- a/aos/uuid.h
+++ b/aos/uuid.h
@@ -6,9 +6,10 @@
 #include <random>
 #include <string>
 
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "absl/types/span.h"
 #include "flatbuffers/flatbuffers.h"
-#include "glog/logging.h"
 
 namespace aos {
 
diff --git a/aos/uuid_collision_test.cc b/aos/uuid_collision_test.cc
index 99b870b..fce026f 100644
--- a/aos/uuid_collision_test.cc
+++ b/aos/uuid_collision_test.cc
@@ -1,7 +1,8 @@
 #include <set>
 #include <unordered_set>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 #include "aos/uuid.h"
diff --git a/aos/uuid_test.cc b/aos/uuid_test.cc
index f6ed21e..edfd5a8 100644
--- a/aos/uuid_test.cc
+++ b/aos/uuid_test.cc
@@ -1,6 +1,7 @@
 #include "aos/uuid.h"
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 #include "gtest/gtest.h"
 
 namespace aos::testing {
diff --git a/aos/vision/debug/BUILD b/aos/vision/debug/BUILD
index 7f796b9..9eae63c 100644
--- a/aos/vision/debug/BUILD
+++ b/aos/vision/debug/BUILD
@@ -51,7 +51,8 @@
         "//aos/vision/image:image_stream",
         "//aos/vision/image:image_types",
         "//aos/vision/image:jpeg_routines",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
         "@usr_repo//:gtk+-3.0",
     ],
     alwayslink = 1,
diff --git a/aos/vision/debug/blob_log-source.cc b/aos/vision/debug/blob_log-source.cc
index c5ee67c..5ce60fb 100644
--- a/aos/vision/debug/blob_log-source.cc
+++ b/aos/vision/debug/blob_log-source.cc
@@ -7,7 +7,8 @@
 #include <functional>
 #include <string>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 #include "aos/vision/blob/codec.h"
 #include "aos/vision/blob/stream_view.h"
diff --git a/aos/vision/events/BUILD b/aos/vision/events/BUILD
index c722acc..09d4d83 100644
--- a/aos/vision/events/BUILD
+++ b/aos/vision/events/BUILD
@@ -58,7 +58,8 @@
     deps = [
         "//aos:macros",
         "//aos/scoped:scoped_fd",
-        "@com_github_google_glog//:glog",
+        "@com_google_absl//absl/log",
+        "@com_google_absl//absl/log:check",
     ],
 )
 
diff --git a/aos/vision/events/udp.cc b/aos/vision/events/udp.cc
index 1b1a053..bc45ec8 100644
--- a/aos/vision/events/udp.cc
+++ b/aos/vision/events/udp.cc
@@ -7,7 +7,8 @@
 #include <cstring>
 #include <ostream>
 
-#include "glog/logging.h"
+#include "absl/log/check.h"
+#include "absl/log/log.h"
 
 namespace aos::events {