Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add src/test/many -- a simple C++ bazel stress test (#535)
This allows you to build a simple bazel C++ build graph of any size. It consists of a toplevel filegroup named `cc`. This filegroup contains `MANY_CC_BINARIES` program binaries, where `MANY_CC_BINARIES` is an environment variable whose default value is `1`. Each of these programs links with `MANY_CC_LIBRARIES`, each of which is generated from `MANY_CC_LIBRARY_SOURCES`+1 files. Simply set the environment variables as desired in order to build the corresponding graph. For instance: MANY_CC_BINARIES=20 MANY_CC_LIBRARIES=10 MANY_CC_LIBRARY_SOURCES=5 bazel build //:cc
- Loading branch information
Showing
6 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.git | ||
src/test/many |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
""" | ||
Provide a simple C++ build graph as large as desired. | ||
You may alter the values of cc_binaries(), cc_libraries(), and | ||
cc_library_sources() via the environment variables MANY_CC_BINARIES, | ||
MANY_CC_LIBRARIES, and MANY_CC_LIBRARY_SOURCES. For instance: | ||
MANY_CC_BINARIES=20 MANY_CC_LIBRARIES=10 MANY_CC_LIBRARY_SOURCES=5 bazel build //:cc | ||
""" | ||
|
||
load(":many-cc.bzl", "many_cc") | ||
load("@many-params//:cc-binaries.bzl", "cc_binaries") | ||
load("@many-params//:cc-libraries.bzl", "cc_libraries") | ||
load("@many-params//:cc-library-sources.bzl", "cc_library_sources") | ||
|
||
many_cc( | ||
name = "cc", | ||
binary_count = cc_binaries(), | ||
library_count = cc_libraries(), | ||
library_source_count = cc_library_sources(), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Many | ||
|
||
This allows you to build a simple bazel C++ build graph of any size. | ||
It consists of a toplevel filegroup named `cc`. This filegroup | ||
contains `MANY_CC_BINARIES` program binaries, where `MANY_CC_BINARIES` | ||
is an environment variable whose default value is `1`. Each of these | ||
programs links with `MANY_CC_LIBRARIES`, each of which is generated | ||
from `MANY_CC_LIBRARY_SOURCES`+1 files. | ||
|
||
Simply set the environment variables as desired in order to build the | ||
corresponding graph. For instance: | ||
|
||
MANY_CC_BINARIES=20 MANY_CC_LIBRARIES=10 MANY_CC_LIBRARY_SOURCES=5 bazel build //:cc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") | ||
|
||
http_archive( | ||
name = "bazel_skylib", | ||
sha256 = "1c531376ac7e5a180e0237938a2536de0c54d93f5c278634818e0efc952dd56c", | ||
urls = [ | ||
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz", | ||
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.3/bazel-skylib-1.0.3.tar.gz", | ||
], | ||
) | ||
|
||
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace") | ||
|
||
bazel_skylib_workspace() | ||
|
||
load(":many-params.bzl", "many_params") | ||
|
||
many_params( | ||
name = "many-params", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
""" | ||
Provide a simple C++ build graph as large as desired. | ||
""" | ||
|
||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") | ||
load("@bazel_skylib//rules:write_file.bzl", _write_file = "write_file") | ||
|
||
def write_file(name, out, lines, **kwargs): | ||
""" | ||
Call the skylib write_file routine, ensuring that all lines end with a newline. | ||
""" | ||
_write_file( | ||
name = name, | ||
out = out, | ||
content = lines + [""], | ||
) | ||
|
||
def id(s): | ||
return s.replace("-", "_") | ||
|
||
def many_cc_library_label(library_key): | ||
return "lib{}".format(library_key) | ||
|
||
def many_cc_library_header(library_key): | ||
return "lib{}.hh".format(library_key) | ||
|
||
def many_cc_library_function(library_key): | ||
return "func_{}".format(id(library_key)) | ||
|
||
def many_cc_library(library_key, library_source_count): | ||
""" | ||
Generate a C++ library. | ||
The library has library_source_count+1 distinct functions. One | ||
function is always present and is named for the library. It calls | ||
all of the remaining functions in the library. | ||
Args: | ||
library_key: determines the name of the C++ library | ||
library_source_count: determines how many source files the library will have | ||
""" | ||
library_source_index = 0 | ||
cc_labels = [] | ||
hh_files = [] | ||
funcnames = [] | ||
for library_source_index in range(library_source_count): | ||
rulename_hh = "lib{}-{}_hh".format(library_key, library_source_index) | ||
filename_hh = "lib{}-{}.hh".format(library_key, library_source_index) | ||
rulename_cc = "lib{}-{}_cc".format(library_key, library_source_index) | ||
filename_cc = "lib{}-{}.cc".format(library_key, library_source_index) | ||
funcname = "func_{}_{}".format(id(library_key), library_source_index) | ||
|
||
cc_labels.append(rulename_cc) | ||
cc_labels.append(rulename_hh) | ||
hh_files.append(filename_hh) | ||
funcnames.append(funcname) | ||
|
||
lines = [] | ||
lines.append("#include <iostream>") | ||
lines.append('#include "{}"'.format(filename_hh)) | ||
lines.append("void {}(void)".format(funcname)) | ||
lines.append("{") | ||
lines.append(' std::cout << "Hello, World! {} {}" << std::endl;'.format(library_key, library_source_index)) | ||
lines.append("}") | ||
|
||
write_file( | ||
name = rulename_cc, | ||
out = filename_cc, | ||
lines = lines, | ||
) | ||
|
||
lines = [] | ||
lines.append("extern void {}(void);".format(funcname)) | ||
|
||
write_file( | ||
name = rulename_hh, | ||
out = filename_hh, | ||
lines = lines, | ||
) | ||
|
||
library_source_index += 1 | ||
|
||
rulename_hh = "lib{}_hh".format(library_key) | ||
filename_hh = many_cc_library_header(library_key) | ||
rulename_cc = "lib{}_cc".format(library_key) | ||
filename_cc = "lib{}.cc".format(library_key) | ||
funcname = many_cc_library_function(library_key) | ||
|
||
lines = [] | ||
lines.extend(['#include "{}"'.format(x) for x in hh_files]) | ||
lines.append('#include "{}"'.format(filename_hh)) | ||
lines.append("void {}(void)".format(funcname)) | ||
lines.append("{") | ||
lines.extend([" {}();".format(x) for x in funcnames]) | ||
lines.append("}") | ||
|
||
write_file( | ||
name = rulename_cc, | ||
out = filename_cc, | ||
lines = lines, | ||
) | ||
|
||
lines = [] | ||
lines.append("extern void {}(void);".format(funcname)) | ||
|
||
write_file( | ||
name = rulename_hh, | ||
out = filename_hh, | ||
lines = lines, | ||
) | ||
|
||
cc_library( | ||
name = many_cc_library_label(library_key), | ||
srcs = cc_labels + [rulename_cc], | ||
hdrs = [rulename_hh], | ||
) | ||
|
||
def many_cc_binary_label(binary_key): | ||
return "{}".format(binary_key) | ||
|
||
def many_cc_binary(binary_key, library_count, library_source_count): | ||
""" | ||
Generate a C++ program. | ||
The program links with library_count libraries, each of which has | ||
library_source_count+1 functions. | ||
Args: | ||
binary_key: determines the name of the C++ program | ||
library_count: how many libraries this program should link with | ||
library_source_count: how many source files each library should have | ||
""" | ||
library_keys = [] | ||
for library_index in range(library_count): | ||
library_key = "{}-{}".format(binary_key, library_index) | ||
library_keys.append(library_key) | ||
many_cc_library(library_key, library_source_count) | ||
|
||
rulename_cc = "{}_cc".format(binary_key) | ||
filename_cc = "{}.cc".format(binary_key) | ||
|
||
lines = [] | ||
lines.extend(['#include "{}"'.format(many_cc_library_header(x)) for x in library_keys]) | ||
lines.append("int main(void)") | ||
lines.append("{") | ||
lines.extend([" {}();".format(many_cc_library_function(x)) for x in library_keys]) | ||
lines.append(" return 0;") | ||
lines.append("}") | ||
|
||
write_file( | ||
name = rulename_cc, | ||
out = filename_cc, | ||
lines = lines, | ||
) | ||
|
||
cc_binary( | ||
name = many_cc_binary_label(binary_key), | ||
srcs = [rulename_cc], | ||
deps = [many_cc_library_label(x) for x in library_keys], | ||
) | ||
|
||
def many_cc(name, binary_count, library_count, library_source_count): | ||
""" | ||
Generate a C++ build graph under a filegroup of the given name. | ||
The build graph has binary_count programs, each of which links with | ||
library_count libraries, each of which has library_source_count+1 | ||
functions. | ||
Args: | ||
name: name of the filegroup to generate | ||
binary_count: how many programs to generate in the filegroup | ||
library_count: how many libraries each program should link with | ||
library_source_count: how many source files each library should have | ||
""" | ||
binary_keys = [] | ||
for binary_index in range(binary_count): | ||
binary_key = "{}-{}".format(name, binary_index) | ||
binary_keys.append(binary_key) | ||
many_cc_binary(binary_key, library_count, library_source_count) | ||
|
||
native.filegroup( | ||
name = name, | ||
srcs = [many_cc_binary_label(x) for x in binary_keys], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
""" | ||
Make the values of certain environment variables available to the rest | ||
of the build as function values. | ||
This is a way to pass parameters into the build that bazel macros can | ||
consume. We cannot use Starlark's user defined build settings for this, | ||
as these are themselves bazel rules, so their values are not available | ||
when bazel processes macros. To get around this limitation, we here | ||
define a custom repository rule that dynamically generates bazel macros | ||
based on the values of environment variables. | ||
""" | ||
|
||
def _many_params_impl(repository_ctx): | ||
params = [ | ||
{ | ||
"path": "cc-binaries.bzl", | ||
"name": "cc_binaries", | ||
"value": repository_ctx.os.environ.get("MANY_CC_BINARIES", "1"), | ||
}, | ||
{ | ||
"path": "cc-libraries.bzl", | ||
"name": "cc_libraries", | ||
"value": repository_ctx.os.environ.get("MANY_CC_LIBRARIES", "1"), | ||
}, | ||
{ | ||
"path": "cc-library-sources.bzl", | ||
"name": "cc_library_sources", | ||
"value": repository_ctx.os.environ.get("MANY_CC_LIBRARY_SOURCES", "1"), | ||
}, | ||
] | ||
|
||
for param in params: | ||
content = """\ | ||
def {name}(): | ||
return {value} | ||
""".format(name = param["name"], value = param["value"]) | ||
|
||
repository_ctx.file( | ||
param["path"], | ||
content = content, | ||
executable = False, | ||
) | ||
|
||
# Need to have a BUILD file to define a bazel package for the rules files above. | ||
repository_ctx.file( | ||
"BUILD", | ||
content = "", | ||
executable = False, | ||
) | ||
|
||
return None | ||
|
||
many_params = repository_rule( | ||
implementation = _many_params_impl, | ||
local = True, | ||
environ = [ | ||
"MANY_CC_BINARIES", | ||
"MANY_CC_LIBRARIES", | ||
"MANY_CC_LIBRARY_SOURCES", | ||
], | ||
) |