readme: Adds docs and getting started guide
diff --git a/README.md b/README.md index d37f1dd..03514dd 100644 --- a/README.md +++ b/README.md
@@ -1 +1,203 @@ -# rules_cc_toolchain \ No newline at end of file +# rules_cc_toolchain +An opinionated hermetic host toolchain for Bazel and C++. Currently this +toolchain supports; +- Completely sandboxed linux builds (i.e. no system deps). +- Code coverage and combined lcov reports e.g. + `bazel coverage //...` + +The toolchain is modular enough that you should be able to BYO; +- Compiler and runtime +- libc +- libc++ / libc++abi +- Startup libraries (e.g. crt1.o) +- Injected toolchain headers and libs +## Getting Started +Add the following to your workspace file; + +```py +# WORKSPACE +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") + +# Set up host hermetic host toolchain. +git_repository( + name = "rules_cc_toolchain", + commit = "dd9265e3ce0daa444911040430bd716076869b34", + remote = "https://github.com/silvergasp/rules_cc_toolchain.git", +) + +load("@rules_cc_toolchain//:rules_cc_toolchain_deps.bzl", "rules_cc_toolchain_deps") + +rules_cc_toolchain_deps() + +load("@rules_cc_toolchain//cc_toolchain:cc_toolchain.bzl", "register_cc_toolchains") + +register_cc_toolchains() +``` + +and the following to your '.bazelrc'; + +``` +# Enforce strict checks of deprecated toolchain api. +build --incompatible_require_linker_input_cc_api + +# Use new cc toolchain resolution api +build --incompatible_enable_cc_toolchain_resolution + +# Code coverage support +coverage --combined_report=lcov +coverage --experimental_use_llvm_covmap +coverage --experimental_generate_llvm_lcov +coverage --incompatible_cc_coverage +``` + +## Defaults and config +This repository provides a set of sane defaults to make up a +[complete toolchain](https://clang.llvm.org/docs/Toolchain.html). By default; + +| Library | Provider | +| ----------------- | -------------------------------------------------- | +| libc | Debian stretch sysroot (GNU glibc6) | +| libc++ | LLVM 12.0.0 libc++ | +| libc++abi | LLVM 12.0.0 libc++abi | +| libunwind | Debian stretch sysroot (GNU gcc6 compiler runtime) | +| Startup Libraries | Debian stretch libcrt (GNU glibc6) | + +This can be viewed in more detail by inspecting `//config/config:BUILD.bazel`. + + +## Bring your own system libraries (Advanced) +This toolchain supports bringing your own precompiled system libraries. +Implementing this can be somewhat complicated and it is unlikely that we will +support specific combinations of libraries on request, although PR's here are +welcome. + +An example of how you might include your own version of libc++ is shown below. + +Add a third_party dependency directory for your libc++ build definitions. +``` sh +mkdir third_party +touch third_party/clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04.BUILD +``` + +Add the following to your WORKSPACE file. +``` py +# WORKSPACE +http_archive( + name = "clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04", + build_file = "//third_party:clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04.BUILD", + sha256 = "9694f4df031c614dbe59b8431f94c68631971ad44173eecc1ea1a9e8ee27b2a3", + strip_prefix = "clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04", + url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz", +) +``` + +From here you will need to add in your definitions that specify the library +files that are provided by this implementation of libc++. +``` py +# third_party:clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04.BUILD +load( + "@rules_cc_toolchain//cc_toolchain:cc_toolchain_import.bzl", + "cc_toolchain_import", +) + +cc_toolchain_import( + name = "llvm_libcxx", + # All the headers to be included with this library + hdrs = glob(["include/c++/v1/**"]), + # It is common for a library e.g. libc++.so to actually just be a linker + # script that points to a different library as is the case here where, + # 'lib/libc++.so' is a linker script that points to 'lib/libc++.so.1'. + # This is done so that dynamic linker can ensure that it is linking + # against a compatible version of the library ABI (in this case version 1). + additional_libs = [ + "lib/libc++.so.1", + ], + includes = ["include/c++/v1"], + + # NOTE: If one of static_library or shared_library is omitted this toolchain + # will default to the other. This is useful if you want to static link a + # particular library. It is also possible to omit both static_library and + # shared_library, creating a header only toolchain lib. + # Use with statically linkage. + static_library = "lib/libc++.a", + # Use with shared linkage. + shared_library = "lib/libc++.so", + + # This is a usefult sanity check to say that this library can only be + # targetted at Linux on an x86 machine. + target_compatible_with = select({ + "@platforms//os:linux": ["@platforms//cpu:x86_64"], + "//conditions:default": ["@platforms//:incompatible"], + }), + + # Here we make sure that this target is visible from the configuration layer. + visibility = ["@rules_cc_toolchain_config//:__pkg__"], + + # This version of libc++ depends on libc and libunwind, by specifying the + # dependency on the configuration layer rather than directly on the imported + # library itself we can ensure that we can swap out the version of libc with + # little effort. + deps = [ + "@rules_cc_toolchain_config//:libc", + "@rules_cc_toolchain_config//:libunwind", + ], +) +``` + +Now we can test the new toolchain to ensure that it functions correctly. +``` sh +bazel coverage @rules_cc_toolchain//tests/... \ + --@rules_cc_toolchain_config//:libc++=@clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04//:llvm_libcxx +``` + +**NOTE:** While the toolchain itself is hermetic the runtime linkage is not in +this example you will need to make sure that you have a recent version of LLVMs +libc++ installed on your system. If you would like to make sure that your +runtime is hermetic use the static linking mode in Bazel, or simply omit the +shared_library attribute to disable shared linkage for that specific library. + +You can also opt to make these changes permanent by overriding the +`rules_cc_toolchain_config` repository. e.g. + +Copy this repositories `config/rules_cc_toolchain_config.BUILD` to your own +repository. You can now update the `build_setting_default` for `libc++` to point +to your implementation. To make this change final you can make use of the + +```py +# WORKSPACE +load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +http_archive( + name = "clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04", + build_file = "//third_party:clang_llvm_12_00_x86_64_linux_gnu_ubuntu_16_04.BUILD", + sha256 = "9694f4df031c614dbe59b8431f94c68631971ad44173eecc1ea1a9e8ee27b2a3", + strip_prefix = "clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04", + url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz", +) + +# Set up host hermetic host toolchain. +git_repository( + name = "rules_cc_toolchain", + commit = "dd9265e3ce0daa444911040430bd716076869b34", + remote = "https://github.com/silvergasp/rules_cc_toolchain.git", +) + +# (NEW) +load("@rules_cc_toolchain//config:rules_cc_toolchain_config_repository.bzl", + "rules_cc_toolchain_config") + +# (NEW) Must be called before rules_cc_toolchain_deps. +rules_cc_toolchain_config( + name = "rules_cc_toolchain_config", + build_file = "//config:rules_cc_toolchain_config.BUILD", +) + +load("@rules_cc_toolchain//:rules_cc_toolchain_deps.bzl", "rules_cc_toolchain_deps") + +rules_cc_toolchain_deps() + +load("@rules_cc_toolchain//cc_toolchain:cc_toolchain.bzl", "register_cc_toolchains") + +register_cc_toolchains() +``` \ No newline at end of file