Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
- [make](make.md)
- [meson](meson.md)
- [ninja](ninja.md)
- [Output Groups](output_groups.md)
198 changes: 198 additions & 0 deletions docs/src/output_groups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Output Groups

Rules Foreign CC provides several output groups that allow you to access different parts of the build output beyond the default outputs. This is particularly useful when you need to package or process the complete install tree or specific build artifacts.

**Output groups are available for all rules_foreign_cc rules:** `cmake`, `make`, `ninja`, `meson`, `configure_make`, and `boost_build`.

## Available Output Groups

### `gen_dir`

The `gen_dir` output group contains the complete install directory tree as it would be created by using the native build tool. This is the most important output group for extracting the entire build result.

**Use cases:**
- Packaging the complete install tree using `rules_pkg`
- Accessing all build outputs including documentation, examples, and other files
- Creating custom deployment packages

### Individual Output Files

Each output file produced by the build is available as a separate output group using the file's basename as the group name. This includes:

**Library files:**
- `libexample.a` - Static library (Unix-like systems)
- `example.lib` - Static library (Windows)
- `libexample.so` - Shared library (Linux)
- `libexample.dylib` - Shared library (macOS)
- `example.dll` - Shared library (Windows)

**Executable files:**
- `example` - Executable binary (Unix-like systems)
- `example.exe` - Executable binary (Windows)

**Header directory:**
- The headers directory (if `out_include_dir` is set) is available by its directory name

> **Note:** Interface libraries (`.lib` files for Windows DLLs) are part of the default outputs but are not currently available as separate output groups. Use the `gen_dir` output group to access all build outputs including interface libraries.

### Build Logs

A logs output group is created for each rule type, containing build scripts and log files:

- `CMake_logs` - For cmake rules
- `Make_logs` - For make rules
- `Ninja_logs` - For ninja rules
- `Meson_logs` - For meson rules
- `Configure_logs` - For configure_make rules
- `BoostBuild_logs` - For boost_build rules

## Basic Usage

To access an output group, use the `output_group` attribute in a `filegroup` rule:

```starlark
load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")

cmake(
name = "mylib",
lib_source = ":srcs",
out_static_libs = ["libmylib.a"],
)

# Access the complete install directory
filegroup(
name = "mylib_install",
srcs = [":mylib"],
output_group = "gen_dir",
)

# Access a specific output file
filegroup(
name = "mylib_static",
srcs = [":mylib"],
output_group = "libmylib.a",
)

# Access build logs
filegroup(
name = "mylib_logs",
srcs = [":mylib"],
output_group = "CMake_logs",
)
```

## Packaging with rules_pkg

Here's a complete example showing how to use output groups with `rules_pkg` to create distribution packages:

```starlark
load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")
load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")

cmake(
name = "example_lib",
lib_source = ":sources",
out_static_libs = ["libexample.a"],
out_binaries = ["example_tool"],
)

# Extract the complete install tree
filegroup(
name = "example_install_tree",
srcs = [":example_lib"],
output_group = "gen_dir",
)

# Create a tar package with the complete install
pkg_tar(
name = "example_package",
srcs = [":example_install_tree"],
package_dir = "/usr/local",
strip_prefix = "example_lib",
)

# Create separate packages for different components
filegroup(
name = "example_binary",
srcs = [":example_lib"],
output_group = "example_tool",
)

pkg_tar(
name = "example_bin_package",
srcs = [":example_binary"],
package_dir = "/usr/bin",
)
```

## Advanced Usage

### Conditional Output Groups

You can use `select()` statements with output groups for platform-specific outputs:

```starlark
filegroup(
name = "platform_binary",
srcs = [":mylib"],
output_group = select({
"@platforms//os:windows": "mylib.exe",
"//conditions:default": "mylib",
}),
)
```

### Multiple Output Groups

To access multiple output groups, create separate filegroup targets:

```starlark
filegroup(
name = "all_libs",
srcs = [
":static_libs",
":shared_libs",
":headers",
],
)

filegroup(
name = "static_libs",
srcs = [":mylib"],
output_group = "libmylib.a",
)

filegroup(
name = "shared_libs",
srcs = [":mylib"],
output_group = "libmylib.so",
)

filegroup(
name = "headers",
srcs = [":mylib"],
output_group = "gen_dir",
)
```

## Tips and Best Practices

1. **Use `gen_dir` for complete packaging** - When you need everything the build produces, use the `gen_dir` output group.

2. **Discover available output groups** - Use `bazel query` to see what output groups are available for a target:
```bash
bazel query --output=build //path/to:target
```
You can also inspect the target after building:
```bash
bazel build //path/to:target
bazel cquery //path/to:target --output=textproto
```

3. **Combine with rules_pkg** - Output groups work excellently with packaging rules to create distribution artifacts.

4. **Platform-specific handling** - Use `select()` statements when dealing with platform-specific file extensions or names.

5. **Access logs for debugging** - The logs output groups are useful for debugging build issues or understanding what the build system is doing.

6. **Check the install directory structure** - The `gen_dir` output group contains the complete install tree layout, which matches what you'd get from running the native build tool's install command.
109 changes: 109 additions & 0 deletions examples/cmake_output_groups/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
Example demonstrating output groups usage with rules_foreign_cc.
This example shows how to access different build outputs using output groups
and how to package them using rules_pkg.
"""

load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")

filegroup(
name = "srcs",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)

# Build a cmake project that produces multiple outputs
cmake(
name = "example_project",
lib_source = ":srcs",
# Install everything to get the complete install tree
install = True,
out_static_libs = select({
"@bazel_tools//src/conditions:windows": ["example_lib.lib"],
"//conditions:default": ["libexample_lib.a"],
}),
out_binaries = select({
"@bazel_tools//src/conditions:windows": ["example_tool.exe"],
"//conditions:default": ["example_tool"],
}),
)

# Example 1: Access the complete install directory tree
# This is the most important use case - getting everything the build produces
filegroup(
name = "complete_install",
srcs = [":example_project"],
output_group = "gen_dir",
visibility = ["//visibility:public"],
)

# Example 2: Access specific output files by their basename
filegroup(
name = "static_library",
srcs = [":example_project"],
output_group = select({
"@bazel_tools//src/conditions:windows": "example_lib.lib",
"//conditions:default": "libexample_lib.a",
}),
)

filegroup(
name = "executable_tool",
srcs = [":example_project"],
output_group = select({
"@bazel_tools//src/conditions:windows": "example_tool.exe",
"//conditions:default": "example_tool",
}),
)

# Example 3: Access build logs for debugging
filegroup(
name = "build_logs",
srcs = [":example_project"],
output_group = "CMake_logs",
)

# Example 4: Packaging with rules_pkg (when available)
# Uncomment the following rules if you have rules_pkg available:
#
# load("@rules_pkg//pkg:pkg.bzl", "pkg_tar")
#
# # Package the complete install tree
# pkg_tar(
# name = "example_package",
# srcs = [":complete_install"],
# package_dir = "/usr/local",
# strip_prefix = "example_project",
# )
#
# # Package just the binary
# pkg_tar(
# name = "example_bin_package",
# srcs = [":executable_tool"],
# package_dir = "/usr/bin",
# )
#
# # Package just the library
# pkg_tar(
# name = "example_lib_package",
# srcs = [":static_library"],
# package_dir = "/usr/lib",
# )

# Example 5: Create a test that uses the executable
genrule(
name = "test_executable",
srcs = [],
outs = ["test_output.txt"],
cmd = "./$(location :executable_tool) > $(location test_output.txt)",
tools = [":executable_tool"],
)

# Example 6: Show how to access multiple outputs in a single target
filegroup(
name = "all_outputs",
srcs = [
":static_library",
":executable_tool",
],
)
22 changes: 22 additions & 0 deletions examples/cmake_output_groups/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
cmake_minimum_required(VERSION 3.10)
project(OutputGroupsExample)

# Create a simple library
add_library(example_lib src/example.c)

# Create a simple executable
add_executable(example_tool src/main.c)
target_link_libraries(example_tool example_lib)

# Install targets
install(TARGETS example_lib example_tool
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
)

# Install headers
install(FILES src/example.h DESTINATION include)

# Install documentation
install(FILES README.txt DESTINATION share/doc/example)
Loading