`std::cout` isn't initialized before any user-defined static initialization
clang version 14.0.7 bazel 5.3.0
The minimal source code source.cc is
#include <iostream>
struct S {
S() {
// std::ios_base::Init init;
std::cout << "static cout" << std::endl;
}
};
static S var_;
int main() {
return 0;
}
BUILD.bazel
cc_binary(
name = "source",
srcs = ["source.cc"],
)
build command:
build --repo_env="ANDROID_NDK_HOME=/**/android-ndk-r25c" --cpu=arm64-v8a --crosstool_top=@androidndk//:toolchain --host_crosstool_top=@bazel_tools//tools/cpp:toolchain --compilation_mode=opt --copt='-O3' --cxxopt='-std=c++17'
Running the binary in development board got Segmentation fault. Uncomment the line // std::ios_base::Init init;, running is successful.
It seems that the global object std::cost didn't initialized at that time. However, if I directly invoke clang by android-ndk-r25c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android23-clang --std=c++17 src/static-test.cc -o bazel-bin/static-clang.i -lstdc++, the Segmentation fault didn't happen.
related issues:
https://github.com/llvm/llvm-project/issues/29324
https://github.com/WebAssembly/wasi-sdk/issues/153
This isn't a bazel issue, nor even a bug. Static initialization order is not defined. You need explicit initialization if you care about order. That's not our choice, that's how C++ works.
Reading through to the LLVM bug you linked, I guess LLVM has some sort of attribute to hack around that? idk how that's implemented so it may not be portable. If you want your code to be portable, don't rely on static initialization order.
In any case, that fix isn't needed in bazel, you just need a new enough NDK.