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.
- Easy integration with open-source projects that use
CMake
andconan
- 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
Tested on Ubuntu 20.04.2 LTS.
May work on other platforms with minor modifications.
Base, libchrome and mini_chromium are general utility libraries from chromium.
See:
- https://github.com/chromium/chromium/tree/master/base
- https://chromium.googlesource.com/chromiumos/docs/+/master/packages/libchrome.md
- https://chromium.googlesource.com/chromium/mini_chromium/
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
orCHECK
. std::thread
replaced withbase::Thread
orbase::PlatformThread
.- Removed already existing functionality (avoids code duplication).
- Ported to more platforms (Android, browser, etc.)
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:
- https://source.chromium.org/chromium/chromium/src/+/b28193d300f6a0853f31d305b3fb917c3a1601b7:remoting/host/it2me/it2me_native_messaging_host_main.cc
- https://source.chromium.org/chromium/chromium/src/+/b28193d300f6a0853f31d305b3fb917c3a1601b7:gpu/vulkan/demo/
- https://source.chromium.org/chromium/chromium/src/+/b28193d300f6a0853f31d305b3fb917c3a1601b7:content/shell/app/shell_main_delegate.cc
- https://source.chromium.org/chromium/chromium/src/+/b28193d300f6a0853f31d305b3fb917c3a1601b7:chrome/browser/chrome_browser_main.cc
Run compiled app with arguments:
--icu-data-file=
must point to icu data file (example.dat
files in https://chromium.googlesource.com/chromium/deps/icu/+/dc4ceac1fd9c77c3cacf6dec4ac83f684e069644/common/)- set logging level using vmodule i.e.
--vmodule=*=9999
--assets-dir=
can be used to changeDIR_ASSETS
(seebase/base_paths.h
)
See ./extensions/docs/
Extra docs:
- The Chromium Projects https://www.chromium.org/developers
- Chromium docs https://chromium.googlesource.com/chromium/src/+/master/docs
- Chromium Chronicle https://developer.chrome.com/tags/chromium-chronicle/
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:
- https://github.com/facebook/folly/tree/master/folly/docs
- https://engineering.fb.com/2012/06/02/developer-tools/folly-the-facebook-open-source-library/
- https://engineering.fb.com/2015/06/19/developer-tools/futures-for-c-11-at-facebook/
- https://engineering.fb.com/2019/04/25/developer-tools/f14/
- https://groups.google.com/g/facebook-folly
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
[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
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 -
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
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
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
[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
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.
#
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
# 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
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 supports communication between multiple processes.
Most of the other IPCs only support communication between two processes.
Read:
- https://blogs.igalia.com/gyuyoung/2020/05/11/how-chromium-got-its-mojo/
- https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/docs/basics.md
- https://chromium.googlesource.com/chromium/src/+/HEAD/docs/mojo_and_services.md
- https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/cpp/bindings/README.md
- https://source.chromium.org/chromium/chromium/src/+/master:mojo/public/cpp/bindings/README.md
- https://xzwang2005.github.io/Prelude/crack_the_code/Chap_3/mojo_101.html
- https://keyou.github.io/blog/2020/01/03/Chromium-Mojo&IPC/
- https://github.com/xzwang2005/Prelude/blob/bd005acdcffcb54564597246a6ee613b21fa592f/prelude/excerpt02_mojo/public/mojom/fortune_cookie.mojom
- https://github.com/metux/chromium-deb/blob/3c08e9b89a1b6f95f103a61ff4f528dbcd57fc42/mojo/public/cpp/bindings/README.md
- https://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
- https://docs.google.com/document/d/1n7qYjQ5iy8xAkQVMYGqjIy_AXu2_JJtMoAcOOupO_jQ/edit
- https://docs.google.com/document/d/1Jwfbzbe8ozaoilhqj5mAPYbYGpgZCen_XAAAdwmyP1E/edit#heading=h.serv9pzfw6sd
- https://docs.google.com/document/d/18pOsJOTuLVH-V7s9xwR-em9t-R4icyPjk7i8I8bfjjg/edit#heading=h.d88n53n8beml
- https://docs.google.com/document/d/1nq3J_HbS-gvVfIoEhcVyxm1uY-9G_7lhD-4Kyxb1WIY/edit
- https://docs.google.com/document/d/1M0-K0gi1xXO0f_-YKSH2LFVh4RJY-xe9T9VaGFOSXb0/edit#
- https://gitlab.developers.cam.ac.uk/jz448/browser-android-tabs/-/blob/f0a26d6eef948eb21d53ca3a9f9962bc633b06ed/docs/README.md#mojo-services
- https://chromium.googlesource.com/chromium/src/+/HEAD/mojo/public/tools/bindings/README.md
- https://mariospr.org/category/mojo-ipc/
- https://groups.google.com/a/chromium.org/g/chromium-mojo
- https://chromium.googlesource.com/chromium/src/+/HEAD/docs/README.md#mojo-services
- proposals https://groups.google.com/a/chromium.org/g/chromium-mojo/c/H7N9mF6gy8Y
- #mojo slack channel https://app.slack.com/client/T039UTRBS/CGGGVPSQ4
- mojo bugs https://bugs.chromium.org/p/chromium/issues/list?q=component%3AInternals%3EMojo&can=2
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"
That open source project based on the Google Chromium project.
This is not official Google product.
Portions Copyright (c) Google Inc.
See LICENSE files.