Skip to content

Modified `base` library from chromium

License

BSD-3-Clause, BSD-3-Clause licenses found

Licenses found

BSD-3-Clause
LICENSE
BSD-3-Clause
LICENSE_chromium.txt
Notifications You must be signed in to change notification settings

blockspacer/chromium_base_conan

About

Modified base library from chromium, see https://github.com/chromium/chromium/tree/master/base

Modification history in extensions/PATCH_HISTORY.md and added files in extensions/.

NOTE: Some features or platforms may be not supported. Run unit tests to check support of some feature.

Project goals

  • Easy integration with open-source projects that use CMake and conan
  • Provide codebase similar to chromium/base, libchrome, mini_chromium etc.
  • Make library cross-platform (add browser support etc.)
  • Extend base library from chromium with extra general-purpose functionality

Supported platforms

Tested on Ubuntu 20.04.2 LTS.

May work on other platforms with minor modifications.

What is base library?

Base, libchrome and mini_chromium are general utility libraries from chromium.

See:

What is basic library?

In ./extensions/basic/ you can find code that extends base library.

For example, basic adopts some code from facebook/folly library.

Some changes made in facebook/folly:

  • Exceptions replaced with StatusOr or CHECK.
  • std::thread replaced with base::Thread or base::PlatformThread.
  • Removed already existing functionality (avoids code duplication).
  • Ported to more platforms (Android, browser, etc.)

How to use it?

Before usage set:

  • setlocale(LC_ALL, "en_US.UTF-8")
  • base::i18n::InitializeICU()
  • logging::InitLogging(settings);
  • base::ThreadPoolInstance::CreateAndStartWithDefaultParams
  • base::AtExitManager
  • base::CommandLine::Init
  • base::RunLoop
  • base::ThreadPoolInstance::Get()->Shutdown()
  • etc.

Usage:

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "base/message_loop/message_pump_type.h"
#include "base/task/single_thread_task_executor.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/trace_event/trace_event.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/i18n/icu_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/check.h"
#include "base/base_switches.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/process/memory.h"
#include "base/process/launch.h"

#include <locale.h>

class AppDemo {
 public:
  AppDemo();
  ~AppDemo();

  void Initialize() {}
  void Destroy();
  void Run();

 private:
  void OnCloseRequest();
  void RenderFrame();

private:
  base::RunLoop* run_loop_ = nullptr;
  bool is_running_ = false;
};

AppDemo::AppDemo() = default;

AppDemo::~AppDemo() = default;

void AppDemo::OnCloseRequest() {
  is_running_ = false;
  if (run_loop_)
    run_loop_->QuitWhenIdle();
}

void AppDemo::RenderFrame() {
  if (!is_running_)
    return;

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::BindOnce(&AppDemo::RenderFrame, base::Unretained(this)));
}

void AppDemo::Destroy() {}

void AppDemo::Run() {
  DCHECK(!is_running_);
  DCHECK(!run_loop_);
  base::RunLoop run_loop;
  is_running_ = true;
  run_loop_ = &run_loop;
  RenderFrame();
  run_loop.Run();

  // base::RunLoop::QuitClosure() causes the message loop to quit
  // immediately, even if pending tasks are still queued.
  // Run a secondary loop to make sure all those are processed.
  // This becomes important when app does
  // a bunch of clean-up tasks asynchronously when shutting down.
  while (runLoop.RunOnce(false /* may_block */)) {
  }

  run_loop_ = nullptr;
}

namespace switches {

const char kLogFile[] = "log-file";

const int kTraceEventAppSortIndex = -1;

const char kTraceToConsole[] = "trace-to-console";

} // namespace switches

namespace tracing {

namespace {
// These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575.
const char kEchoToConsoleCategoryFilter[] = "-ipc,-toplevel";
}  // namespace

base::trace_event::TraceConfig GetConfigForTraceToConsole() {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  DCHECK(command_line.HasSwitch(switches::kTraceToConsole));
  std::string filter = command_line.GetSwitchValueASCII(
      switches::kTraceToConsole);
  if (filter.empty()) {
    filter = kEchoToConsoleCategoryFilter;
  } else {
    filter.append(",");
    filter.append(kEchoToConsoleCategoryFilter);
  }
  return base::trace_event::TraceConfig(
      filter, base::trace_event::ECHO_TO_CONSOLE);
}

}  // namespace tracing

int main(int argc, const char* argv[]) {
  setlocale(LC_ALL, "en_US.UTF-8");

  base::EnableTerminationOnHeapCorruption();

  // Manages the destruction of singletons.
  base::AtExitManager exit_manager;

  CHECK(base::CommandLine::Init(argc, argv));
  const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();

#if defined(OS_WIN) && !defined(NDEBUG)
  base::RouteStdioToConsole(false);
#endif

  base::FilePath log_filename =
      command_line.GetSwitchValuePath(switches::kLogFile);
  if (log_filename.empty()) {
    base::PathService::Get(base::DIR_EXE, &log_filename);
    log_filename = log_filename.AppendASCII("app_logfile.log");
  }

// Only use OutputDebugString in debug mode.
#ifdef NDEBUG
  logging::LoggingDestination destination = logging::LOG_TO_FILE;
#else
  logging::LoggingDestination destination =
      logging::LOG_TO_ALL;
#endif
  logging::LoggingSettings settings;
  settings.logging_dest = destination;

  settings.log_file_path = log_filename.value().c_str();
  settings.delete_old = logging::DELETE_OLD_LOG_FILE;
  logging::InitLogging(settings);

  logging::SetLogItems(true /* Process ID */, true /* Thread ID */,
                       true /* Timestamp */, false /* Tick count */);

  /// \todo provide ICU data file
  /// base::i18n::InitializeICU();

#ifndef NDEBUG
  CHECK(base::debug::EnableInProcessStackDumping());
#endif

  // Initialize tracing.
  base::trace_event::TraceLog::GetInstance()->set_process_name("Browser");
  base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
      switches::kTraceEventAppSortIndex);
  if (command_line.HasSwitch(switches::kTraceToConsole)) {
    base::trace_event::TraceConfig trace_config =
        base::tracing::GetConfigForTraceToConsole();
    base::trace_event::TraceLog::GetInstance()->SetEnabled(
        trace_config, base::trace_event::TraceLog::RECORDING_MODE);
  }

  // Build UI thread task executor. This is used by platform
  // implementations for event polling & running background tasks.
  base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);

  // Initialize ThreadPool.
  constexpr int kMaxForegroundThreads = 6;
  base::ThreadPoolInstance::InitParams thread_pool_init_params(
      kMaxForegroundThreads);

  base::ThreadPoolInstance::Create("AppThreadPool");
  base::ThreadPoolInstance::Get()->Start(thread_pool_init_params);

  AppDemo app_demo;
  app_demo.Initialize();
  app_demo.Run();
  app_demo.Destroy();

  base::ThreadPoolInstance::Get()->Shutdown();
}

See as example:

Run compiled app with arguments:

DOCS

See ./extensions/docs/

Extra docs:

base is similar to abseil, so you may want to read abseil docs:

basic is similar to folly, so you may want to read folly docs:

Before build (dependencies)

sudo apt-get install python3
sudo apt-get install python3-dev
pip3 install -U Jinja2

Create clang conan profile https://docs.conan.io/en/1.34/reference/profiles.html#examples

You can create profile clang12_compiler based on https://github.com/blockspacer/conan_llvm_9

Re-build dependencies:

git clone https://github.com/blockspacer/conan_github_downloader.git ~/conan_github_downloader

export VERBOSE=1
export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10

cmake \
  -DSCRIPT_PATH="$PWD/get_conan_dependencies.cmake"\
  -DEXTRA_CONAN_OPTS="--profile;clang12_compiler\
;-s;build_type=Debug\
;-s;cling_conan:build_type=Release\
;-s;llvm_tools:build_type=Release\
;--build;missing" \
  -P ~/conan_github_downloader/conan_github_downloader.cmake

conan profile example: clang12_compiler

[settings]
# We are building in Ubuntu Linux

os_build=Linux
os=Linux
arch_build=x86_64
arch=x86_64

compiler=clang
compiler.version=12
compiler.libcxx=libstdc++11
compiler.cppstd=17

llvm_9:build_type=Release

[options]
cmake:with_openssl=False

[env]
CC=/usr/bin/clang-12
CXX=/usr/bin/clang++-12

[build_requires]
cmake/3.22.3

Dev-only build (local conan flow)

find . -type f -name "*_buildflags.h" -exec rm {} \;
find . -type f -name "*_buildflags.tmp" -exec rm {} \;

export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10

export PKG_NAME=chromium_base/master@conan/stable

(CONAN_REVISIONS_ENABLED=1 \
    conan remove --force $PKG_NAME || true)

# NOTE: use --build=missing if you got error `ERROR: Missing prebuilt package`
cmake -E time \
  conan install . \
  --install-folder local_build \
  -s build_type=Debug \
  -s cling_conan:build_type=Release \
  -s llvm_tools:build_type=Release \
  --profile clang12_compiler \
  -o chromium_base:shared=True \
  -o openssl:shared=True \
  -o boost:header_only=True \
  -e chromium_base:enable_tests=True \
  -o perfetto:is_hermetic_clang=False

(rm local_build/CMakeCache.txt || true)

cmake -E time \
  conan source . \
  --source-folder . \
  --install-folder local_build

rm -rf .generated

# You can use `cmake --build . -- -j14` on second run.
cmake -E time \
  conan build . \
  --build-folder local_build \
  --source-folder . \
  --install-folder local_build

conan package . \
  --build-folder local_build \
  --package-folder local_build/package_dir \
  --source-folder . \
  --install-folder local_build

cmake -E time \
  conan export-pkg . \
  conan/stable \
  --package-folder local_build/package_dir \
  --force \
  -s build_type=Debug \
  -s cling_conan:build_type=Release \
  -s llvm_tools:build_type=Release \
  --profile clang12_compiler \
  -o boost:header_only=True \
  -o chromium_base:shared=True \
  -o openssl:shared=True \
  -e chromium_base:enable_tests=True \
  -o perfetto:is_hermetic_clang=False

cmake -E time \
  conan test test_package chromium_base/master@conan/stable \
  -s build_type=Debug \
  -s cling_conan:build_type=Release \
  -s llvm_tools:build_type=Release \
  --profile clang12_compiler \
  -o boost:header_only=True \
  -o chromium_base:shared=True \
  -o openssl:shared=True \
  -e chromium_base:enable_tests=True \
  -o perfetto:is_hermetic_clang=False

cd local_build
ctest --verbose \
  --output-on-failure \
  --stop-on-failure
cd -

HOW TO BUILD FROM SOURCE

export VERBOSE=1
export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10

# NOTE: change `build_type=Debug` to `build_type=Release` in production
conan create . \
  conan/stable \
  -s build_type=Debug \
  -s llvm_tools:build_type=Release \
  --profile clang12_compiler \
  --build missing \
  --build cascade \
  -e chromium_base:enable_tests=True \
  -o chromium_base:shared=True \
  -o perfetto:is_hermetic_clang=False \
  -o boost:header_only=True \
  -o openssl:shared=True

# clean build cache
conan remove "*" --build --force

HOW TO BUILD WITH SANITIZERS ENABLED

Use enable_asan or enable_ubsan, etc.

export VERBOSE=1
export CONAN_REVISIONS_ENABLED=1
export CONAN_VERBOSE_TRACEBACK=1
export CONAN_PRINT_RUN_COMMANDS=1
export CONAN_LOGGING_LEVEL=10

# NOTE: change `build_type=Debug` to `build_type=Release` in production
conan create . \
    conan/stable \
    -s build_type=Debug \
    -s llvm_tools:build_type=Release \
    --profile clang12_compiler \
    --build chromium_tcmalloc \
    -s llvm_tools:build_type=Release \
    -o llvm_tools:enable_tsan=True \
    -o llvm_tools:include_what_you_use=False \
    -e chromium_base:enable_tests=True \
    -o chromium_base:enable_tsan=True \
    -e chromium_base:enable_llvm_tools=True \
    -o chromium_base:use_alloc_shim=False \
    -o chromium_base:shared=True \
    -o abseil:enable_tsan=True \
    -e abseil:enable_llvm_tools=True \
    -o perfetto:is_hermetic_clang=False \
    -o boost:header_only=True \
    -o openssl:shared=True

# clean build cache
conan remove "*" --build --force

DEPS

See https://github.com/chromium/chromium/blob/master/base/DEPS

  • icu
  • ced
  • modp_b64
  • dynamic_annotations
  • libevent (on UNIX)
  • tcmalloc (on UNIX)
  • LIBATOMIC (on UNIX)
  • PTHREADS (on UNIX)
  • xdg_mime (on UNIX)
  • xdg_user_dirs (on UNIX)

Extra deps used by ./extensions/basic/:

  • header-only boost libraries
  • fmt
  • abseil

Used chromium version

[base] Add C++23 Enum Helpers

This change adds the C++23 enum utilities std::to_underlying and
std::is_scoped_enum.

Bug: None
Change-Id: Idb275bfb4833080701dbce5f5d307091debe27b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2736976
Reviewed-by: Daniel Cheng <[email protected]>
Commit-Queue: Jan Wilken D?rrie <[email protected]>
Cr-Commit-Position: refs/heads/master@{#860144}
GitOrigin-RevId: f89fc2ac30e582dfe9e334baf19ef8e535eea30d

How to do minor updates

Clone latest base:

cd ~
git clone https://chromium.googlesource.com/chromium/src/base
# see https://chromium.googlesource.com/chromium/src/base/+/944910a3c30b76db99a3978f59098e8a33953617
# see https://source.chromium.org/chromium/chromium/src/base/+/944910a3c30b76db99a3978f59098e8a33953617:
git checkout 944910a3c30b76db99a3978f59098e8a33953617

Copy sources and apply patches by hand.

How to do major updates

#
git config --global url."https://github.com/".insteadOf git://github.com/
git config --global url."https://chromium.googlesource.com/".insteadOf git://chromium.googlesource.com/

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=$PWD/depot_tools:$PATH

mkdir ~/chromium && cd ~/chromium

cat >> git_with_retry.sh << EOF
#!/bin/bash

GIT_TRACE=1
REALGIT=/usr/bin/git

RETRIES=10
DELAY=1
COUNT=1
while [ \$COUNT -lt \$RETRIES ]; do
  \$REALGIT "\$@"
  if [ \$? -eq 0 ]; then
    RETRIES=0
    break
  fi
  let COUNT=\$COUNT+1
  sleep \$DELAY
done
EOF
chmod +x git_with_retry.sh
export PATH=$PWD:$PATH

# see https://chromium.googlesource.com/chromium/src/+/f89fc2ac30e582dfe9e334baf19ef8e535eea30d
wget https://chromium.googlesource.com/chromium/src/+archive/f89fc2ac30e582dfe9e334baf19ef8e535eea30d.tar.gz
mkdir src && cd src
tar xzvf ../f89fc2ac30e582dfe9e334baf19ef8e535eea30d.tar.gz
git init
git remote add origin https://chromium.googlesource.com/chromium/src.git
git_with_retry.sh fetch origin master
git checkout f89fc2ac30e582dfe9e334baf19ef8e535eea30d
git reset --hard f89fc2ac30e582dfe9e334baf19ef8e535eea30d

# Pull in all dependencies for HEAD
gclient.py sync --nohooks --no-history --shallow --revision=f89fc2ac30e582dfe9e334baf19ef8e535eea30d

# see https://chromium.googlesource.com/chromium/src/+/master/build/install-build-deps.sh
sudo apt install -y \
  bzip2 tar bison binutils gperf wdiff python-psutil \
  php php-cli python-psutil

# (only on linux)
./build/install-build-deps.sh

# Once you've run install-build-deps at least once, you can now run the Chromium-specific hooks,
# which will download additional binaries and other things you might need:
gclient runhooks

gn gen out/config --args='is_debug=false is_official_build=true' --ide=json

Follow extensions/README.md

Conan workspace and QT Creator (use during local development)

# remove old build files, but keep conan workspace layout
find conan_workspace\
  \! -name 'conan_workspace' \
  \! -name 'conan_workspace.yml' \
  \! -name 'conan_layout' \
  \! -name 'CMakeLists.txt' \
  -exec rm -rf {} +

cd conan_workspace

conan workspace install \
  ./conan_workspace.yml \
  --profile=clang12_compiler \
  -s build_type=Debug \
  -s cling_conan:build_type=Release \
  -s llvm_tools:build_type=Release \
  -o boost:header_only=True \
  -o openssl:shared=True \
  -e chromium_base:enable_tests=True \
  -o perfetto:is_hermetic_clang=False \
  -o chromium_base:shared=True

rm -rf .generated

cmake -E time \
  conan build .. \
  --build-folder . \
  --package-folder ./package_dir \
  --source-folder .. \
  --install-folder .

We need to run QT Creator from terminal that uses environment variables from activate.sh:

source activate.sh

# run new QtCreator window
qtcreator

Create kit in QT Creator with same compiler version as in conan profile.

Use same CMake as in conan profile, path may look similar to ~/.conan/data/cmake/3.22.3/conan/stable/package/.../bin/cmake i.e. run find ~/.conan/data/cmake/ -name "cmake" to find path to bin/cmake

Open conan_workspace/CMakelists.txt file in QT Creator, but enable only Debug output directory and set Debug output directory to conan_workspace (replace with full path to build folder that used conan build above).

If QT Creator crashes or does not work properly - disable Clang code model i.e. Help - About Plugins - Clang code model

Coroutines support

First, change CXX_STANDARD to (at least) 20: compiler.cppstd=20.

Used conan profile:

[settings]
# We are building in Ubuntu Linux
os_build=Linux
os=Linux
arch_build=x86_64
arch=x86_64

compiler=clang
compiler.version=11
compiler.libcxx=libc++
compiler.cppstd=20

[options]
cmake:with_openssl=False

[env]
CC=/usr/bin/clang-11
CXX=/usr/bin/clang++-11
CXXFLAGS="-v"

[build_requires]
cmake/3.22.3

Used clang version:

# LLVM
sudo apt-get install libllvm-11-ocaml-dev libllvm11 llvm-11 llvm-11-dev llvm-11-doc llvm-11-examples llvm-11-runtime
# Clang and co
sudo apt-get install clang-11 clang-tools-11 clang-11-doc libclang-common-11-dev libclang-11-dev libclang1-11 clang-format-11 clangd-11
# libfuzzer
sudo apt-get install libfuzzer-11-dev
# lldb
sudo apt-get install lldb-11
# lld (linker)
sudo apt-get install lld-11
# libc++
sudo apt-get install libc++-11-dev libc++abi-11-dev
# OpenMP
sudo apt-get install libomp-11-dev
# clang-tidy
sudo apt-get install clang-tidy-11
# libunwind
sudo apt-get install -y libunwind-dev

Re-install conan workspace with --build=missing.

NOTE: You can use -e chromium_base:compile_with_llvm_tools=True instead.

Mojo IPC

Mojo IPC supports communication between multiple processes.

Most of the other IPCs only support communication between two processes.

Read:

Run examples, note example with Promise usage:

# NOTE: will start mojo_cookie_app_consumer as child process
./local_build/mojo_cookie_app_producer \
  --vmodule=*=9999 \
  --test-data-dir="$PWD/tests/data/" \
  --icu-data-file="$PWD/tests/data/resources/icu/optimal/icudt68l.dat"

# NOTE: does nothing, must quit without errors
./local_build/mojo_dummy_example \
  --vmodule=*=9999 \
  --test-data-dir="$PWD/tests/data/" \
  --icu-data-file="$PWD/tests/data/resources/icu/optimal/icudt68l.dat"

Disclaimer

That open source project based on the Google Chromium project.

This is not official Google product.

Portions Copyright (c) Google Inc.

See LICENSE files.

About

Modified `base` library from chromium

Resources

License

BSD-3-Clause, BSD-3-Clause licenses found

Licenses found

BSD-3-Clause
LICENSE
BSD-3-Clause
LICENSE_chromium.txt

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published