aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Poletti <poletti.marco@gmail.com>2020-08-09 11:02:44 -0700
committerMarco Poletti <poletti.marco@gmail.com>2020-08-09 11:02:44 -0700
commit94cefefb42f3685c1d64664e6aa9cbaf834b25ee (patch)
treec4d1dd5d2b0055c5c7bc4b7ff6ef56dd5af0d7b2
parent29c9fd265cfa72ee72fb64257fe4b72198d87264 (diff)
downloadgoogle-fruit-94cefefb42f3685c1d64664e6aa9cbaf834b25ee.tar.gz
Automatically detect compiler features when running under Bazel. Before this commit, bazel builds used a hardcoded configuration, but that doesn't work e.g. on Windows where MSVC needs a different config.
-rw-r--r--BUILD7
-rw-r--r--configuration/bazel/BUILD8
-rw-r--r--configuration/bazel/always_inline_attribute.cpp7
-rw-r--r--configuration/bazel/attribute_deprecated.cpp5
-rw-r--r--configuration/bazel/build_defs.bzl85
-rw-r--r--configuration/bazel/builtin_unreachable.cpp13
-rw-r--r--configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp11
-rw-r--r--configuration/bazel/constexpr_typeid.cpp6
-rw-r--r--configuration/bazel/cxa_demangle.cpp6
-rw-r--r--configuration/bazel/declspec_deprecated.cpp5
-rw-r--r--configuration/bazel/force_inline.cpp7
-rw-r--r--configuration/bazel/fruit/impl/fruit-config-base.h70
-rw-r--r--configuration/bazel/gcc_attribute_deprecated.cpp5
-rw-r--r--configuration/bazel/has_trivial_copy.cpp5
-rw-r--r--configuration/bazel/is_trivially_copyable.cpp5
-rw-r--r--configuration/bazel/max_align_t.cpp5
-rw-r--r--configuration/bazel/msvc_assume.cpp13
-rw-r--r--configuration/bazel/std_is_trivially_copy_constructible.cpp6
-rw-r--r--configuration/bazel/std_is_trivially_copyable.cpp6
-rw-r--r--configuration/bazel/std_max_align_t.cpp5
-rw-r--r--configuration/bazel/typeid.cpp5
21 files changed, 212 insertions, 73 deletions
diff --git a/BUILD b/BUILD
index 7d781ee..4c2aef5 100644
--- a/BUILD
+++ b/BUILD
@@ -6,8 +6,9 @@ filegroup(
name = "fruit_headers",
srcs = glob([
"include/**/*.h",
- "configuration/bazel/**/*.h",
- ]),
+ ]) + [
+ "//third_party/fruit/configuration/bazel:fruit_config",
+ ],
)
cc_library(
@@ -15,7 +16,7 @@ cc_library(
srcs = glob([
"src/*.cpp",
"include/fruit/impl/**/*.h",
- "configuration/bazel/**/*.h"]),
+ ]) + ["//third_party/fruit/configuration/bazel:fruit_config"],
hdrs = glob(["include/fruit/*.h"]),
includes = ["include", "configuration/bazel"],
deps = [
diff --git a/configuration/bazel/BUILD b/configuration/bazel/BUILD
new file mode 100644
index 0000000..112b732
--- /dev/null
+++ b/configuration/bazel/BUILD
@@ -0,0 +1,8 @@
+load("//third_party/fruit/configuration/bazel:build_defs.bzl", "generate_fruit_config")
+
+package(default_visibility = ["//third_party/fruit:__subpackages__"])
+
+generate_fruit_config(
+ name = "fruit_config",
+ check_sources = glob(["*.cpp"])
+)
diff --git a/configuration/bazel/always_inline_attribute.cpp b/configuration/bazel/always_inline_attribute.cpp
new file mode 100644
index 0000000..e6215af
--- /dev/null
+++ b/configuration/bazel/always_inline_attribute.cpp
@@ -0,0 +1,7 @@
+__attribute__((always_inline))
+void f() {
+}
+
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/attribute_deprecated.cpp b/configuration/bazel/attribute_deprecated.cpp
new file mode 100644
index 0000000..245519d
--- /dev/null
+++ b/configuration/bazel/attribute_deprecated.cpp
@@ -0,0 +1,5 @@
+[[deprecated]] void f();
+
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/build_defs.bzl b/configuration/bazel/build_defs.bzl
new file mode 100644
index 0000000..8d683c4
--- /dev/null
+++ b/configuration/bazel/build_defs.bzl
@@ -0,0 +1,85 @@
+load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
+load("@rules_cc//cc:toolchain_utils.bzl", "find_cpp_toolchain")
+
+def _generate_fruit_config_impl(ctx):
+ cc_toolchain = find_cpp_toolchain(ctx)
+
+ feature_configuration = cc_common.configure_features(
+ ctx = ctx,
+ cc_toolchain = cc_toolchain,
+ requested_features = ctx.features,
+ unsupported_features = ctx.disabled_features,
+ )
+ c_compiler_path = cc_common.get_tool_for_action(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ )
+
+ check_output_files = []
+ for check_source in ctx.files.check_sources:
+ output_file = ctx.actions.declare_file(check_source.path + ".o")
+
+ c_compile_variables = cc_common.create_compile_variables(
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ user_compile_flags = ctx.fragments.cpp.copts + ctx.fragments.cpp.conlyopts,
+ source_file = check_source.path,
+ output_file = output_file.path,
+ )
+ command_line = cc_common.get_memory_inefficient_command_line(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = c_compile_variables,
+ )
+ env = cc_common.get_environment_variables(
+ feature_configuration = feature_configuration,
+ action_name = C_COMPILE_ACTION_NAME,
+ variables = c_compile_variables,
+ )
+
+ check_name = check_source.path.split('/')[-1].split('\\')[-1]
+ check_define = 'FRUIT_HAS_%s' % check_name.upper()
+ check_output_file = ctx.actions.declare_file(check_source.path + ".h")
+
+ ctx.actions.run_shell(
+ command = '"$@" &>/dev/null && echo "#define %s 1" >"%s" || echo "#define %s 0" >"%s"; touch "%s"' % (
+ check_define, check_output_file.path, check_define, check_output_file.path, output_file.path
+ ),
+ arguments = [c_compiler_path] + command_line,
+ env = env,
+ inputs = depset(
+ [check_source],
+ transitive = [cc_toolchain.all_files],
+ ),
+ outputs = [output_file, check_output_file],
+ )
+ check_output_files.append(check_output_file)
+
+ merged_output_file = ctx.actions.declare_file(ctx.label.name + ".h")
+ ctx.actions.run_shell(
+ command = '\n'.join([
+ '(',
+ 'echo "#ifndef FRUIT_CONFIG_BASE_H"',
+ 'echo "#define FRUIT_CONFIG_BASE_H"',
+ 'echo "#define FRUIT_USES_BOOST 1"',
+ 'cat %s' % ' '.join([check_output_file.path for check_output_file in check_output_files]),
+ 'echo "#endif"',
+ ')>%s' % merged_output_file.path
+ ]),
+ inputs = check_output_files,
+ outputs = [merged_output_file],
+ )
+
+ return [
+ DefaultInfo(files = depset([merged_output_file])),
+ ]
+
+generate_fruit_config = rule(
+ implementation = _generate_fruit_config_impl,
+ attrs = {
+ "check_sources": attr.label_list(allow_files = True),
+ "_cc_toolchain": attr.label(default = Label("@bazel_tools//tools/cpp:current_cc_toolchain")),
+ },
+ toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
+ fragments = ["cpp"],
+) \ No newline at end of file
diff --git a/configuration/bazel/builtin_unreachable.cpp b/configuration/bazel/builtin_unreachable.cpp
new file mode 100644
index 0000000..11d20cf
--- /dev/null
+++ b/configuration/bazel/builtin_unreachable.cpp
@@ -0,0 +1,13 @@
+int f() {
+ static int x = 1;
+ if (x == 1) {
+ return 0;
+ } else {
+ __builtin_unreachable();
+ // Note: the lack of return here is intentional
+ }
+}
+
+int main() {
+ return f();
+}
diff --git a/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp b/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp
new file mode 100644
index 0000000..67b4317
--- /dev/null
+++ b/configuration/bazel/clang_arbitrary_overload_resolution_bug.cpp
@@ -0,0 +1,11 @@
+template <typename T, typename U>
+struct Pair {};
+
+struct Map : public Pair<int, float>, Pair<int, char> {};
+
+template <typename Value>
+Value f(Pair<int, Value>*) { return Value(); }
+
+int main() {
+ f((Map*)0);
+}
diff --git a/configuration/bazel/constexpr_typeid.cpp b/configuration/bazel/constexpr_typeid.cpp
new file mode 100644
index 0000000..a793377
--- /dev/null
+++ b/configuration/bazel/constexpr_typeid.cpp
@@ -0,0 +1,6 @@
+#include <typeinfo>
+int main() {
+ constexpr static const std::type_info& x = typeid(int);
+ (void) x;
+ return 0;
+}
diff --git a/configuration/bazel/cxa_demangle.cpp b/configuration/bazel/cxa_demangle.cpp
new file mode 100644
index 0000000..3e4f57f
--- /dev/null
+++ b/configuration/bazel/cxa_demangle.cpp
@@ -0,0 +1,6 @@
+#include <cxxabi.h>
+int main() {
+ auto* p = abi::__cxa_demangle;
+ (void) p;
+ return 0;
+}
diff --git a/configuration/bazel/declspec_deprecated.cpp b/configuration/bazel/declspec_deprecated.cpp
new file mode 100644
index 0000000..79a9f43
--- /dev/null
+++ b/configuration/bazel/declspec_deprecated.cpp
@@ -0,0 +1,5 @@
+__declspec(deprecated) void f();
+
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/force_inline.cpp b/configuration/bazel/force_inline.cpp
new file mode 100644
index 0000000..fab42d2
--- /dev/null
+++ b/configuration/bazel/force_inline.cpp
@@ -0,0 +1,7 @@
+__forceinline
+void f() {
+}
+
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/fruit/impl/fruit-config-base.h b/configuration/bazel/fruit/impl/fruit-config-base.h
deleted file mode 100644
index 8e7af1d..0000000
--- a/configuration/bazel/fruit/impl/fruit-config-base.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef FRUIT_CONFIG_BASE_H
-#define FRUIT_CONFIG_BASE_H
-
-// Needed for all Clang versions (as of January 2016), not needed for GCC.
-// This can also be defined for GCC, but it slightly slows down compile time of code using Fruit.
-#define FRUIT_HAS_CLANG_ARBITRARY_OVERLOAD_RESOLUTION_BUG 1
-
-// Whether the compiler defines std::max_align_t.
-#define FRUIT_HAS_STD_MAX_ALIGN_T 1
-
-// Whether the compiler defines ::max_align_t.
-// Ignored if FRUIT_HAS_STD_MAX_ALIGN_T is set.
-#define FRUIT_HAS_MAX_ALIGN_T 1
-
-// Whether the compiler defines std::is_trivially_copyable.
-#define FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE 1
-
-// Whether the compiler defines __has_trivial_copy.
-// Ignored if FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE is set.
-#define FRUIT_HAS_HAS_TRIVIAL_COPY 1
-
-// Whether the compiler defines __is_trivially_copyable.
-// Ignored if FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE is set.
-#define FRUIT_HAS_IS_TRIVIALLY_COPYABLE 1
-
-// Whether the compiler defines std::is_trivially_copy_constructible.
-#define FRUIT_HAS_STD_IS_TRIVIALLY_COPY_CONSTRUCTIBLE 1
-
-// Whether typeid() is available. Typically, it is unless RTTI is disabled.
-#define FRUIT_HAS_TYPEID 1
-
-// Whether typeid() is constexpr. Typically, it is except in MSVC.
-#define FRUIT_HAS_CONSTEXPR_TYPEID 1
-
-// Whether abi::__cxa_demangle() is available after including cxxabi.h.
-#define FRUIT_HAS_CXA_DEMANGLE 1
-
-#define FRUIT_USES_BOOST 1
-
-#define FRUIT_HAS_ALWAYS_INLINE_ATTRIBUTE 1
-
-#define FRUIT_HAS_FORCEINLINE 0
-
-#define FRUIT_HAS_ATTRIBUTE_DEPRECATED 0
-
-#define FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED 1
-
-#define FRUIT_HAS_DECLSPEC_DEPRECATED 0
-
-#define FRUIT_HAS_MSVC_ASSUME 0
-
-#define FRUIT_HAS_BUILTIN_UNREACHABLE 1
-
-#endif // FRUIT_CONFIG_BASE_H
diff --git a/configuration/bazel/gcc_attribute_deprecated.cpp b/configuration/bazel/gcc_attribute_deprecated.cpp
new file mode 100644
index 0000000..6d0bf5f
--- /dev/null
+++ b/configuration/bazel/gcc_attribute_deprecated.cpp
@@ -0,0 +1,5 @@
+void f() __attribute__((deprecated));
+
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/has_trivial_copy.cpp b/configuration/bazel/has_trivial_copy.cpp
new file mode 100644
index 0000000..b9da7d1
--- /dev/null
+++ b/configuration/bazel/has_trivial_copy.cpp
@@ -0,0 +1,5 @@
+int main() {
+ bool b = __has_trivial_copy(int);
+ (void) b;
+ return 0;
+}
diff --git a/configuration/bazel/is_trivially_copyable.cpp b/configuration/bazel/is_trivially_copyable.cpp
new file mode 100644
index 0000000..b8b7379
--- /dev/null
+++ b/configuration/bazel/is_trivially_copyable.cpp
@@ -0,0 +1,5 @@
+int main() {
+ bool b = __is_trivially_copyable(int);
+ (void) b;
+ return 0;
+}
diff --git a/configuration/bazel/max_align_t.cpp b/configuration/bazel/max_align_t.cpp
new file mode 100644
index 0000000..37342f1
--- /dev/null
+++ b/configuration/bazel/max_align_t.cpp
@@ -0,0 +1,5 @@
+#include <cstddef>
+using X = max_align_t;
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/msvc_assume.cpp b/configuration/bazel/msvc_assume.cpp
new file mode 100644
index 0000000..cd9f6ed
--- /dev/null
+++ b/configuration/bazel/msvc_assume.cpp
@@ -0,0 +1,13 @@
+int f() {
+ static int x = 1;
+ if (x == 1) {
+ return 0;
+ } else {
+ __assume(0);
+ // Note: the lack of return here is intentional
+ }
+}
+
+int main() {
+ return f();
+}
diff --git a/configuration/bazel/std_is_trivially_copy_constructible.cpp b/configuration/bazel/std_is_trivially_copy_constructible.cpp
new file mode 100644
index 0000000..7cb8d5b
--- /dev/null
+++ b/configuration/bazel/std_is_trivially_copy_constructible.cpp
@@ -0,0 +1,6 @@
+#include <type_traits>
+int main() {
+ bool b = std::is_trivially_copy_constructible<int>::value;
+ (void) b;
+ return 0;
+}
diff --git a/configuration/bazel/std_is_trivially_copyable.cpp b/configuration/bazel/std_is_trivially_copyable.cpp
new file mode 100644
index 0000000..871b793
--- /dev/null
+++ b/configuration/bazel/std_is_trivially_copyable.cpp
@@ -0,0 +1,6 @@
+#include <type_traits>
+int main() {
+ bool b = std::is_trivially_copyable<int>::value;
+ (void) b;
+ return 0;
+}
diff --git a/configuration/bazel/std_max_align_t.cpp b/configuration/bazel/std_max_align_t.cpp
new file mode 100644
index 0000000..acec695
--- /dev/null
+++ b/configuration/bazel/std_max_align_t.cpp
@@ -0,0 +1,5 @@
+#include <cstddef>
+using X = std::max_align_t;
+int main() {
+ return 0;
+}
diff --git a/configuration/bazel/typeid.cpp b/configuration/bazel/typeid.cpp
new file mode 100644
index 0000000..9621d03
--- /dev/null
+++ b/configuration/bazel/typeid.cpp
@@ -0,0 +1,5 @@
+#include <typeinfo>
+int main() {
+ (void) typeid(int);
+ return 0;
+}