aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2020-09-22 17:50:42 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-09-22 17:50:42 +0000
commitdc3aaf3620582ce933b6f23fe1b93584bc60fce0 (patch)
tree196bf451ec7a656bcbaaeffce735fe19e5c7b66f
parent1b13f367e02e2e90a59a7e6597bf47f64a1cf105 (diff)
parentefde60e7146303998a704e8604e90d27ca3f6241 (diff)
downloadgoogle-fruit-dc3aaf3620582ce933b6f23fe1b93584bc60fce0.tar.gz
Upgrade google-fruit to 928458857f4b85a0016c2d724486343b4660cb46 am: 873eb760e8 am: efde60e714
Original change: https://android-review.googlesource.com/c/platform/external/google-fruit/+/1433213 Change-Id: I58ec27630c20751b61ffab4fb455ba9056dc22e5
-rw-r--r--.gitattributes1
-rw-r--r--.gitignore1
-rw-r--r--BUILD8
-rw-r--r--CMakeLists.txt2
-rw-r--r--METADATA6
-rw-r--r--conanfile.py2
-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.bzl103
-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
-rw-r--r--extras/bazel_usage_example/BUILD8
-rw-r--r--extras/bazel_usage_example/WORKSPACE19
-rw-r--r--extras/bazel_usage_example/main.cpp55
-rwxr-xr-xextras/packaging/deploy_to_bintray.sh2
-rwxr-xr-xextras/scripts/travis_ci_install_osx.sh2
-rw-r--r--include/fruit/impl/component_functors.defn.h14
-rw-r--r--include/fruit/impl/injection_errors.h15
-rw-r--r--tests/BUILD5
-rw-r--r--tests/CMakeLists.txt2
-rwxr-xr-xtests/test_register_constructor.py41
-rwxr-xr-xtests/test_register_factory.py73
37 files changed, 461 insertions, 91 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..912b302
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+*.py linguist-detectable=false
diff --git a/.gitignore b/.gitignore
index 098e886..2a2e921 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ bench_results
/*.vcxproj.user
/out/build/x64-Debug
/out/build/x64-Debug cxx-17
+/extras/bazel_usage_example/bazel-*
diff --git a/BUILD b/BUILD
index 7d781ee..d93719c 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-base",
+ ],
)
cc_library(
@@ -15,11 +16,12 @@ cc_library(
srcs = glob([
"src/*.cpp",
"include/fruit/impl/**/*.h",
- "configuration/bazel/**/*.h"]),
+ ]),
hdrs = glob(["include/fruit/*.h"]),
includes = ["include", "configuration/bazel"],
deps = [
"@boost//:unordered",
+ "//third_party/fruit/configuration/bazel:fruit-config-base",
],
linkopts = ["-lm"],
)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d5b6a64..7efcf7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.2)
-project(Fruit VERSION 3.5.0 LANGUAGES CXX)
+project(Fruit VERSION 3.6.0 LANGUAGES CXX)
set(FRUIT_IS_BEING_BUILT_BY_CONAN FALSE CACHE BOOL "This is set in Conan builds.")
if("${FRUIT_IS_BEING_BUILT_BY_CONAN}")
diff --git a/METADATA b/METADATA
index 89886bf..7390325 100644
--- a/METADATA
+++ b/METADATA
@@ -9,11 +9,11 @@ third_party {
type: GIT
value: "https://github.com/google/fruit.git"
}
- version: "faa69229324e7b0393e2196b9fb919e5056dc675"
+ version: "928458857f4b85a0016c2d724486343b4660cb46"
license_type: NOTICE
last_upgrade_date {
year: 2020
- month: 7
- day: 10
+ month: 9
+ day: 21
}
}
diff --git a/conanfile.py b/conanfile.py
index 9c87a68..a96d39c 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -5,7 +5,7 @@ import os
class FruitConan(ConanFile):
name = "fruit"
- version = "3.5.0"
+ version = "3.6.0"
license = "Apache"
url = "https://github.com/google/fruit"
homepage = "https://github.com/google/fruit"
diff --git a/configuration/bazel/BUILD b/configuration/bazel/BUILD
new file mode 100644
index 0000000..a207462
--- /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-base",
+ 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..28c3b17
--- /dev/null
+++ b/configuration/bazel/build_defs.bzl
@@ -0,0 +1,103 @@
+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:
+ check_name = check_source.path[:-len(".cpp")].split('/')[-1].split('\\')[-1]
+
+ output_file = ctx.actions.declare_file(check_name + ".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_define = 'FRUIT_HAS_%s' % check_name.upper()
+ check_output_file = ctx.actions.declare_file(check_name + ".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("fruit/impl/fruit-config-base.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],
+ )
+
+ compilation_context, compilation_outputs = cc_common.compile(
+ actions = ctx.actions,
+ feature_configuration = feature_configuration,
+ cc_toolchain = cc_toolchain,
+ public_hdrs = [merged_output_file],
+ name = "%s_link" % ctx.label.name,
+ )
+
+ linking_context, linking_outputs = cc_common.create_linking_context_from_compilation_outputs(
+ actions = ctx.actions,
+ feature_configuration = feature_configuration,
+ compilation_outputs = compilation_outputs,
+ cc_toolchain = cc_toolchain,
+ name = "%s_link" % ctx.label.name,
+ )
+
+ return [
+ DefaultInfo(files = depset([merged_output_file]), runfiles = ctx.runfiles(files = [merged_output_file])),
+ CcInfo(compilation_context=compilation_context, linking_context=linking_context),
+ ]
+
+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;
+}
diff --git a/extras/bazel_usage_example/BUILD b/extras/bazel_usage_example/BUILD
new file mode 100644
index 0000000..47934aa
--- /dev/null
+++ b/extras/bazel_usage_example/BUILD
@@ -0,0 +1,8 @@
+
+licenses(["notice"])
+
+cc_binary(
+ name = "hello_world",
+ srcs = ["main.cpp"],
+ deps = ["@com_google_fruit//third_party/fruit"],
+)
diff --git a/extras/bazel_usage_example/WORKSPACE b/extras/bazel_usage_example/WORKSPACE
new file mode 100644
index 0000000..e037168
--- /dev/null
+++ b/extras/bazel_usage_example/WORKSPACE
@@ -0,0 +1,19 @@
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+git_repository(
+ name = "com_github_nelhage_rules_boost",
+ branch = "master",
+ remote = "https://github.com/nelhage/rules_boost",
+)
+
+load("@com_github_nelhage_rules_boost//:boost/boost.bzl", "boost_deps")
+boost_deps()
+
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+git_repository(
+ name = "com_google_fruit",
+ remote = "https://github.com/google/fruit",
+ branch = "master",
+ strip_prefix = "extras/bazel_root",
+)
diff --git a/extras/bazel_usage_example/main.cpp b/extras/bazel_usage_example/main.cpp
new file mode 100644
index 0000000..4364993
--- /dev/null
+++ b/extras/bazel_usage_example/main.cpp
@@ -0,0 +1,55 @@
+
+#include <fruit/fruit.h>
+#include <iostream>
+
+using fruit::Component;
+using fruit::Injector;
+
+class Writer {
+public:
+ virtual void write(std::string s) = 0;
+};
+
+class StdoutWriter : public Writer {
+public:
+ // Like "StdoutWriter() = default;" but also marks this constructor as the
+ // one to use for injection.
+ INJECT(StdoutWriter()) = default;
+
+ virtual void write(std::string s) override {
+ std::cout << s;
+ }
+};
+
+class Greeter {
+public:
+ virtual void greet() = 0;
+};
+
+class GreeterImpl : public Greeter {
+private:
+ Writer* writer;
+
+public:
+ // Like "GreeterImpl(Writer* writer) {...}" but also marks this constructor
+ // as the one to use for injection.
+ INJECT(GreeterImpl(Writer* writer)) : writer(writer) {}
+
+ virtual void greet() override {
+ writer->write("Hello world!\n");
+ }
+};
+
+Component<Greeter> getGreeterComponent() {
+ return fruit::createComponent().bind<Writer, StdoutWriter>().bind<Greeter, GreeterImpl>();
+}
+
+int main() {
+
+ Injector<Greeter> injector(getGreeterComponent);
+ Greeter* greeter = injector.get<Greeter*>();
+
+ greeter->greet();
+
+ return 0;
+}
diff --git a/extras/packaging/deploy_to_bintray.sh b/extras/packaging/deploy_to_bintray.sh
index 0365a6d..78d5c51 100755
--- a/extras/packaging/deploy_to_bintray.sh
+++ b/extras/packaging/deploy_to_bintray.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-FRUIT_VERSION=3.5.0
+FRUIT_VERSION=3.6.0
# To authenticate:
# conan user -p <BINTRAY_API_KEY_HERE> -r fruit-bintray polettimarco
diff --git a/extras/scripts/travis_ci_install_osx.sh b/extras/scripts/travis_ci_install_osx.sh
index 2cbd357..d3cc7c8 100755
--- a/extras/scripts/travis_ci_install_osx.sh
+++ b/extras/scripts/travis_ci_install_osx.sh
@@ -12,7 +12,7 @@ done
install_brew_package() {
time (brew install "$@" || brew outdated "$1" || brew upgrade "$@" || true)
# Some formulas are not linked into /usr/local by default, make sure they are.
- time (brew link --force "$@" || true)
+ time (brew link --force --overwrite "$@" || true)
}
# For md5sum, timeout
diff --git a/include/fruit/impl/component_functors.defn.h b/include/fruit/impl/component_functors.defn.h
index b12f723..e6778b1 100644
--- a/include/fruit/impl/component_functors.defn.h
+++ b/include/fruit/impl/component_functors.defn.h
@@ -402,7 +402,7 @@ template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> {
template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) {
- return std::get<numAssistedBefore>(user_provided_args);
+ return std::move(std::get<numAssistedBefore>(user_provided_args));
}
};
@@ -437,9 +437,9 @@ struct RegisterFactoryHelper {
using Result = Eval<R>;
void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
auto function_provider = [](NakedInjectedArgs... args) {
- auto injected_args = std::make_tuple(args...);
- auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable {
- auto user_provided_args = std::tie(params...);
+ std::tuple<NakedInjectedArgs...> injected_args{args...};
+ auto object_provider = [=](NakedUserProvidedArgs... params) mutable {
+ std::tuple<NakedUserProvidedArgs...> user_provided_args{std::move(params)...};
// These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway.
(void)injected_args;
(void)user_provided_args;
@@ -570,8 +570,8 @@ struct PreProcessRegisterConstructor {
using CDeps = NormalizeTypeVector(AnnotatedArgs);
using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs);
using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, CDeps, CNonConstDeps);
- using type = If(
- Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
+ using type = If(Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
+ If(Not(IsSame(RemoveAssisted(Args), Args)), ConstructError(AssistedParamInRegisterConstructorSignatureErrorTag, AnnotatedSignature),
PropagateError(CheckInjectableType(RemoveAnnotations(C)),
PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)),
If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
@@ -579,7 +579,7 @@ struct PreProcessRegisterConstructor {
RemoveAnnotations(SignatureType(AnnotatedSignature))),
If(Not(IsConstructibleWithVector(C, Args)),
ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature),
- PropagateError(R, ComponentFunctorIdentity(R)))))));
+ PropagateError(R, ComponentFunctorIdentity(R))))))));
};
};
diff --git a/include/fruit/impl/injection_errors.h b/include/fruit/impl/injection_errors.h
index a0e9def..68247d2 100644
--- a/include/fruit/impl/injection_errors.h
+++ b/include/fruit/impl/injection_errors.h
@@ -124,6 +124,16 @@ struct NotASignatureError {
"the form MyClass(int, float).");
};
+template <typename CandidateSignature>
+struct AssistedParamInRegisterConstructorSignatureError {
+ static_assert(AlwaysFalse<CandidateSignature>::value,
+ "CandidateSignature was used as signature for a registerConstructor() (explicit or implicit via the "
+ "INJECT macro / Inject typedef) but it contains an assisted parameter. When using assisted parameters"
+ "You need to inject a factory like std::function<std::unique_ptr<MyClass>(int, float)> instead of "
+ "injecting MyClass directly. If you used an explicit registerConstructor(), you also need to switch "
+ "that to registerFactory().");
+};
+
template <typename CandidateLambda>
struct NotALambdaError {
static_assert(AlwaysFalse<CandidateLambda>::value,
@@ -494,6 +504,11 @@ struct NotASignatureErrorTag {
using apply = NotASignatureError<CandidateSignature>;
};
+struct AssistedParamInRegisterConstructorSignatureErrorTag {
+ template <typename CandidateSignature>
+ using apply = AssistedParamInRegisterConstructorSignatureError<CandidateSignature>;
+};
+
struct NotALambdaErrorTag {
template <typename CandidateLambda>
using apply = NotALambdaError<CandidateLambda>;
diff --git a/tests/BUILD b/tests/BUILD
index b7ff089..e89f144 100644
--- a/tests/BUILD
+++ b/tests/BUILD
@@ -69,7 +69,6 @@ genrule(
],
visibility = ["//third_party/fruit/tests:__subpackages__"],
cmd = ""
- + "FRUIT_HEADERS_LOCATION=`for f in $(locations //third_party/fruit:fruit_headers); do echo \"$$f\"; done | fgrep configuration/bazel/ | head -n 1 | sed 's|configuration/bazel/.*|./|'`;"
+ "TEST_HEADERS_LOCATION=`for f in $(locations :test_headers_filegroup); do echo \"$$f\"; done | fgrep test_macros.h | sed 's|test_macros.h|./|'`;"
+ "LIBFRUIT_LOCATION=`for f in $(locations //third_party/fruit); do echo \"$$f\"; done | fgrep libfruit.so | head -n 1 | sed 's|libfruit.so|./|'`;"
+ "LIBTEST_HEADERS_LOCATION=`for f in $(locations //third_party/fruit/tests:test_headers); do echo \"$$f\"; done | fgrep libtest_headers.so | head -n 1 | sed 's|libtest_headers.so|./|'`;"
@@ -86,8 +85,8 @@ genrule(
+ "PATH_TO_COMPILED_FRUIT_LIB='third_party/fruit/tests'\n"
+ "PATH_TO_COMPILED_TEST_HEADERS='third_party/fruit/tests/test_headers'\n"
+ "PATH_TO_COMPILED_TEST_HEADERS_LIB='third_party/fruit/tests/test_headers'\n"
- + "PATH_TO_FRUIT_STATIC_HEADERS='$${FRUIT_HEADERS_LOCATION}/include'\n"
- + "PATH_TO_FRUIT_GENERATED_HEADERS='$${FRUIT_HEADERS_LOCATION}/configuration/bazel'\n"
+ + "PATH_TO_FRUIT_STATIC_HEADERS='third_party/fruit/include'\n"
+ + "PATH_TO_FRUIT_GENERATED_HEADERS='third_party/fruit/configuration/bazel'\n"
+ "PATH_TO_FRUIT_TEST_HEADERS='$${TEST_HEADERS_LOCATION}'\n"
+ "ADDITIONAL_LINKER_FLAGS='-lstdc++ -lm'\n"
+ "RUN_TESTS_UNDER_VALGRIND='0'\n"
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 479b8aa..095d3db 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -81,7 +81,7 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "^(MSVC)$")
set(FRUIT_TESTONLY_CXXFLAGS "${FRUIT_TESTONLY_CXXFLAGS} /wd4702 /wd4503")
endif()
-add_library(test_headers_copy SHARED test_common.cpp)
+add_library(test_headers_copy STATIC test_common.cpp)
target_link_libraries(test_headers_copy fruit)
# Escape the backslash which is a Windows path separator.
diff --git a/tests/test_register_constructor.py b/tests/test_register_constructor.py
index 3e5137e..b78191f 100755
--- a/tests/test_register_constructor.py
+++ b/tests/test_register_constructor.py
@@ -587,5 +587,46 @@ class TestRegisterConstructor(parameterized.TestCase):
source,
locals())
+ def test_register_constructor_error_assisted_param(self):
+ source = '''
+ struct X {
+ INJECT(X(ASSISTED(double) factor)) {
+ (void) factor;
+ }
+ };
+
+ fruit::Component<X> getComponent() {
+ return fruit::createComponent()
+ .registerConstructor<X(fruit::Assisted<double>)>();
+ }
+ '''
+ expect_compile_error(
+ 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>',
+ 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.',
+ COMMON_DEFINITIONS,
+ source,
+ locals())
+
+ def test_implicit_register_constructor_error_assisted_param(self):
+ source = '''
+ struct X {
+ INJECT(X(ASSISTED(double) factor)) {
+ (void) factor;
+ }
+ };
+
+ fruit::Component<X> getComponent() {
+ return fruit::createComponent();
+ }
+ '''
+ expect_compile_error(
+ 'AssistedParamInRegisterConstructorSignatureError<X\\(fruit::Assisted<double>\\)>',
+ 'CandidateSignature was used as signature for a registerConstructor.* but it contains an assisted parameter.',
+ COMMON_DEFINITIONS,
+ source,
+ locals())
+
+
+
if __name__ == '__main__':
absltest.main()
diff --git a/tests/test_register_factory.py b/tests/test_register_factory.py
index 202d18b..8f62946 100755
--- a/tests/test_register_factory.py
+++ b/tests/test_register_factory.py
@@ -2005,6 +2005,79 @@ class TestRegisterFactory(parameterized.TestCase):
source,
locals())
+ @multiple_parameters([
+ ('X()', 'X'),
+ ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
+ ], [
+ 'WithNoAnnotation',
+ 'WithAnnotation1',
+ ])
+ def test_register_factory_with_non_assignable_injected_param_success(self, ConstructX, XPtr, WithAnnot):
+ source = '''
+ struct Y {
+ Y(const Y&) = delete;
+ Y& operator=(const Y&) = delete;
+
+ Y() = default;
+ Y(Y&&) = default;
+ Y& operator=(Y&&) = default;
+ };
+ struct X {};
+
+ fruit::Component<WithAnnot<Y>> getYComponent() {
+ return fruit::createComponent()
+ .registerConstructor<WithAnnot<Y>()>();
+ }
+
+ fruit::Component<std::function<XPtr()>> getComponent() {
+ return fruit::createComponent()
+ .install(getYComponent)
+ .registerFactory<XPtr(WithAnnot<Y&>)>([](Y&){ return ConstructX; });
+ }
+
+ int main() {
+ fruit::Injector<std::function<XPtr()>> injector(getComponent);
+ XPtr x = injector.get<std::function<XPtr()>>()();
+ (void) x;
+ }
+ '''
+ expect_success(
+ COMMON_DEFINITIONS,
+ source,
+ locals())
+
+ @multiple_parameters([
+ ('X()', 'X'),
+ ('std::unique_ptr<X>(new X())', 'std::unique_ptr<X>'),
+ ])
+ def test_register_factory_with_non_assignable_assisted_param_success(self, ConstructX, XPtr):
+ source = '''
+ struct Y {
+ Y(const Y&) = delete;
+ Y& operator=(const Y&) = delete;
+
+ Y() = default;
+ Y(Y&&) = default;
+ Y& operator=(Y&&) = default;
+ };
+ struct X {};
+
+ fruit::Component<std::function<XPtr(Y)>> getComponent() {
+ return fruit::createComponent()
+ .registerFactory<XPtr(fruit::Assisted<Y>)>([](Y){ return ConstructX; });
+ }
+
+ int main() {
+ fruit::Injector<std::function<XPtr(Y)>> injector(getComponent);
+ XPtr x = injector.get<std::function<XPtr(Y)>>()(Y());
+ (void) x;
+ }
+ '''
+ expect_success(
+ COMMON_DEFINITIONS,
+ source,
+ locals())
+
def test_register_factory_requiring_nonconst_then_requiring_const_ok(self):
source = '''
struct X {};