We start with this program:
static_test1.cpp:
#include <iostream>
class Foo {
public:
static Foo& instance() {
static Foo instance;
return instance;
}
int value = 3;
};
int main() {
std::cout << Foo::instance().value << std::endl;
return 0;
}
BUILD.bazel:
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
cc_binary(
name = "static_test1",
srcs = [
"static_test1.cpp",
],
deps = [":foo"],
)
MODULE.bazel:
bazel_dep(name = "rules_cc", version = "0.2.16")
.bazelversion:
9.0.0
Do a bazel run //:static_test1.
There should be no big surprise.
The output of the program is 3.
Now lets change the program this way:
#include <iostream>
class Foo {
public:
static Foo& instance() {
static Foo instance;
return instance;
}
int value = 3;
};
static const int init_me = []() {
Foo::instance().value = 4;
return 0;
}();
int main() {
std::cout << Foo::instance().value << std::endl;
return 0;
}
main.cpp:
#include "foo.hpp"
#include <iostream>
int main() {
std::cout << Foo::instance().value << std::endl;
return 0;
}
There is no a static variable init_me.
Since static variables get initialzed before main the program now outputs 4.
No lets split our program into some files:
foo.hpp:
class Foo {
public:
static Foo& instance() {
static Foo instance;
return instance;
}
int value = 3;
};
foo.cpp:
static const int muh = []() {
Foo::instance().value = 4;
return 0;
}();
main.cpp:
#include "foo.hpp"
#include <iostream>
int main() {
std::cout << Foo::instance().value << std::endl;
return 0;
}
BUILD.bazel:
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
cc_library(
name = "foo",
srcs = [
"foo.cpp",
"foo.hpp",
],
hdrs = ["foo.hpp"],
visibility = ["//visibility:public"],
)
cc_binary(
name = "main",
srcs = [
"main.cpp",
],
deps = [":foo"],
)
Now lets run bazel run //:main.
The output is now 3.
If we change the cc_library foothis way:
cc_library(
name = "foo",
srcs = [
"foo.cpp",
"foo.hpp",
],
hdrs = ["foo.hpp"],
alwayslink = True,
visibility = ["//visibility:public"],
)
We get the output 4. alwayslink = True forces the linker to include the dynamic initialization.