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.

References