aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/google/devtools')
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MOCK_OSX_CROSSTOOL15789
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MockJ2ObjcSupport.java101
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java300
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java202
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleBinaryTest.java1410
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleDynamicLibraryTest.java195
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryTest.java544
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryTest.java153
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleToolchainSelectionTest.java183
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch1ExtensionTest.java1005
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch2ExtensionTest.java973
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatchExtensionBinaryTest.java171
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleType.java44
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleTypePair.java163
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcBinaryTest.java301
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/HeaderDiscoveryTest.java86
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/HeaderThinningTest.java271
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/InterspersingTest.java78
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/IosApplicationTest.java1175
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/IosDeviceTest.java172
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryTest.java211
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionTest.java638
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/IosTestTest.java1231
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleBinaryTest.java31
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleDynamicLibraryTest.java31
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleStaticLibraryTest.java96
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch1ExtensionTest.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch2ExtensionTest.java59
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatchExtensionBinaryTest.java76
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosApplicationTest.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionBinaryTest.java76
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionTest.java30
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosTestTest.java160
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBinaryTest.java137
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleLibraryTest.java30
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleTest.java31
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcFrameworkTest.java31
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcImportTest.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcLibraryTest.java900
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcProtoLibraryTest.java125
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java918
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibraryTest.java197
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleTest.java77
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkTest.java319
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcImportTest.java131
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcLibraryTest.java1542
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspectTest.java227
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java854
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProviderTest.java95
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java159
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java4852
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ObjcSkylarkTest.java1234
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/OnlyNeedsSourcesRuleType.java42
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/README.md13
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/RuleType.java145
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/TargetDeviceFamilyTest.java87
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/ValueTest.java75
-rw-r--r--src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java2
58 files changed, 38286 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MOCK_OSX_CROSSTOOL b/src/test/java/com/google/devtools/build/lib/packages/util/MOCK_OSX_CROSSTOOL
new file mode 100644
index 0000000000..b624413c80
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MOCK_OSX_CROSSTOOL
@@ -0,0 +1,15789 @@
+
+# This file was generated by generate_crosstool.py and any changes
+# made here will be overwritten the next time it's run. To
+# implement persistent changes, edit
+# MOCK_OSX_CROSSTOOL_generator.textpb
+# (for settings that affect many toolchains) or
+# MOCK_OSX_CROSSTOOL_template.textpb
+# (for settings that affect specific toolchains)
+# and rerun the update script.
+
+
+
+major_version: "1"
+minor_version: "0"
+default_target_cpu: "ios_x86_64"
+default_toolchain {
+ cpu: "darwin"
+ toolchain_identifier: "darwin_x86_64"
+}
+default_toolchain {
+ cpu: "darwin_x86_64"
+ toolchain_identifier: "darwin_x86_64"
+}
+default_toolchain {
+ cpu: "k8"
+ toolchain_identifier: "darwin_x86_64"
+}
+default_toolchain {
+ cpu: "ios_x86_64"
+ toolchain_identifier: "ios_x86_64"
+}
+default_toolchain {
+ cpu: "ios_i386"
+ toolchain_identifier: "ios_i386"
+}
+default_toolchain {
+ cpu: "ios_armv7"
+ toolchain_identifier: "ios_armv7"
+}
+default_toolchain {
+ cpu: "ios_arm64"
+ toolchain_identifier: "ios_arm64"
+}
+default_toolchain {
+ cpu: "watchos_i386"
+ toolchain_identifier: "watchos_i386"
+}
+default_toolchain {
+ cpu: "watchos_armv7k"
+ toolchain_identifier: "watchos_armv7k"
+}
+default_toolchain {
+ cpu: "tvos_x86_64"
+ toolchain_identifier: "tvos_x86_64"
+}
+default_toolchain {
+ cpu: "tvos_arm64"
+ toolchain_identifier: "tvos_arm64"
+}
+toolchain {
+ toolchain_identifier: "darwin_x86_64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "x86_64-apple-macosx"
+ target_cpu: "darwin_x86_64"
+ target_libc: "macosx"
+ compiler: "compiler"
+ abi_version: "darwin_x86_64"
+ abi_libc_version: "darwin_x86_64"
+ tool_path {
+ name: "ar"
+ path: "mac/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "mac/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "mac/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "mac/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "mac/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "mac/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "mac/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "mac/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_MACOSX"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_MACOSX"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mmacosx-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ }
+ }
+ }
+ feature {
+ name: "link_cocoa"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Cocoa"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "mac/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "mac/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "mac/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "darwin_x86_64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "x86_64-apple-macosx"
+ target_cpu: "k8"
+ target_libc: "macosx"
+ compiler: "compiler"
+ abi_version: "darwin_x86_64"
+ abi_libc_version: "darwin_x86_64"
+ tool_path {
+ name: "ar"
+ path: "mac/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "mac/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "mac/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "mac/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "mac/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "mac/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "mac/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "mac/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_MACOSX"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_MACOSX"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mmacosx-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ }
+ }
+ }
+ feature {
+ name: "link_cocoa"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Cocoa"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "mac/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "mac/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "mac/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "mac/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "mac/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "mac/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "ios_x86_64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "x86_64-apple-ios"
+ target_cpu: "ios_x86_64"
+ target_libc: "ios"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "iossim/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "iossim/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "iossim/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "iossim/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "iossim/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "iossim/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "iossim/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "iossim/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "x86_64-apple-ios"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "x86_64-apple-ios"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mios-simulator-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "apply_simulator_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fexceptions"
+ flag: "-fasm-blocks"
+ flag: "-fobjc-abi-version=2"
+ flag: "-fobjc-legacy-dispatch"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "iossim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "iossim/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "iossim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "watchos_i386"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "i386-apple-watchos"
+ target_cpu: "watchos_i386"
+ target_libc: "watchos"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "watchsim/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "watchsim/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "watchsim/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "watchsim/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "watchsim/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "watchsim/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "watchsim/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "watchsim/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "i386-apple-ios"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/WatchSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "i386-apple-watchos"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ flag: "-F%{sdk_framework_dir}"
+ flag: "-F%{platform_developer_framework_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mwatchos-simulator-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "apply_simulator_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fexceptions"
+ flag: "-fasm-blocks"
+ flag: "-fobjc-abi-version=2"
+ flag: "-fobjc-legacy-dispatch"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "watchsim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "i386"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "watchsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "watchsim/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch i386"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "watchsim/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "watchsim/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "watchsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "watchsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "watchsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "watchsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "watchsim/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "watchsim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "i386"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "tvos_x86_64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "x86_64-apple-tvos"
+ target_cpu: "tvos_x86_64"
+ target_libc: "tvos"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "tvsim/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "tvsim/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "tvsim/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "tvsim/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "tvsim/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "tvsim/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "tvsim/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "tvsim/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_TVOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "x86_64-apple-tvos"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ compiler_flag: "-DNS_BLOCK_ASSERTIONS=1"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "x86_64-apple-tvos"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_TVOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mtvos-simulator-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-lc++"
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ flag: "-target"
+ flag: "x86_64-apple-tvos"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-lc++"
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ flag: "-target"
+ flag: "x86_64-apple-tvos"
+ }
+ }
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "apply_simulator_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fexceptions"
+ flag: "-fasm-blocks"
+ flag: "-fobjc-abi-version=2"
+ flag: "-fobjc-legacy-dispatch"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "unfiltered_cxx_flags"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-no-canonical-prefixes"
+ flag: "-pthread"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "tvsim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "tvsim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "tvsim/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch x86_64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "tvsim/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "tvsim/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "tvsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "tvsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "tvsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "tvsim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "tvsim/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "tvsim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "x86_64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "ios_i386"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "i386-apple-ios"
+ target_cpu: "ios_i386"
+ target_libc: "ios"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "iossim/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "iossim/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "iossim/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "iossim/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "iossim/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "iossim/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "iossim/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "iossim/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "i386-apple-ios"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "i386-apple-ios"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mios-simulator-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "apply_simulator_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fexceptions"
+ flag: "-fasm-blocks"
+ flag: "-fobjc-abi-version=2"
+ flag: "-fobjc-legacy-dispatch"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "apply_simulator_compiler_flags"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "iossim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "i386"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "iossim/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch i386"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "iossim/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch i386"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "iossim/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "iossim/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "iossim/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "i386"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "ios_armv7"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "armv7-apple-ios"
+ target_cpu: "ios_armv7"
+ target_libc: "ios"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "ios/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "ios/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "ios/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "ios/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "ios/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "ios/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "ios/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "ios/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "armv7-apple-ios"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "armv7-apple-ios"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-miphoneos-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-bitcode_verify"
+ flag: "-Xlinker"
+ flag: "-bitcode_hide_symbols"
+ flag: "-Xlinker"
+ flag: "-bitcode_symbol_map"
+ flag: "-Xlinker"
+ flag: "%{bitcode_symbol_map_path}"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded_markers"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode-marker"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "ios/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "armv7"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "ios/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch armv7"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "ios/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "armv7"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "watchos_armv7k"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "armv7-apple-watchos"
+ target_cpu: "watchos_armv7k"
+ target_libc: "watchos"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "watchos/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "watchos/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "watchos/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "watchos/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "watchos/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "watchos/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "watchos/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "watchos/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "armv7-apple-watchos"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "armv7k-apple-watchos"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ flag: "-F%{sdk_framework_dir}"
+ flag: "-F%{platform_developer_framework_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mwatchos-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-bitcode_verify"
+ flag: "-Xlinker"
+ flag: "-bitcode_hide_symbols"
+ flag: "-Xlinker"
+ flag: "-bitcode_symbol_map"
+ flag: "-Xlinker"
+ flag: "%{bitcode_symbol_map_path}"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded_markers"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode-marker"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7k"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7k"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7k"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7k"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "watchos/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "armv7k"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "watchos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch armv7k"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "watchos/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch armv7k"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "watchos/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "watchos/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "watchos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "watchos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "watchos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "watchos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "watchos/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "watchos/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "armv7k"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "tvos_arm64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "arm64-apple-tvos"
+ target_cpu: "tvos_arm64"
+ target_libc: "tvos"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "tvos/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "tvos/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "tvos/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "tvos/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "tvos/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "tvos/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "tvos/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "tvos/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_TVOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "arm64-apple-tvos"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ compiler_flag: "-DNS_BLOCK_ASSERTIONS=1"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "arm64-apple-tvos"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_TVOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-mtvos-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-lc++"
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ flag: "-target"
+ flag: "arm64-apple-tvos"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-lc++"
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ flag: "-target"
+ flag: "arm64-apple-tvos"
+ }
+ }
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-bitcode_verify"
+ flag: "-Xlinker"
+ flag: "-bitcode_hide_symbols"
+ flag: "-Xlinker"
+ flag: "-bitcode_symbol_map"
+ flag: "-Xlinker"
+ flag: "%{bitcode_symbol_map_path}"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded_markers"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode-marker"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "unfiltered_cxx_flags"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-no-canonical-prefixes"
+ flag: "-pthread"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ implies: "unfiltered_cxx_flags"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "tvos/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "arm64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "tvos/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "tvos/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch arm64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "tvos/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "tvos/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "tvos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "tvos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "tvos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "tvos/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "tvos/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "tvos/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "arm64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
+toolchain {
+ toolchain_identifier: "ios_arm64"
+ host_system_name: "x86_64-apple-macosx"
+ target_system_name: "arm64-apple-ios"
+ target_cpu: "ios_arm64"
+ target_libc: "ios"
+ compiler: "compiler"
+ abi_version: "local"
+ abi_libc_version: "local"
+ tool_path {
+ name: "ar"
+ path: "ios/ar_wrapper"
+ }
+ tool_path {
+ name: "compat-ld"
+ path: "ios/ld"
+ }
+ tool_path {
+ name: "cpp"
+ path: "ios/cpp"
+ }
+ tool_path {
+ name: "gcov"
+ path: "ios/gcov"
+ }
+ tool_path {
+ name: "gcc"
+ path: "ios/clang"
+ }
+ tool_path {
+ name: "ld"
+ path: "ios/ld"
+ }
+ tool_path {
+ name: "nm"
+ path: "ios/nm"
+ }
+ tool_path {
+ name: "strip"
+ path: "ios/strip"
+ }
+ tool_path {
+ name: "dwp"
+ path: "/usr/bin/dwp"
+ }
+ tool_path {
+ name: "objdump"
+ path: "/usr/bin/objdump"
+ }
+ needsPic: false
+ compiler_flag: "-DCOMPILER_GCC3"
+ compiler_flag: "-DCOMPILER_GCC4"
+ compiler_flag: "-Dunix"
+ compiler_flag: "-DOS_IOS"
+ compiler_flag: "-DU_HAVE_NL_LANGINFO_CODESET=0"
+ compiler_flag: "-DU_HAVE_STD_STRING"
+ compiler_flag: "-D__STDC_FORMAT_MACROS"
+ cxx_flag: "-std=gnu++11"
+ cxx_flag: "-stdlib=libc++"
+ linker_flag: "-lc++"
+ linker_flag: "-target"
+ linker_flag: "arm64-apple-ios"
+ compilation_mode_flags {
+ mode: FASTBUILD
+ compiler_flag: "-O0"
+ compiler_flag: "-DDEBUG"
+ }
+ compilation_mode_flags {
+ mode: OPT
+ compiler_flag: "-Os"
+ compiler_flag: "-DNDEBUG"
+ }
+ compilation_mode_flags {
+ mode: DBG
+ compiler_flag: "-g"
+ compiler_flag: "-DDEBUG"
+ }
+ linking_mode_flags {
+ mode: DYNAMIC
+ }
+ make_variable {
+ name: "STACK_FRAME_UNLIMITED"
+ value: "-Wframe-larger-than=100000000 -Wno-vla"
+ }
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/"
+ cxx_builtin_include_directory: "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/Applications/Xcode_8.2.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs"
+ cxx_builtin_include_directory: "/usr/include"
+ builtin_sysroot: ""
+ unfiltered_cxx_flag: "-no-canonical-prefixes"
+ unfiltered_cxx_flag: "-pthread"
+ unfiltered_cxx_flag: "-target"
+ unfiltered_cxx_flag: "arm64-apple-ios"
+ supports_normalizing_ar: false
+ default_python_version: "python2.7"
+ feature {
+ name: "no_legacy_features"
+ }
+ feature {
+ name: "fastbuild"
+ implies: "fastbuild_only_flag"
+ }
+ feature {
+ name: "opt"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g0"
+ }
+ with_feature {
+ feature: "no_generate_debug_symbols"
+ }
+ }
+ implies: "opt_only_flag"
+ }
+ feature {
+ name: "dbg"
+ implies: "dbg_only_flag"
+ }
+ feature {
+ name: "compile_all_modules"
+ }
+ feature {
+ name: "exclude_private_headers_in_module_maps"
+ }
+ feature {
+ name: "has_configured_linker_path"
+ }
+ feature {
+ name: "only_doth_headers_in_module_maps"
+ }
+ feature {
+ name: "is_not_test_target"
+ }
+ feature {
+ name: "generate_dsym_file"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "DSYM_HINT_LINKED_BINARY=%{linked_binary}"
+ flag: "DSYM_HINT_DSYM_PATH=%{dsym_path}"
+ flag: "DSYM_HINT_DSYM_BUNDLE_ZIP=%{dsym_bundle_zip}"
+ }
+ }
+ }
+ feature {
+ name: "no_generate_debug_symbols"
+ }
+ feature {
+ name: "generate_linkmap"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker -map"
+ flag: "-Xlinker %{linkmap_exec_path}"
+ }
+ }
+ }
+ feature {
+ name: "objc_actions"
+ implies: "objc-compile"
+ implies: "objc++-compile"
+ implies: "objc-fully-link"
+ implies: "objc-archive"
+ implies: "objc-executable"
+ implies: "objc++-executable"
+ implies: "assemble"
+ implies: "preprocess-assemble"
+ implies: "c-compile"
+ implies: "c++-compile"
+ implies: "c++-link-static-library"
+ implies: "c++-link-pic-static-library"
+ implies: "c++-link-interface-dynamic-library"
+ implies: "c++-link-dynamic-library"
+ implies: "c++-link-alwayslink-static-library"
+ implies: "c++-link-alwayslink-pic-static-library"
+ implies: "c++-link-executable"
+ }
+ feature {
+ name: "strip_debug_symbols"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-interface-dynamic-library"
+ flag_group {
+ flag: "-Wl,-S"
+ expand_if_all_available: "strip_debug_symbols"
+ }
+ }
+ }
+ feature {
+ name: "symbol_counts"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,--print-symbol-counts=%{symbol_counts_output}"
+ }
+ expand_if_all_available: "symbol_counts_output"
+ }
+ }
+ feature {
+ name: "shared_flag"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-shared"
+ }
+ }
+ }
+ feature {
+ name: "linkstamps"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "%{linkstamp_paths}"
+ iterate_over: "linkstamp_paths"
+ }
+ expand_if_all_available: "linkstamp_paths"
+ }
+ }
+ feature {
+ name: "output_execpath_flags"
+ flag_set {
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-o"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "output_execpath_flags_executable"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-o"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "/dev/null"
+ flag: "-MMD"
+ flag: "-MF"
+ }
+ expand_if_all_available: "skip_mostly_static"
+ expand_if_all_available: "output_execpath"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "global_whole_archive_open"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-all_load"
+ }
+ expand_if_all_available: "global_whole_archive"
+ }
+ }
+ feature {
+ name: "runtime_root_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}"
+ iterate_over: "runtime_library_search_directories"
+ }
+ expand_if_all_available: "runtime_library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_flags}"
+ iterate_over: "runtime_root_flags"
+ }
+ expand_if_all_available: "runtime_root_flags"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{runtime_root_entries}"
+ iterate_over: "runtime_root_entries"
+ }
+ expand_if_all_available: "runtime_root_entries"
+ }
+ }
+ feature {
+ name: "archiver_flags"
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "rcs"
+ flag: "%{output_execpath}"
+ }
+ expand_if_all_available: "output_execpath"
+ }
+ }
+ feature {
+ name: "input_param_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-L%{library_search_directories}"
+ iterate_over: "library_search_directories"
+ }
+ expand_if_all_available: "library_search_directories"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{libopts}"
+ iterate_over: "libopts"
+ }
+ expand_if_all_available: "libopts"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "-Wl,-force_load,%{whole_archive_linker_params}"
+ iterate_over: "whole_archive_linker_params"
+ }
+ expand_if_all_available: "whole_archive_linker_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "%{linker_input_params}"
+ iterate_over: "linker_input_params"
+ }
+ expand_if_all_available: "linker_input_params"
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag_group {
+ flag: "-Wl,--start-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.object_files}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.object_files}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ iterate_over: "libraries_to_link.object_files"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag: "-Wl,--end-lib"
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file_group"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "object_file"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "interface_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "static_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "dynamic_library"
+ }
+ }
+ flag_group {
+ flag_group {
+ flag: "-l:%{libraries_to_link.name}"
+ expand_if_false: "libraries_to_link.is_whole_archive"
+ }
+ flag_group {
+ flag: "-Wl,-force_load,-l:%{libraries_to_link.name}"
+ expand_if_true: "libraries_to_link.is_whole_archive"
+ }
+ expand_if_equal {
+ variable: "libraries_to_link.type"
+ value: "versioned_dynamic_library"
+ }
+ }
+ iterate_over: "libraries_to_link"
+ }
+ expand_if_all_available: "libraries_to_link"
+ }
+ }
+ feature {
+ name: "force_pic_flags"
+ flag_set {
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-pie"
+ }
+ expand_if_all_available: "force_pic"
+ }
+ }
+ feature {
+ name: "pch"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-include"
+ flag: "%{pch_file}"
+ }
+ }
+ }
+ feature {
+ name: "module_maps"
+ }
+ feature {
+ name: "use_objc_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-name=%{module_name}"
+ flag: "-iquote"
+ flag: "%{module_maps_dir}"
+ flag: "-fmodules-cache-path=%{modules_cache_path}"
+ }
+ }
+ }
+ feature {
+ name: "no_enable_modules"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fmodule-maps"
+ }
+ }
+ requires {
+ feature: "use_objc_modules"
+ }
+ }
+ feature {
+ name: "apply_default_warnings"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-Wshorten-64-to-32"
+ flag: "-Wbool-conversion"
+ flag: "-Wconstant-conversion"
+ flag: "-Wduplicate-method-match"
+ flag: "-Wempty-body"
+ flag: "-Wenum-conversion"
+ flag: "-Wint-conversion"
+ flag: "-Wunreachable-code"
+ flag: "-Wmismatched-return-types"
+ flag: "-Wundeclared-selector"
+ flag: "-Wuninitialized"
+ flag: "-Wunused-function"
+ flag: "-Wunused-variable"
+ }
+ }
+ }
+ feature {
+ name: "preprocessor_defines"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-D%{preprocessor_defines}"
+ iterate_over: "preprocessor_defines"
+ }
+ }
+ }
+ feature {
+ name: "framework_paths"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-F%{framework_paths}"
+ iterate_over: "framework_paths"
+ }
+ }
+ }
+ feature {
+ name: "apply_default_compiler_flags"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-DOS_IOS"
+ }
+ }
+ }
+ feature {
+ name: "include_system_dirs"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "assemble"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-isysroot"
+ flag: "%{sdk_dir}"
+ }
+ }
+ }
+ feature {
+ name: "objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fobjc-arc"
+ }
+ expand_if_all_available: "objc_arc"
+ }
+ }
+ feature {
+ name: "no_objc_arc"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fno-objc-arc"
+ }
+ expand_if_all_available: "no_objc_arc"
+ }
+ }
+ feature {
+ name: "apple_env"
+ env_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-archive"
+ action: "objc-fully-link"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ env_entry {
+ key: "XCODE_VERSION_OVERRIDE"
+ value: "%{xcode_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_VERSION_OVERRIDE"
+ value: "%{apple_sdk_version_override_value}"
+ }
+ env_entry {
+ key: "APPLE_SDK_PLATFORM"
+ value: "%{apple_sdk_platform_value}"
+ }
+ }
+ }
+ feature {
+ name: "legacy_link_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "%{legacy_link_flags}"
+ iterate_over: "legacy_link_flags"
+ }
+ expand_if_all_available: "legacy_link_flags"
+ }
+ }
+ feature {
+ name: "linker_param_file"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-Wl,@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ flag_set {
+ action: "c++-link-static-library"
+ action: "c++-link-alwayslink-static-library"
+ action: "c++-link-pic-static-library"
+ action: "c++-link-alwayslink-pic-static-library"
+ flag_group {
+ flag: "@%{linker_param_file}"
+ }
+ expand_if_all_available: "linker_param_file"
+ }
+ }
+ feature {
+ name: "version_min"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-miphoneos-version-min=%{version_min}"
+ }
+ }
+ }
+ feature {
+ name: "dead_strip"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-dead_strip"
+ flag: "-no_dead_strip_inits_and_terms"
+ }
+ with_feature {
+ feature: "is_not_test_target"
+ }
+ }
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-g"
+ }
+ }
+ requires {
+ feature: "opt"
+ }
+ }
+ feature {
+ name: "dependency_file"
+ flag_set {
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "c++-header-preprocessing"
+ action: "c++-header-parsing"
+ flag_group {
+ flag: "-MD"
+ flag: "-MF"
+ flag: "%{dependency_file}"
+ }
+ expand_if_all_available: "dependency_file"
+ }
+ }
+ feature {
+ name: "random_seed"
+ flag_set {
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ flag_group {
+ flag: "-frandom-seed=%{output_file}"
+ }
+ }
+ }
+ feature {
+ name: "pic"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "c++-module-compile"
+ action: "preprocess-assemble"
+ flag_group {
+ flag: "-fPIC"
+ }
+ expand_if_all_available: "pic"
+ }
+ }
+ feature {
+ name: "per_object_debug_info"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-codegen"
+ action: "assemble"
+ action: "preprocess-assemble"
+ action: "lto-backend"
+ flag_group {
+ flag: "-gsplit-dwarf"
+ }
+ expand_if_all_available: "per_object_debug_info_file"
+ }
+ }
+ feature {
+ name: "include_paths"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-header-parsing"
+ action: "c++-header-preprocessing"
+ action: "c++-module-compile"
+ action: "clif-match"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-iquote"
+ flag: "%{quote_include_paths}"
+ iterate_over: "quote_include_paths"
+ }
+ flag_group {
+ flag: "-I%{include_paths}"
+ iterate_over: "include_paths"
+ }
+ flag_group {
+ flag: "-isystem"
+ flag: "%{system_include_paths}"
+ iterate_over: "system_include_paths"
+ }
+ }
+ }
+ feature {
+ name: "fdo_instrument"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-fprofile-generate=%{fdo_instrument_path}"
+ flag: "-fno-data-sections"
+ }
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "fdo_optimize"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fprofile-use=%{fdo_profile_path}"
+ flag: "-Xclang-only=-Wno-profile-instr-unprofiled"
+ flag: "-Xclang-only=-Wno-profile-instr-out-of-date"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "autofdo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fauto-profile=%{fdo_profile_path}"
+ flag: "-fprofile-correction"
+ }
+ expand_if_all_available: "fdo_profile_path"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "lipo"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ flag_group {
+ flag: "-fripa"
+ }
+ }
+ requires {
+ feature: "autofdo"
+ }
+ requires {
+ feature: "fdo_optimize"
+ }
+ requires {
+ feature: "fdo_instrument"
+ }
+ }
+ feature {
+ name: "asan"
+ flag_set {
+ action: "c-compile"
+ action: "c++-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-O1"
+ flag: "-gmlt"
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fno-sanitize-recover=all"
+ flag: "-DHEAPCHECK_DISABLE"
+ flag: "-DADDRESS_SANITIZER"
+ flag: "-D_GLIBCXX_ADDRESS_SANITIZER_ANNOTATIONS"
+ flag: "-fno-omit-frame-pointer"
+ }
+ }
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,return,returns-nonnull-attribute,shift-exponent,unreachable,vla-bound"
+ flag: "-fsanitize-link-c++-runtime"
+ }
+ }
+ }
+ feature {
+ name: "coverage"
+ }
+ feature {
+ name: "llvm_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ flag: "-fcoverage-mapping"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-instr-generate"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "gcc_coverage_map_format"
+ flag_set {
+ action: "preprocess-assemble"
+ action: "c-compile"
+ action: "c++-compile"
+ action: "c++-module-compile"
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fprofile-arcs"
+ flag: "-ftest-coverage"
+ flag: "-g"
+ }
+ }
+ flag_set {
+ action: "c++-link-interface-dynamic-library"
+ action: "c++-link-dynamic-library"
+ action: "c++-link-executable"
+ flag_group {
+ flag: "-lgcov"
+ }
+ }
+ requires {
+ feature: "coverage"
+ }
+ provides: "profile"
+ }
+ feature {
+ name: "apply_implicit_frameworks"
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-framework Foundation"
+ flag: "-framework UIKit"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode"
+ }
+ }
+ flag_set {
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-bitcode_verify"
+ flag: "-Xlinker"
+ flag: "-bitcode_hide_symbols"
+ flag: "-Xlinker"
+ flag: "-bitcode_symbol_map"
+ flag: "-Xlinker"
+ flag: "%{bitcode_symbol_map_path}"
+ }
+ }
+ }
+ feature {
+ name: "bitcode_embedded_markers"
+ flag_set {
+ action: "objc-compile"
+ action: "objc++-compile"
+ action: "objc-executable"
+ action: "objc++-executable"
+ flag_group {
+ flag: "-fembed-bitcode-marker"
+ }
+ }
+ }
+ feature {
+ name: "cpp_linker_flags"
+ flag_set {
+ action: "c++-link-executable"
+ action: "c++-link-dynamic-library"
+ flag_group {
+ flag: "-undefined"
+ flag: "dynamic_lookup"
+ }
+ }
+ }
+ feature {
+ name: "dbg_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--DBG_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "fastbuild_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--FASTBUILD_ONLY_FLAG"
+ }
+ }
+ }
+ feature {
+ name: "opt_only_flag"
+ flag_set {
+ action: "objc-compile"
+ flag_group {
+ flag: "--OPT_ONLY_FLAG"
+ }
+ }
+ }
+ action_config {
+ config_name: "c-compile"
+ action_name: "c-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-compile"
+ action_name: "c++-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-module-compile"
+ action_name: "c++-module-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-parsing"
+ action_name: "c++-header-parsing"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-header-preprocessing"
+ action_name: "c++-header-preprocessing"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-compile"
+ action_name: "objc-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ }
+ implies: "objc_actions"
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc++-compile"
+ action_name: "objc++-compile"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ }
+ implies: "apply_default_compiler_flags"
+ implies: "apply_default_warnings"
+ implies: "framework_paths"
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "assemble"
+ action_name: "assemble"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "include_system_dirs"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "preprocess-assemble"
+ action_name: "preprocess-assemble"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ implies: "preprocessor_defines"
+ implies: "include_system_dirs"
+ implies: "version_min"
+ implies: "objc_arc"
+ implies: "no_objc_arc"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-archive"
+ action_name: "objc-archive"
+ tool {
+ tool_path: "ios/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-filelist"
+ flag: "%{obj_list_path}"
+ flag: "-arch_only"
+ flag: "arm64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{archive_path}"
+ }
+ }
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-executable"
+ action_name: "objc-executable"
+ tool {
+ tool_path: "ios/wrapped_clang"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-arch arm64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "objc++-executable"
+ action_name: "objc++-executable"
+ tool {
+ tool_path: "ios/wrapped_clang++"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-stdlib=libc++"
+ flag: "-std=gnu++11"
+ }
+ flag_group {
+ flag: "-arch arm64"
+ }
+ flag_group {
+ flag: "-Xlinker"
+ flag: "-objc_abi_version"
+ flag: "-Xlinker"
+ flag: "2"
+ flag: "-Xlinker"
+ flag: "-rpath"
+ flag: "-Xlinker"
+ flag: "@executable_path/Frameworks"
+ flag: "-fobjc-link-runtime"
+ flag: "-ObjC"
+ }
+ flag_group {
+ flag: "-framework %{framework_names}"
+ iterate_over: "framework_names"
+ }
+ flag_group {
+ flag: "-weak_framework %{weak_framework_names}"
+ iterate_over: "weak_framework_names"
+ }
+ flag_group {
+ flag: "-l%{library_names}"
+ iterate_over: "library_names"
+ }
+ flag_group {
+ flag: "-filelist %{filelist}"
+ }
+ flag_group {
+ flag: "-o %{linked_binary}"
+ }
+ flag_group {
+ flag: "-force_load %{force_load_exec_paths}"
+ iterate_over: "force_load_exec_paths"
+ }
+ flag_group {
+ flag: "%{dep_linkopts}"
+ iterate_over: "dep_linkopts"
+ }
+ flag_group {
+ flag: "-Wl,%{attr_linkopts}"
+ iterate_over: "attr_linkopts"
+ }
+ }
+ implies: "include_system_dirs"
+ implies: "framework_paths"
+ implies: "version_min"
+ implies: "legacy_link_flags"
+ implies: "apple_env"
+ implies: "apply_implicit_frameworks"
+ }
+ action_config {
+ config_name: "c++-link-executable"
+ action_name: "c++-link-executable"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "symbol_counts"
+ implies: "linkstamps"
+ implies: "output_execpath_flags_executable"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "force_pic_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-dynamic-library"
+ action_name: "c++-link-dynamic-library"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "has_configured_linker_path"
+ implies: "symbol_counts"
+ implies: "shared_flag"
+ implies: "linkstamps"
+ implies: "output_execpath_flags"
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "input_param_flags"
+ implies: "legacy_link_flags"
+ implies: "strip_debug_symbols"
+ implies: "linker_param_file"
+ implies: "version_min"
+ implies: "apple_env"
+ implies: "cpp_linker_flags"
+ }
+ action_config {
+ config_name: "c++-link-static-library"
+ action_name: "c++-link-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-static-library"
+ action_name: "c++-link-alwayslink-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-pic-static-library"
+ action_name: "c++-link-pic-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-alwayslink-pic-static-library"
+ action_name: "c++-link-alwayslink-pic-static-library"
+ tool {
+ tool_path: "ios/ar_wrapper"
+ }
+ implies: "global_whole_archive_open"
+ implies: "runtime_root_flags"
+ implies: "archiver_flags"
+ implies: "input_param_flags"
+ implies: "linker_param_file"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "c++-link-interface-dynamic-library"
+ action_name: "c++-link-interface-dynamic-library"
+ tool {
+ tool_path: "ios/clang"
+ }
+ implies: "strip_debug_symbols"
+ implies: "apple_env"
+ }
+ action_config {
+ config_name: "objc-fully-link"
+ action_name: "objc-fully-link"
+ tool {
+ tool_path: "ios/libtool"
+ execution_requirement: "requires-darwin"
+ }
+ flag_set {
+ flag_group {
+ flag: "-static"
+ flag: "-arch_only"
+ flag: "arm64"
+ flag: "-syslibroot"
+ flag: "%{sdk_dir}"
+ flag: "-o"
+ flag: "%{fully_linked_archive_path}"
+ }
+ flag_group {
+ flag: "%{objc_library_exec_paths}"
+ iterate_over: "objc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{cc_library_exec_paths}"
+ iterate_over: "cc_library_exec_paths"
+ }
+ flag_group {
+ flag: "%{imported_library_exec_paths}"
+ iterate_over: "imported_library_exec_paths"
+ }
+ }
+ implies: "apple_env"
+ }
+ cc_target_os: "apple"
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockJ2ObjcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockJ2ObjcSupport.java
new file mode 100644
index 0000000000..6079543e01
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockJ2ObjcSupport.java
@@ -0,0 +1,101 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.packages.util;
+
+import java.io.IOException;
+
+/**
+ * Creates mock BUILD files required for J2Objc.
+ */
+public final class MockJ2ObjcSupport {
+ /**
+ * Setup the support for building with J2ObjC.
+ */
+ public static void setup(MockToolsConfig config) throws IOException {
+ config.create("third_party/java/j2objc/jre_emul.jar");
+ config.create("third_party/java/j2objc/jre.h");
+ config.create("third_party/java/j2objc/jre.m");
+ config.create("third_party/java/j2objc/runtime.h");
+ config.create("third_party/java/j2objc/runtime.m");
+ config.create("third_party/java/j2objc/proto_plugin_binary");
+ config.create("third_party/java/j2objc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "licenses(['notice'])",
+ "",
+ "exports_files(['jre_emul.jar'])",
+ "",
+ "objc_library(",
+ " name = 'jre_emul_lib',",
+ " hdrs = ['jre_emul.h'],",
+ " srcs = ['jre_emul.m'],",
+ " deps = [':jre_core_lib', ':jre_io_lib'],",
+ " tags = ['j2objc_jre_lib'])",
+ "",
+ "objc_library(",
+ " name = 'jre_core_lib',",
+ " hdrs = ['jre_core.h'],",
+ " srcs = ['jre_core.m'],",
+ " tags = ['j2objc_jre_lib'])",
+ "",
+ "objc_library(",
+ " name = 'jre_io_lib',",
+ " hdrs = ['jre_io.h'],",
+ " srcs = ['jre_io.m'],",
+ " deps = [':jre_core_lib'],",
+ " tags = ['j2objc_jre_lib'])",
+ "",
+ "objc_library(",
+ " name = 'proto_runtime',",
+ " hdrs = ['runtime.h'],",
+ " srcs = ['runtime.m'])",
+ "",
+ "filegroup(",
+ " name = 'proto_plugin',",
+ " srcs = ['proto_plugin_binary'])");
+
+ config.create("tools/j2objc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "licenses(['notice'])",
+ "filegroup(",
+ " name = 'j2objc_wrapper',",
+ " srcs = ['j2objc_wrapper.py'])",
+ "filegroup(",
+ " name = 'j2objc_header_map',",
+ " srcs = ['j2objc_header_map.py'])",
+ "exports_files(['j2objc_deploy.jar'])",
+ "filegroup(",
+ " name = 'j2objc_proto_blacklist',",
+ " srcs = ['//tools/j2objc/proto:blacklisted.proto'])");
+
+ config.create("tools/j2objc/proto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_library(name = 'blacklisted',",
+ " srcs = ['blacklisted.proto'],",
+ " java_api_version = 2,",
+ " j2objc_api_version = 1)");
+
+ config.create("tools/j2objc/proto/blacklisted.proto");
+
+ if (config.isRealFileSystem()) {
+ config.linkTool("tools/j2objc/j2objc_deploy.jar");
+ config.linkTool("tools/j2objc/j2objc_wrapper.py");
+ config.linkTool("tools/j2objc/j2objc_header_map.py");
+ } else {
+ config.create("tools/j2objc/j2objc_deploy.jar");
+ config.create("tools/j2objc/j2objc_wrapper.py");
+ config.create("tools/j2objc/j2objc_header_map.py");
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java
new file mode 100644
index 0000000000..4cbf95a631
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockObjcSupport.java
@@ -0,0 +1,300 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.packages.util;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.lib.testutil.TestConstants;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig;
+import com.google.devtools.build.lib.view.config.crosstool.CrosstoolConfig.CToolchain;
+import com.google.protobuf.TextFormat;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Creates mock BUILD files required for the objc rules.
+ */
+public final class MockObjcSupport {
+
+ private static final ImmutableList<String> DEFAULT_OSX_CROSSTOOL_DEPS_DIRS =
+ ImmutableList.of("third_party/bazel/tools/osx/crosstool");
+ private static final String DEFAULT_OSX_CROSSTOOL_DIR = "tools/osx/crosstool";
+ private static final String MOCK_OSX_CROSSTOOL_FILE =
+ "com/google/devtools/build/lib/packages/util/MOCK_OSX_CROSSTOOL";
+ /**
+ * The build label for the mock OSX crosstool configuration.
+ */
+ public static final String DEFAULT_OSX_CROSSTOOL =
+ "//" + DEFAULT_OSX_CROSSTOOL_DIR + ":crosstool";
+
+ public static final String DEFAULT_XCODE_VERSION = "7.3.1";
+ public static final String DEFAULT_IOS_SDK_VERSION = "8.4";
+
+ /**
+ * Sets up the support for building ObjC.
+ * Any partial toolchain line will be merged into every toolchain stanza in the crosstool
+ * loaded from file.
+ */
+ public static void setup(
+ MockToolsConfig config, String... partialToolchainLines) throws IOException {
+ for (String tool :
+ ImmutableSet.of(
+ "actoolwrapper",
+ "bundlemerge",
+ "objc_dummy.mm",
+ "environment_plist.sh",
+ "gcov",
+ "ibtoolwrapper",
+ "momcwrapper",
+ "plmerge",
+ "realpath",
+ "swiftstdlibtoolwrapper",
+ "testrunner",
+ "xcrunwrapper",
+ "mcov",
+ "libtool")) {
+ config.create("tools/objc/" + tool);
+ }
+ config.create(
+ "tools/objc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "exports_files(glob(['**']))",
+ "filegroup(name = 'default_provisioning_profile', srcs = ['foo.mobileprovision'])",
+ "filegroup(name = 'compile_protos', srcs = ['compile_protos.py'])",
+ "filegroup(name = 'protobuf_compiler_wrapper', srcs = ['protobuf_compiler_wrapper.sh'])",
+ "filegroup(name = 'protobuf_compiler', srcs = ['protobuf_compiler_helper.py'])",
+ "filegroup(",
+ " name = 'protobuf_compiler_support',",
+ " srcs = ['proto_support', 'protobuf_compiler_helper.py'],",
+ ")",
+ "filegroup(name = 'xctest_infoplist', srcs = ['xctest.plist'])",
+ "filegroup(name = 'j2objc_dead_code_pruner', srcs = ['j2objc_dead_code_pruner.py'])",
+ "ios_application(name = 'xctest_app', binary = ':xctest_appbin')",
+ "objc_binary(name = 'xctest_appbin', srcs = ['objc_dummy.mm'])",
+ "filegroup(",
+ " name = 'protobuf_well_known_types',",
+ " srcs = ['//objcproto:well_known_type.proto'],",
+ ")",
+ "xcode_config(name = 'host_xcodes', default = ':version7_3_1')",
+ "xcode_version(",
+ " name = 'version7_3_1',",
+ " version = '" + DEFAULT_XCODE_VERSION + "',",
+ " default_ios_sdk_version = \"" + DEFAULT_IOS_SDK_VERSION + "\",",
+ ")",
+ "objc_library(name = 'dummy_lib', srcs = ['objc_dummy.mm'])");
+ config.create("tools/objc/foo.mobileprovision", "No such luck");
+ config.create("tools/objc/compile_protos.py");
+ config.create("tools/objc/xctest.plist");
+ config.create("tools/objc/proto_support");
+ config.create("tools/objc/ios_runner.sh.mac_template");
+ config.create("tools/objc/j2objc_dead_code_pruner.py");
+ config.create("tools/objc/header_scanner");
+ createCrosstoolPackage(config, partialToolchainLines);
+ }
+
+ /**
+ * Sets up mock IOS test support.
+ */
+ public static void setupIosTest(MockToolsConfig config) throws IOException {
+ config.create("tools/objc/precomp_testrunner_deploy.jar");
+ config.create("tools/objc/StdRedirect.dylib");
+ createMemleaksSim(config);
+ config.create("tools/objc/ios_test.sh.bazel_template");
+ }
+
+ /**
+ * Sets up mock IOS simulated device support.
+ */
+ public static void setupIosSimDevice(MockToolsConfig config) throws IOException {
+ config.create(
+ "tools/objc/sim_devices/BUILD",
+ "ios_device(",
+ " name = 'default',",
+ " ios_version = '9.8',",
+ " type = 'iChimpanzee',",
+ ")");
+ }
+
+ private static void createMemleaksSim(MockToolsConfig config) throws IOException {
+ config.create("tools/objc/memleaks/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "objc_library(",
+ " name = 'memleaks',",
+ " srcs = ['memleaks.m'],",
+ ")");
+
+ config.create("tools/objc/memleaks/libmemleaks.a");
+ config.create("tools/objc/memleaks_plugin");
+ }
+
+ /**
+ * Sets up the support for building protocol buffers for ObjC.
+ */
+ public static void setupObjcProto(MockToolsConfig config) throws IOException {
+ config.overwrite(
+ "WORKSPACE",
+ TestConstants.WORKSPACE_CONTENT + "bind(",
+ " name = 'objc_proto_lib',",
+ " actual = '//objcproto:ProtocolBuffers_lib',",
+ ")",
+ "bind(",
+ " name = 'objc_protobuf_lib',",
+ " actual = '//objcproto:protobuf_lib',",
+ ")");
+
+ config.create(
+ "objcproto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "objc_library(",
+ " name = 'ProtocolBuffers_lib',",
+ " srcs = ['empty.m'],",
+ ")",
+ "objc_library(",
+ " name = 'protobuf_lib',",
+ " srcs = ['empty.m'],",
+ " hdrs = ['include/header.h'],",
+ " includes = ['include'],",
+ ")",
+ "exports_files(['well_known_type.proto'])",
+ "proto_library(",
+ " name = 'well_known_type_proto',",
+ " srcs = ['well_known_type.proto'],",
+ ")");
+ config.create("objcproto/empty.m");
+ config.create("objcproto/empty.cc");
+ config.create("objcproto/well_known_type.proto");
+ }
+
+ /**
+ * Test setup method which creates a package containing the mock OSX crosstool. The crosstool
+ * will be available at {@link #DEFAULT_OSX_CROSSTOOL}.
+ */
+ public static void createCrosstoolPackage(
+ MockToolsConfig config, String... partialToolchainLines) throws IOException {
+ if (config.isRealFileSystem()) {
+ for (String depDir : DEFAULT_OSX_CROSSTOOL_DEPS_DIRS) {
+ config.linkTools(depDir);
+ }
+ config.linkTools(DEFAULT_OSX_CROSSTOOL_DIR);
+ } else {
+ // Read the crosstool file into crosstoolString.
+ InputStream crosstoolFileStream =
+ MockObjcSupport.class.getClassLoader().getResourceAsStream(MOCK_OSX_CROSSTOOL_FILE);
+ String crosstoolString =
+ new String(ByteStreams.toByteArray(crosstoolFileStream), StandardCharsets.UTF_8);
+
+ // Create a config builder and merge the crosstoolString into it.
+ CrosstoolConfig.CrosstoolRelease.Builder configBuilder =
+ CrosstoolConfig.CrosstoolRelease.newBuilder();
+ TextFormat.merge(crosstoolString, configBuilder);
+
+ // Merge partialToolchainLines into the builder.
+ CToolchain.Builder toolchainBuilder = CToolchain.newBuilder();
+ TextFormat.merge(Joiner.on("\n").join(partialToolchainLines), toolchainBuilder);
+ CToolchain partialToolchain = toolchainBuilder.buildPartial();
+ for (CToolchain.Builder partialToolchainBuilder :
+ configBuilder.getToolchainBuilderList()) {
+ partialToolchainBuilder.mergeFrom(partialToolchain);
+ }
+
+ // Extract the modified crosstoolString and set things up so
+ // that tests can use a crosstool parsed from it.
+ crosstoolString = TextFormat.printToString(configBuilder);
+ config.overwrite(DEFAULT_OSX_CROSSTOOL_DIR + "/CROSSTOOL", crosstoolString);
+
+ // Create special lines specifying the compiler map entry for
+ // each toolchain.
+ StringBuilder compilerMap = new StringBuilder();
+ for (CToolchain toolchain : configBuilder.build().getToolchainList()) {
+ compilerMap.append(String.format("'%s|%s': ':cc-compiler-%s',\n",
+ toolchain.getTargetCpu(), toolchain.getCompiler(), toolchain.getTargetCpu()));
+ }
+
+ // Create the test BUILD file.
+ Builder<String> crosstoolBuild =
+ ImmutableList.<String>builder()
+ .add(
+ "exports_files(glob(['**']))",
+ "cc_toolchain_suite(",
+ " name = 'crosstool',",
+ " toolchains = { " + compilerMap + " },",
+ ")",
+ "",
+ "cc_library(",
+ " name = 'custom_malloc',",
+ ")",
+ "",
+ "filegroup(",
+ " name = 'empty',",
+ " srcs = [],",
+ ")",
+ "",
+ "filegroup(",
+ " name = 'link',",
+ " srcs = [",
+ " 'ar',",
+ " 'libempty.a',",
+ " '//tools/objc:libtool'",
+ " ],",
+ ")");
+
+ for (String arch :
+ ImmutableList.of(
+ "ios_x86_64",
+ "ios_i386",
+ "ios_armv7",
+ "ios_arm64",
+ "darwin_x86_64",
+ "watchos_i386",
+ "watchos_armv7k",
+ "tvos_x86_64",
+ "tvos_arm64",
+ // TODO(b/36471772): Remove 'k8' once unit tests do not require a host configuration
+ // transition from the apple crosstool configuration.
+ "k8")) {
+ crosstoolBuild.add(
+ "apple_cc_toolchain(",
+ " name = 'cc-compiler-" + arch + "',",
+ " all_files = ':empty',",
+ " compiler_files = ':empty',",
+ " cpu = 'ios',",
+ " dwp_files = ':empty',",
+ " dynamic_runtime_libs = [':empty'],",
+ " linker_files = ':link',",
+ " objcopy_files = ':empty',",
+ " static_runtime_libs = [':empty'],",
+ " strip_files = ':empty',",
+ " supports_param_files = 0,",
+ ")");
+ }
+
+ config.create(DEFAULT_OSX_CROSSTOOL_DIR + "/BUILD",
+ Joiner.on("\n").join(crosstoolBuild.build()));
+ }
+ }
+
+ /** Test setup for the Apple SDK targets that are used in tests. */
+ public static void setupAppleSdks(MockToolsConfig config) throws IOException {
+ config.create(
+ "third_party/apple_sdks/BUILD",
+ "package(default_visibility=['//visibility:public'])\n"
+ + "licenses([\"notice\"])\n"
+ + "filegroup(name = \"apple_sdk_compile\")");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java b/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java
new file mode 100644
index 0000000000..0f815e2673
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/MockProtoSupport.java
@@ -0,0 +1,202 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.packages.util;
+
+import java.io.IOException;
+
+/**
+ * Creates mock BUILD files required for the proto_library rule.
+ */
+public final class MockProtoSupport {
+ /**
+ * Setup the support for building proto_library. You additionally need to setup support for each
+ * of the languages used in the specific test.
+ *
+ * <p>Cannot be used for integration tests that actually need to run protoc.
+ */
+ public static void setup(MockToolsConfig config) throws IOException {
+ createNetProto2(config);
+ // TODO(ulfjack): Consider moving these elsewhere; it's not needed for most proto_library tests.
+ createJsPbPlugin(config);
+ createJavascriptClosureProto2(config);
+ }
+
+ /**
+ * Create a dummy "net/proto2 compiler and proto APIs for all languages
+ * and versions.
+ */
+ private static void createNetProto2(MockToolsConfig config) throws IOException {
+ config.create("net/proto2/compiler/public/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "exports_files(['protocol_compiler'])");
+
+ if (config.isRealFileSystem()) {
+ // when using a "real" file system, import the jars and link to ensure compilation
+ config.create("java/com/google/io/protocol/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_import(name = 'protocol',",
+ " jars = [ 'protocol.jar' ])");
+ config.create("java/com/google/io/protocol2/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_import(name = 'protocol2',",
+ " jars = [ 'protocol2.jar' ])");
+
+ config.linkTool("net/proto2/compiler/public/release/protocol_compiler_linux",
+ "net/proto2/compiler/public/protocol_compiler");
+ config.linkTool("javatests/com/google/devtools/build/lib/prepackaged_protocol_deploy.jar",
+ "java/com/google/io/protocol/protocol.jar");
+ config.linkTool("javatests/com/google/devtools/build/lib/prepackaged_protocol2_deploy.jar",
+ "java/com/google/io/protocol2/protocol2.jar");
+ } else {
+ // for "fake" file systems, provide stub rules. This is different from the "real" filesystem,
+ // as it produces the interface jars that the production environment has.
+ config.create("java/com/google/io/protocol/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'protocol',",
+ " srcs = [ 'Protocol.java' ])");
+ config.create("java/com/google/io/protocol/Protocol.java");
+ config.create("java/com/google/io/protocol2/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'protocol2',",
+ " srcs = [ 'Protocol2.java' ])");
+ config.create("java/com/google/io/protocol/Protocol2.java");
+ }
+
+ config.create(
+ "java/com/google/protobuf/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "filegroup(name = 'protobuf_proto_sources', srcs = [])");
+
+ // RPC generator plugins.
+ config.create("net/rpc/compiler/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_binary(name = 'proto2_py_plugin',",
+ " srcs = [ 'proto2_py_plugin.cc' ])",
+ "cc_binary(name = 'proto2_java_plugin',",
+ " srcs = [ 'proto2_java_plugin.cc' ])");
+
+ config.create("net/grpc/compiler/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_binary(name = 'composite_cc_plugin',",
+ " srcs = [ 'composite_cc_plugin.cc' ])");
+
+ // Fake targets for proto API libs of all languages and versions.
+ config.create("net/proto2/public/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'proto2',",
+ " srcs = [ 'proto2.cc' ])");
+ config.create("net/proto2/python/public/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "py_library(name = 'public',",
+ " srcs = [ 'pyproto2.py' ])");
+ config.create("net/proto2/bridge/public/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'message_downgrader',",
+ " srcs = [ 'downgrader.cc' ])",
+ "cc_library(name = 'compatibility_mode_support',",
+ " srcs = [ 'compatibility.cc' ])");
+ config.create(
+ "net/proto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'proto',",
+ " srcs = [ 'proto.cc' ])",
+ "py_library(name = 'pyproto',",
+ " srcs = [ 'pyproto.py' ])");
+ config.create("net/proto/python/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "py_library(name = 'proto1',",
+ " srcs = [ 'pyproto.py' ])");
+ config.create("net/rpc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'rpc_noloas')");
+ config.create("net/rpc4/public/core/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'rpc4_base')");
+ config.create("net/grpc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "cc_library(name = 'grpc++_codegen_lib')");
+ config.create("net/rpc/python/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "py_library(name = 'python_lite',",
+ " srcs = [ 'pyrpc.py' ])");
+ config.create("java/com/google/net/rpc/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'rpc',",
+ " srcs = [ 'Rpc.java' ])",
+ "java_library(name = 'rpc_noloas_internal',",
+ " srcs = [ 'RpcNoloas.java' ])");
+ config.create("java/com/google/net/rpc3/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'rpc3',",
+ " deps = [':rpc3_noloas_internal'],",
+ " srcs = [ 'Rpc3.java' ])",
+ "java_library(name = 'rpc3_noloas_internal',",
+ " deps = ['//java/com/google/net/rpc:rpc_noloas_internal'],",
+ " srcs = [ 'Rpc3Noloas.java' ])");
+ config.create("net/proto2/proto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "genrule(name = 'go_internal_bootstrap_hack',",
+ " srcs = [ 'descriptor.pb.go-prebuilt' ],",
+ " outs = [ 'descriptor.pb.go' ],",
+ " cmd = '')",
+ "proto_library(name='descriptor',",
+ " srcs=['descriptor.proto'],",
+ " internal_bootstrap_hack = 1)");
+ config.create("net/proto2/go/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "go_library(name = 'proto',",
+ " srcs = [ 'proto.go' ])");
+ config.create("net/proto2/compiler/go/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "go_binary(name = 'protoc-gen-go',",
+ " srcs = [ 'main.go' ])");
+ config.create("net/rpc/go/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "go_library(name = 'rpc',",
+ " srcs = [ 'rpc.go' ])");
+ config.create("go/context/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "go_library(name = 'context',",
+ " srcs = [ 'context.go' ])");
+ }
+
+ /**
+ * Create a dummy "java/com/google/apps/jspb" package.
+ */
+ private static void createJsPbPlugin(MockToolsConfig config) throws IOException {
+ config.create("java/com/google/apps/jspb/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_binary(name = 'JsPbCodeGeneratorPlugin',",
+ " srcs = ['jspb.java'])");
+ config.create(
+ "javascript/apps/jspb/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "js_library(name = 'message',",
+ " srcs = ['message.js'],",
+ " deps_mgmt = 'legacy')");
+ }
+
+ /**
+ * Create a dummy "javascript/closure/proto2" package.
+ */
+ private static void createJavascriptClosureProto2(MockToolsConfig config) throws IOException {
+ config.create(
+ "javascript/closure/proto2/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "js_library(name = 'message',",
+ " srcs = ['message.js'],",
+ " deps_mgmt = 'legacy')");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleBinaryTest.java
new file mode 100644
index 0000000000..37a12f9626
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleBinaryTest.java
@@ -0,0 +1,1410 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.objc.AppleBinary.BinaryType;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_binary. */
+@RunWith(JUnit4.class)
+public class AppleBinaryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new RuleType("apple_binary") {
+ @Override
+ Iterable<String> requiredAttributes(Scratch scratch, String packageDir,
+ Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("srcs") && !alreadyAdded.contains("non_arc_srcs")) {
+ scratch.file(packageDir + "/a.m");
+ scratch.file(packageDir + "/private.h");
+ attributes.add("srcs = ['a.m', 'private.h']");
+ }
+ if (!alreadyAdded.contains("platform_type")) {
+ attributes.add("platform_type = 'ios'");
+ }
+ return attributes.build();
+ }
+ };
+
+ private static final String COCOA_FRAMEWORK_FLAG = "-framework Cocoa";
+ private static final String FOUNDATION_FRAMEWORK_FLAG = "-framework Foundation";
+ private static final String UIKIT_FRAMEWORK_FLAG = "-framework UIKit";
+ private static final ImmutableSet<String> IMPLICIT_NON_MAC_FRAMEWORK_FLAGS =
+ ImmutableSet.of(FOUNDATION_FRAMEWORK_FLAG, UIKIT_FRAMEWORK_FLAG);
+ private static final ImmutableSet<String> IMPLICIT_MAC_FRAMEWORK_FLAGS =
+ ImmutableSet.of(FOUNDATION_FRAMEWORK_FLAG);
+ private static final ImmutableSet<String> COCOA_FEATURE_FLAGS =
+ ImmutableSet.of(COCOA_FRAMEWORK_FLAG);
+
+ @Test
+ public void testLipoActionEnv() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'watchos'");
+
+ useConfiguration("--watchos_cpus=i386,armv7k", "--xcode_version=7.3",
+ "--watchos_sdk_version=2.1");
+
+ CommandAction action = (CommandAction) lipoBinAction("//x:x");
+ assertAppleSdkVersionEnv(action, "2.1");
+ assertAppleSdkPlatformEnv(action, "WatchOS");
+ assertXcodeVersionEnv(action, "7.3");
+ }
+
+ @Test
+ public void testSymlinkInsteadOfLipoSingleArch() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']");
+
+ SymlinkAction action = (SymlinkAction) lipoBinAction("//x:x");
+ CommandAction linkAction = linkAction("//x:x");
+
+ assertThat(action.getInputs())
+ .containsExactly(Iterables.getOnlyElement(linkAction.getOutputs()));
+ }
+
+ @Test
+ public void testLipoActionEnv_sdkVersionPadding() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'watchos'");
+
+ useConfiguration("--watchos_cpus=i386,armv7k",
+ "--xcode_version=7.3", "--watchos_sdk_version=2");
+
+ CommandAction action = (CommandAction) lipoBinAction("//x:x");
+ assertAppleSdkVersionEnv(action, "2.0");
+ }
+
+ @Test
+ public void testCcDependencyLinkoptsArePropagatedToLinkAction() throws Exception {
+ checkCcDependencyLinkoptsArePropagatedToLinkAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testUnknownPlatformType() throws Exception {
+ checkError(
+ "package",
+ "test",
+ String.format(MultiArchSplitTransitionProvider.UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT,
+ "meow_meow_os"),
+ "apple_binary(name = 'test', srcs = [ 'a.m' ], platform_type = 'meow_meow_os')");
+ }
+
+ @Test
+ public void testProtoDylibDeps() throws Exception {
+ checkProtoDedupingDeps(BinaryType.DYLIB);
+ }
+
+ @Test
+ public void testProtoBundleLoaderDeps() throws Exception {
+ checkProtoDedupingDeps(BinaryType.LOADABLE_BUNDLE);
+ }
+
+ /**
+ * Test scenario where all proto symbols are contained within the lower level dependency. There is
+ * an implicit dependency hierarchy between the different apple_binary types (executable,
+ * loadable_bundle, dylib) which looks like this (top level binary types can depend on lower level
+ * binary types):
+ *
+ * loadable_bundle
+ * / \
+ * dylib(s) executable
+ * |
+ * dylibs
+ *
+ * The mechanism to remove duplicate dependencies between dylibs and executable binaries works the
+ * same way between executable and loadable_bundle binaries; the only difference is through which
+ * attribute the dependency is declared (dylibs vs bundle_loader). This test scenario sets up
+ * dependencies for low level and top level binaries and checks that the correct files are linked
+ * for each of the binaries.
+ *
+ * @param depBinaryType either {@link BinaryType#DYLIB} or {@link BinaryType#LOADABLE_BUNDLE}, as
+ * this deduping test is applicable for either
+ */
+ private void checkProtoDedupingDeps(BinaryType depBinaryType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_1',",
+ " srcs = ['data_a.proto', 'data_b.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_2',",
+ " srcs = ['data_b.proto', 'data_c.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_3',",
+ " srcs = ['data_a.proto', 'data_c.proto', 'data_d.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_a',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_1'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_b',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos_2', ':protos_3'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_a', '//protos:objc_protos_b']",
+ ")");
+
+ if (depBinaryType == BinaryType.DYLIB) {
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file(
+ "depBinary/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:objc_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'dylib',",
+ ")",
+ "framework_stub_rule(",
+ " name = 'low_level_framework',",
+ " deps = [':apple_low_level_binary'],",
+ " binary = ':apple_low_level_binary')");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'executable'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:objc_lib']",
+ "dylibs",
+ "['//depBinary:low_level_framework']",
+ "defines",
+ "['SHOULDNOTBEINPROTOS']",
+ "copts",
+ "['-ISHOULDNOTBEINPROTOS']");
+
+ } else {
+ assertThat(depBinaryType == BinaryType.LOADABLE_BUNDLE).isTrue();
+ scratch.file(
+ "depBinary/BUILD",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:objc_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'executable',",
+ ")");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'loadable_bundle'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:objc_lib']",
+ "bundle_loader",
+ "'//depBinary:apple_low_level_binary'");
+ }
+
+ // The proto libraries objc_lib depends on should be linked into the low level binary but not x.
+ Artifact lowLevelBinary =
+ Iterables.getOnlyElement(linkAction("//depBinary:apple_low_level_binary").getOutputs());
+ ImmutableList<Artifact> lowLevelObjectFiles = getAllObjectFilesLinkedInBin(lowLevelBinary);
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataA.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataB.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataC.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataD.pbobjc.o")).isNotNull();
+
+ Artifact bin = Iterables.getOnlyElement(linkAction("//x:x").getOutputs());
+ ImmutableList<Artifact> binObjectFiles = getAllObjectFilesLinkedInBin(bin);
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataA.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataB.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataC.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataD.pbobjc.o")).isNull();
+ }
+
+ @Test
+ public void testProtoDylibDepsPartial() throws Exception {
+ checkProtoDedupingDepsPartial(AppleBinary.BinaryType.DYLIB);
+ }
+
+ @Test
+ public void testProtoBundleLoaderDepsPartial() throws Exception {
+ checkProtoDedupingDepsPartial(AppleBinary.BinaryType.LOADABLE_BUNDLE);
+ }
+
+ /**
+ * Test scenario where proto symbols are mixed between the low and top level binaries. There is
+ * an implicit dependency hierarchy between the different apple_binary types (executable,
+ * loadable_bundle, dylib) which looks like this (top level binary types can depend on lower level
+ * binary types):
+ *
+ * loadable_bundle
+ * / \
+ * dylib(s) executable
+ * |
+ * dylibs
+ *
+ * The mechanism to remove duplicate dependencies between dylibs and executable binaries works the
+ * same way between executable and loadable_bundle binaries; the only difference is through which
+ * attribute the dependency is declared (dylibs vs bundle_loader). This test scenario sets up
+ * dependencies for low level and top level binaries and checks that the correct files are linked
+ * for each of the binaries.
+ *
+ * @param depBinaryType either {@link BinaryType#DYLIB} or {@link BinaryType#LOADABLE_BUNDLE}, as
+ * this deduping test is applicable for either
+ */
+ private void checkProtoDedupingDepsPartial(BinaryType depBinaryType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_1',",
+ " srcs = ['data_a.proto', 'data_b.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_2',",
+ " srcs = ['data_b.proto', 'data_c.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_3',",
+ " srcs = ['data_a.proto', 'data_c.proto', 'data_d.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_a',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_1'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_b',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos_2', ':protos_3'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'main_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_a', '//protos:objc_protos_b']",
+ ")",
+ "objc_library(",
+ " name = 'apple_low_level_lib',",
+ " srcs = ['b.m'],",
+ " deps = ['//protos:objc_protos_a']",
+ ")");
+
+ if (depBinaryType == BinaryType.DYLIB) {
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file(
+ "depBinary/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:apple_low_level_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'dylib',",
+ ")",
+ "framework_stub_rule(",
+ " name = 'low_level_framework',",
+ " deps = [':apple_low_level_binary'],",
+ " binary = ':apple_low_level_binary')");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'executable'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:main_lib']",
+ "dylibs",
+ "['//depBinary:low_level_framework']",
+ "defines",
+ "['SHOULDNOTBEINPROTOS']",
+ "copts",
+ "['-ISHOULDNOTBEINPROTOS']");
+
+ } else {
+ assertThat(depBinaryType == BinaryType.LOADABLE_BUNDLE).isTrue();
+ scratch.file(
+ "depBinary/BUILD",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:apple_low_level_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'executable',",
+ ")");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'loadable_bundle'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:main_lib']",
+ "bundle_loader",
+ "'//depBinary:apple_low_level_binary'",
+ "defines",
+ "['SHOULDNOTBEINPROTOS']",
+ "copts",
+ "['-ISHOULDNOTBEINPROTOS']");
+ }
+
+ // The proto libraries objc_lib depends on should be linked into the low level binary but not x.
+ Artifact lowLevelBinary =
+ Iterables.getOnlyElement(linkAction("//depBinary:apple_low_level_binary").getOutputs());
+ ImmutableList<Artifact> lowLevelObjectFiles = getAllObjectFilesLinkedInBin(lowLevelBinary);
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataA.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataB.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataC.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataD.pbobjc.o")).isNull();
+
+ Artifact bin = Iterables.getOnlyElement(linkAction("//x:x").getOutputs());
+ ImmutableList<Artifact> binObjectFiles = getAllObjectFilesLinkedInBin(bin);
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataA.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataB.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataC.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataD.pbobjc.o")).isNotNull();
+ }
+
+ @Test
+ public void testProtoDepsViaDylib() throws Exception {
+ checkProtoDisjointDeps(BinaryType.DYLIB);
+ }
+
+ @Test
+ public void testProtoDepsViaBundleLoader() throws Exception {
+ checkProtoDisjointDeps(BinaryType.LOADABLE_BUNDLE);
+ }
+
+ /**
+ * Test scenario where a proto in the top level binary depends on a proto in a low level binary.
+ * There is an implicit dependency hierarchy between the different apple_binary types (executable,
+ * loadable_bundle, dylib) which looks like this (top level binary types can depend on lower level
+ * binary types):
+ *
+ * loadable_bundle
+ * / \
+ * dylib(s) executable
+ * |
+ * dylibs
+ *
+ * The mechanism to remove duplicate dependencies between dylibs and executable binaries works the
+ * same way between executable and loadable_bundle binaries; the only difference is through which
+ * attribute the dependency is declared (dylibs vs bundle_loader). This test scenario sets up
+ * dependencies for low level and top level binaries and checks that the correct files are linked
+ * for each of the binaries.
+ *
+ * @param depBinaryType either {@link BinaryType#DYLIB} or {@link BinaryType#LOADABLE_BUNDLE}, as
+ * this deduping test is applicable for either
+ */
+ private void checkProtoDisjointDeps(BinaryType depBinaryType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_main',",
+ " srcs = ['data_a.proto', 'data_b.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_low_level',",
+ " srcs = ['data_b.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_main',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_main'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_low_level',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos_low_level'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'main_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_main',]",
+ ")",
+ "objc_library(",
+ " name = 'apple_low_level_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_low_level',]",
+ ")");
+
+ if (depBinaryType == BinaryType.DYLIB) {
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file(
+ "depBinary/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:apple_low_level_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'dylib',",
+ ")",
+ "framework_stub_rule(",
+ " name = 'low_level_framework',",
+ " deps = [':apple_low_level_binary'],",
+ " binary = ':apple_low_level_binary')");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'executable'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:main_lib']",
+ "dylibs",
+ "['//depBinary:low_level_framework']",
+ "defines",
+ "['SHOULDNOTBEINPROTOS']",
+ "copts",
+ "['-ISHOULDNOTBEINPROTOS']");
+
+ } else {
+ assertThat(depBinaryType == BinaryType.LOADABLE_BUNDLE).isTrue();
+ scratch.file(
+ "depBinary/BUILD",
+ "apple_binary(",
+ " name = 'apple_low_level_binary',",
+ " srcs = ['b.m'],",
+ " deps = ['//libs:apple_low_level_lib'],",
+ " platform_type = 'ios',",
+ " binary_type = 'executable',",
+ ")");
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "binary_type",
+ "'loadable_bundle'",
+ "srcs",
+ "['main.m']",
+ "deps",
+ "['//libs:main_lib']",
+ "bundle_loader",
+ "'//depBinary:apple_low_level_binary'",
+ "defines",
+ "['SHOULDNOTBEINPROTOS']",
+ "copts",
+ "['-ISHOULDNOTBEINPROTOS']");
+ }
+
+ // The proto libraries objc_lib depends on should be linked into apple_dylib but not x.
+ Artifact lowLevelBinary =
+ Iterables.getOnlyElement(linkAction("//depBinary:apple_low_level_binary").getOutputs());
+ ImmutableList<Artifact> lowLevelObjectFiles = getAllObjectFilesLinkedInBin(lowLevelBinary);
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataA.pbobjc.o")).isNull();
+ assertThat(getFirstArtifactEndingWith(lowLevelObjectFiles, "DataB.pbobjc.o")).isNotNull();
+
+ Artifact bin = Iterables.getOnlyElement(linkAction("//x:x").getOutputs());
+ ImmutableList<Artifact> binObjectFiles = getAllObjectFilesLinkedInBin(bin);
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataA.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(binObjectFiles, "DataB.pbobjc.o")).isNull();
+ Action dataAObjectAction =
+ getGeneratingAction(getFirstArtifactEndingWith(binObjectFiles, "DataA.pbobjc.o"));
+ assertThat(getFirstArtifactEndingWith(dataAObjectAction.getInputs(), "DataB.pbobjc.h"))
+ .isNotNull();
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingDoesNotHappen() throws Exception {
+ useConfiguration("--noenable_apple_binary_native_protos");
+ checkProtoBundlingDoesNotHappen(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsObjectsWithCrosstool() throws Exception {
+ checkAvoidDepsObjectsWithCrosstool(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleLoaderCantBeSetWithoutBundleBinaryType() throws Exception {
+ scratch.file("bin/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'ios',",
+ ")");
+ checkError(
+ "bundle", "bundle", AppleBinary.BUNDLE_LOADER_NOT_IN_BUNDLE_ERROR,
+ "apple_binary(",
+ " name = 'bundle',",
+ " bundle_loader = '//bin:bin',",
+ " platform_type = 'ios',",
+ ")");
+ }
+
+ /** Returns the bcsymbolmap artifact for given architecture. */
+ protected Artifact bitcodeSymbol(String arch) throws Exception {
+ SpawnAction lipoAction = (SpawnAction) lipoBinAction("//examples/apple_skylark:bin");
+
+ String bin =
+ configurationBin(arch, ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "examples/apple_skylark/bin_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+ return getFirstArtifactEndingWith(linkAction.getOutputs(), "bcsymbolmap");
+ }
+
+ /** Returns the path to the dSYM binary artifact for given architecture. */
+ protected String dsymBinaryPath(String arch) throws Exception {
+ return configurationBin(arch, ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "examples/apple_skylark/bin.app.dSYM/Contents/Resources/DWARF/bin_bin";
+ }
+
+ /** Returns the path to the linkmap artifact for a given architecture. */
+ protected String linkmapPath(String arch) throws Exception {
+ return configurationBin(arch, ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "examples/apple_skylark/bin.linkmap";
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testProvider_dylib() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " provider = dep[apple_common.AppleDylibBinary]",
+ " return struct(",
+ " binary = provider.binary,",
+ " objc = provider.objc,",
+ " dep_dir = dir(dep),",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False,)",
+ "})");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " binary_type = '" + BinaryType.DYLIB + "',",
+ " platform_type = 'ios',",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':bin'],",
+ ")");
+
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ assertThat(skylarkTarget.get("binary")).isInstanceOf(Artifact.class);
+ assertThat(skylarkTarget.get("objc")).isInstanceOf(ObjcProvider.class);
+
+ List<String> depProviders = (List<String>) skylarkTarget.getValue("dep_dir");
+ assertThat(depProviders).doesNotContain("AppleExecutableBinary");
+ assertThat(depProviders).doesNotContain("AppleLoadableBundleBinary");
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testProvider_executable() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " provider = dep[apple_common.AppleExecutableBinary]",
+ " return struct(",
+ " binary = provider.binary,",
+ " objc = provider.objc,",
+ " dep_dir = dir(dep),",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False,)",
+ "})");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " binary_type = '" + BinaryType.EXECUTABLE + "',",
+ " platform_type = 'ios',",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':bin'],",
+ ")");
+
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ assertThat(skylarkTarget.get("binary")).isInstanceOf(Artifact.class);
+ assertThat(skylarkTarget.get("objc")).isInstanceOf(ObjcProvider.class);
+
+ List<String> depProviders = (List<String>) skylarkTarget.get("dep_dir");
+ assertThat(depProviders).doesNotContain("AppleDylibBinary");
+ assertThat(depProviders).doesNotContain("AppleLoadableBundleBinary");
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testProvider_loadableBundle() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " provider = dep[apple_common.AppleLoadableBundleBinary]",
+ " return struct(",
+ " binary = provider.binary,",
+ " dep_dir = dir(dep),",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False,)",
+ "})");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " binary_type = '" + BinaryType.LOADABLE_BUNDLE + "',",
+ " platform_type = 'ios',",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':bin'],",
+ ")");
+
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ assertThat((Artifact) skylarkTarget.get("binary")).isNotNull();
+
+ List<String> depProviders = (List<String>) skylarkTarget.get("dep_dir");
+ assertThat(depProviders).doesNotContain("AppleExecutableBinary");
+ assertThat(depProviders).doesNotContain("AppleDylibBinary");
+ }
+
+ @Test
+ public void testDuplicateLinkopts() throws Exception {
+ RULE_TYPE.scratchTarget(scratch, "linkopts", "['-foo', 'bar', '-foo', 'baz']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ String linkArgs = Joiner.on(" ").join(linkAction.getArguments());
+ assertThat(linkArgs).contains("-Wl,-foo -Wl,bar");
+ assertThat(linkArgs).contains("-Wl,-foo -Wl,baz");
+ }
+
+ @Test
+ public void testCanUseCrosstool_singleArch() throws Exception {
+ checkLinkingRuleCanUseCrosstool_singleArch(RULE_TYPE);
+ }
+
+ @Test
+ public void testCanUseCrosstool_multiArch() throws Exception {
+ checkLinkingRuleCanUseCrosstool_multiArch(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkIphoneosPlatformEnv() throws Exception {
+ checkAppleSdkIphoneosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ checkXcodeVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksImplicitFrameworksWithCrosstoolIos() throws Exception {
+ useConfiguration(
+ ObjcCrosstoolMode.ALL,
+ "--ios_multi_cpus=x86_64",
+ "--ios_sdk_version=10.0",
+ "--ios_minimum_os=8.0");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'ios'");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "x/x_bin");
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertThat(linkAction.getArguments()).containsAllIn(IMPLICIT_NON_MAC_FRAMEWORK_FLAGS);
+ }
+
+ @Test
+ public void testLinksImplicitFrameworksWithCrosstoolWatchos() throws Exception {
+ useConfiguration(
+ ObjcCrosstoolMode.ALL,
+ "--watchos_cpus=i386",
+ "--watchos_sdk_version=3.0",
+ "--watchos_minimum_os=2.0");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'watchos'");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "x/x_bin");
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertThat(linkAction.getArguments()).containsAllIn(IMPLICIT_NON_MAC_FRAMEWORK_FLAGS);
+ }
+
+ @Test
+ public void testLinksImplicitFrameworksWithCrosstoolTvos() throws Exception {
+ useConfiguration(
+ ObjcCrosstoolMode.ALL,
+ "--tvos_cpus=x86_64",
+ "--tvos_sdk_version=10.1",
+ "--tvos_minimum_os=10.0");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'tvos'");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "x/x_bin");
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertThat(linkAction.getArguments()).containsAllIn(IMPLICIT_NON_MAC_FRAMEWORK_FLAGS);
+ }
+
+ @Test
+ public void testLinksImplicitFrameworksWithCrosstoolMacos() throws Exception {
+ useConfiguration(
+ ObjcCrosstoolMode.ALL,
+ "--macos_cpus=x86_64",
+ "--macos_sdk_version=10.11",
+ "--macos_minimum_os=10.11");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'macos'");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "x/x_bin");
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertThat(linkAction.getArguments()).containsAllIn(IMPLICIT_MAC_FRAMEWORK_FLAGS);
+ assertThat(linkAction.getArguments())
+ .containsNoneOf(COCOA_FRAMEWORK_FLAG, UIKIT_FRAMEWORK_FLAG);
+ }
+
+ @Test
+ public void testLinkCocoaFeatureWithCrosstoolMacos() throws Exception {
+ useConfiguration(
+ ObjcCrosstoolMode.ALL,
+ "--macos_cpus=x86_64",
+ "--macos_sdk_version=10.11",
+ "--macos_minimum_os=10.11");
+ RULE_TYPE.scratchTarget(
+ scratch, "srcs", "['a.m']", "platform_type", "'macos'", "features", "['link_cocoa']");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "x/x_bin");
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertThat(linkAction.getArguments()).containsAllIn(IMPLICIT_MAC_FRAMEWORK_FLAGS);
+ assertThat(linkAction.getArguments()).containsAllIn(COCOA_FEATURE_FLAGS);
+ assertThat(linkAction.getArguments()).doesNotContain(UIKIT_FRAMEWORK_FLAG);
+ }
+
+ @Test
+ public void testAliasedLinkoptsThroughObjcLibrary() throws Exception {
+ checkAliasedLinkoptsThroughObjcLibrary(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ checkAppleSdkVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ checkNonDefaultAppleSdkVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ checkAppleSdkDefaultPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsThroughDylib() throws Exception {
+ checkAvoidDepsThroughDylib(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsObjects_avoidViaCcLibrary() throws Exception {
+ checkAvoidDepsObjects_avoidViaCcLibrary(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleLoaderIsCorrectlyPassedToTheLinker() throws Exception {
+ checkBundleLoaderIsCorrectlyPassedToTheLinker(RULE_TYPE);
+ }
+
+ @Test
+ public void testNoSrcs() throws Exception {
+ checkNoSrcs(RULE_TYPE);
+ }
+
+ @Test
+ public void testLipoBinaryAction() throws Exception {
+ checkLipoBinaryAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionHasCorrectIosSimulatorMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'ios'");
+ useConfiguration("--ios_multi_cpus=x86_64", "--ios_sdk_version=10.0", "--ios_minimum_os=8.0");
+ checkLinkMinimumOSVersion(
+ ConfigurationDistinguisher.APPLEBIN_IOS, "x86_64", "-mios-simulator-version-min=8.0");
+ }
+
+ @Test
+ public void testLinkActionHasCorrectIosMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']", "platform_type", "'ios'");
+ useConfiguration("--ios_multi_cpus=arm64", "--ios_sdk_version=10.0", "--ios_minimum_os=8.0");
+ checkLinkMinimumOSVersion(
+ ConfigurationDistinguisher.APPLEBIN_IOS, "arm64", "-miphoneos-version-min=8.0");
+ }
+
+ @Test
+ public void testWatchSimulatorDepCompile() throws Exception {
+ checkWatchSimulatorDepCompile(RULE_TYPE);
+ }
+
+ @Test
+ public void testDylibBinaryType() throws Exception {
+ RULE_TYPE.scratchTarget(scratch, "binary_type", "'dylib'");
+
+ CommandAction linkAction = linkAction("//x:x");
+ assertThat(Joiner.on(" ").join(linkAction.getArguments())).contains("-dynamiclib");
+ }
+
+ @Test
+ public void testBinaryTypeIsCorrectlySetToBundle() throws Exception {
+ RULE_TYPE.scratchTarget(scratch, "binary_type", "'loadable_bundle'");
+
+ CommandAction linkAction = linkAction("//x:x");
+ assertThat(Joiner.on(" ").join(linkAction.getArguments())).contains("-bundle");
+ }
+
+ @Test
+ public void testMultiarchCcDep() throws Exception {
+ checkMultiarchCcDep(RULE_TYPE);
+ }
+
+ @Test
+ public void testWatchSimulatorLipoAction() throws Exception {
+ checkWatchSimulatorLipoAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionsWithSrcs() throws Exception {
+ checkLinkActionsWithSrcs(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testFrameworkDepLinkFlags() throws Exception {
+ checkFrameworkDepLinkFlags(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testDylibDependencies() throws Exception {
+ checkDylibDependencies(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testMinimumOs() throws Exception {
+ checkMinimumOsLinkAndCompileArg(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_watchos() throws Exception {
+ checkMinimumOsLinkAndCompileArg_watchos(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid_nonVersion() throws Exception {
+ checkMinimumOs_invalid_nonVersion(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid_containsAlphabetic() throws Exception {
+ checkMinimumOs_invalid_containsAlphabetic(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid_tooManyComponents() throws Exception {
+ checkMinimumOs_invalid_tooManyComponents(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenfilesProtoGetsCorrectPath() throws Exception {
+ scratch.file(
+ "examples/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "apple_binary(",
+ " name = 'bin',",
+ " deps = [':objc_protos'],",
+ " platform_type = 'ios',",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos',",
+ " portable_proto_filters = ['filter.pbascii'],",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['genfile.proto'],",
+ ")",
+ "genrule(",
+ " name = 'copy_proto',",
+ " srcs = ['original.proto'],",
+ " outs = ['genfile.proto'],",
+ " cmd = '/bin/cp $< $@',",
+ ")");
+
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+
+ Action lipoAction = actionProducingArtifact("//examples:bin", "_lipobin");
+ ArrayList<String> genfileRoots = new ArrayList<>();
+
+ for (Artifact archBinary : lipoAction.getInputs()) {
+ if (archBinary.getExecPathString().endsWith("bin_bin")) {
+ Artifact protoLib =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(archBinary).getInputs(), "BundledProtos_0.a");
+ Artifact protoObject =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(protoLib).getInputs(), "Genfile.pbobjc.o");
+ Artifact protoObjcSource =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(protoObject).getInputs(), "Genfile.pbobjc.m");
+ Artifact protoSource =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(protoObjcSource).getInputs(), "genfile.proto");
+ genfileRoots.add(protoSource.getRoot().getExecPathString());
+ }
+ }
+
+ // Make sure there are genrules for both arm64 and armv7 configurations.
+ Collections.sort(genfileRoots);
+ assertThat(genfileRoots).hasSize(2);
+ assertThat(genfileRoots.get(0)).contains("arm64");
+ assertThat(genfileRoots.get(1)).contains("armv7");
+ }
+
+ @Test
+ public void testDifferingProtoDepsPerArchitecture() throws Exception {
+ scratch.file(
+ "examples/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "apple_binary(",
+ " name = 'bin',",
+ " deps = [':objc_protos'],",
+ " platform_type = 'ios',",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos',",
+ " portable_proto_filters = ['filter.pbascii'],",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = select({",
+ " ':armv7': [ 'one.proto', ],",
+ " '//conditions:default': [ 'two.proto', ],",
+ " }),",
+ ")",
+ "config_setting(",
+ " name = 'armv7',",
+ " values = {'apple_split_cpu': 'armv7'},",
+ ")");
+
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+
+ Action lipoAction = actionProducingArtifact("//examples:bin", "_lipobin");
+
+ Artifact armv7Binary = getSingleArchBinary(lipoAction, "armv7");
+ Artifact arm64Binary = getSingleArchBinary(lipoAction, "arm64");;
+
+ Artifact armv7ProtoLib =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(armv7Binary).getInputs(), "BundledProtos_0.a");
+ Artifact armv7ProtoObject =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(armv7ProtoLib).getInputs(), "One.pbobjc.o");
+ Artifact armv7ProtoObjcSource =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(armv7ProtoObject).getInputs(), "One.pbobjc.m");
+ assertThat(getFirstArtifactEndingWith(
+ getGeneratingAction(armv7ProtoObjcSource).getInputs(), "one.proto")).isNotNull();
+
+ Artifact arm64ProtoLib =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(arm64Binary).getInputs(), "BundledProtos_0.a");
+ Artifact arm64ProtoObject =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(arm64ProtoLib).getInputs(), "Two.pbobjc.o");
+ Artifact arm64ProtoObjcSource =
+ getFirstArtifactEndingWith(
+ getGeneratingAction(arm64ProtoObject).getInputs(), "Two.pbobjc.m");
+ assertThat(getFirstArtifactEndingWith(
+ getGeneratingAction(arm64ProtoObjcSource).getInputs(), "two.proto")).isNotNull();
+ }
+
+ private Artifact getSingleArchBinary(Action lipoAction, String arch) throws Exception {
+ for (Artifact archBinary : lipoAction.getInputs()) {
+ String execPath = archBinary.getExecPathString();
+ if (execPath.endsWith("bin_bin") && execPath.contains(arch)) {
+ return archBinary;
+ }
+ }
+ throw new AssertionError("Lipo action does not contain an input binary from arch " + arch);
+ }
+
+ private SkylarkDict<String, SkylarkDict<String, Artifact>>
+ generateAppleDebugOutputsSkylarkProviderMap() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " provider = dep[apple_common.AppleDebugOutputs]",
+ " return struct(",
+ " outputs_map=provider.outputs_map,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(",
+ " allow_files = False,",
+ " mandatory = False,",
+ " providers = [apple_common.AppleDebugOutputs],",
+ " )",
+ "})");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'ios',",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':bin'],",
+ ")");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ // This cast is safe: struct providers are represented as SkylarkDict.
+ @SuppressWarnings("unchecked")
+ SkylarkDict<String, SkylarkDict<String, Artifact>> outputMap =
+ (SkylarkDict<String, SkylarkDict<String, Artifact>>)
+ skylarkTarget.get("outputs_map");
+ return outputMap;
+ }
+
+ private void checkAppleDebugSymbolProvider_DsymEntries(
+ SkylarkDict<String, SkylarkDict<String, Artifact>> outputMap) throws Exception {
+ assertThat(outputMap).containsKey("arm64");
+ assertThat(outputMap).containsKey("armv7");
+
+ Map<String, Artifact> arm64 = outputMap.get("arm64");
+ assertThat(arm64).containsEntry("bitcode_symbols", bitcodeSymbol("arm64"));
+ assertThat(arm64.get("dsym_binary").getExecPathString()).isEqualTo(dsymBinaryPath("arm64"));
+
+ Map<String, Artifact> armv7 = outputMap.get("armv7");
+ assertThat(armv7).containsEntry("bitcode_symbols", bitcodeSymbol("armv7"));
+ assertThat(armv7.get("dsym_binary").getExecPathString()).isEqualTo(dsymBinaryPath("armv7"));
+
+ Map<String, Artifact> x8664 = outputMap.get("x86_64");
+ // Simulator build has bitcode disabled.
+ assertThat(x8664).doesNotContainKey("bitcode_symbols");
+ assertThat(x8664.get("dsym_binary").getExecPathString()).isEqualTo(dsymBinaryPath("x86_64"));
+ }
+
+ private void checkAppleDebugSymbolProvider_LinkMapEntries(
+ SkylarkDict<String, SkylarkDict<String, Artifact>> outputMap) throws Exception {
+ assertThat(outputMap).containsKey("arm64");
+ assertThat(outputMap).containsKey("armv7");
+
+ Map<String, Artifact> arm64 = outputMap.get("arm64");
+ assertThat(arm64.get("linkmap").getExecPathString()).isEqualTo(linkmapPath("arm64"));
+
+ Map<String, Artifact> armv7 = outputMap.get("armv7");
+ assertThat(armv7.get("linkmap").getExecPathString()).isEqualTo(linkmapPath("armv7"));
+
+ Map<String, Artifact> x8664 = outputMap.get("x86_64");
+ assertThat(x8664.get("linkmap").getExecPathString()).isEqualTo(linkmapPath("x86_64"));
+ }
+
+ @Test
+ public void testAppleDebugSymbolProviderWithDsymsExposedToSkylark() throws Exception {
+ useConfiguration(
+ "--apple_bitcode=embedded", "--apple_generate_dsym", "--ios_multi_cpus=armv7,arm64,x86_64");
+ checkAppleDebugSymbolProvider_DsymEntries(generateAppleDebugOutputsSkylarkProviderMap());
+ }
+
+ @Test
+ public void testAppleDebugSymbolProviderWithLinkMapsExposedToSkylark() throws Exception {
+ useConfiguration(
+ "--apple_bitcode=embedded",
+ "--objc_generate_linkmap",
+ "--ios_multi_cpus=armv7,arm64,x86_64");
+ checkAppleDebugSymbolProvider_LinkMapEntries(generateAppleDebugOutputsSkylarkProviderMap());
+ }
+
+ @Test
+ public void testAppleDebugSymbolProviderWithDsymsAndLinkMapsExposedToSkylark() throws Exception {
+ useConfiguration(
+ "--apple_bitcode=embedded",
+ "--objc_generate_linkmap",
+ "--apple_generate_dsym",
+ "--ios_multi_cpus=armv7,arm64,x86_64");
+
+ SkylarkDict<String, SkylarkDict<String, Artifact>> outputMap =
+ generateAppleDebugOutputsSkylarkProviderMap();
+ checkAppleDebugSymbolProvider_DsymEntries(outputMap);
+ checkAppleDebugSymbolProvider_LinkMapEntries(outputMap);
+ }
+
+ @Test
+ public void testFilesToCompileOutputGroup() throws Exception {
+ checkFilesToCompileOutputGroup(RULE_TYPE);
+ }
+
+ @Test
+ public void testInstrumentedFilesProviderContainsDepsAndBundleLoaderFiles() throws Exception {
+ useConfiguration("--collect_code_coverage");
+ scratch.file(
+ "examples/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "apple_binary(",
+ " name = 'bin',",
+ " deps = [':lib'],",
+ " platform_type = 'ios',",
+ ")",
+ "apple_binary(",
+ " name = 'bundle',",
+ " deps = [':bundle_lib'],",
+ " binary_type = '" + BinaryType.LOADABLE_BUNDLE + "',",
+ " bundle_loader = ':bin',",
+ " platform_type = 'ios',",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ ")",
+ "objc_library(",
+ " name = 'bundle_lib',",
+ " srcs = ['bundle_lib.m'],",
+ ")");
+
+ ConfiguredTarget bundleTarget = getConfiguredTarget("//examples:bundle");
+ InstrumentedFilesProvider instrumentedFilesProvider =
+ bundleTarget.getProvider(InstrumentedFilesProvider.class);
+ assertThat(instrumentedFilesProvider).isNotNull();
+
+ assertThat(Artifact.toRootRelativePaths(instrumentedFilesProvider.getInstrumentedFiles()))
+ .containsAllOf("examples/lib.m", "examples/bundle_lib.m");
+ }
+
+ @Test
+ public void testAppleSdkWatchsimulatorPlatformEnv() throws Exception {
+ checkAppleSdkWatchsimulatorPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkWatchosPlatformEnv() throws Exception {
+ checkAppleSdkWatchosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkTvsimulatorPlatformEnv() throws Exception {
+ checkAppleSdkTvsimulatorPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkTvosPlatformEnv() throws Exception {
+ checkAppleSdkTvosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionHasCorrectWatchosSimulatorMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'watchos'");
+ useConfiguration(
+ "--watchos_cpus=i386", "--watchos_sdk_version=3.0", "--watchos_minimum_os=2.0");
+ checkLinkMinimumOSVersion(ConfigurationDistinguisher.APPLEBIN_WATCHOS, "i386",
+ "-mwatchos-simulator-version-min=2.0");
+ }
+
+ @Test
+ public void testLinkActionHasCorrectWatchosMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'watchos'");
+ useConfiguration(
+ "--watchos_cpus=armv7k", "--watchos_sdk_version=3.0", "--watchos_minimum_os=2.0");
+ checkLinkMinimumOSVersion(ConfigurationDistinguisher.APPLEBIN_WATCHOS, "armv7k",
+ "-mwatchos-version-min=2.0");
+ }
+
+ @Test
+ public void testLinkActionHasCorrectTvosSimulatorMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'tvos'");
+ useConfiguration(
+ "--tvos_cpus=x86_64", "--tvos_sdk_version=10.1", "--tvos_minimum_os=10.0");
+ checkLinkMinimumOSVersion(ConfigurationDistinguisher.APPLEBIN_TVOS, "x86_64",
+ "-mtvos-simulator-version-min=10.0");
+ }
+
+ @Test
+ public void testLinkActionHasCorrectTvosMinVersion() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "platform_type", "'tvos'");
+ useConfiguration(
+ "--tvos_cpus=arm64", "--tvos_sdk_version=10.1", "--tvos_minimum_os=10.0");
+ checkLinkMinimumOSVersion(ConfigurationDistinguisher.APPLEBIN_TVOS, "arm64",
+ "-mtvos-version-min=10.0");
+ }
+
+ @Test
+ public void testWatchSimulatorLinkAction() throws Exception {
+ checkWatchSimulatorLinkAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsObjects() throws Exception {
+ checkAvoidDepsObjects(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleLoaderPropagatesAppleExecutableBinaryProvider() throws Exception {
+ scratch.file(
+ "bin/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " hdrs = ['a.h'],",
+ " platform_type = 'ios',",
+ ")");
+ scratch.file(
+ "test/BUILD",
+ "apple_binary(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " binary_type = 'loadable_bundle',",
+ " bundle_loader = '//bin:bin',",
+ " platform_type = 'ios',",
+ ")");
+ ConfiguredTarget binTarget = getConfiguredTarget("//bin:bin");
+ AppleExecutableBinaryProvider executableBinaryProvider =
+ (AppleExecutableBinaryProvider) binTarget.get(
+ AppleExecutableBinaryProvider.SKYLARK_CONSTRUCTOR.getKey());
+ assertThat(executableBinaryProvider).isNotNull();
+
+ CommandAction testLinkAction = linkAction("//test:test");
+ assertThat(testLinkAction.getInputs())
+ .contains(executableBinaryProvider.getAppleExecutableBinary());
+ }
+
+ @Test
+ public void testLoadableBundleBinaryAddsRpathLinkOptWithNoBundleLoader() throws Exception {
+ scratch.file(
+ "test/BUILD",
+ "apple_binary(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " binary_type = 'loadable_bundle',",
+ " platform_type = 'ios',",
+ ")");
+
+ CommandAction testLinkAction = linkAction("//test:test");
+ assertThat(Joiner.on(" ").join(testLinkAction.getArguments()))
+ .contains("@loader_path/Frameworks");
+ }
+
+ @Test
+ public void testLoadableBundleBinaryAddsRpathLinkOptWithBundleLoader() throws Exception {
+ scratch.file(
+ "bin/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " hdrs = ['a.h'],",
+ " platform_type = 'ios',",
+ ")");
+ scratch.file(
+ "test/BUILD",
+ "apple_binary(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " binary_type = 'loadable_bundle',",
+ " bundle_loader = '//bin:bin',",
+ " platform_type = 'ios',",
+ ")");
+
+ CommandAction testLinkAction = linkAction("//test:test");
+ assertThat(Joiner.on(" ").join(testLinkAction.getArguments()))
+ .contains("@loader_path/Frameworks");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleDynamicLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleDynamicLibraryTest.java
new file mode 100644
index 0000000000..3feec504a3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleDynamicLibraryTest.java
@@ -0,0 +1,195 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_dyamic_library. */
+@RunWith(JUnit4.class)
+public class AppleDynamicLibraryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new RuleType("apple_binary") {
+ @Override
+ Iterable<String> requiredAttributes(Scratch scratch, String packageDir,
+ Set<String> alreadyAdded) throws IOException {
+ return Iterables.concat(ImmutableList.of("binary_type = 'dylib'"),
+ AppleBinaryTest.RULE_TYPE.requiredAttributes(scratch, packageDir, alreadyAdded));
+ }
+ };
+
+ @Test
+ public void testCcDependencyLinkoptsArePropagatedToLinkAction() throws Exception {
+ checkCcDependencyLinkoptsArePropagatedToLinkAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testUnknownPlatformType() throws Exception {
+ checkError(
+ "package",
+ "test",
+ String.format(MultiArchSplitTransitionProvider.UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT,
+ "meow_meow_os"),
+ "apple_binary(name = 'test', binary_type = 'dylib', srcs = [ 'a.m' ], "
+ + "platform_type = 'meow_meow_os')");
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testCanUseCrosstool_singleArch() throws Exception {
+ checkLinkingRuleCanUseCrosstool_singleArch(RULE_TYPE);
+ }
+
+ @Test
+ public void testCanUseCrosstool_multiArch() throws Exception {
+ checkLinkingRuleCanUseCrosstool_multiArch(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkIphoneosPlatformEnv() throws Exception {
+ checkAppleSdkIphoneosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ checkXcodeVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAliasedLinkoptsThroughObjcLibrary() throws Exception {
+ checkAliasedLinkoptsThroughObjcLibrary(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ checkAppleSdkVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ checkNonDefaultAppleSdkVersionEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ checkAppleSdkDefaultPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsObjects_avoidViaCcLibrary() throws Exception {
+ checkAvoidDepsObjects_avoidViaCcLibrary(RULE_TYPE);
+ }
+
+ @Test
+ public void testNoSrcs() throws Exception {
+ checkNoSrcs(RULE_TYPE);
+ }
+
+ @Test
+ public void testLipoBinaryAction() throws Exception {
+ checkLipoBinaryAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testWatchSimulatorDepCompile() throws Exception {
+ checkWatchSimulatorDepCompile(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultiarchCcDep() throws Exception {
+ checkMultiarchCcDep(RULE_TYPE);
+ }
+
+ @Test
+ public void testWatchSimulatorLipoAction() throws Exception {
+ checkWatchSimulatorLipoAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionsWithSrcs() throws Exception {
+ checkLinkActionsWithSrcs(RULE_TYPE,
+ new ExtraLinkArgs("-dynamiclib"));
+ }
+
+ @Test
+ public void testFrameworkDepLinkFlags() throws Exception {
+ checkFrameworkDepLinkFlags(RULE_TYPE, new ExtraLinkArgs("-dynamiclib"));
+ }
+
+ @Test
+ public void testDylibDependencies() throws Exception {
+ checkDylibDependencies(RULE_TYPE, new ExtraLinkArgs("-dynamiclib"));
+ }
+
+ @Test
+ public void testMinimumOs() throws Exception {
+ checkMinimumOsLinkAndCompileArg(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_watchos() throws Exception {
+ checkMinimumOsLinkAndCompileArg_watchos(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid() throws Exception {
+ checkMinimumOs_invalid_nonVersion(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkWatchsimulatorPlatformEnv() throws Exception {
+ checkAppleSdkWatchsimulatorPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkWatchosPlatformEnv() throws Exception {
+ checkAppleSdkWatchosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkTvsimulatorPlatformEnv() throws Exception {
+ checkAppleSdkTvsimulatorPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkTvosPlatformEnv() throws Exception {
+ checkAppleSdkTvosPlatformEnv(RULE_TYPE);
+ }
+
+ @Test
+ public void testWatchSimulatorLinkAction() throws Exception {
+ checkWatchSimulatorLinkAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testAvoidDepsObjects() throws Exception {
+ checkAvoidDepsObjects(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryTest.java
new file mode 100644
index 0000000000..c410ce51cd
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStaticLibraryTest.java
@@ -0,0 +1,544 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.LIPO;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.cpp.CppLinkAction;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_static_library. */
+@RunWith(JUnit4.class)
+public class AppleStaticLibraryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new RuleType("apple_static_library") {
+ @Override
+ Iterable<String> requiredAttributes(Scratch scratch, String packageDir,
+ Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("srcs") && !alreadyAdded.contains("non_arc_srcs")) {
+ scratch.file(packageDir + "/a.m");
+ scratch.file(packageDir + "/private.h");
+ attributes.add("srcs = ['a.m', 'private.h']");
+ }
+ if (!alreadyAdded.contains("platform_type")) {
+ attributes.add("platform_type = 'ios'");
+ }
+ return attributes.build();
+ }
+ };
+
+
+ @Test
+ public void testUnknownPlatformType() throws Exception {
+ checkError(
+ "package",
+ "test",
+ String.format(MultiArchSplitTransitionProvider.UNSUPPORTED_PLATFORM_TYPE_ERROR_FORMAT,
+ "meow_meow_os"),
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'meow_meow_os')");
+ }
+
+ @Test
+ public void testCanUseCrosstool() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+
+ // If the target is indeed using the c++ backend, then its archive action should be a
+ // CppLinkAction.
+ Action lipoLibAction = lipoLibAction("//x:x");
+ Artifact archive = getFirstArtifactEndingWith(lipoLibAction.getInputs(), ".a");
+ Action archiveAction = getGeneratingAction(archive);
+ assertThat(archiveAction).isInstanceOf(CppLinkAction.class);
+ }
+
+ @Test
+ public void testCanUseCrosstool_multiArch() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--ios_multi_cpus=i386,x86_64");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+
+ // If the target is indeed using the c++ backend, then its archive action should be a
+ // CppLinkAction.
+ Action lipoLibAction = lipoLibAction("//x:x");
+ Artifact archive = getFirstArtifactEndingWith(lipoLibAction.getInputs(), ".a");
+ Action archiveAction = getGeneratingAction(archive);
+ assertThat(archiveAction).isInstanceOf(CppLinkAction.class);
+ }
+
+ @Test
+ public void testSymlinkInsteadOfLipoSingleArch() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "srcs", "['a.m']");
+
+ SymlinkAction action = (SymlinkAction) lipoLibAction("//x:x");
+ CommandAction linkAction = linkLibAction("//x:x");
+
+ assertThat(action.getInputs())
+ .containsExactly(Iterables.getOnlyElement(linkAction.getOutputs()));
+ }
+
+ @Test
+ public void testAvoidDepsProviders() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " deps = [':objcLib'],",
+ " platform_type = 'ios',",
+ " avoid_deps = [':avoidLib'],",
+ ")",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ], deps = [':avoidLib', ':baseLib'])",
+ "objc_library(",
+ " name = 'baseLib',",
+ " srcs = [ 'base.m' ],",
+ " sdk_frameworks = ['BaseSDK'],",
+ " resources = [':base.png']",
+ ")",
+ "objc_library(",
+ " name = 'avoidLib',",
+ " srcs = [ 'c.m' ],",
+ " sdk_frameworks = ['AvoidSDK'],",
+ " resources = [':avoid.png']",
+ ")");
+
+ ObjcProvider provider = providerForTarget("//package:test");
+ // Do not remove SDK_FRAMEWORK or GENERAL_RESOURCE_FILE values in avoid_deps.
+ assertThat(provider.get(ObjcProvider.SDK_FRAMEWORK))
+ .containsAllOf(new SdkFramework("AvoidSDK"), new SdkFramework("BaseSDK"));
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.GENERAL_RESOURCE_FILE)))
+ .containsExactly("package/base.png");
+ }
+
+ @Test
+ public void testNoSrcs() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " deps = [':objcLib'],",
+ " platform_type = 'ios',",
+ ")",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction action = linkLibAction("//package:test");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).contains("package/libobjcLib.a");
+ }
+
+ @Test
+ public void testLipoAction() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test',",
+ " platform_type = 'ios',",
+ " srcs = [ 'a.m' ])");
+
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+
+ CommandAction action = (CommandAction) lipoLibAction("//package:test");
+ String i386Lib =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS) + "package/test-fl.a";
+ String x8664Lib =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS) + "package/test-fl.a";
+
+ assertThat(Artifact.toExecPaths(action.getInputs()))
+ .containsExactly(i386Lib, x8664Lib, MOCK_XCRUNWRAPPER_PATH);
+
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_XCRUNWRAPPER_PATH,
+ LIPO,
+ "-create",
+ i386Lib,
+ x8664Lib,
+ "-o",
+ execPathEndingWith(action.getOutputs(), "test_lipo.a"))
+ .inOrder();
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("package/test_lipo.a");
+ assertRequiresDarwin(action);
+ }
+
+ @Test
+ public void testWatchSimulatorDepCompile() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " srcs = ['a.m'],",
+ " deps = [':objcLib'],",
+ " platform_type = 'watchos'",
+ ")",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+
+ Action lipoAction = lipoLibAction("//package:test");
+
+ String i386Bin =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS) + "package/test-fl.a";
+ Artifact libArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(libArtifact);
+ CommandAction objcLibCompileAction =
+ (CommandAction)
+ getGeneratingAction(getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+
+ assertAppleSdkPlatformEnv(objcLibCompileAction, "WatchSimulator");
+ assertThat(objcLibCompileAction.getArguments()).containsAllOf("-arch_only", "i386").inOrder();
+ }
+
+ @Test
+ public void testMultiarchCcDep() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(name = 'test',",
+ " srcs = [ 'a.m' ],",
+ " deps = [ ':cclib' ],",
+ " platform_type = 'ios')",
+ "cc_library(name = 'cclib', srcs = ['dep.c'])");
+
+ useConfiguration(
+ "--ios_multi_cpus=i386,x86_64",
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ CommandAction action = (CommandAction) lipoLibAction("//package:test");
+ String i386Prefix =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS,
+ DEFAULT_IOS_SDK_VERSION);
+ String x8664Prefix =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS,
+ DEFAULT_IOS_SDK_VERSION);
+
+ CommandAction i386BinAction =
+ (CommandAction)
+ getGeneratingAction(
+ getFirstArtifactEndingWith(action.getInputs(), i386Prefix + "package/test-fl.a"));
+
+ CommandAction x8664BinAction =
+ (CommandAction)
+ getGeneratingAction(
+ getFirstArtifactEndingWith(action.getInputs(), x8664Prefix + "package/test-fl.a"));
+
+ assertThat(Artifact.toExecPaths(i386BinAction.getInputs()))
+ .containsAllOf(i386Prefix + "package/libtest.a", i386Prefix + "package/libcclib.a");
+ assertThat(Artifact.toExecPaths(x8664BinAction.getInputs()))
+ .containsAllOf(x8664Prefix + "package/libtest.a", x8664Prefix + "package/libcclib.a");
+ }
+
+ @Test
+ public void testWatchSimulatorLipoAction() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'watchos')");
+
+ // Tests that ios_multi_cpus and ios_cpu are completely ignored.
+ useConfiguration("--ios_multi_cpus=x86_64", "--ios_cpu=x86_64", "--watchos_cpus=i386,armv7k");
+
+ CommandAction action = (CommandAction) lipoLibAction("//package:test");
+ String i386Bin = configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "package/test-fl.a";
+ String armv7kBin = configurationBin("armv7k", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "package/test-fl.a";
+
+ assertThat(Artifact.toExecPaths(action.getInputs()))
+ .containsExactly(i386Bin, armv7kBin, MOCK_XCRUNWRAPPER_PATH);
+
+ assertContainsSublist(action.getArguments(), ImmutableList.of(
+ MOCK_XCRUNWRAPPER_PATH, LIPO, "-create"));
+ assertThat(action.getArguments()).containsAllOf(armv7kBin, i386Bin);
+ assertContainsSublist(action.getArguments(), ImmutableList.of(
+ "-o", execPathEndingWith(action.getOutputs(), "test_lipo.a")));
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("package/test_lipo.a");
+ assertAppleSdkPlatformEnv(action, "WatchOS");
+ assertRequiresDarwin(action);
+ }
+
+ @Test
+ public void testProtoDeps() throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_main',",
+ " srcs = ['data_a.proto', 'data_b.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_low_level',",
+ " srcs = ['data_b.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_main',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_main'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_low_level',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos_low_level'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'main_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_main',]",
+ ")",
+ "objc_library(",
+ " name = 'apple_low_level_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_low_level',]",
+ ")");
+
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "deps", "['//libs:main_lib']",
+ "avoid_deps", "['//libs:apple_low_level_lib']");
+
+ CommandAction linkAction = linkLibAction("//x:x");
+ Iterable<Artifact> linkActionInputs = linkAction.getInputs();
+
+ ImmutableList.Builder<Artifact> objects = ImmutableList.builder();
+ for (Artifact binActionArtifact : linkActionInputs) {
+ if (binActionArtifact.getRootRelativePath().getPathString().endsWith(".a")) {
+ CommandAction subLinkAction = (CommandAction) getGeneratingAction(binActionArtifact);
+ for (Artifact linkActionArtifact : subLinkAction.getInputs()) {
+ if (linkActionArtifact.getRootRelativePath().getPathString().endsWith(".o")) {
+ objects.add(linkActionArtifact);
+ }
+ }
+ }
+ }
+
+ ImmutableList<Artifact> objectFiles = objects.build();
+ assertThat(getFirstArtifactEndingWith(objectFiles, "DataA.pbobjc.o")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(objectFiles, "DataB.pbobjc.o")).isNull();
+ }
+
+ @Test
+ public void testMinimumOs() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "minimum_os_version", "'5.4'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction linkAction = linkLibAction("//x:x");
+ CommandAction objcLibArchiveAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+ CommandAction objcLibCompileAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(objcLibArchiveAction.getInputs(), "b.o"));
+
+ String compileArgs = Joiner.on(" ").join(objcLibCompileAction.getArguments());
+ assertThat(compileArgs).contains("-mios-simulator-version-min=5.4");
+ }
+
+ @Test
+ public void testMinimumOs_watchos() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "platform_type", "'watchos'",
+ "minimum_os_version", "'5.4'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction linkAction = linkLibAction("//x:x");
+ CommandAction objcLibArchiveAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+ CommandAction objcLibCompileAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(objcLibArchiveAction.getInputs(), "b.o"));
+
+ String compileArgs = Joiner.on(" ").join(objcLibCompileAction.getArguments());
+ assertThat(compileArgs).contains("-mwatchos-simulator-version-min=5.4");
+ }
+
+ @Test
+ public void testMinimumOs_invalid_nonVersion() throws Exception {
+ checkMinimumOs_invalid_nonVersion(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid_containsAlphabetic() throws Exception {
+ checkMinimumOs_invalid_containsAlphabetic(RULE_TYPE);
+ }
+
+ @Test
+ public void testMinimumOs_invalid_tooManyComponents() throws Exception {
+ checkMinimumOs_invalid_tooManyComponents(RULE_TYPE);
+ }
+
+ @Test
+ public void testFilesToCompileOutputGroup() throws Exception {
+ checkFilesToCompileOutputGroup(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'ios')");
+
+ CommandAction action = linkLibAction("//package:test");
+
+ assertAppleSdkVersionEnv(action);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'ios')");
+ useConfiguration("--ios_sdk_version=8.1");
+
+ CommandAction action = linkLibAction("//package:test");
+
+ assertAppleSdkVersionEnv(action, "8.1");
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'ios')");
+ CommandAction action = linkLibAction("//package:test");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneSimulator");
+ }
+
+ @Test
+ public void testAppleSdkIphoneosPlatformEnv() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'ios')");
+ useConfiguration("--cpu=ios_arm64");
+
+ CommandAction action = linkLibAction("//package:test");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneOS");
+ }
+
+ @Test
+ public void testAppleSdkWatchsimulatorPlatformEnv() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'watchos')");
+ useConfiguration("--watchos_cpus=i386");
+
+ Action lipoAction = lipoLibAction("//package:test");
+
+ String i386Lib =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS) + "package/test-fl.a";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Lib);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchSimulator");
+ }
+
+ @Test
+ public void testAppleSdkWatchosPlatformEnv() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'watchos')");
+ useConfiguration("--watchos_cpus=armv7k");
+
+ Action lipoAction = lipoLibAction("//package:test");
+
+ String armv7kLib =
+ configurationBin("armv7k", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "package/test-fl.a";
+ Artifact libArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), armv7kLib);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(libArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchOS");
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(name = 'test', srcs = [ 'a.m' ], platform_type = 'ios')");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction action = linkLibAction("//package:test");
+
+ assertXcodeVersionEnv(action, "5.8");
+ }
+
+ @Test
+ public void testWatchSimulatorLinkAction() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " srcs = ['a.m'],",
+ " deps = [':objcLib'],",
+ " platform_type = 'watchos'",
+ ")",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+
+ // Tests that ios_multi_cpus and ios_cpu are completely ignored.
+ useConfiguration("--ios_multi_cpus=x86_64", "--ios_cpu=x86_64", "--watchos_cpus=i386");
+
+ Action lipoAction = lipoLibAction("//package:test");
+
+ String i386Bin =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS) + "package/test-fl.a";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchSimulator");
+ assertThat(normalizeBashArgs(linkAction.getArguments()))
+ .containsAllOf("-arch_only", "i386")
+ .inOrder();
+ }
+
+ @Test
+ public void testAppleStaticLibraryProvider() throws Exception {
+ scratch.file(
+ "lib/BUILD",
+ "apple_static_library(",
+ " name = 'applelib',",
+ " srcs = ['a.m'],",
+ " platform_type = 'ios',",
+ " hdrs = ['a.h'],",
+ ")");
+ ConfiguredTarget binTarget = getConfiguredTarget("//lib:applelib");
+ AppleStaticLibraryProvider provider =
+ (AppleStaticLibraryProvider) binTarget.get(
+ AppleStaticLibraryProvider.SKYLARK_CONSTRUCTOR.getKey());
+ assertThat(provider).isNotNull();
+ assertThat(provider.getMultiArchArchive()).isNotNull();
+ assertThat(provider.getDepsObjcProvider()).isNotNull();
+ assertThat(provider.getMultiArchArchive()).isEqualTo(
+ Iterables.getOnlyElement(
+ provider.getDepsObjcProvider().get(ObjcProvider.MULTI_ARCH_LINKED_ARCHIVES)));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryTest.java
new file mode 100644
index 0000000000..d1927fd53d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleStubBinaryTest.java
@@ -0,0 +1,153 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.rules.apple.Platform.PlatformType;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_stub_binary. */
+@RunWith(JUnit4.class)
+public class AppleStubBinaryTest extends ObjcRuleTestCase {
+
+ static final RuleType RULE_TYPE =
+ new RuleType("apple_stub_binary") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("platform_type")) {
+ attributes.add("platform_type = 'ios'");
+ }
+ return attributes.build();
+ }
+ };
+
+ @Test
+ public void testCopyActionEnv() throws Exception {
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "xcenv_based_path",
+ "'$(SDKROOT)/Library/Application Support/WatchKit/WK'",
+ "platform_type",
+ "'watchos'");
+
+ useConfiguration(
+ "--watchos_cpus=i386,armv7k", "--xcode_version=7.3", "--watchos_sdk_version=2.1");
+
+ CommandAction action = (CommandAction) lipoBinAction("//x:x");
+ assertAppleSdkVersionEnv(action, "2.1");
+ assertAppleSdkPlatformEnv(action, "WatchOS");
+ assertXcodeVersionEnv(action, "7.3");
+ }
+
+ @Test
+ public void testFailsWithUndefinedVar() throws Exception {
+ String target =
+ RULE_TYPE.target(
+ scratch,
+ "x",
+ "x",
+ "xcenv_based_path",
+ "'$(NOT_ALLOWED)/Library/Application Support/WatchKit/WK'");
+ useConfiguration("--xcode_version=7.3");
+
+ checkError("x", "x", "The stub binary path must be rooted at", target);
+ }
+
+ @Test
+ public void testFailsIfPathDoesNotBeginWithVar() throws Exception {
+ String target =
+ RULE_TYPE.target(
+ scratch, "x", "x", "xcenv_based_path", "'/Library/Application Support/WatchKit/WK'");
+ useConfiguration("--xcode_version=7.3");
+
+ checkError("x", "x", "The stub binary path must be rooted at", target);
+ }
+
+ @Test
+ public void testFailsWithUnnormalizedPath() throws Exception {
+ String target =
+ RULE_TYPE.target(
+ scratch,
+ "x",
+ "x",
+ "xcenv_based_path",
+ "'$(SDKROOT)/../Library/Application Support/WatchKit/WK'");
+ useConfiguration("--xcode_version=7.3");
+
+ checkError("x", "x", AppleStubBinary.PATH_NOT_NORMALIZED_ERROR, target);
+ }
+
+ @Test
+ public void testPlatformSelectionIos() throws Exception {
+ checkObjcPropagatedResourcesRespectPlatform(PlatformType.IOS);
+ }
+
+ @Test
+ public void testPlatformSelectionTvos() throws Exception {
+ checkObjcPropagatedResourcesRespectPlatform(PlatformType.TVOS);
+ }
+
+ private void checkObjcPropagatedResourcesRespectPlatform(PlatformType platformType)
+ throws Exception {
+ String platformName = platformType.toString();
+
+ scratch.file("x/a.m");
+ scratch.file("x/ios.txt");
+ scratch.file("x/tvos.txt");
+ scratch.file(
+ "x/BUILD",
+ "apple_stub_binary(",
+ " name = 'bin',",
+ " platform_type = '" + platformName + "',",
+ " xcenv_based_path = '$(SDKROOT)/foo/bar',",
+ " deps = [':lib'],",
+ ")",
+ "",
+ "config_setting(name = 'ios', values = {'apple_platform_type': 'ios'})",
+ "config_setting(name = 'tvos', values = {'apple_platform_type': 'tvos'})",
+ "",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " resources = select({",
+ " ':ios': ['ios.txt'],",
+ " ':tvos': ['tvos.txt'],",
+ " })",
+ ")");
+
+ ConfiguredTarget target = getConfiguredTarget("//x:bin");
+ ObjcProvider objc = (ObjcProvider) target.get(ObjcProvider.OBJC_SKYLARK_PROVIDER_NAME);
+
+ // The propagated objc provider should only contain one file, and that file is the one selected
+ // for the given platform type.
+ NestedSet<BundleableFile> bundleFiles = objc.get(ObjcProvider.BUNDLE_FILE);
+ assertThat(bundleFiles).hasSize(1);
+
+ BundleableFile bundleFile = bundleFiles.iterator().next();
+ assertThat(bundleFile.getBundled().getFilename()).isEqualTo(platformName + ".txt");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleToolchainSelectionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleToolchainSelectionTest.java
new file mode 100644
index 0000000000..b062851303
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleToolchainSelectionTest.java
@@ -0,0 +1,183 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+
+import com.google.common.base.Joiner;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.cpp.CppConfiguration;
+import com.google.devtools.build.lib.rules.cpp.CppLinkAction;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for the use of the OSX crosstool. */
+@RunWith(JUnit4.class)
+public class AppleToolchainSelectionTest extends ObjcRuleTestCase {
+
+ @Override
+ protected void useConfiguration(String... args) throws Exception {
+ useConfiguration(ObjcCrosstoolMode.LIBRARY, args);
+ }
+
+ /**
+ * Returns the given target in the configuration that it would be given by this
+ * {@code BuildViewTestCase}'s {@code Transitions}, were the target a top-level target.
+ */
+ private ConfiguredTarget getTopLevelConfiguredTarget(ConfiguredTarget target)
+ throws InterruptedException {
+ BuildConfiguration topLevelConfig = getAppleCrosstoolConfiguration();
+ return getConfiguredTarget(target.getLabel(), topLevelConfig);
+ }
+
+ /**
+ * Returns the action that produces the artifact with the given label and suffix, in a output
+ * directory consistent with that action being registered by a top-level target.
+ */
+ private CommandAction actionProducingArtifactForTopLevelTarget(String targetLabel,
+ String artifactSuffix) throws Exception {
+ ConfiguredTarget libraryTarget = getConfiguredTarget(targetLabel);
+ ConfiguredTarget topLevelLibraryTarget = getTopLevelConfiguredTarget(libraryTarget);
+ Label parsedLabel = Label.parseAbsolute(targetLabel);
+ Artifact linkedLibrary = getBinArtifact(
+ parsedLabel.getName() + artifactSuffix,
+ topLevelLibraryTarget);
+ return (CommandAction) getGeneratingAction(linkedLibrary);
+ }
+
+ @Test
+ public void testToolchainSelectionDefault() throws Exception {
+ createLibraryTargetWriter("//a:lib").write();
+ CppConfiguration cppConfig =
+ getAppleCrosstoolConfiguration().getFragment(CppConfiguration.class);
+
+ assertThat(cppConfig.getCrosstoolTopPathFragment().toString())
+ .isEqualTo("tools/osx/crosstool");
+ assertThat(cppConfig.getToolchainIdentifier())
+ .isEqualTo("ios_x86_64");
+ }
+
+ @Test
+ public void testToolchainSelectionIosDevice() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ createLibraryTargetWriter("//a:lib").write();
+ CppConfiguration cppConfig =
+ getAppleCrosstoolConfiguration().getFragment(CppConfiguration.class);
+
+ assertThat(cppConfig.getCrosstoolTopPathFragment().toString())
+ .isEqualTo("tools/osx/crosstool");
+ assertThat(cppConfig.getToolchainIdentifier())
+ .isEqualTo("ios_armv7");
+ }
+
+ @Test
+ public void testToolchainSelectionCcDepDefault() throws Exception {
+ useConfiguration(
+ "--experimental_disable_jvm",
+ "--experimental_disable_go");
+ ScratchAttributeWriter
+ .fromLabelString(this, "cc_library", "//b:lib")
+ .setList("srcs", "b.cc")
+ .write();
+ createBinaryTargetWriter("//a:bin")
+ .setList("srcs", "a.m")
+ .setList("deps", "//b:lib")
+ .write();
+
+ CommandAction linkAction = actionProducingArtifactForTopLevelTarget("//a:bin", "_bin");
+ Artifact ccArchive = getFirstArtifactEndingWith(linkAction.getInputs(), "liblib.a");
+ CommandAction ccArchiveAction = (CommandAction) getGeneratingAction(ccArchive);
+ Artifact ccObjectFile = getFirstArtifactEndingWith(ccArchiveAction.getInputs(), ".o");
+ CommandAction ccCompileAction = (CommandAction) getGeneratingAction(ccObjectFile);
+ assertThat(ccCompileAction.getArguments()).contains("tools/osx/crosstool/iossim/wrapped_clang");
+ }
+
+ @Test
+ public void testToolchainSelectionCcDepDevice() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ ScratchAttributeWriter
+ .fromLabelString(this, "cc_library", "//b:lib")
+ .setList("srcs", "b.cc")
+ .write();
+ createBinaryTargetWriter("//a:bin")
+ .setList("srcs", "a.m")
+ .setList("deps", "//b:lib")
+ .write();
+ CommandAction linkAction = actionProducingArtifactForTopLevelTarget("//a:bin", "_bin");
+ Artifact ccArchive = getFirstArtifactEndingWith(linkAction.getInputs(), "liblib.a");
+ CommandAction ccArchiveAction = (CommandAction) getGeneratingAction(ccArchive);
+ Artifact ccObjectFile = getFirstArtifactEndingWith(ccArchiveAction.getInputs(), ".o");
+ CommandAction ccCompileAction = (CommandAction) getGeneratingAction(ccObjectFile);
+ assertThat(ccCompileAction.getArguments()).contains("tools/osx/crosstool/ios/wrapped_clang");
+ }
+
+ @Test
+ public void testToolchainSelectionMultiArchIos() throws Exception {
+ useConfiguration(
+ "--experimental_disable_jvm",
+ "--ios_multi_cpus=armv7,arm64");
+ ScratchAttributeWriter
+ .fromLabelString(this, "cc_library", "//b:lib")
+ .setList("srcs", "a.cc")
+ .write(getAppleCrosstoolConfiguration());
+ ScratchAttributeWriter
+ .fromLabelString(this, "apple_binary", "//a:bin")
+ .set("platform_type", "'ios'")
+ .setList("deps", "//b:lib")
+ .write();
+ Action lipoAction = actionProducingArtifact("//a:bin", "_lipobin");
+ String armv64Bin =
+ configurationBin("arm64", ConfigurationDistinguisher.APPLEBIN_IOS,
+ DEFAULT_IOS_SDK_VERSION)
+ + "a/bin_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), armv64Bin);
+ CommandAction linkAction = getGeneratingSpawnAction(binArtifact);
+ CppLinkAction objcLibArchiveAction = (CppLinkAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "liblib.a"));
+ assertThat(Joiner.on(" ").join(objcLibArchiveAction.getArgv())).contains("ios_arm64");
+ }
+
+ @Test
+ public void testToolchainSelectionMultiArchWatchos() throws Exception {
+ useConfiguration(
+ "--experimental_disable_jvm",
+ "--ios_multi_cpus=armv7,arm64",
+ "--watchos_cpus=armv7k");
+ ScratchAttributeWriter
+ .fromLabelString(this, "cc_library", "//b:lib")
+ .setList("srcs", "a.cc")
+ .write(getAppleCrosstoolConfiguration());
+ ScratchAttributeWriter
+ .fromLabelString(this, "apple_binary", "//a:bin")
+ .setList("deps", "//b:lib")
+ .set("platform_type", "\"watchos\"")
+ .write();
+
+ CommandAction linkAction = linkAction("//a:bin");
+ CppLinkAction objcLibCompileAction = (CppLinkAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "liblib.a"));
+ assertThat(Joiner.on(" ").join(objcLibCompileAction.getArgv())).contains("watchos_armv7k");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch1ExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch1ExtensionTest.java
new file mode 100644
index 0000000000..9bad38b731
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch1ExtensionTest.java
@@ -0,0 +1,1005 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_PROVISIONING_PROFILE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_PROVISIONING_PROFILE_ATTR;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multiset;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.Control;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.MergeZip;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_watch1_extension. */
+@RunWith(JUnit4.class)
+public class AppleWatch1ExtensionTest extends ObjcRuleTestCase {
+ private static final RuleType RULE_TYPE = new RuleType("apple_watch1_extension") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("binary")) {
+ scratch.file(packageDir + "/extension_binary/a.m");
+ scratch.file(packageDir + "/extension_binary/BUILD",
+ "apple_watch_extension_binary(",
+ " name = 'extension_binary',",
+ " srcs = ['a.m'],",
+ ")");
+ attributes.add(String.format("binary = '//%s/extension_binary'", packageDir));
+ }
+ if (!alreadyAdded.contains("app_name")) {
+ attributes.add("app_name = 'y'");
+ }
+ return attributes.build();
+ }
+ };
+
+ protected static final BinaryRuleTypePair RULE_TYPE_PAIR =
+ new BinaryRuleTypePair(
+ AppleWatchExtensionBinaryTest.RULE_TYPE,
+ RULE_TYPE,
+ ReleaseBundlingSupport.EXTENSION_BUNDLE_DIR_FORMAT);
+
+ private ConfiguredTarget addMockExtensionAndLibs(String... extraExtAttributes)
+ throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ scratch.file("x/a.m");
+ scratch.file("x/BUILD",
+ "apple_watch_extension_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " deps = ['//lib1:lib1', '//lib2:lib2'],",
+ ")",
+ "",
+ "apple_watch1_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = ':bin',",
+ Joiner.on(',').join(extraExtAttributes),
+ ")");
+ return getConfiguredTarget("//x:x");
+ }
+
+ private void addEntitlements() throws Exception {
+ scratch.file("x/ext_entitlements.entitlements");
+ scratch.file("x/app_entitlements.entitlements");
+ addMockExtensionAndLibs(
+ "ext_entitlements = 'ext_entitlements.entitlements'",
+ "app_entitlements = 'app_entitlements.entitlements'");
+ }
+
+ private Action watchApplicationIpaGeneratingAction() throws Exception {
+ return getGeneratingAction(getBinArtifact("_watch/x/y.ipa",
+ "//x:x"));
+ }
+
+ @Test
+ public void testExtensionSigningAction() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) getGeneratingActionForLabel("//x:x.ipa");
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ @Test
+ public void testApplicationSigningAction() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) watchApplicationIpaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x-y.entitlements", "foo.mobileprovision", "x-y.unprocessed.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/_watch/x/y.ipa");
+ }
+
+ @Test
+ public void testExtensionSigningWithCertName() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_signing_cert_name=Foo Bar");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) getGeneratingActionForLabel("//x:x.ipa");
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("--sign \"Foo Bar\"");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ @Test
+ public void testApplicationSigningWithCertName() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_signing_cert_name=Foo Bar");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) watchApplicationIpaGeneratingAction();
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x-y.entitlements", "foo.mobileprovision", "x-y.unprocessed.ipa");
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("--sign \"Foo Bar\"");
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/_watch/x/y.ipa");
+ }
+
+ @Test
+ public void testSigning_simulatorBuild() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild_multiCpu() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testUserSpecifiedExtensionProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, false,
+ WATCH_EXT_PROVISIONING_PROFILE_ATTR);
+ }
+
+ @Test
+ public void testUserSpecifiedApplicationProvisioningProfile_deviceBuild() throws Exception {
+ checkSpecifiedApplicationProvisioningProfile(false);
+ }
+
+ @Test
+ public void testUserSpecifiedExtensionProvisioningProfile_deviceBuild_multiCpu()
+ throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, true,
+ WATCH_EXT_PROVISIONING_PROFILE_ATTR);
+ }
+
+ @Test
+ public void testUserSpecifiedApplicationProvisioningProfile_deviceBuild_multiCpu()
+ throws Exception {
+ checkSpecifiedApplicationProvisioningProfile(true);
+ }
+
+ private void checkSpecifiedApplicationProvisioningProfile(boolean useMultiCpu) throws Exception {
+ setArtifactPrefix("y");
+ if (useMultiCpu) {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--cpu=ios_i386");
+ } else {
+ useConfiguration("--cpu=ios_armv7");
+ }
+
+ addCustomProvisioningProfile(RULE_TYPE_PAIR, WATCH_APP_PROVISIONING_PROFILE_ATTR);
+ getConfiguredTarget("//x:x");
+
+ Artifact defaultProvisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ Artifact customProvisioningProfile =
+ getFileConfiguredTarget("//custom:pp.mobileprovision").getArtifact();
+ Action signingAction = watchApplicationIpaGeneratingAction();
+ assertThat(signingAction.getInputs()).contains(customProvisioningProfile);
+ assertThat(signingAction.getInputs()).doesNotContain(defaultProvisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ Map<String, String> expectedProfiles = ImmutableMap.of(
+ customProvisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ @Test
+ public void testExtensionMergeControlAction() throws Exception {
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly(
+ "x/x.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .addBundleFile(
+ BundleFile.newBuilder()
+ .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "x_lipobin"))
+ .setBundlePath("x")
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build())
+ .setBundleRoot("PlugIns/x.appex")
+ .addMergeZip(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("PlugIns/x.appex/")
+ .setSourcePath(
+ execPathEndingWith(mergeAction.getInputs(), "_watch/x/y.zip"))
+ .build())
+ .setBundleInfoPlistFile(
+ getMergedInfoPlist(getConfiguredTarget("//x:x")).getExecPathString())
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x.unprocessed.ipa"))
+ .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.ext.x")
+ .build());
+ }
+
+ @Test
+ public void testApplicationMergeControlAction() throws Exception {
+ setArtifactPrefix("y");
+ addMockExtensionAndLibs("app_infoplists = ['Info.plist']");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly(
+ "x/x-y.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .setBundleRoot("Payload/y.app")
+ .addMergeZip(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/y.app/")
+ .setSourcePath(
+ getBinArtifact("_watch/x/WatchKitStub.zip", "//x:x")
+ .getExecPathString())
+ .build())
+ .setBundleInfoPlistFile(
+ getMergedInfoPlist(getConfiguredTarget("//x:x")).getExecPathString())
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x-y.unprocessed.ipa"))
+ .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.app.y")
+ .build());
+ }
+
+ @Test
+ public void testMergeExtensionBundleAction() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ "ext_infoplists", "['Info.plist']");
+ SpawnAction action = bundleMergeAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ "x/x_lipobin",
+ "x/x.ipa-control",
+ "x/x-MergedInfo.plist",
+ "x/_watch/x/y.zip");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ execPathEndingWith(action.getInputs(), "x.ipa-control"))
+ .inOrder();
+ }
+
+ @Test
+ public void testMergeApplicationBundleAction() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ "app_infoplists", "['Info.plist']");
+ setArtifactPrefix("y");
+ SpawnAction action = bundleMergeAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ "x/x-y.ipa-control",
+ "x/x-y-MergedInfo.plist",
+ "x/_watch/x/WatchKitStub.zip");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x-y.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ execPathEndingWith(action.getInputs(), "x-y.ipa-control"))
+ .inOrder();
+ }
+
+ protected List<BuildConfiguration> getExtensionConfigurations() throws InterruptedException {
+ return getSplitConfigurations(getTargetConfiguration(),
+ AppleWatch1Extension.MINIMUM_OS_AND_SPLIT_ARCH_TRANSITION);
+ }
+
+ @Test
+ public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, WATCH_APP_ICON_ATTR, WATCH_EXT_INFOPLISTS_ATTR,
+ "['pl.plist']");
+ }
+
+ @Override
+ protected void checkCollectsAssetCatalogsTransitively(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ scratch.file("lib/ac.xcassets/foo");
+ scratch.file("lib/ac.xcassets/bar");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+
+ scratch.file("x/ac.xcassets/baz");
+ scratch.file("x/ac.xcassets/42");
+ ruleTypePair.scratchTargets(scratch,
+ "deps", "['//lib:lib']",
+ "app_asset_catalogs", "glob(['ac.xcassets/**'])");
+
+ // Test that the actoolzip Action for extension has arguments and inputs obtained from
+ // dependencies.
+ SpawnAction extensionActoolZipAction = actoolZipActionForIpa("//x:x");
+ assertThat(Artifact.toExecPaths(extensionActoolZipAction.getInputs())).containsExactly(
+ "lib/ac.xcassets/foo", "lib/ac.xcassets/bar",
+ MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(extensionActoolZipAction.getArguments(),
+ ImmutableList.of("lib/ac.xcassets"));
+
+ // Test that the actoolzip Action for application has arguments and inputs obtained from
+ // dependencies.
+ SpawnAction applicationActoolZipAction = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x-y.actool.zip", "//x:x"));
+ assertThat(Artifact.toExecPaths(applicationActoolZipAction.getInputs())).containsExactly(
+ "x/ac.xcassets/baz", "x/ac.xcassets/42",
+ MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(applicationActoolZipAction.getArguments(),
+ ImmutableList.of("x/ac.xcassets"));
+ }
+
+ @Test
+ public void testCollectsAssetCatalogsTransitively() throws Exception {
+ checkCollectsAssetCatalogsTransitively(RULE_TYPE_PAIR);
+ }
+
+ private void addTargetWithAssetCatalogs() throws IOException {
+ scratch.file("x/foo.xcassets/foo");
+ scratch.file("x/foo.xcassets/bar");
+ scratch.file("x/a.m");
+ scratch.file("x/BUILD",
+ "apple_watch_extension_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "apple_watch1_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testActoolActionCorrectness() throws Exception {
+ addTargetWithAssetCatalogs();
+ setArtifactPrefix("y");
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION,
+ TargetDeviceFamily.WATCH.getNameInRule().toLowerCase(), "iphonesimulator");
+ }
+
+ @Test
+ public void testPassesFamiliesToActool() throws Exception {
+ checkPassesFamiliesToActool(RULE_TYPE_PAIR, AppleWatch1ExtensionRule.WATCH_EXT_FAMILIES_ATTR);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE_PAIR, AppleWatch1ExtensionRule.WATCH_EXT_FAMILIES_ATTR);
+ }
+
+ @Test
+ public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE,
+ AppleWatch1ExtensionRule.WATCH_EXT_FAMILIES_ATTR);
+ }
+
+ @Test
+ public void testMergeActionsWithAssetCatalog() throws Exception {
+ addTargetWithAssetCatalogs();
+ setArtifactPrefix("y");
+ Artifact actoolZipOut = getBinArtifact("x-y.actool.zip", "//x:x");
+ assertThat(bundleMergeAction("//x:x").getInputs()).contains(actoolZipOut);
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/y.app/")
+ .setSourcePath(actoolZipOut.getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/y.app/")
+ .setSourcePath(getBinArtifact("_watch/x/WatchKitStub.zip", "//x:x")
+ .getExecPathString())
+ .build());
+ }
+
+ private void addBinAndLibWithRawResources() throws Exception {
+ addBinAndLibWithResources(
+ "resources", "resource1.txt", "ja.lproj/resource2.txt", "apple_watch_extension_binary");
+ scratch.file("app_resource.txt");
+ scratch.file("ext_resource.txt");
+ scratch.file("x/BUILD",
+ "apple_watch1_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = '//bin:bin',",
+ " app_resources = ['app_resource.txt'],",
+ " ext_resources = ['ext_resource.txt'],",
+ ")");
+ }
+
+ private void addBinAndLibWithStrings() throws Exception {
+ addBinAndLibWithResources(
+ "strings", "foo.strings", "ja.lproj/bar.strings", "apple_watch_extension_binary");
+ scratch.file("app.strings");
+ scratch.file("x/BUILD",
+ "apple_watch1_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = '//bin:bin',",
+ " app_strings = ['app.strings'],",
+ ")");
+ }
+
+ @Test
+ public void testCollectsRawResourceFilesTransitively() throws Exception {
+ addBinAndLibWithRawResources();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("lib/resource1.txt", "bin/ja.lproj/resource2.txt"),
+ ImmutableList.of("lib/resource1.txt"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin", ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "x_x", ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt",
+ "x/ext_resource.txt"),
+ "lib_lib", ImmutableMultiset.of("lib/resource1.txt"),
+ "y__x", ImmutableMultiset.of("x/app_resource.txt")));
+ }
+
+ @Test
+ public void testCollectsStringsFilesTransitively() throws Exception {
+ addBinAndLibWithStrings();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("x/lib/foo.strings.binary", "x/bin/ja.lproj/bar.strings.binary"),
+ ImmutableList.of("lib/foo.strings.binary"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin", ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "x_x", ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "lib_lib", ImmutableMultiset.of("lib/foo.strings"),
+ "y__x", ImmutableMultiset.of("x/app.strings")));
+ }
+
+ @Test
+ public void testResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithRawResources();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "resource1.txt", "resource1.txt",
+ "ja.lproj/resource2.txt", "ja.lproj/resource2.txt"));
+ }
+
+ @Test
+ public void testStringsFilesMergedInBundle() throws Exception {
+ addBinAndLibWithStrings();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "foo.strings.binary", "foo.strings",
+ "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings"));
+ }
+
+ @Test
+ public void testPlistRequiresDotInName() throws Exception {
+ String errorMessage = "'//x:Infoplist' does not produce any apple_watch1_extension "
+ + "ext_infoplists files (expected .plist)";
+ checkError("x", "x",
+ errorMessage,
+ "apple_watch_extension_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "apple_watch1_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " ext_infoplists = ['Infoplist'],",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZipsForApplication() throws Exception {
+ addStoryboards();
+ setArtifactPrefix("y");
+ Artifact libsbOutputZip = getBinArtifact("x-y/libsb.storyboard.zip", "//x:x");
+
+ Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList()).containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/y.app/")
+ .setSourcePath(libsbOutputZip.getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/y.app/")
+ .setSourcePath(getBinArtifact("_watch/x/WatchKitStub.zip", "//x:x")
+ .getExecPathString())
+ .build());
+ }
+
+ protected void addStoryboards() throws Exception {
+ scratch.file("lib/libsb.storyboard");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("storyboards", "libsb.storyboard")
+ .write();
+
+ scratch.file("bndl/bndlsb.storyboard");
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " storyboards = ['ext_bndlsb.storyboard'],",
+ ")");
+
+ scratch.file("x/xsb.storyboard");
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ "storyboards", "['ext.storyboard']",
+ "app_deps", "['//lib:lib']",
+ "bundles", "['//bndl:bndl']");
+ getConfiguredTarget("//x:x");
+ }
+
+ @Test
+ public void testMergesPartialInfoplists() throws Exception {
+ scratch.file("x/primary-Info.plist");
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ "app_asset_catalogs", "['foo.xcassets/bar']",
+ "app_infoplists", "['primary-Info.plist']");
+
+ String targetName = "//x:x";
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+ Artifact merged = getBinArtifact("x-y-MergedInfo.plist", target);
+ Artifact actoolPartial = getBinArtifact("x-y.actool-PartialInfo.plist", "//x:x");
+
+ Artifact versionInfoplist = getBinArtifact("plists/x-y-version.plist", target);
+ Artifact environmentInfoplist = getBinArtifact("plists/x-y-environment.plist", target);
+ Artifact automaticInfoplist = getBinArtifact("plists/x-y-automatic.plist", target);
+
+ assertPlistMergeControlUsesSourceFiles(
+ control,
+ ImmutableList.<String>of(
+ "x/primary-Info.plist",
+ versionInfoplist.getExecPathString(),
+ environmentInfoplist.getExecPathString(),
+ automaticInfoplist.getExecPathString(),
+ actoolPartial.getExecPathString()));
+ assertThat(control.getOutFile()).isEqualTo(merged.getExecPathString());
+ assertThat(control.getVariableSubstitutionMapMap())
+ .containsExactlyEntriesIn(variableSubstitutionsForWatchApplication());
+ assertThat(control.getFallbackBundleId()).isEqualTo("example.app.y");
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPassesExtensionFallbackBundleIdToBundleMerging() throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Ext-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch,
+ WATCH_EXT_INFOPLISTS_ATTR, "['Ext-Info.plist']");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.hasPrimaryBundleIdentifier()).isFalse();
+ assertThat(control.getFallbackBundleIdentifier()).isEqualTo("example.ext.x");
+ }
+
+ @Test
+ public void testPassesApplicationFallbackBundleIdToBundleMerging() throws Exception {
+ setArtifactPrefix("y");
+ scratch.file("bin/a.m");
+ scratch.file("bin/App-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch,
+ WATCH_APP_INFOPLISTS_ATTR, "['App-Info.plist']");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.hasPrimaryBundleIdentifier()).isFalse();
+ assertThat(control.getFallbackBundleIdentifier()).isEqualTo("example.app.y");
+ }
+
+ @Test
+ public void testPassesExtensionPrimaryBundleIdToBundleMerging() throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Ext-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch,
+ WATCH_EXT_INFOPLISTS_ATTR, "['Ext-Info.plist']",
+ WATCH_EXT_BUNDLE_ID_ATTR, "'com.bundle.ext.id'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.bundle.ext.id");
+ assertThat(control.hasFallbackBundleIdentifier()).isFalse();
+ }
+
+ @Test
+ public void testPassesApplicationPrimaryBundleIdToBundleMerging() throws Exception {
+ setArtifactPrefix("y");
+ scratch.file("bin/a.m");
+ scratch.file("bin/App-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch,
+ WATCH_APP_INFOPLISTS_ATTR, "['App-Info.plist']",
+ WATCH_APP_BUNDLE_ID_ATTR, "'com.bundle.app.id'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.bundle.app.id");
+ assertThat(control.hasFallbackBundleIdentifier()).isFalse();
+ }
+
+ @Test
+ public void testMultiPlatformBuild_fails() throws Exception {
+ checkBinaryActionMultiPlatform_fails(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiArchitectureResources() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ RULE_TYPE_PAIR.scratchTargets(scratch, "resources", "['foo.png']");
+
+ assertThat(Artifact.toRootRelativePaths(bundleMergeAction("//x:x").getInputs()))
+ .containsExactly(
+ "x/foo.png",
+ "x/x_lipobin",
+ "tools/objc/bundlemerge",
+ "x/x.ipa-control",
+ "x/x-MergedInfo.plist",
+ "x/_watch/x/y.zip");
+ }
+
+ @Override
+ protected void addCommonResources(BinaryRuleTypePair ruleTypePair) throws Exception {
+ ruleTypePair.scratchTargets(scratch,
+ "strings", "['foo.strings']",
+ "storyboards", "['baz.storyboard']");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResources() throws Exception {
+ checkMultiCpuCompiledResources(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testConvertStringsActions() throws Exception {
+ checkConvertStringsAction(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testRegistersStoryboardCompileActions() throws Exception {
+ checkRegistersStoryboardCompileActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResourcesFromGenrule() throws Exception {
+ checkMultiCpuCompiledResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiCpuGeneratedResourcesFromGenrule() throws Exception {
+ checkMultiCpuGeneratedResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testTwoStringsOneBundlePath() throws Exception {
+ checkTwoStringsOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testTwoResourcesOneBundlePath() throws Exception {
+ checkTwoResourcesOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testSameStringsTwice() throws Exception {
+ checkSameStringsTwice(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInBundleMerge() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1");
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion())
+ .isEqualTo(WatchUtils.MINIMUM_OS_VERSION.toString());
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsVersionInBundleMergeAtMost82() throws Exception {
+ useConfiguration("--ios_minimum_os=8.3");
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion())
+ .isEqualTo("8.3");
+ }
+
+ @Test
+ public void testCheckExtensionPrimaryBundleIdInMergedPlist() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ WATCH_EXT_INFOPLISTS_ATTR, "['Info.plist']",
+ WATCH_EXT_BUNDLE_ID_ATTR, "'com.ext.bundle.id'");
+ scratch.file("ext/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.ext.bundle.id"),
+ getVariableSubstitutionArguments(RULE_TYPE_PAIR),
+ "example.ext.x");
+ }
+
+ @Test
+ public void testCheckApplicationPrimaryBundleIdInMergedPlist() throws Exception {
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ WATCH_APP_INFOPLISTS_ATTR, "['Info.plist']",
+ WATCH_APP_BUNDLE_ID_ATTR, "'com.app.bundle.id'");
+ scratch.file("app/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.app.bundle.id"),
+ variableSubstitutionsForWatchApplication(),
+ "example.app.y");
+ }
+
+ @Test
+ public void testCheckExtensionFallbackBundleIdInMergedPlist() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ WATCH_EXT_INFOPLISTS_ATTR, "['Info.plist']");
+ scratch.file("ext/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(),
+ getVariableSubstitutionArguments(RULE_TYPE_PAIR),
+ "example.ext.x");
+ }
+
+ @Test
+ public void testCheckApplicationFallbackBundleIdInMergedPlist() throws Exception {
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(scratch,
+ WATCH_APP_INFOPLISTS_ATTR, "['Info.plist']");
+ scratch.file("app/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(),
+ variableSubstitutionsForWatchApplication(),
+ "example.app.y");
+ }
+
+ private ImmutableMap<String, String> variableSubstitutionsForWatchApplication() {
+ return new ImmutableMap.Builder<String, String>()
+ .put("EXECUTABLE_NAME", "y")
+ .put("BUNDLE_NAME", "y.app")
+ .put("PRODUCT_NAME", "y")
+ .build();
+ }
+
+ protected void checkExtensionReplacesMinimumOsInCompilation() throws Exception {
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ Action lipoAction = lipoBinAction("//x:x");
+
+ for (Artifact bin : lipoAction.getInputs()) {
+ CommandAction action = (CommandAction) getGeneratingAction(bin);
+ if (action == null) {
+ continue;
+ }
+ assertThat(generatingArgumentsToString(action))
+ .contains("-mios-simulator-version-min=" + WatchUtils.MINIMUM_OS_VERSION);
+ assertThat(generatingArgumentsToString(action))
+ .doesNotContain("-mios-simulator-version-min=7.1");
+ }
+ }
+
+ private String generatingArgumentsToString(CommandAction generatingAction) {
+ return Joiner.on(' ').join(generatingAction.getArguments());
+ }
+
+ protected void checkExtensionDoesNotReplaceMinimumOsInCompilation() throws Exception {
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ Action lipoAction = lipoBinAction("//x:x");
+
+ for (Artifact bin : lipoAction.getInputs()) {
+ CommandAction action = (CommandAction) getGeneratingAction(bin);
+ if (action == null) {
+ continue;
+ }
+ assertThat(generatingArgumentsToString(action)).contains("-mios-simulator-version-min=8.3");
+ assertThat(generatingArgumentsToString(action))
+ .doesNotContain("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION);
+ }
+ }
+
+ @Test
+ public void testGenruleWithoutJavaCcDeps() throws Exception {
+ checkGenruleWithoutJavaCcDependency(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCcDependencyWithProtoDependencyMultiArch() throws Exception {
+ checkCcDependencyWithProtoDependencyMultiArch(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ BuildConfiguration extensionConfiguration =
+ Iterables.getOnlyElement(getExtensionConfigurations());
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE_PAIR, extensionConfiguration);
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZipsForExtension() throws Exception {
+ BuildConfiguration configuration = Iterables.getOnlyElement(getExtensionConfigurations());
+ addStoryboards();
+
+ Artifact extBndlsbOutputZip =
+ getBinArtifact(
+ "bndl/ext_bndlsb.storyboard.zip", getConfiguredTarget("//bndl:bndl", configuration));
+ Artifact extsbOutputZip = getBinArtifact("x/ext.storyboard.zip", "//x:x");
+
+ String bundleDir = RULE_TYPE_PAIR.getBundleDir();
+ Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(extsbOutputZip.getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(getBinArtifact("_watch/x/y.zip", "//x:x").getExecPathString())
+ .build());
+
+ Control nestedMergeControl = Iterables.getOnlyElement(mergeControl.getNestedBundleList());
+ assertThat(nestedMergeControl.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/bndl.bundle/")
+ .setSourcePath(extBndlsbOutputZip.getExecPathString())
+ .build());
+ }
+
+ @Test
+ public void testCcDependency() throws Exception {
+ checkCcDependency(RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyMultiArch() throws Exception {
+ checkCcDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyWithProtoDependency() throws Exception {
+ checkCcDependencyWithProtoDependency(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyAndJ2objcDependency() throws Exception {
+ checkCcDependencyAndJ2objcDependency(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testMultiArchitectureFanOut() throws Exception {
+ checkBinaryLipoActionMultiCpu(RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testGenruleDependencyMultiArch() throws Exception {
+ checkGenruleDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.WATCH_OS1_EXTENSION);
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilation() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1");
+ checkExtensionReplacesMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationAtMost82() throws Exception {
+ useConfiguration("--ios_minimum_os=8.3");
+ checkExtensionDoesNotReplaceMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationMultiArch() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1", "--ios_multi_cpus=i386,x86_64");
+ checkExtensionReplacesMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationAtMost82MultiArch() throws Exception {
+ useConfiguration("--ios_minimum_os=8.3", "--ios_multi_cpus=i386,x86_64");
+ checkExtensionDoesNotReplaceMinimumOsInCompilation();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch2ExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch2ExtensionTest.java
new file mode 100644
index 0000000000..0e187eccdb
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatch2ExtensionTest.java
@@ -0,0 +1,973 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_PROVISIONING_PROFILE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_PROVISIONING_PROFILE_ATTR;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ObjectArrays;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.Control;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.MergeZip;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_watch2_extension. */
+@RunWith(JUnit4.class)
+public class AppleWatch2ExtensionTest extends ObjcRuleTestCase {
+ private static final RuleType RULE_TYPE =
+ new RuleType("apple_watch2_extension") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("binary")) {
+ scratch.file(packageDir + "/extension_binary/a.m");
+ scratch.file(
+ packageDir + "/extension_binary/BUILD",
+ "apple_binary(",
+ " name = 'extension_binary',",
+ " srcs = ['a.m'],",
+ " platform_type = 'watchos'",
+ ")");
+ attributes.add(String.format("binary = '//%s/extension_binary'", packageDir));
+ }
+ if (!alreadyAdded.contains("app_name")) {
+ attributes.add("app_name = 'y'");
+ }
+ return attributes.build();
+ }
+ };
+
+ protected static final BinaryRuleTypePair RULE_TYPE_PAIR =
+ new BinaryRuleTypePair(
+ AppleBinaryTest.RULE_TYPE, RULE_TYPE, ReleaseBundlingSupport.EXTENSION_BUNDLE_DIR_FORMAT);
+
+ private ConfiguredTarget addMockExtensionAndLibs(String... extraExtAttributes) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ scratch.file("x/a.m");
+ scratch.file(
+ "x/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " deps = ['//lib1:lib1', '//lib2:lib2'],",
+ " platform_type = 'watchos'",
+ ")",
+ "",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = ':bin',",
+ Joiner.on(',').join(extraExtAttributes),
+ ")");
+ return getConfiguredTarget("//x:x");
+ }
+
+ private void addEntitlements() throws Exception {
+ scratch.file("x/ext_entitlements.entitlements");
+ scratch.file("x/app_entitlements.entitlements");
+ addMockExtensionAndLibs(
+ "ext_entitlements = 'ext_entitlements.entitlements'",
+ "app_entitlements = 'app_entitlements.entitlements'");
+ }
+
+ private Action watchApplicationIpaGeneratingAction() throws Exception {
+ return getGeneratingAction(getBinArtifact("y.ipa", "//x:x"));
+ }
+
+ @Test
+ public void testExtensionSigningAction() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--watchos_cpus=armv7k");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ @Test
+ public void testApplicationSigningAction() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--watchos_cpus=armv7k");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) watchApplicationIpaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x-y.entitlements", "foo.mobileprovision", "x-y.unprocessed.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/y.ipa");
+ }
+
+ @Test
+ public void testExtensionSigningWithCertName() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_signing_cert_name=Foo Bar", "--watchos_cpus=armv7k");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("--sign \"Foo Bar\"");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ @Test
+ public void testApplicationSigningWithCertName() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_signing_cert_name=Foo Bar", "--watchos_cpus=armv7k");
+ addEntitlements();
+ SpawnAction action = (SpawnAction) watchApplicationIpaGeneratingAction();
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x-y.entitlements", "foo.mobileprovision", "x-y.unprocessed.ipa");
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("--sign \"Foo Bar\"");
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/y.ipa");
+ }
+
+ @Test
+ public void testSigning_simulatorBuild() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild_multiCpu() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testUserSpecifiedExtensionProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileUserSpecified(
+ RULE_TYPE_PAIR, false, WATCH_EXT_PROVISIONING_PROFILE_ATTR);
+ }
+
+ @Test
+ public void testUserSpecifiedApplicationProvisioningProfile_deviceBuild() throws Exception {
+ checkSpecifiedApplicationProvisioningProfile(false);
+ }
+
+ @Test
+ public void testUserSpecifiedExtensionProvisioningProfile_deviceBuild_multiCpu()
+ throws Exception {
+ checkProvisioningProfileUserSpecified(
+ RULE_TYPE_PAIR, true, WATCH_EXT_PROVISIONING_PROFILE_ATTR);
+ }
+
+ @Test
+ public void testUserSpecifiedApplicationProvisioningProfile_deviceBuild_multiCpu()
+ throws Exception {
+ checkSpecifiedApplicationProvisioningProfile(true);
+ }
+
+ private void checkSpecifiedApplicationProvisioningProfile(boolean useMultiCpu) throws Exception {
+ setArtifactPrefix("y");
+ if (useMultiCpu) {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--cpu=ios_i386", "--watchos_cpus=armv7k");
+ } else {
+ useConfiguration("--cpu=ios_armv7", "--watchos_cpus=armv7k");
+ }
+
+ addCustomProvisioningProfile(RULE_TYPE_PAIR, WATCH_APP_PROVISIONING_PROFILE_ATTR);
+ getConfiguredTarget("//x:x");
+
+ Artifact defaultProvisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ Artifact customProvisioningProfile =
+ getFileConfiguredTarget("//custom:pp.mobileprovision").getArtifact();
+ Action signingAction = watchApplicationIpaGeneratingAction();
+ assertThat(signingAction.getInputs()).contains(customProvisioningProfile);
+ assertThat(signingAction.getInputs()).doesNotContain(defaultProvisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ Map<String, String> expectedProfiles =
+ ImmutableMap.of(
+ customProvisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ @Test
+ public void testExtensionMergeControlAction() throws Exception {
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+ useConfiguration("--watchos_sdk_version=2.2");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .addBundleFile(
+ BundleFile.newBuilder()
+ .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "bin_lipobin"))
+ .setBundlePath("x")
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build())
+ .setBundleRoot("PlugIns/x.appex")
+ .setBundleInfoPlistFile(
+ getMergedInfoPlist(getConfiguredTarget("//x:x")).getExecPathString())
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x.unprocessed.ipa"))
+ .setMinimumOsVersion("2.2")
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.ext.x")
+ .build());
+ }
+
+ @Test
+ public void testApplicationMergeControlAction() throws Exception {
+ setArtifactPrefix("y");
+ addMockExtensionAndLibs("app_infoplists = ['Info.plist']");
+ useConfiguration("--watchos_sdk_version=2.2");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x-y.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .setBundleRoot("Watch/y.app")
+ .addMergeZip(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Watch/y.app/")
+ .setSourcePath(getBinArtifact("x.ipa", "//x:x").getExecPathString())
+ .build())
+ .addMergeZip(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Watch/y.app/")
+ .setSourcePath(
+ getBinArtifact("_watch/x/WatchKitStub.zip", "//x:x")
+ .getExecPathString())
+ .build())
+ .setBundleInfoPlistFile(
+ getMergedInfoPlist(getConfiguredTarget("//x:x")).getExecPathString())
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x-y.unprocessed.ipa"))
+ .setMinimumOsVersion("2.2")
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.app.y")
+ .build());
+ }
+
+ @Test
+ public void testMergeExtensionBundleAction() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch, "ext_infoplists", "['Info.plist']");
+ SpawnAction action = bundleMergeAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH, "x/bin_lipobin", "x/x.ipa-control", "x/x-MergedInfo.plist");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH, execPathEndingWith(action.getInputs(), "x.ipa-control"))
+ .inOrder();
+ }
+
+ @Test
+ public void testMergeApplicationBundleAction() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch, "app_infoplists", "['Info.plist']");
+ setArtifactPrefix("y");
+ SpawnAction action = bundleMergeAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ "x/x-y.ipa-control",
+ "x/x-y-MergedInfo.plist",
+ "x/_watch/x/WatchKitStub.zip",
+ "x/x.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x-y.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH, execPathEndingWith(action.getInputs(), "x-y.ipa-control"))
+ .inOrder();
+ }
+
+ @Test
+ public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(
+ RULE_TYPE, WATCH_APP_ICON_ATTR, WATCH_EXT_INFOPLISTS_ATTR, "['pl.plist']");
+ }
+
+ @Override
+ protected void checkCollectsAssetCatalogsTransitively(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ scratch.file("lib/ac.xcassets/foo");
+ scratch.file("lib/ac.xcassets/bar");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+
+
+ scratch.file("x/ac.xcassets/baz");
+ scratch.file("x/ac.xcassets/42");
+ ruleTypePair.scratchTargets(
+ scratch, "deps", "['//lib:lib']", "app_asset_catalogs", "glob(['ac.xcassets/**'])");
+
+ // Test that the actoolzip Action for extension has arguments and inputs obtained from
+ // dependencies.
+ SpawnAction extensionActoolZipAction = actoolZipActionForIpa("//x:x");
+ assertThat(Artifact.toExecPaths(extensionActoolZipAction.getInputs()))
+ .containsExactly("lib/ac.xcassets/foo", "lib/ac.xcassets/bar", MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(
+ extensionActoolZipAction.getArguments(), ImmutableList.of("lib/ac.xcassets"));
+
+ // Test that the actoolzip Action for application has arguments and inputs obtained from
+ // dependencies.
+ SpawnAction applicationActoolZipAction =
+ (SpawnAction) getGeneratingAction(getBinArtifact("x-y.actool.zip", "//x:x"));
+ assertThat(Artifact.toExecPaths(applicationActoolZipAction.getInputs()))
+ .containsExactly("x/ac.xcassets/baz", "x/ac.xcassets/42", MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(
+ applicationActoolZipAction.getArguments(), ImmutableList.of("x/ac.xcassets"));
+ }
+
+ @Test
+ public void testCollectsAssetCatalogsTransitively() throws Exception {
+ checkCollectsAssetCatalogsTransitively(RULE_TYPE_PAIR);
+ }
+
+ private void addTargetWithAssetCatalogs() throws IOException {
+ scratch.file("x/foo.xcassets/foo");
+ scratch.file("x/foo.xcassets/bar");
+ scratch.file("x/a.m");
+ scratch.file(
+ "x/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'watchos',",
+ ")",
+ "",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testActoolActionCorrectness() throws Exception {
+ addTargetWithAssetCatalogs();
+ setArtifactPrefix("y");
+ useConfiguration("--watchos_sdk_version=2.2");
+ checkActoolActionCorrectness(
+ DottedVersion.fromString("2.2"), TargetDeviceFamily.WATCH.getNameInRule().toLowerCase(),
+ "watchsimulator");
+ }
+
+ @Test
+ public void testMergeActionsWithAssetCatalog() throws Exception {
+ addTargetWithAssetCatalogs();
+ setArtifactPrefix("y");
+ Artifact actoolZipOut = getBinArtifact("x-y.actool.zip", "//x:x");
+ assertThat(bundleMergeAction("//x:x").getInputs()).contains(actoolZipOut);
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .containsAllOf(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Watch/y.app/")
+ .setSourcePath(getBinArtifact("x.ipa", "//x:x").getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Watch/y.app/")
+ .setSourcePath(
+ getBinArtifact("_watch/x/WatchKitStub.zip", "//x:x").getExecPathString())
+ .build());
+ }
+
+ private void addBinAndLibWithRawResources() throws Exception {
+ addBinAndLibWithResources(
+ "resources", "resource1.txt", "ja.lproj/resource2.txt", "apple_binary",
+ "platform_type = 'watchos'");
+ scratch.file("app_resource.txt");
+ scratch.file("ext_resource.txt");
+ scratch.file(
+ "x/BUILD",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = '//bin:bin',",
+ " app_resources = ['app_resource.txt'],",
+ " ext_resources = ['ext_resource.txt'],",
+ ")");
+ }
+
+ private void addBinAndLibWithStrings() throws Exception {
+ addBinAndLibWithResources("strings", "foo.strings", "ja.lproj/bar.strings", "apple_binary",
+ "platform_type = 'watchos'");
+ scratch.file("app.strings");
+ scratch.file(
+ "x/BUILD",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = '//bin:bin',",
+ " app_strings = ['app.strings'],",
+ ")");
+ }
+
+ @Test
+ public void testCollectsRawResourceFilesTransitively() throws Exception {
+ addBinAndLibWithRawResources();
+ Action mergeBundleAction = bundleMergeAction("//x:x");
+
+ assertThat(Artifact.toRootRelativePaths(mergeBundleAction.getInputs()))
+ .containsAllOf("lib/resource1.txt", "bin/ja.lproj/resource2.txt");
+ }
+
+ @Test
+ public void testCollectsStringsFilesTransitively() throws Exception {
+ addBinAndLibWithStrings();
+
+ Action mergeBundleAction = bundleMergeAction("//x:x");
+
+ assertThat(Artifact.toRootRelativePaths(mergeBundleAction.getInputs()))
+ .containsAllOf("x/lib/foo.strings.binary", "x/bin/ja.lproj/bar.strings.binary");
+ }
+
+ @Test
+ public void testResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithRawResources();
+ checkBundleablesAreMerged(
+ "//x:x",
+ ImmutableListMultimap.of(
+ "resource1.txt", "resource1.txt",
+ "ja.lproj/resource2.txt", "ja.lproj/resource2.txt"));
+ }
+
+ @Test
+ public void testStringsFilesMergedInBundle() throws Exception {
+ addBinAndLibWithStrings();
+ checkBundleablesAreMerged(
+ "//x:x",
+ ImmutableListMultimap.of(
+ "foo.strings.binary", "foo.strings",
+ "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings"));
+ }
+
+ @Test
+ public void testPlistRequiresDotInName() throws Exception {
+ String errorMessage =
+ "'//x:Infoplist' does not produce any apple_watch2_extension "
+ + "ext_infoplists files (expected .plist)";
+ checkError(
+ "x",
+ "x",
+ errorMessage,
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'watchos'",
+ ")",
+ "",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " ext_infoplists = ['Infoplist'],",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZipsForApplication() throws Exception {
+ addStoryboards();
+ setArtifactPrefix("y");
+ Artifact libsbOutputZip = getBinArtifact("x-y/appsb.storyboard.zip", "//x:x");
+
+ Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .contains(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix("Watch/y.app/")
+ .setSourcePath(libsbOutputZip.getExecPathString())
+ .build());
+ }
+
+ protected void addStoryboards() throws Exception {
+ scratch.file("lib/libsb.storyboard");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("storyboards", "libsb.storyboard")
+ .write();
+
+ scratch.file("bndl/bndlsb.storyboard");
+ scratch.file(
+ "bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " storyboards = ['ext_bndlsb.storyboard'],",
+ ")");
+
+ scratch.file(
+ "x/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " bundles = ['//bndl:bndl'],",
+ " deps = ['//lib:lib'],",
+ " storyboards = ['ext.storyboard'],",
+ " platform_type = 'watchos',",
+ ")",
+ "",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " app_storyboards = ['appsb.storyboard'],",
+ " binary = ':bin',",
+ ")");
+
+ scratch.file("x/appsb.storyboard");
+ getConfiguredTarget("//x:x");
+ }
+
+ @Test
+ public void testMergesPartialInfoplists() throws Exception {
+ scratch.file("x/primary-Info.plist");
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(
+ scratch,
+ "app_asset_catalogs",
+ "['foo.xcassets/bar']",
+ "app_infoplists",
+ "['primary-Info.plist']");
+
+ String targetName = "//x:x";
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+ Artifact merged = getBinArtifact("x-y-MergedInfo.plist", target);
+ Artifact actoolPartial = getBinArtifact("x-y.actool-PartialInfo.plist", "//x:x");
+
+ Artifact versionInfoplist = getBinArtifact("plists/x-y-version.plist", target);
+ Artifact environmentInfoplist = getBinArtifact("plists/x-y-environment.plist", target);
+ Artifact automaticInfoplist = getBinArtifact("plists/x-y-automatic.plist", target);
+
+ assertPlistMergeControlUsesSourceFiles(
+ control,
+ ImmutableList.<String>of(
+ "x/primary-Info.plist",
+ versionInfoplist.getExecPathString(),
+ environmentInfoplist.getExecPathString(),
+ automaticInfoplist.getExecPathString(),
+ actoolPartial.getExecPathString()));
+ assertThat(control.getOutFile()).isEqualTo(merged.getExecPathString());
+ assertThat(control.getVariableSubstitutionMapMap())
+ .containsExactlyEntriesIn(variableSubstitutionsForWatchApplication());
+ assertThat(control.getFallbackBundleId()).isEqualTo("example.app.y");
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPassesExtensionFallbackBundleIdToBundleMerging() throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Ext-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch, WATCH_EXT_INFOPLISTS_ATTR, "['Ext-Info.plist']");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.hasPrimaryBundleIdentifier()).isFalse();
+ assertThat(control.getFallbackBundleIdentifier()).isEqualTo("example.ext.x");
+ }
+
+ @Test
+ public void testPassesApplicationFallbackBundleIdToBundleMerging() throws Exception {
+ setArtifactPrefix("y");
+ scratch.file("bin/a.m");
+ scratch.file("bin/App-Info.plist");
+
+ RULE_TYPE.scratchTarget(scratch, WATCH_APP_INFOPLISTS_ATTR, "['App-Info.plist']");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.hasPrimaryBundleIdentifier()).isFalse();
+ assertThat(control.getFallbackBundleIdentifier()).isEqualTo("example.app.y");
+ }
+
+ @Test
+ public void testPassesExtensionPrimaryBundleIdToBundleMerging() throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Ext-Info.plist");
+
+ RULE_TYPE.scratchTarget(
+ scratch,
+ WATCH_EXT_INFOPLISTS_ATTR,
+ "['Ext-Info.plist']",
+ WATCH_EXT_BUNDLE_ID_ATTR,
+ "'com.bundle.ext.id'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.bundle.ext.id");
+ assertThat(control.hasFallbackBundleIdentifier()).isFalse();
+ }
+
+ @Test
+ public void testPassesApplicationPrimaryBundleIdToBundleMerging() throws Exception {
+ setArtifactPrefix("y");
+ scratch.file("bin/a.m");
+ scratch.file("bin/App-Info.plist");
+
+ RULE_TYPE.scratchTarget(
+ scratch,
+ WATCH_APP_INFOPLISTS_ATTR,
+ "['App-Info.plist']",
+ WATCH_APP_BUNDLE_ID_ATTR,
+ "'com.bundle.app.id'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.bundle.app.id");
+ assertThat(control.hasFallbackBundleIdentifier()).isFalse();
+ }
+
+ @Test
+ public void testMultiPlatformBuild_fails() throws Exception {
+ checkBinaryActionMultiPlatform_fails(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiArchitectureResources() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ RULE_TYPE_PAIR.scratchTargets(scratch, "resources", "['foo.png']");
+
+ assertThat(Artifact.toRootRelativePaths(bundleMergeAction("//x:x").getInputs()))
+ .containsExactly(
+ "x/foo.png",
+ "x/bin_lipobin",
+ "tools/objc/bundlemerge",
+ "x/x.ipa-control",
+ "x/x-MergedInfo.plist");
+ }
+
+ @Test
+ public void testDeviceSimulatorMismatch() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--watchos_cpus=armv7k");
+ checkError(
+ "x",
+ "x",
+ "Building a watch extension for watch device architectures [armv7k] "
+ + "requires a device ios architecture. Found [i386,x86_64] instead.",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'watchos',",
+ ")",
+ "",
+ "apple_watch2_extension(",
+ " name = 'x',",
+ " app_name = 'y',",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Override
+ protected void addCommonResources(BinaryRuleTypePair ruleTypePair) throws Exception {
+ ruleTypePair.scratchTargets(
+ scratch, "strings", "['foo.strings']", "storyboards", "['baz.storyboard']");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResources() throws Exception {
+ checkMultiCpuCompiledResources(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testConvertStringsActions() throws Exception {
+ checkConvertStringsAction(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ useConfiguration("--watchos_sdk_version=2.2");
+ checkCompileXibActions(RULE_TYPE_PAIR, DottedVersion.fromString("2.2"), "watch");
+ }
+
+ @Test
+ public void testRegistersStoryboardCompileActions() throws Exception {
+ useConfiguration("--watchos_sdk_version=2.2");
+ checkRegistersStoryboardCompileActions(RULE_TYPE_PAIR, DottedVersion.fromString("2.2"),
+ "watch");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResourcesFromGenrule() throws Exception {
+ checkMultiCpuCompiledResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiCpuGeneratedResourcesFromGenrule() throws Exception {
+ checkMultiCpuGeneratedResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testTwoStringsOneBundlePath() throws Exception {
+ checkTwoStringsOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testTwoResourcesOneBundlePath() throws Exception {
+ checkTwoResourcesOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testWatchSdkDefaultMinVersion() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1", "--watchos_sdk_version=2.4");
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion()).isEqualTo("2.4");
+ }
+
+ @Test
+ public void testWatchSdkMinimumOs() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1", "--watchos_sdk_version=2.2",
+ "--watchos_minimum_os=2.0");
+ addMockExtensionAndLibs("ext_infoplists = ['Info.plist']");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion()).isEqualTo("2.0");
+ }
+
+ @Test
+ public void testCheckExtensionPrimaryBundleIdInMergedPlist() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(
+ scratch,
+ WATCH_EXT_INFOPLISTS_ATTR,
+ "['Info.plist']",
+ WATCH_EXT_BUNDLE_ID_ATTR,
+ "'com.ext.bundle.id'");
+ scratch.file("ext/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.ext.bundle.id"),
+ getVariableSubstitutionArguments(RULE_TYPE_PAIR),
+ "example.ext.x");
+ }
+
+ @Test
+ public void testCheckApplicationPrimaryBundleIdInMergedPlist() throws Exception {
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(
+ scratch,
+ WATCH_APP_INFOPLISTS_ATTR,
+ "['Info.plist']",
+ WATCH_APP_BUNDLE_ID_ATTR,
+ "'com.app.bundle.id'");
+ scratch.file("app/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.app.bundle.id"),
+ variableSubstitutionsForWatchApplication(),
+ "example.app.y");
+ }
+
+ @Test
+ public void testCheckExtensionFallbackBundleIdInMergedPlist() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch, WATCH_EXT_INFOPLISTS_ATTR, "['Info.plist']");
+ scratch.file("ext/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(),
+ getVariableSubstitutionArguments(RULE_TYPE_PAIR),
+ "example.ext.x");
+ }
+
+ @Test
+ public void testCheckApplicationFallbackBundleIdInMergedPlist() throws Exception {
+ setArtifactPrefix("y");
+ RULE_TYPE_PAIR.scratchTargets(scratch, WATCH_APP_INFOPLISTS_ATTR, "['Info.plist']");
+ scratch.file("app/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(), variableSubstitutionsForWatchApplication(), "example.app.y");
+ }
+
+ @Test
+ public void testSameStringsTwice() throws Exception {
+ String targets =
+ RULE_TYPE.target(
+ scratch,
+ "x",
+ "bndl",
+ "app_resources",
+ "['Resources/en.lproj/foo.strings']",
+ "app_strings",
+ "['Resources/en.lproj/foo.strings']");
+ checkError(
+ "x",
+ "bndl",
+ "The same file was included multiple times in this rule: x/Resources/en.lproj/foo.strings",
+ targets);
+ }
+
+ private ImmutableMap<String, String> variableSubstitutionsForWatchApplication() {
+ return new ImmutableMap.Builder<String, String>()
+ .put("EXECUTABLE_NAME", "y")
+ .put("BUNDLE_NAME", "y.app")
+ .put("PRODUCT_NAME", "y")
+ .build();
+ }
+
+ protected void createSwiftBinaryTarget(String... lines) throws Exception {
+ scratch.file("x/main.m");
+
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_rule_impl(ctx):",
+ " return struct(objc=apple_common.new_objc_provider(uses_swift=True))",
+ "swift_rule = rule(implementation = swift_rule_impl, attrs = {})");
+
+ String[] impl =
+ ObjectArrays.concat(
+ new String[] {
+ "load('//examples/rule:apple_rules.bzl', 'swift_rule')",
+ "swift_rule(name='swift_bin')",
+ "apple_binary(",
+ " name = 'x',",
+ " srcs = ['main.m'],",
+ " deps = [':swift_bin'],",
+ " platform_type = 'watchos',",
+ ")",
+ "",
+ },
+ lines,
+ String.class);
+ scratch.file("x/BUILD", impl);
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ // Regression test for b/30916137. Verifies that all tools are available in the watch2 extension
+ // rule to handle bundling of swift objects.
+ public void testSwiftSrcs() throws Exception {
+ createSwiftBinaryTarget(
+ "apple_watch2_extension(",
+ " name = 'ext',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " binary = ':x',",
+ ")");
+
+ getConfiguredTarget("//x:x");
+ }
+
+ @Override
+ protected Action ipaGeneratingAction() throws Exception {
+ ConfiguredTarget test = getConfiguredTarget("//x:x");
+ return getGeneratingAction(getBinArtifact("x.ipa", test));
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE_PAIR, getTargetConfiguration());
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZipsForExtension() throws Exception {
+ addStoryboards();
+
+ Artifact libsbOutputZip = getBinArtifact("x/libsb.storyboard.zip", "//x:x");
+ Artifact extBndlsbOutputZip =
+ getBinArtifact("bndl/ext_bndlsb.storyboard.zip", getConfiguredTarget("//bndl:bndl"));
+ Artifact extsbOutputZip = getBinArtifact("x/ext.storyboard.zip", "//x:x");
+
+ String bundleDir = RULE_TYPE_PAIR.getBundleDir();
+ Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(libsbOutputZip.getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(extsbOutputZip.getExecPathString())
+ .build());
+
+ Control nestedMergeControl = Iterables.getOnlyElement(mergeControl.getNestedBundleList());
+ assertThat(nestedMergeControl.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/bndl.bundle/")
+ .setSourcePath(extBndlsbOutputZip.getExecPathString())
+ .build());
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatchExtensionBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatchExtensionBinaryTest.java
new file mode 100644
index 0000000000..d317b82658
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/AppleWatchExtensionBinaryTest.java
@@ -0,0 +1,171 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.BinaryLinkingTargetFactory.REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for apple_watch_extension_binary. */
+@RunWith(JUnit4.class)
+public class AppleWatchExtensionBinaryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new OnlyNeedsSourcesRuleType("apple_watch_extension_binary");
+ protected static final ExtraLinkArgs EXTRA_LINK_ARGS =
+ new ExtraLinkArgs("-fapplication-extension", "-framework", "WatchKit");
+
+ @Test
+ public void testCreate_runfiles() throws Exception {
+ scratch.file("x/a.m");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget binary = getConfiguredTarget("//x:x");
+ RunfilesProvider runfiles = binary.getProvider(RunfilesProvider.class);
+ assertThat(runfiles.getDefaultRunfiles().getArtifacts()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactly("x/x_bin");
+ }
+
+ @Test
+ public void testCreate_errorForNoSourceOrDep() throws Exception {
+ checkError("x", "x", REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE,
+ "apple_watch_extension_binary(name='x')");
+ }
+
+ @Test
+ public void testCompileWithDotMFileInHeaders() throws Exception {
+ checkCompileWithDotMFileInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksWeakFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksWeakFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksDylibsTransitively() throws Exception {
+ checkLinksDylibsTransitively(RULE_TYPE);
+ }
+
+ @Test
+ public void testPopulatesCompilationArtifacts() throws Exception {
+ checkPopulatesCompilationArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception {
+ checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ checkObjcCopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ checkObjcCopts_argumentOrdering(RULE_TYPE);
+ }
+
+ @Test
+ public void testAllowVariousNonBlacklistedTypesInHeaders() throws Exception {
+ checkAllowVariousNonBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testWarningForBlacklistedTypesInHeaders() throws Exception {
+ checkWarningForBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testCppSourceCompilesWithCppFlags() throws Exception {
+ checkCppSourceCompilesWithCppFlags(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkingRuleCanUseCrosstool() throws Exception {
+ checkLinkingRuleCanUseCrosstool(RULE_TYPE);
+ }
+
+ @Test
+ public void testBinaryStrippings() throws Exception {
+ checkBinaryStripAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForDebug() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimized() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testClangCoptsForDebugModeWithoutGlib() throws Exception {
+ checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionCorrect() throws Exception {
+ checkLinkActionCorrect(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.LLVMCOV);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleType.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleType.java
new file mode 100644
index 0000000000..50e1608a13
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleType.java
@@ -0,0 +1,44 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This exists for convenience for any rule type requires the exact same attributes as
+ * {@code objc_binary}. If some rule ever changes to require more or fewer attributes, it is OK
+ * to stop using this class.
+ */
+final class BinaryRuleType extends RuleType {
+ BinaryRuleType(String ruleTypeName) {
+ super(ruleTypeName);
+ }
+
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageName, Set<String> alreadyAdded) throws IOException {
+ List<String> attributes = new ArrayList<>();
+ if (!alreadyAdded.contains("srcs") && !alreadyAdded.contains("non_arc_srcs")) {
+ scratch.file(packageName + "/a.m");
+ scratch.file(packageName + "/private.h");
+ attributes.add("srcs = ['a.m', 'private.h']");
+ }
+ return attributes;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleTypePair.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleTypePair.java
new file mode 100644
index 0000000000..57eeef63ef
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BinaryRuleTypePair.java
@@ -0,0 +1,163 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.devtools.build.lib.rules.objc.AppleWatch1ExtensionRule.WATCH_APP_DEPS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.INFOPLIST_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.ENTITLEMENTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_STORYBOARD_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.PROVISIONING_PROFILE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_ASSET_CATALOGS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_PROVISIONING_PROFILE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchApplicationBundleRule.WATCH_APP_STORYBOARDS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_INFOPLISTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.WatchExtensionBundleRule.WATCH_EXT_PROVISIONING_PROFILE_ATTR;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.util.Preconditions;
+import java.io.IOException;
+import java.util.Arrays;
+
+/**
+ * Represents a pair of rule types, one being a binary and one an bundling type.
+ *
+ * <p>TODO(bazel-team): Remove this class and refactor tests using it when the binary rule types and
+ * bundling rule types are merged.
+ */
+final class BinaryRuleTypePair {
+ private final RuleType binaryType;
+ private final RuleType bundlingType;
+ private final String bundleDirFormat;
+ private final String bundleName;
+
+ /**
+ * Creates a rule pair.
+ *
+ * @param binaryType rule type for the binary half of the pair (e.g. ios_extension_binary)
+ * @param bundlingType rule type for wrapper (e.g. ios_extension)
+ * @param bundleDirFormat path format for location inside of bundle (e.g. Plugins/%s.appex),
+ * will be substituted with bundle name
+ * @param bundleName name of the bundle
+ */
+ BinaryRuleTypePair(RuleType binaryType, RuleType bundlingType, String bundleDirFormat,
+ String bundleName) {
+ this.binaryType = binaryType;
+ this.bundlingType = bundlingType;
+ this.bundleDirFormat = bundleDirFormat;
+ this.bundleName = bundleName;
+ }
+
+ /**
+ * Creates a binary rule pair with bundle name of "x".
+ */
+ BinaryRuleTypePair(RuleType binaryType, RuleType bundlingType, String bundleDirFormat) {
+ this(binaryType, bundlingType, bundleDirFormat, "x");
+ }
+
+ /**
+ * Returns the name of this bundle.
+ */
+ String getBundleName() {
+ return bundleName;
+ }
+
+ /**
+ * Returns a bundle dir path by combining {@code bundleDirFormat} and {@code bundleName}.
+ */
+ String getBundleDir() {
+ return String.format(bundleDirFormat, bundleName);
+ }
+
+ /**
+ * Returns the binary type as it appears in {@code BUILD} files, such as {@code objc_binary}.
+ */
+ RuleType getBinaryRuleType() {
+ return binaryType;
+ }
+
+ /**
+ * Returns the bundling type as it appears in {@code BUILD} files, such as
+ * {@code ios_application}.
+ */
+ RuleType getBundlingRuleType() {
+ return bundlingType;
+ }
+
+ /**
+ * Generates the String necessary to define a bundling and binary rule of these types.
+ * This includes an "x" (bundling) and "bin" (binary) target in the given package, setting binary
+ * attributes in {@code checkSpecificAttrs} on the binary target, and all other attributes on the
+ * bundling target.
+ */
+ String targets(Scratch scratch, String packageName, String... checkSpecificAttrs)
+ throws IOException {
+ Preconditions.checkArgument(checkSpecificAttrs.length % 2 == 0,
+ "An even number of attribute parameters (kev and value pairs) is required but got: %s",
+ Arrays.asList(checkSpecificAttrs));
+
+ ImmutableList.Builder<String> binaryAttributes = new ImmutableList.Builder<>();
+ ImmutableList.Builder<String> bundlingAttributes = new ImmutableList.Builder<>();
+ bundlingAttributes.add("binary", "':bin'");
+
+ for (int i = 0; i < checkSpecificAttrs.length; i += 2) {
+ String attributeName = checkSpecificAttrs[i];
+ String value = checkSpecificAttrs[i + 1];
+ switch (attributeName) {
+ case APP_ICON_ATTR:
+ case LAUNCH_IMAGE_ATTR:
+ case LAUNCH_STORYBOARD_ATTR:
+ case BUNDLE_ID_ATTR:
+ case FAMILIES_ATTR:
+ case PROVISIONING_PROFILE_ATTR:
+ case ENTITLEMENTS_ATTR:
+ case INFOPLIST_ATTR:
+ case AppleWatch1ExtensionRule.WATCH_EXT_FAMILIES_ATTR:
+ case WATCH_EXT_INFOPLISTS_ATTR:
+ case WATCH_APP_INFOPLISTS_ATTR:
+ case WATCH_APP_PROVISIONING_PROFILE_ATTR:
+ case WATCH_EXT_PROVISIONING_PROFILE_ATTR:
+ case WATCH_EXT_BUNDLE_ID_ATTR:
+ case WATCH_APP_BUNDLE_ID_ATTR:
+ case WATCH_APP_STORYBOARDS_ATTR:
+ case WATCH_APP_ASSET_CATALOGS_ATTR:
+ case WATCH_APP_DEPS_ATTR:
+ bundlingAttributes.add(attributeName, value);
+ break;
+ default:
+ binaryAttributes.add(attributeName, value);
+ }
+ }
+ return binaryType.target(scratch, packageName, "bin",
+ binaryAttributes.build().toArray(new String[0]))
+ + "\n"
+ + bundlingType.target(scratch, packageName, "x",
+ bundlingAttributes.build().toArray(new String[0]));
+ }
+
+ /**
+ * Creates targets at //x:x and //x:bin which are the only targets in the BUILD file.
+ */
+ void scratchTargets(Scratch scratch, String... checkSpecificAttrs) throws IOException {
+ scratch.file("x/BUILD", targets(scratch, "x", checkSpecificAttrs));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcBinaryTest.java
new file mode 100644
index 0000000000..c40d547be3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ExperimentalObjcBinaryTest.java
@@ -0,0 +1,301 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.LegacyCompilationSupport.AUTOMATIC_SDK_FRAMEWORKS;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.Platform;
+import com.google.devtools.build.lib.rules.cpp.CppCompileAction;
+import com.google.devtools.build.lib.rules.cpp.CppLinkAction;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for linking targets with the OSX crosstool. */
+@RunWith(JUnit4.class)
+public class ExperimentalObjcBinaryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new BinaryRuleType("objc_binary");
+
+ private static final String WRAPPED_CLANG = "wrapped_clang";
+ private static final String WRAPPED_CLANGPLUSPLUS = "wrapped_clang++";
+
+ private ConfiguredTarget addMockBinAndLibs(List<String> srcs) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ return createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", srcs)
+ .setList("deps", "//lib1:lib1", "//lib2:lib2")
+ .write();
+ }
+
+ private ImmutableList<String> automaticSdkFrameworks() {
+ ImmutableList.Builder<String> result = ImmutableList.<String>builder();
+ for (SdkFramework framework : AUTOMATIC_SDK_FRAMEWORKS) {
+ result.add("-framework " + framework.getName());
+ }
+ return result.build();
+ }
+
+ @Test
+ public void testDeviceBuild() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+ Platform platform = Platform.IOS_DEVICE;
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+ assertRequiresDarwin(action);
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ "bin/libbin.a",
+ "lib1/liblib1.a",
+ "lib2/liblib2.a",
+ "bin/bin-linker.objlist");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("bin/bin_bin");
+ verifyObjlist(
+ action,
+ "bin-linker.objlist",
+ execPathEndingWith(action.getInputs(), "libbin.a"),
+ execPathEndingWith(action.getInputs(), "liblib1.a"),
+ execPathEndingWith(action.getInputs(), "liblib2.a"));
+ assertThat(action.getArguments())
+ .containsExactlyElementsIn(
+ new ImmutableList.Builder<String>()
+ .add("tools/osx/crosstool/ios/" + WRAPPED_CLANG)
+ .add("-F" + AppleToolchain.sdkDir() + AppleToolchain.DEVELOPER_FRAMEWORK_PATH)
+ .add("-F" + frameworkDir(platform))
+ .add("-isysroot")
+ .add(AppleToolchain.sdkDir())
+ // TODO(b/35853671): Factor out "-lc++"
+ .add("-lc++")
+ .add("-target", "armv7-apple-ios")
+ .add("-miphoneos-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .addAll(automaticSdkFrameworks())
+ .add("-arch armv7")
+ .add("-Xlinker", "-objc_abi_version", "-Xlinker", "2")
+ .add("-Xlinker", "-rpath", "-Xlinker", "@executable_path/Frameworks")
+ .add("-fobjc-link-runtime")
+ .add("-ObjC")
+ .add("-filelist " + execPathEndingWith(action.getInputs(), "bin-linker.objlist"))
+ .add("-o " + Iterables.getOnlyElement(Artifact.toExecPaths(action.getOutputs())))
+ .build())
+ .inOrder();
+ }
+
+ @Test
+ public void testSimulatorBuild() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_x86_64",
+ "--ios_cpu=x86_64");
+ Platform platform = Platform.IOS_SIMULATOR;
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+ assertThat(action.getArguments())
+ .containsAllOf(
+ "tools/osx/crosstool/iossim/" + WRAPPED_CLANG,
+ "-arch x86_64",
+ "-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION,
+ "-F" + frameworkDir(platform));
+ }
+
+ @Test
+ public void testAlwaysLinkCcDependenciesAreForceLoaded() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+
+ scratch.file(
+ "bin/BUILD",
+ "cc_library(",
+ " name = 'cclib1',",
+ " srcs = ['dep1.c'],",
+ " alwayslink = 1,",
+ ")",
+ "cc_library(",
+ " name = 'cclib2',",
+ " srcs = ['dep2.c'],",
+ " deps = [':cclib1'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':cclib2'],",
+ ")");
+
+ // cclib1 is force loaded.
+ assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments()))
+ .containsMatch(Pattern.compile(" -force_load [^\\s]+/libcclib1.lo\\b"));
+ }
+
+ @Test
+ public void testObjcPlusPlusLinkAction() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+
+ addMockBinAndLibs(ImmutableList.of("a.mm"));
+
+ CommandAction action = linkAction("//bin:bin");
+ assertThat(action.getArguments())
+ .containsAllOf(
+ "tools/osx/crosstool/ios/" + WRAPPED_CLANGPLUSPLUS,
+ "-stdlib=libc++",
+ "-std=gnu++11");
+ }
+
+ @Test
+ public void testUnstrippedArtifactGeneratedForBinaryStripping() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--objc_enable_binary_stripping",
+ "--compilation_mode=opt");
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ Action linkAction = actionProducingArtifact("//bin:bin", "_bin_unstripped");
+ Action stripAction = actionProducingArtifact("//bin:bin", "_bin");
+ assertThat(linkAction).isNotNull();
+ assertThat(stripAction).isNotNull();
+ }
+
+
+ @Test
+ public void testDeadStripLinkArguments() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7",
+ "--objc_enable_binary_stripping",
+ "--compilation_mode=opt");
+ addMockBinAndLibs(ImmutableList.of("a.mm"));
+ CommandAction linkAction =
+ (CommandAction) actionProducingArtifact("//bin:bin", "_bin_unstripped");
+ assertThat(linkAction.getArguments())
+ .containsAllOf("-dead_strip", "-no_dead_strip_inits_and_terms");
+ }
+
+ @Test
+ public void testDeadStripLinkArgumentsNotPresentIfStrippingNotEnabled() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7",
+ "--compilation_mode=opt");
+ addMockBinAndLibs(ImmutableList.of("a.mm"));
+ CommandAction linkAction =
+ (CommandAction) actionProducingArtifact("//bin:bin", "_bin");
+ assertThat(linkAction.getArguments())
+ .containsNoneOf("--dead_strip", "--no_dead_strip_inits_and_terms");
+ }
+
+ @Test
+ public void testDeadStripLinkArgumentsNotPresentIfCompilationModeFastbuild() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7",
+ "--objc_enable_binary_stripping",
+ "--compilation_mode=fastbuild");
+ addMockBinAndLibs(ImmutableList.of("a.mm"));
+ CommandAction linkAction =
+ (CommandAction) actionProducingArtifact("//bin:bin", "_bin");
+ assertThat(linkAction.getArguments())
+ .containsNoneOf("--dead_strip", "--no_dead_strip_inits_and_terms");
+ }
+
+ @Test
+ public void testCompileEnv() throws Exception {
+ MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
+ useConfiguration(
+ ObjcCrosstoolMode.LIBRARY,
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--ios_sdk_version=2.9",
+ "--xcode_version=5.0",
+ "--cpu=ios_x86_64");
+ ScratchAttributeWriter.fromLabelString(this, "objc_library", "//main:lib")
+ .setList("srcs", "a.m")
+ .write();
+
+ CppCompileAction compileAction = (CppCompileAction) compileAction("//main:lib", "a.o");
+
+ Map<String, String> environment = compileAction.getEnvironment();
+ assertThat(environment).containsEntry("XCODE_VERSION_OVERRIDE", "5.0");
+ assertThat(environment).containsEntry("APPLE_SDK_VERSION_OVERRIDE", "2.9");
+ }
+
+ @Test
+ public void testArchiveEnv() throws Exception {
+ MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
+ useConfiguration(
+ ObjcCrosstoolMode.LIBRARY,
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--ios_sdk_version=2.9",
+ "--xcode_version=5.0",
+ "--cpu=ios_x86_64");
+ ScratchAttributeWriter.fromLabelString(this, "objc_library", "//main:lib")
+ .setList("srcs", "a.m")
+ .write();
+
+ CppLinkAction archiveAction = (CppLinkAction) archiveAction("//main:lib");
+
+ Map<String, String> environment = archiveAction.getEnvironment();
+ assertThat(environment).containsEntry("XCODE_VERSION_OVERRIDE", "5.0");
+ assertThat(environment).containsEntry("APPLE_SDK_VERSION_OVERRIDE", "2.9");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderDiscoveryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderDiscoveryTest.java
new file mode 100644
index 0000000000..7b99bca8aa
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderDiscoveryTest.java
@@ -0,0 +1,86 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for discovery of used headers during compilation. */
+@RunWith(JUnit4.class)
+public class HeaderDiscoveryTest extends ObjcRuleTestCase {
+
+ @Override
+ protected void useConfiguration(String... args) throws Exception {
+ // Don't test crosstool for header discovery
+ useConfiguration(ObjcCrosstoolMode.OFF, args);
+ }
+
+ private NestedSet<Artifact> getDiscoveredInputsForDotdFile(String... lines) throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setList("srcs", "a.m")
+ .setList("hdrs", "used.h", "not_used.h")
+ .write();
+ CommandAction commandAction = compileAction("//objc:lib", "a.o");
+ assertThat(commandAction).isInstanceOf(ObjcCompileAction.class);
+ ObjcCompileAction objcCompileAction = (ObjcCompileAction) commandAction;
+
+ Artifact dotdFile = ActionsTestUtil.getOutput(objcCompileAction, "a.d");
+ scratch.file(dotdFile.getPath().toString(), lines);
+ return objcCompileAction.discoverInputsFromDotdFiles(
+ directories.getExecRoot(), view.getArtifactFactory());
+ }
+
+ @Test
+ public void testObjcHeaderDiscoveryFindsInputs() throws Exception {
+ NestedSet<Artifact> discoveredInputs =
+ getDiscoveredInputsForDotdFile("a.o: \\", " objc/a.m \\", " objc/used.h \\");
+ assertThat(Artifact.toExecPaths(discoveredInputs)).containsExactly("objc/a.m", "objc/used.h");
+ }
+
+ @Test
+ public void testObjcHeaderDiscoveryIgnoresOutsideExecRoot() throws Exception {
+ NestedSet<Artifact> discoveredInputs =
+ getDiscoveredInputsForDotdFile("a.o: \\", " /foo/a.h \\", " /bar/b.h");
+ assertThat(Artifact.toExecPaths(discoveredInputs)).isEmpty();
+ }
+
+ @Test
+ public void testInputsArePruned() throws Exception {
+ NestedSet<Artifact> discoveredInputs =
+ getDiscoveredInputsForDotdFile("a.o: \\", " objc/a.m \\", " objc/used.h \\");
+ ObjcCompileAction compileAction = (ObjcCompileAction) compileAction("//objc:lib", "a.o");
+ compileAction.updateActionInputs(discoveredInputs);
+
+ assertThat(Artifact.toExecPaths(compileAction.getInputs())).doesNotContain("objc/not_used.h");
+ }
+
+ @Test
+ public void testSrcsAreMandatoryInputs() throws Exception {
+ NestedSet<Artifact> discoveredInputs =
+ getDiscoveredInputsForDotdFile("a.o: \\", " objc/used.h");
+ ObjcCompileAction compileAction = (ObjcCompileAction) compileAction("//objc:lib", "a.o");
+ compileAction.updateActionInputs(discoveredInputs);
+
+ assertThat(Artifact.toExecPaths(compileAction.getInputs())).contains("objc/a.m");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderThinningTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderThinningTest.java
new file mode 100644
index 0000000000..cdd9d72764
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/HeaderThinningTest.java
@@ -0,0 +1,271 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
+import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
+import com.google.devtools.build.lib.actions.ExecException;
+import com.google.devtools.build.lib.actions.UserExecException;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.cpp.CppCompileAction;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for header thinning. */
+@RunWith(JUnit4.class)
+public class HeaderThinningTest extends ObjcRuleTestCase {
+
+ private static final String CPP_COMPILE_ACTION_RULE_TYPE = "objc_library";
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
+ MockObjcSupport.setupAppleSdks(mockToolsConfig);
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_header_thinning",
+ "--objc_use_dotd_pruning",
+ "--xcode_version=" + MockObjcSupport.DEFAULT_XCODE_VERSION,
+ "--ios_sdk_version=" + MockObjcSupport.DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testCppCompileActionHeaderThinningCanDetermineAdditionalInputs() throws Exception {
+ Artifact sourceFile = getSourceArtifact("objc/a.m");
+ CppCompileAction action = createCppCompileAction(sourceFile);
+ List<Artifact> expectedHeaders =
+ ImmutableList.of(
+ getSourceArtifact("objc/a.pch"),
+ getSourceArtifact("objc/b.h"),
+ getSourceArtifact("objc/c"),
+ getSourceArtifact("objc/d.hpp"));
+ HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
+ writeToHeadersListFile(action, "objc/a.pch", "objc/b.h", "objc/c", "objc/d.hpp");
+
+ Iterable<Artifact> headersFound = headerThinning.determineAdditionalInputs(null, action, null);
+ assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
+ }
+
+ @Test
+ public void testCppCompileActionHeaderThinningThrowsWhenUnknownHeaderFound() throws Exception {
+ Artifact sourceFile = getSourceArtifact("objc/a.m");
+ CppCompileAction action = createCppCompileAction(sourceFile);
+ List<Artifact> expectedHeaders =
+ ImmutableList.of(getSourceArtifact("objc/a.h"), getSourceArtifact("objc/b.h"));
+ HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
+ writeToHeadersListFile(action, "objc/a.h", "objc/b.h", "objc/c.h");
+
+ try {
+ headerThinning.determineAdditionalInputs(null, action, null);
+ fail("Exception was not thrown");
+ } catch (ExecException e) {
+ assertThat(e).hasMessageThat().containsMatch("(objc/c.h)");
+ assertThat(e).isInstanceOf(UserExecException.class);
+ }
+ }
+
+ @Test
+ public void testCppCompileActionHeaderThinningFindsHeadersInTreeArtifacts() throws Exception {
+ Artifact sourceFile = getSourceArtifact("objc/a.m");
+ CppCompileAction action = createCppCompileAction(sourceFile);
+ List<Artifact> expectedHeaders =
+ ImmutableList.of(getSourceArtifact("objc/a.h"), getTreeArtifact("tree/dir"));
+ HeaderThinning headerThinning = new HeaderThinning(getPotentialHeaders(expectedHeaders));
+ writeToHeadersListFile(action, "objc/a.h", "tree/dir/c.h");
+
+ Iterable<Artifact> headersFound = headerThinning.determineAdditionalInputs(null, action, null);
+ assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
+ }
+
+ @Test
+ public void testObjcCompileActionHeaderThinningCanFindRequiredHeaderInputs() throws Exception {
+ Artifact sourceFile = getSourceArtifact("objc/a.m");
+ Artifact headersListFile = getHeadersListArtifact(sourceFile);
+ scratch.file(
+ headersListFile.getExecPathString(), "objc/a.pch", "objc/b.h", "objc/c", "objc/d.hpp");
+ List<Artifact> expectedHeaders =
+ ImmutableList.of(
+ getSourceArtifact("objc/a.pch"),
+ getSourceArtifact("objc/b.h"),
+ getSourceArtifact("objc/c"),
+ getSourceArtifact("objc/d.hpp"));
+
+ Iterable<Artifact> headersFound =
+ HeaderThinning.findRequiredHeaderInputs(
+ sourceFile,
+ headersListFile,
+ createHeaderFilesMap(getPotentialHeaders(expectedHeaders)));
+ assertThat(headersFound).containsExactlyElementsIn(expectedHeaders);
+ }
+
+ private void writeToHeadersListFile(CppCompileAction action, String... lines) throws Exception {
+ Artifact headersListFile = null;
+ for (Artifact input : action.getMandatoryInputs()) {
+ if (input.getExtension().equals("headers_list")) {
+ headersListFile = input;
+ break;
+ }
+ }
+ assertThat(headersListFile).isNotNull();
+ scratch.file(headersListFile.getPath().getPathString(), lines);
+ }
+
+ /**
+ * Simple utility to populate some unused header Artifacts along with the ones we expect to find.
+ */
+ private Iterable<Artifact> getPotentialHeaders(List<Artifact> expectedHeaders) {
+ return Iterables.concat(
+ ImmutableList.of(
+ getSourceArtifact("objc/unused.h"),
+ getSourceArtifact("some/other.h"),
+ getSourceArtifact("objc/foo.pch")),
+ expectedHeaders);
+ }
+
+ private CppCompileAction createCppCompileAction(Artifact sourceFile) throws Exception {
+ String ownerLabel = "//objc:lib";
+ ScratchAttributeWriter.fromLabelString(this, CPP_COMPILE_ACTION_RULE_TYPE, ownerLabel)
+ .setList("srcs", sourceFile.getFilename())
+ .write();
+ ConfiguredTarget target = getConfiguredTarget(ownerLabel);
+ List<CppCompileAction> allActions =
+ actionsTestUtil()
+ .findTransitivePrerequisitesOf(
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".a"),
+ CppCompileAction.class);
+ for (CppCompileAction action : allActions) {
+ if (action.getSourceFile().getExecPath().equals(sourceFile.getExecPath())) {
+ return action;
+ }
+ }
+ return null;
+ }
+
+ private Artifact getHeadersListArtifact(Artifact sourceFile) {
+ return getSourceArtifact(
+ FileSystemUtils.replaceExtension(sourceFile.getExecPath(), ".headers_list"),
+ sourceFile.getRoot());
+ }
+
+ private static Map<PathFragment, Artifact> createHeaderFilesMap(Iterable<Artifact> artifacts) {
+ ImmutableMap.Builder<PathFragment, Artifact> headerFilesMapBuilder = ImmutableMap.builder();
+ for (Artifact artifact : artifacts) {
+ headerFilesMapBuilder.put(artifact.getExecPath(), artifact);
+ }
+ return headerFilesMapBuilder.build();
+ }
+
+ private Artifact getTreeArtifact(String name) {
+ Artifact treeArtifactBase = getSourceArtifact(name);
+ return new SpecialArtifact(
+ treeArtifactBase.getPath(),
+ treeArtifactBase.getRoot(),
+ treeArtifactBase.getExecPath(),
+ treeArtifactBase.getArtifactOwner(),
+ SpecialArtifactType.TREE);
+ }
+
+ @Test
+ public void generatesHeaderScanningAction() throws Exception {
+ Set<SpawnAction> scanningActions =
+ createTargetAndGetHeaderScanningActions(ImmutableList.of("one.m", "two.m"));
+ assertThat(scanningActions).hasSize(1);
+ }
+
+ @Test
+ public void generates2HeaderScanningActionsWhenObjcAndCppSources() throws Exception {
+ Set<SpawnAction> scanningActions =
+ createTargetAndGetHeaderScanningActions(ImmutableList.of("one.m", "two.cc"));
+ assertThat(scanningActions).hasSize(2);
+ }
+
+ @Test
+ public void generatesMultipleHeaderScanningActionsForLargeTargets2() throws Exception {
+ validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
+ 2, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
+ }
+
+ @Test
+ public void generatesMultipleHeaderScanningActionsForLargeTargets4() throws Exception {
+ validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
+ 4, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
+ }
+
+ @Test
+ public void generatesMultipleHeaderScanningActionsForLargeTargets8() throws Exception {
+ validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
+ 8, targetConfig.getFragment(ObjcConfiguration.class).objcHeaderThinningPartitionSize());
+ }
+
+ @Test
+ public void generatesMultipleHeaderScanningActionsForLargeTargetsCustomPartition()
+ throws Exception {
+ int partitionSize = 5;
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_header_thinning",
+ "--objc_header_thinning_partition_size=" + 5,
+ "--objc_use_dotd_pruning",
+ "--xcode_version=" + MockObjcSupport.DEFAULT_XCODE_VERSION,
+ "--ios_sdk_version=" + MockObjcSupport.DEFAULT_IOS_SDK_VERSION);
+ validateGeneratesMultipleHeaderScanningActionsForLargeTargets(12, partitionSize);
+ }
+
+ private void validateGeneratesMultipleHeaderScanningActionsForLargeTargets(
+ int actionCount, int partitionSize) throws Exception {
+ ImmutableList.Builder<String> sourcesBuilder = ImmutableList.builder();
+ for (int i = 0; i < partitionSize * actionCount; ++i) {
+ sourcesBuilder.add(String.format("source_%d.m", i));
+ }
+ Set<SpawnAction> scanningActions =
+ createTargetAndGetHeaderScanningActions(sourcesBuilder.build());
+ assertThat(scanningActions).hasSize(actionCount);
+ }
+
+ private Set<SpawnAction> createTargetAndGetHeaderScanningActions(Iterable<String> sources)
+ throws Exception {
+ String ownerLabel = "//objc:lib";
+ ScratchAttributeWriter.fromLabelString(this, CPP_COMPILE_ACTION_RULE_TYPE, ownerLabel)
+ .setList("srcs", sources)
+ .write();
+ ConfiguredTarget target = getConfiguredTarget(ownerLabel);
+ List<SpawnAction> spawnActions =
+ actionsTestUtil()
+ .findTransitivePrerequisitesOf(
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), ".a"),
+ SpawnAction.class);
+ return Sets.newHashSet(
+ Iterables.filter(spawnActions, a -> a.getMnemonic().equals("ObjcHeaderScanning")));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/InterspersingTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/InterspersingTest.java
new file mode 100644
index 0000000000..06ae707521
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/InterspersingTest.java
@@ -0,0 +1,78 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for the Interspersing utility. */
+@RunWith(JUnit4.class)
+public class InterspersingTest {
+ @Test
+ public void beforeEach_empty() {
+ assertThat(Interspersing.beforeEach("foo", ImmutableList.<String>of())).isEmpty();
+ }
+
+ @Test
+ public void beforeEach_isLazy() {
+ Iterable<Integer> result = Interspersing.beforeEach(1011, Iterables.cycle(1, 2, 3));
+ assertThat(Iterables.get(result, 0)).isEqualTo((Object) 1011);
+ assertThat(Iterables.get(result, 1)).isEqualTo((Object) 1);
+ assertThat(Iterables.get(result, 2)).isEqualTo((Object) 1011);
+ assertThat(Iterables.get(result, 3)).isEqualTo((Object) 2);
+ }
+
+ @Test
+ public void beforeEach_throwsForNullWhat() {
+ try {
+ Interspersing.beforeEach(null, ImmutableList.of("a"));
+ fail("should have thrown");
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void prependEach_empty() {
+ assertThat(Interspersing.prependEach("foo", ImmutableList.<String>of())).isEmpty();
+ }
+
+ @Test
+ public void prependEach_isLazy() {
+ Iterable<String> result = Interspersing.prependEach(
+ "#", Iterables.cycle(1, 2, 3), Functions.toStringFunction());
+ assertThat(Iterables.get(result, 0)).isEqualTo("#1");
+ }
+
+ @Test
+ public void prependEach_typicalList() {
+ Iterable<String> result = Interspersing.prependEach(
+ "*", ImmutableList.of("a", "b", "c"));
+ assertThat(result).containsExactly("*a", "*b", "*c").inOrder();
+ }
+
+ @Test
+ public void prependEach_throwsForNullWhat() {
+ try {
+ Interspersing.prependEach(null, ImmutableList.of("a"));
+ fail("should have thrown");
+ } catch (NullPointerException expected) {}
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/IosApplicationTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/IosApplicationTest.java
new file mode 100644
index 0000000000..a7dda26d2a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/IosApplicationTest.java
@@ -0,0 +1,1175 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multiset;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget.Mode;
+import com.google.devtools.build.lib.analysis.RuleContext;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for ios_application. */
+@RunWith(JUnit4.class)
+public class IosApplicationTest extends ObjcRuleTestCase {
+ protected static final RuleType RULE_TYPE =
+ new RuleType("ios_application") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("binary")) {
+ scratch.file(packageDir + "/bin/a.m");
+ scratch.file(packageDir + "/bin/BUILD", "objc_binary(name = 'bin', srcs = ['a.m'])");
+ attributes.add("binary = '//" + packageDir + "/bin:bin'");
+ }
+ return attributes.build();
+ }
+ };
+
+ protected static final BinaryRuleTypePair RULE_TYPE_PAIR =
+ new BinaryRuleTypePair(
+ ObjcBinaryTest.RULE_TYPE, RULE_TYPE, ReleaseBundlingSupport.APP_BUNDLE_DIR_FORMAT);
+
+ private ConfiguredTarget addMockAppAndLibs(String... extraAppAttributes)
+ throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ scratch.file("x/a.m");
+ scratch.file("x/x-Info.plist");
+ scratch.file("x/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " deps = ['//lib1:lib1', '//lib2:lib2'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ Joiner.on(',').join(extraAppAttributes),
+ ")");
+ return getConfiguredTarget("//x:x");
+ }
+
+ @Test
+ public void testSplitConfigurationProviders() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ scratch.file("x/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " infoplist = 'Info.plist',",
+ " binary = ':bin',",
+ ")");
+ RuleContext ruleContext = getRuleContext(getConfiguredTarget("//x:x"));
+ ImmutableListMultimap<BuildConfiguration, ObjcProvider> prereqByConfig =
+ ruleContext.getPrerequisitesByConfiguration("binary", Mode.SPLIT, ObjcProvider.class);
+ List<String> childCpus = Lists.transform(prereqByConfig.keySet().asList(),
+ new Function<BuildConfiguration, String>() {
+ @Override
+ public String apply(BuildConfiguration config) {
+ return config.getFragment(AppleConfiguration.class).getIosCpu();
+ }
+ });
+ assertThat(childCpus).containsExactly("i386", "x86_64");
+ }
+
+ @Test
+ public void testRunfiles() throws Exception {
+ ConfiguredTarget application = addMockAppAndLibs();
+ RunfilesProvider runfiles = application.getProvider(RunfilesProvider.class);
+ assertThat(runfiles.getDefaultRunfiles().getArtifacts()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactly("x/x.ipa");
+ }
+
+ @Test
+ public void testFilesToRun() throws Exception {
+ checkFilesToRun(RULE_TYPE);
+ }
+
+ @Test
+ public void testNoRunfilesSupportForDevice() throws Exception {
+ checkNoRunfilesSupportForDevice(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenerateRunnerScriptAction() throws Exception {
+ checkGenerateRunnerScriptAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenerateRunnerScriptAction_escaped() throws Exception {
+ checkGenerateRunnerScriptAction_escaped(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningAction() throws Exception {
+ checkDeviceSigningAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningWithCertName() throws Exception {
+ checkSigningWithCertName(RULE_TYPE);
+ }
+
+ @Test
+ public void testPostProcessingAction() throws Exception {
+ checkPostProcessingAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningAndPostProcessing() throws Exception {
+ checkSigningAndPostProcessing(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild_multiCpu() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testUserSpecifiedProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testUserSpecifiedProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testMergeControlAction() throws Exception {
+ addMockAppAndLibs("infoplist = 'Info.plist'");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .addBundleFile(
+ BundleFile.newBuilder()
+ .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "x_lipobin"))
+ .setBundlePath("x")
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build())
+ .setBundleRoot(String.format(ReleaseBundlingSupport.APP_BUNDLE_DIR_FORMAT, "x"))
+ .setBundleInfoPlistFile(execPathEndingWith(mergeAction.getInputs(), "Info.plist"))
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x.unprocessed.ipa"))
+ .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.x")
+ .build());
+ }
+
+ @Test
+ public void testMergeBundleAction() throws Exception {
+ checkMergeBundleAction(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCheckPrimaryBundleIdInMergedPlist() throws Exception {
+ checkPrimaryBundleIdInMergedPlist(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCheckFallbackBundleIdInMergedPlist() throws Exception {
+ checkFallbackBundleIdInMergedPlist(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testErrorForLaunchImageGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, LAUNCH_IMAGE_ATTR);
+ }
+
+ @Test
+ public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, APP_ICON_ATTR);
+ }
+
+ @Test
+ public void testCollectsAssetCatalogsTransitively() throws Exception {
+ checkCollectsAssetCatalogsTransitively(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency() throws Exception {
+ checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(
+ RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION);
+ }
+
+ private void addTargetWithAssetCatalogs() throws IOException {
+ scratch.file("x/foo.xcassets/foo");
+ scratch.file("x/foo.xcassets/bar");
+ scratch.file("x/a.m");
+ scratch.file("x/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testActoolAction() throws Exception {
+ addTargetWithAssetCatalogs();
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testPassesFamiliesToActool() throws Exception {
+ checkPassesFamiliesToActool(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergeActionsWithAssetCatalog() throws Exception {
+ // TODO(matvore): add this test to IosTestTest.java.
+ addTargetWithAssetCatalogs();
+ checkMergeActionsWithAssetCatalog(RULE_TYPE_PAIR);
+ }
+
+ private void addBinAndLibWithRawResources() throws Exception {
+ addBinAndLibWithResources(
+ "resources", "resource1.txt", "ja.lproj/resource2.txt", "objc_binary");
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ }
+
+ private void addBinAndLibWithStrings() throws Exception {
+ addBinAndLibWithResources(
+ "strings", "foo.strings", "ja.lproj/bar.strings", "objc_binary");
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ }
+
+ @Test
+ public void testCollectsRawResourceFilesTransitively() throws Exception {
+ addBinAndLibWithRawResources();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("lib/resource1.txt", "bin/ja.lproj/resource2.txt"),
+ ImmutableList.of("lib/resource1.txt"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin",
+ ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "bin_static_lib_bin",
+ ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "x_x",
+ ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "lib_lib",
+ ImmutableMultiset.of("lib/resource1.txt")));
+ }
+
+ @Test
+ public void testCollectsStringsFilesTransitively() throws Exception {
+ addBinAndLibWithStrings();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("x/lib/foo.strings.binary", "x/bin/ja.lproj/bar.strings.binary"),
+ ImmutableList.of("x/lib/foo.strings.binary"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin",
+ ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "bin_static_lib_bin",
+ ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "x_x",
+ ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "lib_lib",
+ ImmutableMultiset.of("lib/foo.strings")));
+ }
+
+ @Test
+ public void testResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithRawResources();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "resource1.txt", "resource1.txt",
+ "ja.lproj/resource2.txt", "ja.lproj/resource2.txt"));
+ }
+
+ @Test
+ public void testResourceFlattenedInBundle() throws Exception {
+ addBinAndLibWithResources(
+ "resources", "libres/resource1.txt", "binres/resource2.txt", "objc_binary");
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "libres/resource1.txt", "resource1.txt",
+ "binres/resource2.txt", "resource2.txt"));
+ }
+
+ @Test
+ public void testStructuredResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithResources(
+ "structured_resources", "libres/resource1.txt", "binres/resource2.txt", "objc_binary");
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "libres/resource1.txt", "libres/resource1.txt",
+ "binres/resource2.txt", "binres/resource2.txt"));
+ }
+
+ @Test
+ public void testStringsFilesMergedInBundle() throws Exception {
+ addBinAndLibWithStrings();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "foo.strings.binary", "foo.strings",
+ "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings"));
+ }
+
+ @Test
+ public void testMergesXcdatamodelZips() throws Exception {
+ checkMergesXcdatamodelZips(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPlistRequiresDotInName() throws Exception {
+ checkError("x", "x",
+ "'//x:Infoplist' does not produce any ios_application infoplist files (expected .plist)",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " infoplist = 'Infoplist',",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testPopulatesBundling() throws Exception {
+ scratch.file("x/x-Info.plist");
+ scratch.file("x/a.m");
+ scratch.file("x/assets.xcassets/1");
+ scratch.file("x/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " asset_catalogs = ['assets.xcassets/1']",
+ ")",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ " infoplist = 'x-Info.plist',",
+ ")");
+
+ PlMergeProtos.Control control = plMergeControl("//x:x");
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/x-Info.plist").getExecPathString());
+
+ Artifact actoolzipOutput = getBinArtifact("x.actool.zip", "//x:x");
+ assertThat(getGeneratingAction(actoolzipOutput).getInputs())
+ .contains(getSourceArtifact("x/assets.xcassets/1"));
+ }
+
+ @Test
+ public void testMergesPartialInfoplists() throws Exception {
+ checkMergesPartialInfoplists(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testNoEntitlementsDefined() throws Exception {
+ checkNoEntitlementsDefined(RULE_TYPE);
+ }
+
+ @Test
+ public void testEntitlementsDefined() throws Exception {
+ checkEntitlementsDefined(RULE_TYPE);
+ }
+
+ @Test
+ public void testExtraEntitlements() throws Exception {
+ checkExtraEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testDebugEntitlements() throws Exception {
+ checkDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testFastbuildDebugEntitlements() throws Exception {
+ checkFastbuildDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testOptNoDebugEntitlements() throws Exception {
+ checkOptNoDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testExplicitNoDebugEntitlements() throws Exception {
+ checkExplicitNoDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultiPlatformBuild_fails() throws Exception {
+ checkBinaryActionMultiPlatform_fails(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiArchitectureResources() throws Exception {
+ checkMultiCpuResourceInheritance(RULE_TYPE_PAIR);
+ }
+
+ /**
+ * Regression test for b/27946171. Verifies that nodistinct_host_configuration functions in
+ * builds with more than one split transition. (In this case, both ios_application and
+ * ios_extension split into two child configurations.)
+ */
+ @Test
+ public void testNoDistinctHostConfiguration() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--nodistinct_host_configuration");
+ scratch.file("x/BUILD",
+ "ios_extension_binary(",
+ " name = 'ext_bin',",
+ " srcs = ['ebin.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'ext',",
+ " binary = ':ext_bin',",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ " extensions = [':ext'],",
+ ")");
+
+ getConfiguredTarget("//x:app");
+
+ // Assert that only the deprecation warnings are emitted, but no other events.
+ assertContainsEventWithFrequency(
+ "This rule is deprecated. Please use the new Apple build rules "
+ + "(https://github.com/bazelbuild/rules_apple) to build Apple targets.",
+ 4);
+ }
+
+ @Test
+ public void testApplicationExtensionSharedDependencyResourceActions() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'res',",
+ " xibs = ['interface.xib'],",
+ " storyboards = ['story.storyboard'],",
+ " datamodels = ['data.xcdatamodel/1'],",
+ " asset_catalogs = ['assets.xcassets/foo'],",
+ ")",
+ "",
+ "ios_extension_binary(",
+ " name = 'ext_bin',",
+ " srcs = ['ebin.m'],",
+ " deps = [':res'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'ext',",
+ " binary = ':ext_bin',",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':res'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ " extensions = [':ext'],",
+ ")");
+
+ Action appIpaAction = bundleMergeAction("//x:app");
+
+ Action extIpaAction = bundleMergeAction("//x:ext");
+
+ Artifact appNibZip = Iterables.getOnlyElement(inputsEndingWith(appIpaAction, "nib.zip"));
+ Artifact extNibZip = Iterables.getOnlyElement(inputsEndingWith(extIpaAction, "nib.zip"));
+ assertThat(appNibZip.getExecPath()).isNotEqualTo(extNibZip.getExecPath());
+
+ Artifact appStoryboardZip =
+ Iterables.getOnlyElement(inputsEndingWith(appIpaAction, "story.storyboard.zip"));
+ Artifact extStoryboardZip =
+ Iterables.getOnlyElement(inputsEndingWith(extIpaAction, "story.storyboard.zip"));
+ assertThat(appStoryboardZip.getExecPath()).isNotEqualTo(extStoryboardZip.getExecPath());
+
+ Artifact appDatamodelZip = Iterables.getOnlyElement(inputsEndingWith(appIpaAction, "data.zip"));
+ Artifact extDatamodelZip = Iterables.getOnlyElement(inputsEndingWith(extIpaAction, "data.zip"));
+ assertThat(appDatamodelZip.getExecPath()).isNotEqualTo(extDatamodelZip.getExecPath());
+
+ Artifact appAssetZip = Iterables.getOnlyElement(inputsEndingWith(appIpaAction, "actool.zip"));
+ Artifact extAssetZip = Iterables.getOnlyElement(inputsEndingWith(extIpaAction, "actool.zip"));
+ assertThat(appAssetZip.getExecPath()).isNotEqualTo(extAssetZip.getExecPath());
+ }
+
+ @Test
+ public void testMultiCpuCompiledResources() throws Exception {
+ checkMultiCpuCompiledResources(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMomczipActions() throws Exception {
+ checkMomczipActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testConvertStringsActions() throws Exception {
+ checkConvertStringsAction(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testRegistersStoryboardCompileActions() throws Exception {
+ checkRegistersStoryboardCompileActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResourcesFromGenrule() throws Exception {
+ checkMultiCpuCompiledResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiCpuGeneratedResourcesFromGenrule() throws Exception {
+ checkMultiCpuGeneratedResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testTwoStringsOneBundlePath() throws Exception {
+ //TODO(bazel-team): This error should be on //x:x but shows up on :bin right now until that
+ // doesn't support bundling anymore.
+ checkTwoStringsOneBundlePath(RULE_TYPE_PAIR, "bin");
+ }
+
+ @Test
+ public void testTwoResourcesOneBundlePath() throws Exception {
+ //TODO(bazel-team): This error should be on //x:x but shows up on :bin right now until that
+ // doesn't support bundling anymore.
+ checkTwoResourcesOneBundlePath(RULE_TYPE_PAIR, "bin");
+ }
+
+ @Test
+ public void testSameStringsTwice() throws Exception {
+ //TODO(bazel-team): This error should be on //x:x but shows up on :bin right now until that
+ // doesn't support bundling anymore.
+ checkSameStringsTwice(RULE_TYPE_PAIR, "bin");
+ }
+
+ @Test
+ public void testGenruleWithoutJavaCcDeps() throws Exception {
+ checkGenruleWithoutJavaCcDependency(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCcDependencyWithProtoDependencyMultiArch() throws Exception {
+ checkCcDependencyWithProtoDependencyMultiArch(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch);
+
+ useConfiguration("--ios_multi_cpus=x86_64,i386");
+ SpawnAction action = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ assertAppleSdkVersionEnv(action);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch);
+
+ useConfiguration("--ios_sdk_version=8.1", "--ios_multi_cpus=x86_64,i386");
+ SpawnAction action = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ assertAppleSdkVersionEnv(action, "8.1");
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch);
+
+ useConfiguration("--ios_multi_cpus=x86_64,i386");
+ SpawnAction action = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ assertAppleSdkPlatformEnv(action, "iPhoneSimulator");
+ }
+
+ @Test
+ public void testAppleSdkDevicePlatformEnv() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch);
+
+ useConfiguration("--ios_multi_cpus=arm64,armv7");
+ SpawnAction action = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ assertAppleSdkPlatformEnv(action, "iPhoneOS");
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ RULE_TYPE_PAIR.scratchTargets(scratch);
+
+ useConfiguration("--xcode_version=5.8", "--ios_multi_cpus=x86_64,i386");
+ SpawnAction action = (SpawnAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ assertXcodeVersionEnv(action, "5.8");
+ }
+
+ @Test
+ public void testLaunchStoryboardIncluded() throws Exception {
+ checkLaunchStoryboardIncluded(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testLaunchStoryboardXibIncluded() throws Exception {
+ checkLaunchStoryboardXib(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testLaunchStoryboardLproj() throws Exception {
+ checkLaunchStoryboardLproj(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultipleInfoPlists() throws Exception {
+ checkMultipleInfoPlists(RULE_TYPE);
+ }
+
+ @Test
+ public void testInfoplistAndInfoplistsTogether() throws Exception {
+ checkInfoplistAndInfoplistsTogether(RULE_TYPE);
+ }
+
+ @Test
+ public void testLateLoadedObjcFrameworkInFinalBundle() throws Exception {
+ scratch.file("x/Foo.framework/Foo");
+ scratch.file("x/Foo.framework/Info.plist");
+ scratch.file("x/Foo.framework/Headers/Foo.h");
+ scratch.file("x/Foo.framework/Resources/bar.png");
+ scratch.file(
+ "x/BUILD",
+ "objc_framework(",
+ " name = 'foo_framework',",
+ " framework_imports = glob(['Foo.framework/**']),",
+ " is_dynamic = 1,",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = [ 'a.m' ],",
+ " runtime_deps = [ ':foo_framework' ],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+
+ assertThat(mergeControl.getBundleFileList())
+ .containsAllOf(
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Foo")
+ .setSourceFile(getSourceArtifact("x/Foo.framework/Foo").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build(),
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Info.plist")
+ .setSourceFile(getSourceArtifact("x/Foo.framework/Info.plist").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build(),
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Resources/bar.png")
+ .setSourceFile(
+ getSourceArtifact("x/Foo.framework/Resources/bar.png").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+
+ assertThat(mergeControl.getBundleFileList())
+ .doesNotContain(
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Headers/Foo.h")
+ .setSourceFile(
+ getSourceArtifact("x/Foo.framework/Headers/Foo.h").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+ }
+
+ @Test
+ public void testLateloadedObjcFrameworkSigned() throws Exception {
+ useConfiguration("--cpu=ios_arm64");
+
+ scratch.file("x/Foo.framework/Foo");
+ scratch.file("x/Foo.framework/Info.plist");
+ scratch.file("x/Foo.framework/Headers/Foo.h");
+ scratch.file("x/Foo.framework/Resources/bar.png");
+ scratch.file(
+ "x/BUILD",
+ "objc_framework(",
+ " name = 'foo_framework',",
+ " framework_imports = glob(['Foo.framework/**']),",
+ " is_dynamic = 1,",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = [ 'a.m' ],",
+ " runtime_deps = [ ':foo_framework' ],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+
+ SpawnAction signingAction = (SpawnAction) ipaGeneratingAction();
+
+ assertThat(normalizeBashArgs(signingAction.getArguments()))
+ .containsAllOf("--sign", "${t}/Payload/x.app/Frameworks/*", "--sign", "${t}/Payload/x.app")
+ .inOrder();
+ }
+
+ @Test
+ public void aspectOnSplitAttributeRegressionTest() throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+ scratch.file("x/a.m");
+ scratch.file("x/x-Info.plist");
+ scratch.file(
+ "x/extension.bzl",
+ "def _my_aspect_impl(target, ctx):",
+ " if type(ctx.rule.attr.binary) != 'list':",
+ " fail('Expected a list for split')",
+ " if len(ctx.rule.attr.binary) != 2:",
+ " fail('Expected 2 items in split')",
+ " return struct()",
+ "my_aspect = aspect(_my_aspect_impl)",
+ "def _my_rule_impl(ctx):",
+ " pass",
+ "my_rule = rule(_my_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [my_aspect]) })"
+ );
+ scratch.file("x/BUILD",
+ "load(':extension.bzl', 'my_rule')",
+ "objc_binary(name = 'bin', srcs = ['a.m'], )",
+ "ios_application(name = 'x', binary = ':bin',)",
+ "my_rule(name = 'y', deps = [ ':x' ])"
+ );
+ getConfiguredTarget("//x:y");
+ }
+
+ @Test
+ public void aspectOnSplitAttributeNoSplitRegressionTest() throws Exception {
+ useConfiguration("--ios_multi_cpus=arm64");
+ scratch.file("x/a.m");
+ scratch.file("x/x-Info.plist");
+ scratch.file(
+ "x/extension.bzl",
+ "def _my_aspect_impl(target, ctx):",
+ " if type(ctx.rule.attr.binary) != 'list':",
+ " fail('Expected a list for split')",
+ " if len(ctx.rule.attr.binary) != 1:",
+ " fail('Expected 1 items in split')",
+ " return struct()",
+ "my_aspect = aspect(_my_aspect_impl)",
+ "def _my_rule_impl(ctx):",
+ " pass",
+ "my_rule = rule(_my_rule_impl, attrs = { 'deps' : attr.label_list(aspects = [my_aspect]) })"
+ );
+ scratch.file("x/BUILD",
+ "load(':extension.bzl', 'my_rule')",
+ "objc_binary(name = 'bin', srcs = ['a.m'], )",
+ "ios_application(name = 'x', binary = ':bin',)",
+ "my_rule(name = 'y', deps = [ ':x' ])"
+ );
+ getConfiguredTarget("//x:y");
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE_PAIR, targetConfig);
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZips() throws Exception {
+ checkIncludesStoryboardOutputZipsAsMergeZips(RULE_TYPE_PAIR, targetConfig);
+ }
+
+ @Test
+ public void testCcDependency() throws Exception {
+ checkCcDependency(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testCcDependencyMultiArch() throws Exception {
+ checkCcDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testCCDependencyWithProtoDependency() throws Exception {
+ checkCcDependencyWithProtoDependency(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testCcDependencyAndJ2objcDependency() throws Exception {
+ checkCcDependencyAndJ2objcDependency(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testApplicationExtension() throws Exception {
+ // Including minimum OS version to trigger a special code path in extension split transitions
+ // which have a higher chance of conflicting with application transitions. See flag
+ // --DO_NOT_USE_configuration_distinguisher for details.
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--ios_minimum_os=8.1");
+ DottedVersion minOsString = DottedVersion.fromString("8.1");
+ scratch.file(
+ "x/BUILD",
+ "ios_extension_binary(",
+ " name = 'ext_bin',",
+ " srcs = ['ebin.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'ext',",
+ " binary = ':ext_bin',",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ " extensions = [':ext'],",
+ ")");
+
+ SpawnAction appLipoAction =
+ (SpawnAction)
+ getGeneratingAction(
+ getBinArtifact(
+ "app_lipobin", getConfiguredTarget("//x:app", getTargetConfiguration())));
+
+ assertThat(Artifact.toExecPaths(appLipoAction.getInputs()))
+ .containsExactly(
+ configurationBin("i386", ConfigurationDistinguisher.IOS_APPLICATION, minOsString)
+ + "x/bin_bin",
+ configurationBin("x86_64", ConfigurationDistinguisher.IOS_APPLICATION, minOsString)
+ + "x/bin_bin",
+ MOCK_XCRUNWRAPPER_PATH);
+
+ SpawnAction extLipoAction =
+ (SpawnAction)
+ getGeneratingAction(
+ getBinArtifact(
+ "ext_lipobin", getConfiguredTarget("//x:ext", getTargetConfiguration())));
+
+ assertThat(Artifact.toExecPaths(extLipoAction.getInputs()))
+ .containsExactly(
+ configurationBin("i386", ConfigurationDistinguisher.IOS_EXTENSION, minOsString)
+ + "x/ext_bin_bin",
+ configurationBin("x86_64", ConfigurationDistinguisher.IOS_EXTENSION, minOsString)
+ + "x/ext_bin_bin", MOCK_XCRUNWRAPPER_PATH);
+ }
+
+ @Test
+ public void testGenruleDependencyMultiArch() throws Exception {
+ checkGenruleDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testTargetHasCpuSpecificDsymFiles() throws Exception {
+ checkTargetHasCpuSpecificDsymFiles(RULE_TYPE);
+ }
+
+ @Test
+ public void testTargetHasDsymPlist() throws Exception {
+ checkTargetHasDsymPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testPropagatesDebugSymbolsFromExtensions() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--apple_generate_dsym");
+ scratch.file(
+ "x/BUILD",
+ "ios_extension_binary(",
+ " name = 'ext2_bin',",
+ " srcs = ['ebin.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'ext2',",
+ " binary = ':ext2_bin',",
+ ")",
+ "",
+ "ios_extension_binary(",
+ " name = 'ext_bin',",
+ " srcs = ['ebin.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'ext',",
+ " binary = ':ext_bin',",
+ ")",
+ "",
+ "apple_watch_extension_binary(",
+ " name = 'watch_bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "apple_watch1_extension(",
+ " name = 'watch_ext',",
+ " app_name = 'y',",
+ " binary = ':watch_bin',",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ " extensions = [':ext', ':ext2', ':watch_ext'],",
+ ")");
+
+ Iterable<Artifact> filesToBuild =
+ getConfiguredTarget("//x:app").getProvider(FileProvider.class).getFilesToBuild();
+ assertThat(filesToBuild)
+ .containsAllOf(
+ getBinArtifact("app.app.dSYM/Contents/Resources/DWARF/app_i386", "//x:app"),
+ getBinArtifact("app.app.dSYM/Contents/Resources/DWARF/app_x86_64", "//x:app"),
+ getBinArtifact("app.app.dSYM/Contents/Info.plist", "//x:app"),
+ getBinArtifact("ext.app.dSYM/Contents/Resources/DWARF/ext_i386", "//x:app"),
+ getBinArtifact("ext.app.dSYM/Contents/Resources/DWARF/ext_x86_64", "//x:app"),
+ getBinArtifact("ext.app.dSYM/Contents/Info.plist", "//x:app"),
+ getBinArtifact("ext2.app.dSYM/Contents/Resources/DWARF/ext2_i386", "//x:app"),
+ getBinArtifact("ext2.app.dSYM/Contents/Resources/DWARF/ext2_x86_64", "//x:app"),
+ getBinArtifact("ext2.app.dSYM/Contents/Info.plist", "//x:app"),
+ getBinArtifact("watch_ext.app.dSYM/Contents/Resources/DWARF/watch_ext_i386", "//x:app"),
+ getBinArtifact(
+ "watch_ext.app.dSYM/Contents/Resources/DWARF/watch_ext_x86_64", "//x:app"),
+ getBinArtifact("watch_ext.app.dSYM/Contents/Info.plist", "//x:app"));
+ }
+
+ @Test
+ public void testMultiArchitectureFanOut() throws Exception {
+ checkBinaryLipoActionMultiCpu(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_APPLICATION);
+ }
+
+ @Test
+ public void testMultiArchitectureWithConfigurableAttribute() throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--cpu=ios_i386");
+ scratch.file(
+ "x/BUILD",
+ "config_setting(",
+ " name = 'i386',",
+ " values = {'cpu': 'ios_i386'},",
+ ")",
+ "",
+ "config_setting(",
+ " name = 'armv7',",
+ " values = {'cpu': 'ios_armv7'},",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'libi386',",
+ " srcs = ['i386.m'],",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'libarmv7',",
+ " srcs = ['armv7.m'],",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'libdefault',",
+ " srcs = ['default.m'],",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = select({",
+ " ':i386': [':libi386'],",
+ " ':armv7': [':libarmv7'],",
+ " '//conditions:default': [':libdefault'],",
+ " }),",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ ")");
+
+ CommandAction appLipoAction =
+ (CommandAction)
+ getGeneratingAction(
+ getBinArtifact(
+ "app_lipobin", getConfiguredTarget("//x:app", getTargetConfiguration())));
+
+ assertThat(Artifact.toExecPaths(appLipoAction.getInputs()))
+ .containsExactly(
+ configurationBin("armv7", ConfigurationDistinguisher.IOS_APPLICATION) + "x/bin_bin",
+ configurationBin("arm64", ConfigurationDistinguisher.IOS_APPLICATION) + "x/bin_bin",
+ MOCK_XCRUNWRAPPER_PATH);
+
+ ImmutableSet.Builder<Artifact> binInputs = ImmutableSet.builder();
+ for (Artifact bin : appLipoAction.getInputs()) {
+ CommandAction binAction = (CommandAction) getGeneratingAction(bin);
+ if (binAction != null) {
+ binInputs.addAll(binAction.getInputs());
+ }
+ }
+
+ assertThat(Artifact.toExecPaths(binInputs.build()))
+ .containsAllOf(
+ configurationBin("armv7", ConfigurationDistinguisher.IOS_APPLICATION)
+ + "x/liblibarmv7.a",
+ configurationBin("arm64", ConfigurationDistinguisher.IOS_APPLICATION)
+ + "x/liblibdefault.a");
+
+ assertThat(Artifact.toExecPaths(binInputs.build()))
+ .doesNotContain(
+ configurationBin("i386", ConfigurationDistinguisher.IOS_APPLICATION)
+ + "x/liblibi386.a");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/IosDeviceTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/IosDeviceTest.java
new file mode 100644
index 0000000000..49b7540b69
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/IosDeviceTest.java
@@ -0,0 +1,172 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RuleConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.rules.apple.XcodeVersionProperties;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for the {@code ios_device} rule.
+ */
+@RunWith(JUnit4.class)
+public class IosDeviceTest extends BuildViewTestCase {
+
+ @Test
+ public void testIosVersion_specified() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_device(name = 'foo', ios_version = '42.0', type = 'IPHONE_6',)");
+
+ assertIosVersion("//test:foo", "42.0");
+ }
+
+ @Test
+ public void testIosVersion_default() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_device(name = 'foo', type = 'IPHONE_6',)");
+
+ assertIosVersion("//test:foo", AppleCommandLineOptions.DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testIosVersion_flagValue() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_device(name = 'foo', type = 'IPHONE_6',)");
+ useConfiguration("--ios_sdk_version=42.3");
+
+ assertIosVersion("//test:foo", "42.3");
+ }
+
+ /**
+ * Tests that if {@code ios_device} specifies an xcode version that does not specify a {@code
+ * default_ios_sdk_version}, the ios sdk version of the device defaults to the default value of
+ * {@code default_ios_sdk_version} instead of the build configuration value. This is a confusing
+ * (perhaps convoluted) corner case.
+ */
+ @Test
+ public void testXcodeVersion_noIosVersion() throws Exception {
+ scratch.file("test/BUILD",
+ "xcode_version(name = 'my_xcode', version = '15.2')",
+ "ios_device(name = 'foo', type = 'IPHONE_6', xcode = ':my_xcode')");
+ useConfiguration("--xcode_version=2.1", "--ios_sdk_version=42.3");
+
+ assertXcodeVersion("//test:foo", "15.2");
+ assertIosVersion("//test:foo", XcodeVersionProperties.DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testXcodeVersion_withIosVersion() throws Exception {
+ scratch.file("test/BUILD",
+ "xcode_version(name = 'my_xcode', version = '15.2', default_ios_sdk_version='17.8')",
+ "ios_device(name = 'foo', type = 'IPHONE_6', xcode = ':my_xcode')");
+ useConfiguration("--xcode_version=2.1", "--ios_sdk_version=42.3");
+
+ assertXcodeVersion("//test:foo", "15.2");
+ assertIosVersion("//test:foo", "17.8");
+ }
+
+ @Test
+ public void testXcodeVersion_iosVersionOverride() throws Exception {
+ scratch.file("test/BUILD",
+ "xcode_version(name = 'my_xcode', version = '15.2', default_ios_sdk_version='17.8')",
+ "ios_device(name = 'foo', type = 'IPHONE_6', ios_version='98.7', xcode = ':my_xcode')");
+ useConfiguration("--xcode_version=2.1", "--ios_sdk_version=42.3");
+
+ assertXcodeVersion("//test:foo", "15.2");
+ assertIosVersion("//test:foo", "98.7");
+ }
+
+ @Test
+ public void testType() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_device(name = 'foo', type = 'IPHONE_6',)");
+
+ assertThat(view.hasErrors(getConfiguredTarget("//test:foo"))).isFalse();
+
+ ConfiguredTarget target = getConfiguredTarget("//test:foo");
+ IosDeviceProvider provider =
+ (IosDeviceProvider) target.get(IosDeviceProvider.SKYLARK_CONSTRUCTOR.getKey());
+ assertThat(provider.getType()).isEqualTo("IPHONE_6");
+ }
+
+ @Test
+ public void testIosDeviceAttributesCanBeReadFromSkylark() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " ios_device_attr = ctx.attr.ios_device[apple_common.IosDevice]",
+ " return struct(",
+ " xcode_version=ios_device_attr.xcode_version,",
+ " ios_version=ios_device_attr.ios_version,",
+ " type=ios_device_attr.type",
+ " )",
+ "my_rule = rule(implementation = my_rule_impl,",
+ " attrs = {",
+ " 'ios_device': attr.label(),",
+ " },",
+ ")");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'my_rule')",
+ "my_rule(",
+ " name = 'my_target',",
+ " ios_device = ':my_device',",
+ ")",
+ "ios_device(",
+ " name = 'my_device',",
+ " type = 'IPHONE_8',",
+ " xcode = ':my_xcode',",
+ " ios_version='98.7'",
+ ")",
+ "xcode_version(",
+ " name = 'my_xcode',",
+ " version = '15.2'",
+ ")");
+
+ RuleConfiguredTarget skylarkTarget =
+ (RuleConfiguredTarget) getConfiguredTarget("//examples/apple_skylark:my_target");
+ assertThat((String) skylarkTarget.get("xcode_version")).isEqualTo("15.2");
+ assertThat((String) skylarkTarget.get("type")).isEqualTo("IPHONE_8");
+ assertThat((String) skylarkTarget.get("ios_version")).isEqualTo("98.7");
+ }
+
+ private void assertXcodeVersion(String label, String version) throws Exception {
+ assertThat(view.hasErrors(getConfiguredTarget(label))).isFalse();
+
+ ConfiguredTarget target = getConfiguredTarget(label);
+ IosDeviceProvider provider =
+ (IosDeviceProvider) target.get(IosDeviceProvider.SKYLARK_CONSTRUCTOR.getKey());
+ assertThat(provider.getXcodeVersion()).isEqualTo(DottedVersion.fromString(version));
+ }
+
+ private void assertIosVersion(String label, String version) throws Exception {
+ assertThat(view.hasErrors(getConfiguredTarget(label))).isFalse();
+
+ ConfiguredTarget target = getConfiguredTarget(label);
+ IosDeviceProvider provider =
+ (IosDeviceProvider) target.get(IosDeviceProvider.SKYLARK_CONSTRUCTOR.getKey());
+ assertThat(provider.getIosVersion()).isEqualTo(DottedVersion.fromString(version));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryTest.java
new file mode 100644
index 0000000000..1de925d0e4
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionBinaryTest.java
@@ -0,0 +1,211 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.BinaryLinkingTargetFactory.REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.ASSET_CATALOG;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for ios_extension_binary. */
+@RunWith(JUnit4.class)
+public class IosExtensionBinaryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new OnlyNeedsSourcesRuleType("ios_extension_binary");
+ protected static final ExtraLinkArgs EXTRA_LINK_ARGS =
+ new ExtraLinkArgs("-e", "_NSExtensionMain", "-fapplication-extension");
+
+ @Before
+ public final void initializeToolsConfigMock() throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+ }
+
+ @Test
+ public void testCreate_runfiles() throws Exception {
+ scratch.file("x/a.m");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget binary = getConfiguredTarget("//x:x");
+ RunfilesProvider runfiles = binary.getProvider(RunfilesProvider.class);
+ assertThat(runfiles.getDefaultRunfiles().getArtifacts()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactly("x/x_bin");
+ }
+
+ @Test
+ public void testCreate_errorForNoSourceOrDep() throws Exception {
+ checkError("x", "x", REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE,
+ "ios_extension_binary(name='x')");
+ }
+
+ @Test
+ public void testCompileWithDotMFileInHeaders() throws Exception {
+ checkCompileWithDotMFileInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcProviderExportsAssetCatalogs() throws Exception {
+ scratch.file("x/BUILD",
+ "ios_extension_binary(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ " asset_catalogs = ['foo.xcassets/bar', 'foo.xcassets/baz'],",
+ ")");
+ ObjcProvider provider = providerForTarget("//x:x");
+ assertThat(provider.get(ASSET_CATALOG))
+ .containsExactly(
+ getSourceArtifact("x/foo.xcassets/bar"),
+ getSourceArtifact("x/foo.xcassets/baz"));
+ }
+
+ @Test
+ public void testLinksFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksWeakFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksWeakFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksDylibsTransitively() throws Exception {
+ checkLinksDylibsTransitively(RULE_TYPE);
+ }
+
+ @Test
+ public void testPopulatesCompilationArtifacts() throws Exception {
+ checkPopulatesCompilationArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testArchivesPrecompiledObjectFiles() throws Exception {
+ checkArchivesPrecompiledObjectFiles(RULE_TYPE);
+ }
+
+ @Test
+ public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception {
+ checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ checkObjcCopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ checkObjcCopts_argumentOrdering(RULE_TYPE);
+ }
+
+ @Test
+ public void testAllowVariousNonBlacklistedTypesInHeaders() throws Exception {
+ checkAllowVariousNonBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testWarningForBlacklistedTypesInHeaders() throws Exception {
+ checkWarningForBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testCppSourceCompilesWithCppFlags() throws Exception {
+ checkCppSourceCompilesWithCppFlags(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkOpts() throws Exception {
+ checkLinkopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkingRuleCanUseCrosstool() throws Exception {
+ checkLinkingRuleCanUseCrosstool(RULE_TYPE);
+ }
+
+ @Test
+ public void testBinaryStrippings() throws Exception {
+ checkBinaryStripAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForDebug() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimized() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testClangCoptsForDebugModeWithoutGlib() throws Exception {
+ checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionCorrect() throws Exception {
+ checkLinkActionCorrect(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testFrameworkDepLinkFlags() throws Exception {
+ checkFrameworkDepLinkFlags(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.LLVMCOV);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionTest.java
new file mode 100644
index 0000000000..af7f0f1f89
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/IosExtensionTest.java
@@ -0,0 +1,638 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multiset;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for ios_extension. */
+@RunWith(JUnit4.class)
+public class IosExtensionTest extends ObjcRuleTestCase {
+ protected static final RuleType RULE_TYPE =
+ new RuleType("ios_extension") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("binary")) {
+ scratch.file(packageDir + "/extension_binary/a.m");
+ scratch.file(
+ packageDir + "/extension_binary/BUILD",
+ "ios_extension_binary(",
+ " name = 'extension_binary',",
+ " srcs = ['a.m'],",
+ ")");
+ attributes.add(String.format("binary = '//%s/extension_binary'", packageDir));
+ }
+ return attributes.build();
+ }
+ };
+
+ protected static final BinaryRuleTypePair RULE_TYPE_PAIR =
+ new BinaryRuleTypePair(
+ IosExtensionBinaryTest.RULE_TYPE,
+ RULE_TYPE,
+ ReleaseBundlingSupport.EXTENSION_BUNDLE_DIR_FORMAT);
+
+ private ConfiguredTarget addMockExtensionAndLibs(String... extraExtAttributes)
+ throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ scratch.file("x/a.m");
+ scratch.file("x/BUILD",
+ "ios_extension_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " deps = ['//lib1:lib1', '//lib2:lib2'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'x',",
+ " binary = ':bin',",
+ Joiner.on(',').join(extraExtAttributes),
+ ")");
+ return getConfiguredTarget("//x:x");
+ }
+
+ @Test
+ public void testSigningAction() throws Exception {
+ checkDeviceSigningAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningWithCertName() throws Exception {
+ checkSigningWithCertName(RULE_TYPE);
+ }
+
+ @Test
+ public void testPostProcessingAction() throws Exception {
+ checkPostProcessingAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningAndPostProcessing() throws Exception {
+ checkSigningAndPostProcessing(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testSigning_simulatorBuild_multiCpu() throws Exception {
+ checkSigningSimulatorBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileDeviceBuild(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testUserSpecifiedProvisioningProfile_deviceBuild() throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, false);
+ }
+
+ @Test
+ public void testUserSpecifiedProvisioningProfile_deviceBuild_multiCpu() throws Exception {
+ checkProvisioningProfileUserSpecified(RULE_TYPE_PAIR, true);
+ }
+
+ @Test
+ public void testMergeControlAction() throws Exception {
+ addMockExtensionAndLibs("infoplist = 'Info.plist'");
+ Action mergeAction = bundleMergeAction("//x:x");
+ Action action = bundleMergeControlAction("//x:x");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly(
+ "x/x.ipa-control");
+ assertThat(bundleMergeControl("//x:x"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .addBundleFile(
+ BundleFile.newBuilder()
+ .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "x_lipobin"))
+ .setBundlePath("x")
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build())
+ .setBundleRoot("PlugIns/x.appex")
+ .setBundleInfoPlistFile(
+ getMergedInfoPlist(getConfiguredTarget("//x:x")).getExecPathString())
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "x.unprocessed.ipa"))
+ .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.x")
+ .build());
+ }
+
+ @Test
+ public void testMergeBundleAction() throws Exception {
+ checkMergeBundleAction(RULE_TYPE_PAIR);
+ }
+
+ protected List<BuildConfiguration> getExtensionConfigurations() throws InterruptedException {
+ return getSplitConfigurations(getTargetConfiguration(),
+ IosExtension.MINIMUM_OS_AND_SPLIT_ARCH_TRANSITION);
+ }
+
+ @Test
+ public void testErrorForLaunchImageGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, LAUNCH_IMAGE_ATTR);
+ }
+
+ @Test
+ public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, APP_ICON_ATTR);
+ }
+
+ @Test
+ public void testCollectsAssetCatalogsTransitively() throws Exception {
+ checkCollectsAssetCatalogsTransitively(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency() throws Exception {
+ checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(
+ RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION);
+ }
+
+ private void addTargetWithAssetCatalogs() throws IOException {
+ scratch.file("x/foo.xcassets/foo");
+ scratch.file("x/foo.xcassets/bar");
+ scratch.file("x/a.m");
+ scratch.file("x/BUILD",
+ "ios_extension_binary(",
+ " name = 'bin',",
+ " asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testActoolActionCorrectness() throws Exception {
+ addTargetWithAssetCatalogs();
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testPassesFamiliesToActool() throws Exception {
+ checkPassesFamiliesToActool(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergeActionsWithAssetCatalog() throws Exception {
+ addTargetWithAssetCatalogs();
+ checkMergeActionsWithAssetCatalog(RULE_TYPE_PAIR);
+ }
+
+ private void addBinAndLibWithRawResources() throws Exception {
+ addBinAndLibWithResources(
+ "resources", "resource1.txt", "ja.lproj/resource2.txt", "ios_extension_binary");
+ scratch.file("x/BUILD",
+ "ios_extension(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ }
+
+ private void addBinAndLibWithStrings() throws Exception {
+ addBinAndLibWithResources(
+ "strings", "foo.strings", "ja.lproj/bar.strings", "ios_extension_binary");
+ scratch.file("x/BUILD",
+ "ios_extension(",
+ " name = 'x',",
+ " binary = '//bin:bin',",
+ ")");
+ }
+
+ @Test
+ public void testCollectsRawResourceFilesTransitively() throws Exception {
+ addBinAndLibWithRawResources();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("lib/resource1.txt", "bin/ja.lproj/resource2.txt"),
+ ImmutableList.of("lib/resource1.txt"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin", ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "x_x", ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "lib_lib", ImmutableMultiset.of("lib/resource1.txt")));
+ }
+
+ @Test
+ public void testCollectsStringsFilesTransitively() throws Exception {
+ addBinAndLibWithStrings();
+ checkCollectsResourceFilesTransitively(
+ "//x:x",
+ ImmutableList.of("x/lib/foo.strings.binary", "x/bin/ja.lproj/bar.strings.binary"),
+ ImmutableList.of("lib/foo.strings.binary"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin", ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "x_x", ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "lib_lib", ImmutableMultiset.of("lib/foo.strings")));
+ }
+
+ @Test
+ public void testResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithRawResources();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "resource1.txt", "resource1.txt",
+ "ja.lproj/resource2.txt", "ja.lproj/resource2.txt"));
+ }
+
+ @Test
+ public void testStringsFilesMergedInBundle() throws Exception {
+ addBinAndLibWithStrings();
+ checkBundleablesAreMerged("//x:x",
+ ImmutableListMultimap.of(
+ "foo.strings.binary", "foo.strings",
+ "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings"));
+ }
+
+ @Test
+ public void testMergesXcdatamodelZips() throws Exception {
+ checkMergesXcdatamodelZips(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testPlistRequiresDotInName() throws Exception {
+ checkError("x", "x",
+ "'//x:Infoplist' does not produce any ios_extension infoplist files (expected .plist)",
+ "ios_extension_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_extension(",
+ " name = 'x',",
+ " infoplist = 'Infoplist',",
+ " binary = ':bin',",
+ ")");
+ }
+
+ @Test
+ public void testMergesPartialInfoplists() throws Exception {
+ checkMergesPartialInfoplists(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testNoEntitlementsDefined() throws Exception {
+ checkNoEntitlementsDefined(RULE_TYPE);
+ }
+
+ @Test
+ public void testEntitlementsDefined() throws Exception {
+ checkEntitlementsDefined(RULE_TYPE);
+ }
+
+ @Test
+ public void testExtraEntitlements() throws Exception {
+ checkExtraEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testDebugEntitlements() throws Exception {
+ checkDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testFastbuildDebugEntitlements() throws Exception {
+ checkFastbuildDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testOptNoDebugEntitlements() throws Exception {
+ checkOptNoDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testExplicitNoDebugEntitlements() throws Exception {
+ checkExplicitNoDebugEntitlements(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesFallbackBundleIdToBundleMerging() throws Exception {
+ checkBundleIdPassedAsFallbackId(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesPrimaryBundleIdToBundleMerging() throws Exception {
+ checkBundleIdPassedAsPrimaryId(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultiPlatformBuild_fails() throws Exception {
+ checkBinaryActionMultiPlatform_fails(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiArchitectureResources() throws Exception {
+ checkMultiCpuResourceInheritance(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiCpuCompiledResources() throws Exception {
+ checkMultiCpuCompiledResources(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMomczipActions() throws Exception {
+ checkMomczipActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testConvertStringsActions() throws Exception {
+ checkConvertStringsAction(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testRegistersStoryboardCompileActions() throws Exception {
+ checkRegistersStoryboardCompileActions(
+ RULE_TYPE_PAIR, DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ @Test
+ public void testMultiCpuCompiledResourcesFromGenrule() throws Exception {
+ checkMultiCpuCompiledResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testMultiCpuGeneratedResourcesFromGenrule() throws Exception {
+ checkMultiCpuGeneratedResourcesFromGenrule(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testTwoStringsOneBundlePath() throws Exception {
+ checkTwoStringsOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testTwoResourcesOneBundlePath() throws Exception {
+ checkTwoResourcesOneBundlePath(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testSameStringsTwice() throws Exception {
+ checkSameStringsTwice(RULE_TYPE_PAIR, "x");
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInBundleMerge() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1");
+ addMockExtensionAndLibs("infoplist = 'Info.plist'");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion())
+ .isEqualTo(IosExtension.EXTENSION_MINIMUM_OS_VERSION.toString());
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsVersionInBundleMergeAtMost80() throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ addMockExtensionAndLibs("infoplist = 'Info.plist'");
+
+ assertThat(bundleMergeControl("//x:x").getMinimumOsVersion())
+ .isEqualTo("8.1");
+ }
+
+ @Test
+ public void testCheckPrimaryBundleIdInMergedPlist() throws Exception {
+ checkPrimaryBundleIdInMergedPlist(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCheckFallbackBundleIdInMergedPlist() throws Exception {
+ checkFallbackBundleIdInMergedPlist(RULE_TYPE_PAIR);
+ }
+
+ protected void checkExtensionReplacesMinimumOsInCompilation() throws Exception {
+ addMockExtensionAndLibs("infoplist = 'Info.plist'");
+
+ Action lipoAction = lipoBinAction("//x:x");
+
+ for (Artifact bin : lipoAction.getInputs()) {
+ CommandAction action = (CommandAction) getGeneratingAction(bin);
+ if (action == null) {
+ continue;
+ }
+ assertThat(generatingArgumentsToString(action))
+ .contains("-mios-simulator-version-min=" + IosExtension.EXTENSION_MINIMUM_OS_VERSION);
+ assertThat(generatingArgumentsToString(action))
+ .doesNotContain("-mios-simulator-version-min=7.1");
+ }
+ }
+
+ private String generatingArgumentsToString(CommandAction generatingAction) {
+ return Joiner.on(' ').join(generatingAction.getArguments());
+ }
+
+ protected void checkExtensionDoesNotReplaceMinimumOsInCompilation() throws Exception {
+ addMockExtensionAndLibs("infoplist = 'Info.plist'");
+
+ Action lipoAction = lipoBinAction("//x:x");
+
+ for (Artifact bin : lipoAction.getInputs()) {
+ CommandAction action = (CommandAction) getGeneratingAction(bin);
+ if (action == null) {
+ continue;
+ }
+ assertThat(generatingArgumentsToString(action)).contains("-mios-simulator-version-min=8.1");
+ assertThat(generatingArgumentsToString(action))
+ .doesNotContain("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION);
+ }
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsVersionInMomcZipAtMost80() throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ checkMomczipActions(RULE_TYPE_PAIR, DottedVersion.fromString("8.1"));
+ }
+
+ @Test
+ public void testGenruleWithoutJavaCcDeps() throws Exception {
+ checkGenruleWithoutJavaCcDependency(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testCcDependencyWithProtoDependencyMultiArch() throws Exception {
+ checkCcDependencyWithProtoDependencyMultiArch(
+ RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testLaunchStoryboardIncluded() throws Exception {
+ checkLaunchStoryboardIncluded(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testLaunchStoryboardXibIncluded() throws Exception {
+ checkLaunchStoryboardXib(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testLaunchStoryboardLproj() throws Exception {
+ checkLaunchStoryboardLproj(RULE_TYPE_PAIR);
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ BuildConfiguration extensionConfiguration =
+ Iterables.getOnlyElement(getExtensionConfigurations());
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE_PAIR, extensionConfiguration);
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZips() throws Exception {
+ BuildConfiguration extensionConfiguration =
+ Iterables.getOnlyElement(getExtensionConfigurations());
+ checkIncludesStoryboardOutputZipsAsMergeZips(RULE_TYPE_PAIR, extensionConfiguration);
+ }
+
+ @Test
+ public void testCcDependency() throws Exception {
+ checkCcDependency(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyMultiArch() throws Exception {
+ checkCcDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyWithProtoDependency() throws Exception {
+ checkCcDependencyWithProtoDependency(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testCcDependencyAndJ2objcDependency() throws Exception {
+ checkCcDependencyAndJ2objcDependency(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testMultiArchitectureFanOut() throws Exception {
+ checkBinaryLipoActionMultiCpu(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testTargetHasCpuSpecificDsymFiles() throws Exception {
+ checkTargetHasCpuSpecificDsymFiles(RULE_TYPE);
+ }
+
+ @Test
+ public void testTargetHasDsymPlist() throws Exception {
+ checkTargetHasDsymPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenruleDependencyMultiArch() throws Exception {
+ checkGenruleDependencyMultiArch(RULE_TYPE_PAIR, ConfigurationDistinguisher.IOS_EXTENSION);
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilation() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1");
+ checkExtensionReplacesMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationAtMost80() throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ checkExtensionDoesNotReplaceMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationMultiArch() throws Exception {
+ useConfiguration("--ios_minimum_os=7.1", "--ios_multi_cpus=i386,x86_64");
+ checkExtensionReplacesMinimumOsInCompilation();
+ }
+
+ @Test
+ public void testExtensionReplacesMinimumOsInCompilationAtMost80MultiArch() throws Exception {
+ useConfiguration("--ios_minimum_os=8.1", "--ios_multi_cpus=i386,x86_64");
+ checkExtensionDoesNotReplaceMinimumOsInCompilation();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/IosTestTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/IosTestTest.java
new file mode 100644
index 0000000000..1c93df5bc1
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/IosTestTest.java
@@ -0,0 +1,1231 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.apple.XcodeVersionProperties;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import com.google.devtools.build.lib.rules.test.InstrumentedFilesProvider;
+import com.google.devtools.build.lib.rules.test.TestProvider;
+import com.google.devtools.build.lib.rules.test.TestRunnerAction;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for ios_test. */
+@RunWith(JUnit4.class)
+public class IosTestTest extends ObjcRuleTestCase {
+ protected static final RuleType RULE_TYPE = new BinaryRuleType("ios_test");
+
+ @Before
+ public final void setUpToolsConfigMock() throws Exception {
+ MockObjcSupport.setupIosTest(mockToolsConfig);
+ MockObjcSupport.setupIosSimDevice(mockToolsConfig);
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+
+ invalidatePackages();
+ }
+
+ @Test
+ public void testRunfiles() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ ConfiguredTarget target = addSimpleIosTest(
+ "bin", "bin", ImmutableList.of("src.m"), ImmutableList.of("//lib1:lib1", "//lib2:lib2"));
+
+ ImmutableList<String> expectedRunfiles =
+ ImmutableList.of(
+ "bin/bin.ipa",
+ "tools/objc/xctest_app.ipa",
+ "bin/bin_test_script",
+ "tools/objc/StdRedirect.dylib",
+ "tools/objc/testrunner");
+
+ RunfilesProvider runfiles = target.getProvider(RunfilesProvider.class);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDefaultRunfiles().getArtifacts()))
+ .containsExactlyElementsIn(expectedRunfiles);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactlyElementsIn(expectedRunfiles);
+ }
+
+ @Test
+ public void testRunfilesInCoverage() throws Exception {
+ useConfiguration("--collect_code_coverage", "--instrument_test_targets");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ ConfiguredTarget target =
+ addSimpleIosTest(
+ "bin",
+ "bin",
+ ImmutableList.of("src.m"),
+ ImmutableList.of("//lib1:lib1", "//lib2:lib2"));
+
+ ImmutableList<String> expectedRunfiles =
+ ImmutableList.of(
+ "tools/objc/mcov",
+ "bin/src.m",
+ "lib1/a.m",
+ "lib1/b.m",
+ "lib2/a.m",
+ "lib2/b.m",
+ "tools/objc/objc_dummy.mm",
+ "lib1/private.h",
+ "lib1/hdr.h",
+ "lib2/private.h",
+ "lib2/hdr.h");
+
+ RunfilesProvider runfiles = target.getProvider(RunfilesProvider.class);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDefaultRunfiles().getArtifacts()))
+ .containsAllIn(expectedRunfiles);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsAllIn(expectedRunfiles);
+ }
+
+ @Test
+ public void testInstrumentedFilesInCoverage() throws Exception {
+ useConfiguration("--collect_code_coverage", "--instrument_test_targets");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ ConfiguredTarget target =
+ addSimpleIosTest(
+ "bin",
+ "bin",
+ ImmutableList.of("src.m"),
+ ImmutableList.of("//lib1:lib1", "//lib2:lib2"));
+
+ InstrumentedFilesProvider instrumentedFilesProvider =
+ target.getProvider(InstrumentedFilesProvider.class);
+ assertThat(Artifact.toRootRelativePaths(instrumentedFilesProvider.getInstrumentedFiles()))
+ .containsExactly(
+ "bin/src.m",
+ "lib1/a.m",
+ "lib1/b.m",
+ "lib2/a.m",
+ "lib2/b.m",
+ "tools/objc/objc_dummy.mm",
+ "lib1/private.h",
+ "lib1/hdr.h",
+ "lib2/private.h",
+ "lib2/hdr.h");
+ assertThat(
+ Artifact.toRootRelativePaths(
+ instrumentedFilesProvider.getInstrumentationMetadataFiles()))
+ .containsExactly(
+ "bin/_objs/bin/bin/src.gcno",
+ "lib1/_objs/lib1/lib1/a.gcno",
+ "lib1/_objs/lib1/lib1/b.gcno",
+ "lib2/_objs/lib2/lib2/a.gcno",
+ "lib2/_objs/lib2/lib2/b.gcno",
+ "tools/objc/_objs/xctest_appbin/tools/objc/objc_dummy.gcno");
+ }
+
+ @Test
+ public void testBuildIpa() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ ConfiguredTarget target =
+ addSimpleIosTest(
+ "bin",
+ "bin",
+ ImmutableList.of("src.m"),
+ ImmutableList.of("//lib1:lib1", "//lib2:lib2"));
+
+ Iterable<Artifact> filesToBuild = target.getProvider(FileProvider.class).getFilesToBuild();
+ ImmutableList<String> expectedFilesToBuild =
+ ImmutableList.of(
+ "bin/bin.ipa",
+ "tools/objc/xctest_app.ipa");
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsExactlyElementsIn(expectedFilesToBuild);
+ }
+
+ @Test
+ public void testXcTestAppIpaIsInFilesToBuild() throws Exception {
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'xctest_app',",
+ " binary = ':xctest_app_bin',",
+ " infoplist = 'Info.plist',",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'xctest_app_bin',",
+ " srcs = ['a.m'],",
+ ")",
+ "",
+ "ios_test(",
+ " name = 'x',",
+ " xctest = 1,",
+ " xctest_app = ':xctest_app',",
+ " srcs = ['test.m'],",
+ ")");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Iterable<Artifact> filesToBuild = target.getProvider(FileProvider.class).getFilesToBuild();
+ assertThat(filesToBuild).contains(getBinArtifact("xctest_app.ipa", target));
+ }
+
+ @Test
+ public void testIpaIsImplicitOutput() throws Exception {
+ addSimpleIosTest("bin", "bin", ImmutableList.of("src.m"), ImmutableList.<String>of());
+ assertThat(getConfiguredTarget("//bin:bin.ipa")).isNotNull();
+ }
+
+ @Test
+ public void testXcTest() throws Exception {
+ setUpXCTestClient();
+ ConfiguredTarget target = getConfiguredTarget("//test:XcTest");
+
+ ImmutableList<String> expectedRunfiles =
+ ImmutableList.of(
+ "test/XcTest.ipa",
+ "test/testApp.ipa",
+ "test/XcTest_test_script",
+ "tools/objc/StdRedirect.dylib",
+ "tools/objc/testrunner");
+ RunfilesProvider runfiles = target.getProvider(RunfilesProvider.class);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDefaultRunfiles().getArtifacts()))
+ .containsExactlyElementsIn(expectedRunfiles);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactlyElementsIn(expectedRunfiles);
+ }
+
+ @Test
+ public void testXcTestInCoverage() throws Exception {
+ useConfiguration("--collect_code_coverage", "--instrument_test_targets");
+ setUpXCTestClient();
+ ConfiguredTarget target = getConfiguredTarget("//test:XcTest");
+
+ InstrumentedFilesProvider instrumentedFilesProvider =
+ target.getProvider(InstrumentedFilesProvider.class);
+ assertThat(Artifact.toRootRelativePaths(instrumentedFilesProvider.getInstrumentedFiles()))
+ .containsExactly("test/src.m", "test/test-src.m");
+ assertThat(
+ Artifact.toRootRelativePaths(
+ instrumentedFilesProvider.getInstrumentationMetadataFiles()))
+ .containsExactly(
+ "test/_objs/XcTest/test/test-src.gcno", "test/_objs/testAppBin/test/src.gcno");
+ }
+
+ @Test
+ public void testXcTestInCoverageFilter() throws Exception {
+ useConfiguration("--collect_code_coverage", "--instrumentation_filter=-XcTest$");
+ setUpXCTestClient();
+ ConfiguredTarget target = getConfiguredTarget("//test:XcTest");
+
+
+ InstrumentedFilesProvider instrumentedFilesProvider =
+ target.getProvider(InstrumentedFilesProvider.class);
+
+ // Missing "test/test-src.m" since the target including it has been excluded.
+ assertThat(Artifact.toRootRelativePaths(instrumentedFilesProvider.getInstrumentedFiles()))
+ .containsExactly("test/src.m");
+ }
+
+ @Test
+ public void testXcTest_linkAction() throws Exception {
+ setUpXCTestClient();
+ CommandAction action = linkAction("//test:XcTest");
+
+ String commandLine = Joiner.on(" ").join(action.getArguments());
+ assertThat(commandLine).contains("-bundle");
+ assertThat(commandLine).contains("-Xlinker -rpath -Xlinker @loader_path/Frameworks");
+ }
+
+ @Test
+ public void testXcTest_linkAction_Crosstool() throws Exception {
+ useConfiguration(ObjcCrosstoolMode.ALL);
+ testXcTest_linkAction();
+ }
+
+ @Test
+ public void testVariableSubstitution() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ addSimpleIosTest(
+ "bin", "bin", ImmutableList.of("src.m"), ImmutableList.of("//lib1:lib1", "//lib2:lib2"));
+
+ PlMergeProtos.Control control = plMergeControl("//bin:bin");
+ Map<String, String> substitutions = control.getVariableSubstitutionMapMap();
+ assertThat(substitutions)
+ .containsExactlyEntriesIn(
+ ImmutableMap.<String, String>of(
+ "EXECUTABLE_NAME", "bin",
+ "BUNDLE_NAME", "bin.xctest",
+ "PRODUCT_NAME", "bin"));
+ }
+
+ protected void setUpXCTestClient() throws Exception {
+ scratch.file("/test/XcTest-Info.plist");
+ scratch.file("/test/App-Info.plist");
+ scratch.file("/test/src.m");
+ scratch.file("/test/test-src.m");
+
+ scratch.file("test/BUILD",
+ "objc_binary(",
+ " name = 'testAppBin',",
+ " srcs = ['src.m'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':testAppBin',",
+ ")",
+ "ios_test(",
+ " name = 'XcTest',",
+ " srcs = ['test-src.m'],",
+ " xctest = True,",
+ " xctest_app = ':testApp',",
+ ")");
+ }
+
+ @Test
+ public void testCreate_recognizesDylibsAttribute() throws Exception {
+ createBinaryTargetWriter("//bin:bin").setAndCreateFiles("srcs", "a.m").write();
+ scratch.file("test/BUILD",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = '//bin:bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test-src.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " sdk_dylibs = ['libdy'],",
+ ")");
+ CommandAction action = linkAction("//test:test");
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains("-ldy");
+ }
+
+ @Test
+ public void testPopulatesCompilationArtifacts() throws Exception {
+ checkPopulatesCompilationArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testArchivesPrecompiledObjectFiles() throws Exception {
+ checkArchivesPrecompiledObjectFiles(RULE_TYPE);
+ }
+
+ @Test
+ public void testPopulatesBundling() throws Exception {
+ checkPopulatesBundling(RULE_TYPE);
+ }
+
+ @Test
+ public void testRegistersStoryboardCompilationActions() throws Exception {
+ checkRegistersStoryboardCompileActions(RULE_TYPE, "iphone");
+ }
+
+ @Test
+ public void testRegistersSwiftStdlibActions() throws Exception {
+ checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator");
+ }
+
+ @Test
+ public void testRegistersSwiftSupportActions() throws Exception {
+ checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator");
+ }
+
+ @Test
+ public void testRegistersSwiftStdlibActionsWithToolchain() throws Exception {
+ useConfiguration("--xcode_toolchain=test_toolchain");
+ checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator", "test_toolchain");
+ }
+
+ @Test
+ public void testRegistersSwiftSupportActionsWithToolchain() throws Exception {
+ useConfiguration("--xcode_toolchain=test_toolchain");
+ checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator", "test_toolchain");
+ }
+
+ @Test
+ public void testAddsStoryboardZipsToFilesToBuild() throws Exception {
+ ConfiguredTarget target = createTargetWithStoryboards(RULE_TYPE);
+
+ assertThat(getFilesToBuild(getConfiguredTarget("//x:x")))
+ .containsAllOf(
+ getBinArtifact("x/1.storyboard.zip", target),
+ getBinArtifact("x/2.storyboard.zip", target));
+ }
+
+ @Test
+ public void testAddsXcdatamodelZipsToFilesToBuild() throws Exception {
+ RULE_TYPE.scratchTarget(scratch,
+ "datamodels", "['modela.xcdatamodel/a', 'modelb.xcdatamodeld/modelb1/a']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ assertThat(getFilesToBuild(target))
+ .containsAllOf(
+ getBinArtifact("x/modela.zip", target),
+ getBinArtifact("x/modelb.zip", target));
+ }
+
+ @Test
+ public void testHasDefaultInfoplistForXcTest() throws Exception {
+ createBinaryTargetWriter("//bin:bin").setAndCreateFiles("srcs", "a.m").write();
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = '//bin:bin',",
+ ")",
+ "ios_test(",
+ " name = 'x',",
+ " srcs = ['x-src.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ PlMergeProtos.Control control = plMergeControl("//x:x");
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("tools/objc/xctest.plist").getExecPathString());
+ }
+
+ @Test
+ public void testCheckPrimaryBundleIdInMergedPlist() throws Exception {
+ checkPrimaryBundleIdInMergedPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testCheckFallbackBundleIdInMergedPlist() throws Exception {
+ checkFallbackBundleIdInMergedPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception {
+ checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE);
+ }
+
+ @Test
+ public void testErrorForNoSources() throws Exception {
+ createBinaryTargetWriter("//bin:bin").setAndCreateFiles("srcs", "a.m").write();
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ checkError("x", "x",
+ IosTest.REQUIRES_SOURCE_ERROR,
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = '//bin:bin',",
+ ")",
+ "ios_test(",
+ " name = 'x',",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " deps = ['//lib:lib'],",
+ ")");
+ }
+
+ private void checkTestScript(Map<String, String> templateArguments, String... extraAttrs)
+ throws Exception {
+ createBinaryTargetWriter("//bin:bin").setAndCreateFiles("srcs", "a.m").write();
+ scratch.file("x/BUILD",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = '//bin:bin',",
+ ")",
+ "ios_test(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ Joiner.on(",").join(extraAttrs),
+ ")");
+ TemplateExpansionAction action =
+ (TemplateExpansionAction)
+ getGeneratingAction(getBinArtifact("x_test_script", getConfiguredTarget("//x:x")));
+
+ for (Map.Entry<String, String> templateArgument : templateArguments.entrySet()) {
+ assertThat(action.getSubstitutions()).contains(
+ Substitution.of("%(" + templateArgument.getKey() + ")s", templateArgument.getValue()));
+ }
+ }
+
+ @Test
+ public void testTargetDeviceUsesIosVersionAttributeIfGiven() throws Exception {
+ scratch.file("devices/BUILD",
+ "ios_device(",
+ " name = 'dev',",
+ " type = 'test_type',",
+ " ios_version = '42.9993',",
+ ")");
+ checkTestScript(
+ ImmutableMap.of("simulator_sdk", "42.9993", "device_type", "test_type"),
+ "target_device = '//devices:dev'");
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ scratch.file("x/a.m");
+ addSimpleIosTest("bin", "bin", ImmutableList.of("a.m"), ImmutableList.<String>of());
+ List<String> args = compileAction("//bin:bin", "a.o").getArguments();
+ assertThat(args).contains("-foo");
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ scratch.file("x/a.m");
+ addSimpleIosTest(
+ "bin", "bin", ImmutableList.of("a.m"), ImmutableList.<String>of(), "copts=['-bar']");
+ List<String> args = compileAction("//bin:bin", "a.o").getArguments();
+ assertThat(args).containsAllOf("-fobjc-arc", "-foo", "-bar").inOrder();
+ }
+
+ @Test
+ public void testGetsDefinesFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " defines = ['LIB_DEFINE=1'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " defines = ['BIN_DEFINE=1'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " defines = ['TEST_DEFINE=1'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ assertContainsSublist(compileAction("//x:test", "test.o").getArguments(),
+ ImmutableList.of("-DLIB_DEFINE=1", "-DBIN_DEFINE=1", "-DTEST_DEFINE=1"));
+ }
+
+ @Test
+ public void testGetsSdkDylibsFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " sdk_dylibs = ['lib_dylib'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " sdk_dylibs = ['bin_dylib'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " sdk_dylibs = ['test_dylib'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+
+ String linkArgs = Joiner.on(' ').join(linkAction("//x:test").getArguments());
+ assertThat(linkArgs).contains("-l_dylib");
+ assertThat(linkArgs).contains("-lbin_dylib");
+ assertThat(linkArgs).contains("-ltest_dylib");
+ }
+
+ @Test
+ public void testGetsSdkFrameworksFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " sdk_frameworks = ['lib_fx'],",
+ " weak_sdk_frameworks = ['lib_wfx'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " sdk_frameworks = ['bin_fx'],",
+ " weak_sdk_frameworks = ['bin_wfx'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " sdk_frameworks = ['test_fx'],",
+ " weak_sdk_frameworks = ['test_wfx'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+
+ String linkArgs = Joiner.on(' ').join(linkAction("//x:test").getArguments());
+ assertThat(linkArgs).contains("-framework lib_fx");
+ assertThat(linkArgs).contains("-weak_framework lib_wfx");
+ assertThat(linkArgs).contains("-framework bin_fx");
+ assertThat(linkArgs).contains("-weak_framework bin_wfx");
+ assertThat(linkArgs).contains("-framework test_fx");
+ assertThat(linkArgs).contains("-weak_framework test_wfx");
+ }
+
+ @Test
+ public void testLinkIncludeOrder_staticLibsFirst() throws Exception {
+ checkLinkIncludeOrderStaticLibsFirst(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkIncludeOrder_frameworksAndSystemLibsFirst() throws Exception {
+ checkLinkIncludeOrderFrameworksAndSystemLibsFirst(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergesActoolPartialInfoplist() throws Exception {
+ checkMergesPartialInfoplists(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE);
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE);
+ }
+
+ @Test
+ public void testActoolActionCorrectness() throws Exception {
+ addTargetWithAssetCatalogs(RULE_TYPE);
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testPassesFamiliesToActool() throws Exception {
+ checkPassesFamiliesToActool(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE);
+ }
+
+ @Test
+ public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE);
+ }
+
+ @Test
+ public void testCppSourceCompilesWithCppFlags() throws Exception {
+ checkCppSourceCompilesWithCppFlags(RULE_TYPE);
+ }
+
+ @Test
+ public void testNoMultiCpu() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386", "--ios_cpu=armv7");
+
+ checkError("x", "x",
+ IosTest.NO_MULTI_CPUS_ERROR,
+ "ios_test(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ ")");
+ }
+
+ @Test
+ public void testXcTestAppFromSkylarkRule() throws Exception {
+ scratch.file("examples/rule/BUILD",
+ "exports_files(['test.ipa'])");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _skylark_xctest_app_impl(ctx):",
+ " artifact = list(ctx.attr.test_ipa.files)[0]",
+ " objc_provider = apple_common.new_objc_provider(define=depset(['TEST_DEFINE']))",
+ " xctest_app_provider = apple_common.new_xctest_app_provider(",
+ " bundle_loader=artifact, ipa=artifact, objc_provider=objc_provider)",
+ " return struct(",
+ " xctest_app=xctest_app_provider,",
+ " )",
+ "skylark_xctest_app = rule(implementation = _skylark_xctest_app_impl,",
+ " attrs = {",
+ " 'test_ipa': attr.label(",
+ " allow_single_file=True,",
+ " default=Label('//examples/rule:test.ipa')),",
+ " })");
+
+ scratch.file(
+ "examples/ios_test/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'skylark_xctest_app')",
+ "skylark_xctest_app(",
+ " name = 'my_xctest_app',",
+ ")",
+ "ios_test(",
+ " name = 'my_tests',",
+ " srcs = ['tests.m'],",
+ " xctest_app = ':my_xctest_app',",
+ ")");
+
+ ConfiguredTarget testTarget = getConfiguredTarget("//examples/ios_test:my_tests");
+
+ assertThat(
+ Artifact.toRootRelativePaths(
+ testTarget.getProvider(FileProvider.class).getFilesToBuild()))
+ .contains("examples/rule/test.ipa");
+ }
+
+ @Test
+ public void testApplePlatformAndXcode() throws Exception {
+ scratch.file("test/BUILD",
+ "xcode_version(",
+ " name = 'test_xcode',",
+ " version = '2.3',",
+ ")",
+ "ios_device(",
+ " name = 'test_device',",
+ " ios_version = '3.4',",
+ " xcode = ':test_xcode',",
+ " type = 'iChimpanzee',",
+ ")",
+ "ios_test(",
+ " name = 'some_test',",
+ " srcs = ['SomeTest.m'],",
+ " xctest = 0,",
+ " target_device = ':test_device',",
+ ")");
+
+ scratch.file("test/SomeTest.m");
+
+ ConfiguredTarget testTarget = getConfiguredTarget("//test:some_test");
+
+ TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(
+ Iterables.getOnlyElement(TestProvider.getTestStatusArtifacts(testTarget)));
+ TemplateExpansionAction templateExpansionAction =
+ getTestScriptGenerationAction(getConfiguredTarget("//test:some_test"));
+
+ assertThat(templateExpansionAction.getSubstitutions())
+ .contains(Substitution.of("%(simulator_sdk)s", "3.4"));
+ assertThat(testAction.getExtraTestEnv()).containsEntry("XCODE_VERSION_OVERRIDE", "2.3");
+ }
+
+ @Test
+ public void testAppleEnvironmentVariables_configurationXcodeVersion() throws Exception {
+ useConfiguration("--xcode_version=5.8");
+
+ scratch.file("test/BUILD",
+ "ios_device(",
+ " name = 'test_device',",
+ " type = 'iChimpanzee',",
+ ")",
+ "ios_test(",
+ " name = 'some_test',",
+ " srcs = ['SomeTest.m'],",
+ " xctest = 0,",
+ " target_device = ':test_device',",
+ ")");
+
+ scratch.file("test/SomeTest.m");
+
+ ConfiguredTarget testTarget = getConfiguredTarget("//test:some_test");
+
+ TestRunnerAction testAction = (TestRunnerAction) getGeneratingAction(
+ Iterables.getOnlyElement(TestProvider.getTestStatusArtifacts(testTarget)));
+ TemplateExpansionAction templateExpansionAction =
+ getTestScriptGenerationAction(getConfiguredTarget("//test:some_test"));
+
+ assertThat(templateExpansionAction.getSubstitutions()).contains(
+ Substitution.of("%(simulator_sdk)s", XcodeVersionProperties.DEFAULT_IOS_SDK_VERSION));
+ assertThat(testAction.getExtraTestEnv())
+ .containsEntry("XCODE_VERSION_OVERRIDE", "5.8");
+ }
+
+ @Test
+ public void testRunnerSubstitution() throws Exception {
+ addSimpleIosTest("test", "some_test", ImmutableList.of("a.m"), ImmutableList.<String>of());
+
+ TemplateExpansionAction action =
+ getTestScriptGenerationAction(getConfiguredTarget("//test:some_test"));
+ assertThat(action.getSubstitutions()).containsExactly(
+ Substitution.of("%(memleaks)s", "false"),
+
+ Substitution.of("%(test_app_ipa)s", "test/some_test.ipa"),
+ Substitution.of("%(test_app_name)s", "some_test"),
+ Substitution.of("%(test_bundle_path)s", "test/some_test.ipa"),
+
+ Substitution.of("%(xctest_app_ipa)s", "tools/objc/xctest_app.ipa"),
+ Substitution.of("%(xctest_app_name)s", "xctest_app"),
+ Substitution.of("%(test_host_path)s", "tools/objc/xctest_app.ipa"),
+
+ Substitution.of("%(plugin_jars)s", ""),
+ Substitution.of("%(device_type)s", "iChimpanzee"),
+ Substitution.of("%(locale)s", "en"),
+ Substitution.of("%(simulator_sdk)s", "9.8"),
+ Substitution.of("%(testrunner_binary)s", "tools/objc/testrunner"),
+ Substitution.of("%(std_redirect_dylib_path)s", "tools/objc/StdRedirect.dylib"),
+ Substitution.of("%(test_env)s", ""),
+ Substitution.of("%(test_type)s", "XCTEST")
+ );
+ }
+
+ @Test
+ public void testNonXcTestSubstitution() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_test(",
+ " name = 'some_test',",
+ " srcs = ['SomeTest.m'],",
+ " xctest = 0,",
+ ")");
+
+ scratch.file("test/SomeTest.m");
+
+ ConfiguredTarget target = getConfiguredTarget("//test:some_test");
+
+ TemplateExpansionAction action =
+ getTestScriptGenerationAction(target);
+ assertThat(action.getSubstitutions()).containsExactly(
+ Substitution.of("%(memleaks)s", "false"),
+
+ Substitution.of("%(test_app_ipa)s", "test/some_test.ipa"),
+ Substitution.of("%(test_bundle_path)s", "test/some_test.ipa"),
+ Substitution.of("%(test_app_name)s", "some_test"),
+
+ Substitution.of("%(xctest_app_ipa)s", ""),
+ Substitution.of("%(xctest_app_name)s", ""),
+ Substitution.of("%(test_host_path)s", ""),
+
+ Substitution.of("%(plugin_jars)s", ""),
+ Substitution.of("%(device_type)s", "iChimpanzee"),
+ Substitution.of("%(locale)s", "en"),
+ Substitution.of("%(simulator_sdk)s", "9.8"),
+ Substitution.of("%(testrunner_binary)s", "tools/objc/testrunner"),
+ Substitution.of("%(std_redirect_dylib_path)s", "tools/objc/StdRedirect.dylib"),
+ Substitution.of("%(test_env)s", ""),
+ Substitution.of("%(test_type)s", "KIF")
+ );
+
+ assertRunfilesContainsRootRelativePaths(target,
+ "test/some_test.ipa",
+ "test/some_test_test_script",
+ "tools/objc/testrunner");
+ }
+
+ @Test
+ public void testRunnerWithDevice() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_test(",
+ " name = 'some_test_with_device',",
+ " srcs = ['SomeOtherTest.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " target_device = ':device',",
+ ")",
+ "ios_device(",
+ " name = 'device',",
+ " ios_version = '1.2',",
+ " type = 'iMarmoset',",
+ " locale = 'en-gb'",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "objc_binary(name = 'bin',",
+ " srcs = ['app.m'],",
+ ")");
+
+ scratch.file("test/SomeOtherTest.m");
+ scratch.file("test/app.m");
+
+ TemplateExpansionAction action =
+ getTestScriptGenerationAction(getConfiguredTarget("//test:some_test_with_device"));
+ assertThat(action.getSubstitutions()).containsExactly(
+ Substitution.of("%(memleaks)s", "false"),
+
+ Substitution.of("%(test_app_ipa)s", "test/some_test_with_device.ipa"),
+ Substitution.of("%(test_app_name)s", "some_test_with_device"),
+ Substitution.of("%(test_bundle_path)s", "test/some_test_with_device.ipa"),
+
+ Substitution.of("%(xctest_app_ipa)s", "test/testApp.ipa"),
+ Substitution.of("%(xctest_app_name)s", "testApp"),
+ Substitution.of("%(test_host_path)s", "test/testApp.ipa"),
+
+ Substitution.of("%(plugin_jars)s", ""),
+ Substitution.of("%(device_type)s", "iMarmoset"),
+ Substitution.of("%(locale)s", "en-gb"),
+ Substitution.of("%(simulator_sdk)s", "1.2"),
+ Substitution.of("%(testrunner_binary)s", "tools/objc/testrunner"),
+ Substitution.of("%(std_redirect_dylib_path)s", "tools/objc/StdRedirect.dylib"),
+ Substitution.of("%(test_env)s", ""),
+ Substitution.of("%(test_type)s", "XCTEST")
+ );
+ }
+
+ @Test
+ public void testPlugins() throws Exception {
+ scratch.file("test/BUILD",
+ "ios_test(",
+ " name = 'one_plugin',",
+ " srcs = ['SomeTest.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " plugins = [':a_plugin_deploy.jar'],",
+ ")",
+ "ios_test(",
+ " name = 'two_plugins',",
+ " srcs = ['SomeOtherTest.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " plugins = [':a_plugin_deploy.jar', ':b_plugin_deploy.jar'],",
+ ")",
+ "java_binary(",
+ " name = 'a_plugin',",
+ " srcs = ['A.java'],",
+ " main_class = 'A',",
+ ")",
+ "java_binary(",
+ " name = 'b_plugin',",
+ " srcs = ['B.java'],",
+ " main_class = 'B',",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "objc_binary(name = 'bin',",
+ " srcs = ['app.m'],",
+ ")");
+
+ scratch.file("test/SomeTest.m");
+ scratch.file("test/SomeOtherTest.m");
+ scratch.file("test/app.m");
+ scratch.file("test/A.java");
+ scratch.file("test/B.java");
+
+ ConfiguredTarget onePluginTarget = getConfiguredTarget("//test:one_plugin");
+ TemplateExpansionAction onePluginAction =
+ getTestScriptGenerationAction(onePluginTarget);
+ assertThat(onePluginAction.getSubstitutions()).contains(
+ Substitution.of("%(plugin_jars)s", "test/a_plugin_deploy.jar"));
+ assertRunfilesContainsRootRelativePaths(onePluginTarget, "test/a_plugin_deploy.jar");
+
+ ConfiguredTarget twoPluginsTarget = getConfiguredTarget("//test:two_plugins");
+ TemplateExpansionAction twoPluginsAction =
+ getTestScriptGenerationAction(twoPluginsTarget);
+ assertThat(twoPluginsAction.getSubstitutions()).contains(
+ Substitution.of("%(plugin_jars)s", "test/a_plugin_deploy.jar:test/b_plugin_deploy.jar")
+ );
+ assertRunfilesContainsRootRelativePaths(twoPluginsTarget,
+ "test/a_plugin_deploy.jar", "test/b_plugin_deploy.jar");
+ }
+
+ private TemplateExpansionAction getTestScriptGenerationAction(ConfiguredTarget target)
+ throws Exception {
+ Artifact testScript = getBinArtifact(target.getLabel().getName() + "_test_script", target);
+ return (TemplateExpansionAction) getGeneratingAction(testScript);
+ }
+
+ private void assertRunfilesContainsRootRelativePaths(
+ ConfiguredTarget target, String... expectedRunfiles) {
+ RunfilesProvider runfiles = target.getProvider(RunfilesProvider.class);
+ ImmutableList<String> listToAvoidDumbUnsafeVarargsWarning =
+ ImmutableList.copyOf(expectedRunfiles);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDefaultRunfiles().getArtifacts()))
+ .containsAllIn(listToAvoidDumbUnsafeVarargsWarning);
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsAllIn(listToAvoidDumbUnsafeVarargsWarning);
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkOpts() throws Exception {
+ checkLinkopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkingRuleCanUseCrosstool() throws Exception {
+ checkLinkingRuleCanUseCrosstool(RULE_TYPE);
+ }
+
+ @Test
+ public void testBinaryStrippings() throws Exception {
+ checkBinaryStripAction(RULE_TYPE, "-S");
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE);
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZips() throws Exception {
+ checkIncludesStoryboardOutputZipsAsMergeZips(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForDebug() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testClangCoptsForDebugModeWithoutGlib() throws Exception {
+ checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimized() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testProtobufPropagatedHeaderSearchPaths() throws Exception {
+ scratch.file(
+ "test/BUILD",
+ "ios_test(",
+ " name = 'protos_test',",
+ " srcs = ['SomeTest.m'],",
+ " xctest = 1,",
+ " xctest_app = ':protos_app',",
+ ")",
+ "ios_application(",
+ " name = 'protos_app',",
+ " binary = ':protos_bin',",
+ ")",
+ "objc_binary(",
+ " name = 'protos_bin',",
+ " srcs = ['app.m'],",
+ " deps = [':protos_objc'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'protos_objc',",
+ " deps = [':protos_lib'],",
+ " portable_proto_filters = ['filter.pbascii'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_lib',",
+ " srcs = ['a.proto'],",
+ ")");
+
+ ObjcProvider appProvider =
+ getConfiguredTarget("//test:protos_app")
+ .getProvider(XcTestAppProvider.class)
+ .getObjcProvider();
+ ConfiguredTarget binTarget = getConfiguredTarget("//test:protos_bin");
+ Artifact protoHeader =
+ getBinArtifact("_generated_protos/protos_bin/test/A.pbobjc.h", binTarget);
+
+ assertThat(PathFragment.safePathStrings(appProvider.get(ObjcProvider.INCLUDE)))
+ .containsAllOf(
+ "objcproto/include",
+ protoHeader.getExecPath().getParentDirectory().getParentDirectory().toString());
+ }
+
+ @Test
+ public void testCcDependency() throws Exception {
+ checkCcDependency(RULE_TYPE, "xctest", "0");
+ }
+
+ @Test
+ public void testPassesTestRigAppAsBundleLoaderFlagToLinker() throws Exception {
+ useConfiguration("--cpu=ios_x86_64",
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go");
+ scratch.file("x/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ CommandAction testLinkAction = linkAction("//x:test");
+ Action appLipoAction = lipoBinAction("//x:testApp");
+ Artifact rigBinary = Iterables.getOnlyElement(appLipoAction.getOutputs());
+
+ String linkArgs = Joiner.on(' ').join(testLinkAction.getArguments());
+ assertThat(linkArgs).contains("-bundle_loader " + rigBinary.getExecPath());
+ assertThat(testLinkAction.getInputs()).contains(rigBinary);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testMultiArchUserHeaderSearchPathsUsed() throws Exception {
+ // Usually, an ios_test would depend on apple_binary through a skylark_ios_application in its
+ // 'binary' attribute. Since we don't have skylark_ios_application here, we use the 'deps'
+ // attribute instead.
+ scratch.file("x/BUILD",
+ "genrule(",
+ " name = 'gen_hdrs',",
+ " outs = ['generated.h'],",
+ " cmd = 'echo hello > \\$@',",
+ ")",
+ "apple_binary(",
+ " name = 'apple_bin',",
+ " srcs = ['apple_bin.m'],",
+ " platform_type = 'ios',",
+ " hdrs = ['generated.h'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ " deps = [':apple_bin']",
+ ")");
+ CommandAction compileAction = compileAction("//x:test", "test.o");
+ // The genfiles root for child configurations must be present in the compile action so that
+ // generated headers can be resolved.
+ assertThat(Joiner.on(" ").join(compileAction.getArguments())).contains("-iquote "
+ + configurationGenfiles("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS,
+ defaultMinimumOs(ConfigurationDistinguisher.APPLEBIN_IOS)));
+ }
+
+ @Test
+ public void testXcTest_linkAction_inCoverageMode() throws Exception {
+ useConfiguration("--collect_code_coverage");
+ setUpXCTestClient();
+ CommandAction action = linkAction("//test:XcTest");
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains("-bundle");
+ for (String linkerCoverageFlag : CompilationSupport.LINKER_COVERAGE_FLAGS) {
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains(linkerCoverageFlag);
+ }
+ }
+
+ @Test
+ public void testXcTest_linkAction_inLLVMCoverageMode() throws Exception {
+ useConfiguration("--collect_code_coverage", "--experimental_use_llvm_covmap");
+ setUpXCTestClient();
+ CommandAction action = linkAction("//test:XcTest");
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains("-bundle");
+ for (String linkerCoverageFlag : CompilationSupport.LINKER_LLVM_COVERAGE_FLAGS) {
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains(linkerCoverageFlag);
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleBinaryTest.java
new file mode 100644
index 0000000000..7f919ceee3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleBinaryTest.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleBinaryTest extends AppleBinaryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleDynamicLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleDynamicLibraryTest.java
new file mode 100644
index 0000000000..ca1844f6d3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleDynamicLibraryTest.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleDynamicLibraryTest extends AppleDynamicLibraryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleStaticLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleStaticLibraryTest.java
new file mode 100644
index 0000000000..d25de7b30e
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleStaticLibraryTest.java
@@ -0,0 +1,96 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleStaticLibraryTest extends AppleStaticLibraryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testAvoidDepsObjects() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " deps = [':objcLib'],",
+ " avoid_deps = [':avoidLib'],",
+ " platform_type = 'ios',",
+ ")",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ], deps = [':avoidLib', ':baseLib'])",
+ "objc_library(name = 'baseLib', srcs = [ 'base.m' ])",
+ "objc_library(name = 'avoidLib', srcs = [ 'c.m' ])");
+
+ CommandAction action = linkLibAction("//package:test");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsExactly(
+ "package/libobjcLib.a", "package/libbaseLib.a", MOCK_LIBTOOL_PATH);
+ }
+
+ @Test
+ // Tests that if there is a cc_library in avoid_deps, all of its dependencies are
+ // transitively avoided, even if it is not present in deps.
+ public void testAvoidDepsObjects_avoidViaCcLibrary() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " deps = [':objcLib'],",
+ " avoid_deps = [':avoidCclib'],",
+ " platform_type = 'ios',",
+ ")",
+ "cc_library(name = 'avoidCclib', srcs = ['cclib.c'], deps = [':avoidLib'])",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ], deps = [':avoidLib'])",
+ "objc_library(name = 'avoidLib', srcs = [ 'c.m' ])");
+
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm");
+ CommandAction action = linkLibAction("//package:test");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsExactly(
+ "package/libobjcLib.a", MOCK_LIBTOOL_PATH);
+ }
+
+ @Test
+ // Tests that if there is a cc_library in avoid_deps, and it is present in deps, it will
+ // be avoided, as well as its transitive dependencies.
+ public void testAvoidDepsObjects_avoidCcLibrary() throws Exception {
+ scratch.file("package/BUILD",
+ "apple_static_library(",
+ " name = 'test',",
+ " deps = [':objcLib', ':avoidCclib'],",
+ " avoid_deps = [':avoidCclib'],",
+ " platform_type = 'ios',",
+ ")",
+ "cc_library(name = 'avoidCclib', srcs = ['cclib.c'], deps = [':avoidLib'])",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])",
+ "objc_library(name = 'avoidLib', srcs = [ 'c.m' ])");
+
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm");
+ CommandAction action = linkLibAction("//package:test");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsExactly(
+ "package/libobjcLib.a", MOCK_LIBTOOL_PATH);
+ }
+
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch1ExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch1ExtensionTest.java
new file mode 100644
index 0000000000..dc386625e8
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch1ExtensionTest.java
@@ -0,0 +1,36 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleWatch1ExtensionTest extends AppleWatch1ExtensionTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testGenruleDependency() throws Exception {
+ checkGenruleDependency(RULE_TYPE_PAIR);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch2ExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch2ExtensionTest.java
new file mode 100644
index 0000000000..89ed19475d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatch2ExtensionTest.java
@@ -0,0 +1,59 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleWatch2ExtensionTest extends AppleWatch2ExtensionTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testRegistersSwiftSupportActions() throws Exception {
+ createSwiftBinaryTarget(
+ "apple_watch2_extension(",
+ " name = 'ext',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " binary = ':x',",
+ ")");
+
+ checkRegisterSwiftSupportActions(
+ getConfiguredTarget("//x:ext", getAppleCrosstoolConfiguration()), "watchsimulator");
+ }
+
+ @Test
+ public void testRegistersSwiftStdlibActions() throws Exception {
+ createSwiftBinaryTarget(
+ "apple_watch2_extension(",
+ " name = 'ext',",
+ " app_name = 'y',",
+ " app_asset_catalogs = ['foo.xcassets/foo', 'bar.xcassets/bar'],",
+ " binary = ':x',",
+ ")");
+
+ checkRegisterSwiftStdlibActions(
+ getConfiguredTarget("//x:ext", getAppleCrosstoolConfiguration()), "watchsimulator");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatchExtensionBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatchExtensionBinaryTest.java
new file mode 100644
index 0000000000..84bd7cc4ad
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyAppleWatchExtensionBinaryTest.java
@@ -0,0 +1,76 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyAppleWatchExtensionBinaryTest extends AppleWatchExtensionBinaryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testLinkActionWithTransitiveCppDependency() throws Exception {
+ checkLinkActionWithTransitiveCppDependency(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testCompilesSources() throws Exception {
+ checkCompilesSources(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesSourcesWithModuleMapsEnabled() throws Exception {
+ checkCompilesSourcesWithModuleMapsEnabled(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompileWithTextualHeaders() throws Exception {
+ checkCompileWithTextualHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts() throws Exception {
+ checkLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesWithHdrs() throws Exception {
+ checkCompilesWithHdrs(RULE_TYPE);
+ }
+
+ @Test
+ public void testForceLoadsAlwayslinkTargets() throws Exception {
+ checkForceLoadsAlwayslinkTargets(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testReceivesTransitivelyPropagatedDefines() throws Exception {
+ checkReceivesTransitivelyPropagatedDefines(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileAction() throws Exception {
+ checkSdkIncludesUsedInCompileAction(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosApplicationTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosApplicationTest.java
new file mode 100644
index 0000000000..e319b9e37f
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosApplicationTest.java
@@ -0,0 +1,36 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyIosApplicationTest extends IosApplicationTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testGenruleDependency() throws Exception {
+ checkGenruleDependency(RULE_TYPE_PAIR);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionBinaryTest.java
new file mode 100644
index 0000000000..2cdfe47413
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionBinaryTest.java
@@ -0,0 +1,76 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyIosExtensionBinaryTest extends IosExtensionBinaryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testLinkActionWithTransitiveCppDependency() throws Exception {
+ checkLinkActionWithTransitiveCppDependency(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testCompilesSources() throws Exception {
+ checkCompilesSources(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesSourcesWithModuleMapsEnabled() throws Exception {
+ checkCompilesSourcesWithModuleMapsEnabled(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompileWithTextualHeaders() throws Exception {
+ checkCompileWithTextualHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts() throws Exception {
+ checkLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesWithHdrs() throws Exception {
+ checkCompilesWithHdrs(RULE_TYPE);
+ }
+
+ @Test
+ public void testForceLoadsAlwayslinkTargets() throws Exception {
+ checkForceLoadsAlwayslinkTargets(RULE_TYPE, EXTRA_LINK_ARGS);
+ }
+
+ @Test
+ public void testReceivesTransitivelyPropagatedDefines() throws Exception {
+ checkReceivesTransitivelyPropagatedDefines(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileAction() throws Exception {
+ checkSdkIncludesUsedInCompileAction(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionTest.java
new file mode 100644
index 0000000000..fc2ca29b9a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosExtensionTest.java
@@ -0,0 +1,30 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyIosExtensionTest extends IosExtensionTest {
+ @Override
+ public ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosTestTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosTestTest.java
new file mode 100644
index 0000000000..28c103416b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyIosTestTest.java
@@ -0,0 +1,160 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyIosTestTest extends IosTestTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testCompilesWithHdrs() throws Exception {
+ checkCompilesWithHdrs(RULE_TYPE);
+ }
+
+ @Test
+ public void testGetsHeadersFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " hdrs = ['lib.h'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " hdrs = ['bin.h'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " hdrs = ['test.h'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ Iterable<Artifact> compileInputs = compileAction("//x:test", "test.o").getInputs();
+ assertThat(Artifact.toExecPaths(compileInputs))
+ .containsAllOf("x/lib.h", "x/bin.h", "x/test.h");
+ }
+
+ @Test
+ public void testGetsIncludesFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " includes = ['libinc'],",
+ " sdk_includes = ['libinc_sdk'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " includes = ['bininc'],",
+ " sdk_includes = ['bininc_sdk'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " includes = ['testinc'],",
+ " sdk_includes = ['testinc_sdk'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ List<String> compileArgs = compileAction("//x:test", "test.o").getArguments();
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", "x/libinc"));
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", "x/bininc"));
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", "x/testinc"));
+
+ String sdkIncludeDir = AppleToolchain.sdkDir() + "/usr/include/";
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", sdkIncludeDir + "libinc_sdk"));
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", sdkIncludeDir + "bininc_sdk"));
+ assertContainsSublist(compileArgs, ImmutableList.of("-I", sdkIncludeDir + "testinc_sdk"));
+ }
+
+ @Test
+ public void testGetsFrameworksFromTestRig() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_framework(",
+ " name = 'fx',",
+ " framework_imports = ['fx.framework/1'],",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " deps = [':fx'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':lib'],",
+ ")",
+ "ios_application(",
+ " name = 'testApp',",
+ " binary = ':bin',",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " xctest = 1,",
+ " xctest_app = ':testApp',",
+ ")");
+ CommandAction compileAction = compileAction("//x:test", "test.o");
+
+ assertThat(Artifact.toExecPaths(compileAction.getInputs()))
+ .contains("x/fx.framework/1");
+ assertContainsSublist(compileAction.getArguments(), ImmutableList.of("-F", "x"));
+
+ CommandAction linkAction = linkAction("//x:test");
+ assertThat(Joiner.on(" ").join(linkAction.getArguments())).doesNotContain("-framework fx");
+ }
+
+ @Test
+ public void testReceivesTransitivelyPropagatedDefines() throws Exception {
+ checkReceivesTransitivelyPropagatedDefines(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileAction() throws Exception {
+ checkSdkIncludesUsedInCompileAction(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBinaryTest.java
new file mode 100644
index 0000000000..af13d04ad1
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBinaryTest.java
@@ -0,0 +1,137 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Joiner;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcBinaryTest extends ObjcBinaryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testLinkActionWithTransitiveCppDependency() throws Exception {
+ checkLinkActionWithTransitiveCppDependency(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testCompilesSources() throws Exception {
+ checkCompilesSources(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesSourcesWithModuleMapsEnabled() throws Exception {
+ checkCompilesSourcesWithModuleMapsEnabled(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompileWithTextualHeaders() throws Exception {
+ checkCompileWithTextualHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts() throws Exception {
+ checkLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesWithHdrs() throws Exception {
+ checkCompilesWithHdrs(RULE_TYPE);
+ }
+
+ @Test
+ public void testForceLoadsAlwayslinkTargets() throws Exception {
+ checkForceLoadsAlwayslinkTargets(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testReceivesTransitivelyPropagatedDefines() throws Exception {
+ checkReceivesTransitivelyPropagatedDefines(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileAction() throws Exception {
+ checkSdkIncludesUsedInCompileAction(RULE_TYPE);
+ }
+
+ @Override
+ @Test
+ public void testCreate_debugSymbolActionWithAppleFlag() throws Exception {
+ useConfiguration("--apple_generate_dsym");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact artifact = getBinArtifact("x.app.dSYM.temp.zip", target);
+ String execPath = artifact.getExecPath().getParentDirectory().toString();
+ CommandAction linkAction = (CommandAction) getGeneratingAction(artifact);
+ assertThat(Joiner.on(" ").join(linkAction.getArguments()))
+ .contains(
+ Joiner.on(" ")
+ .join(
+ "&&",
+ MOCK_XCRUNWRAPPER_PATH,
+ ObjcRuleClasses.DSYMUTIL,
+ execPath + "/x_bin",
+ "-o",
+ execPath + "/x.app.dSYM.temp",
+ "&&",
+ "zipped_bundle=${PWD}/" + artifact.getExecPathString(),
+ "&&",
+ "cd " + artifact.getExecPathString().replace(".zip", ""),
+ "&&",
+ "/usr/bin/zip -q -r \"${zipped_bundle}\" ."));
+
+ Artifact plistArtifact = getBinArtifact("x.app.dSYM/Contents/Info.plist", target);
+ Artifact debugSymbolArtifact =
+ getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_bin", target);
+ SpawnAction plistAction = (SpawnAction) getGeneratingAction(plistArtifact);
+ SpawnAction debugSymbolAction = (SpawnAction) getGeneratingAction(debugSymbolArtifact);
+ assertThat(debugSymbolAction).isEqualTo(plistAction);
+
+ String dsymUnzipActionArg =
+ "unzip -p "
+ + execPath
+ + "/x.app.dSYM.temp.zip"
+ + " Contents/Info.plist > "
+ + plistArtifact.getExecPathString()
+ + " && unzip -p "
+ + execPath
+ + "/x.app.dSYM.temp.zip"
+ + " Contents/Resources/DWARF/x_bin > "
+ + debugSymbolArtifact.getExecPathString();
+ assertThat(plistAction.getArguments()).contains(dsymUnzipActionArg);
+ }
+
+ @Test
+ public void testGenruleDependency() throws Exception {
+ checkGenruleDependency(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleLibraryTest.java
new file mode 100644
index 0000000000..f999b21938
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleLibraryTest.java
@@ -0,0 +1,30 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcBundleLibraryTest extends ObjcBundleLibraryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleTest.java
new file mode 100644
index 0000000000..696e650341
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcBundleTest.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README. The class is empty
+ * because each test is also run in the superclass, which tests --experimental_objc_crosstool=all.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcBundleTest extends ObjcBundleTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcFrameworkTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcFrameworkTest.java
new file mode 100644
index 0000000000..c209b2cbe7
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcFrameworkTest.java
@@ -0,0 +1,31 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README. The class is empty
+ * because each test is also run in the superclass, which tests --experimental_objc_crosstool=all.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcFrameworkTest extends ObjcFrameworkTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcImportTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcImportTest.java
new file mode 100644
index 0000000000..b8cf7325af
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcImportTest.java
@@ -0,0 +1,36 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcImportTest extends ObjcImportTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileActionsOfDependers() throws Exception {
+ checkSdkIncludesUsedInCompileActionsOfDependers(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcLibraryTest.java
new file mode 100644
index 0000000000..3d931b961b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcLibraryTest.java
@@ -0,0 +1,900 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.baseArtifactNames;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.Platform;
+import com.google.devtools.build.lib.rules.cpp.HeaderDiscovery;
+import com.google.devtools.build.lib.rules.cpp.LinkerInput;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Legacy test case (that is, without the OSX crosstool) for objc_library. */
+@RunWith(JUnit4.class)
+public class LegacyObjcLibraryTest extends ObjcLibraryTest {
+ private static final RuleType RULE_TYPE = new OnlyNeedsSourcesRuleType("objc_library");
+ private static final String XCRUNWRAPPER = "xcrunwrapper";
+ private static final String LIBTOOL = "libtool";
+
+ @Override
+ protected void useConfiguration(String... args) throws Exception {
+ // Crosstool case is tested in {@link ObjcLibraryTest}
+ useConfiguration(ObjcCrosstoolMode.OFF, args);
+ }
+
+ @Test
+ public void testLibFileIsCorrectForSlashInTargetName() throws Exception {
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:dir/Target")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ Iterable<Artifact> outputArtifacts = getFilesToBuild(target);
+ assertThat(Artifact.toRootRelativePaths(outputArtifacts)).containsExactly("objc/libTarget.a");
+ }
+
+ @Test
+ public void testNonPropagatedDepsDiamond() throws Exception {
+ // Non-propagated.
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h")
+ .write();
+ // Conflicts with non-propagated.
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h")
+ .write();
+
+ createLibraryTargetWriter("//objc3:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "b.h")
+ .setList("non_propagated_deps", "//objc:lib")
+ .write();
+
+ createLibraryTargetWriter("//objc4:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setList("deps", "//objc2:lib", "//objc3:lib")
+ .write();
+
+ Action action = compileAction("//objc4:lib", "a.o");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsAllOf("objc2/a.h", "objc3/b.h", "objc4/c.h", "objc4/a.m", "objc4/private.h");
+ }
+
+ static Iterable<String> iquoteArgs(ObjcProvider provider, BuildConfiguration configuration) {
+ return Interspersing.beforeEach(
+ "-iquote",
+ PathFragment.safePathStrings(ObjcCommon.userHeaderSearchPaths(provider, configuration)));
+ }
+
+ // Override required for distinct compiler path
+ @Override
+ @Test
+ public void testCompilationActions_simulator() throws Exception {
+ useConfiguration("--cpu=ios_i386", "--ios_minimum_os=1.0");
+ Platform platform = Platform.IOS_SIMULATOR;
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setAndCreateFiles("non_arc_srcs", "not_arc.m")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ CommandAction compileActionNotArc = compileAction("//objc:lib", "not_arc.o");
+
+ List<String> commonCompileFlags =
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(ObjcRuleClasses.CLANG)
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .add("-fexceptions")
+ .add("-fasm-blocks")
+ .add("-fobjc-abi-version=2")
+ .add("-fobjc-legacy-dispatch")
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .add("-mios-simulator-version-min=1.0")
+ .add("-arch", "i386")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add("-F", AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")
+ .add("-F", frameworkDir(platform))
+ .addAll(FASTBUILD_COPTS)
+ .addAll(
+ iquoteArgs(
+ getConfiguredTarget("//objc:lib").getProvider(ObjcProvider.class),
+ getTargetConfiguration()))
+ .build();
+
+ assertThat(compileActionA.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .addAll(commonCompileFlags)
+ .add("-fobjc-arc")
+ .add("-c", "objc/a.m")
+ .addAll(outputArgs(compileActionA.getOutputs()))
+ .build());
+ assertThat(compileActionNotArc.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .addAll(commonCompileFlags)
+ .add("-fno-objc-arc")
+ .add("-c", "objc/not_arc.m")
+ .addAll(outputArgs(compileActionNotArc.getOutputs()))
+ .build());
+
+ assertRequiresDarwin(compileActionA);
+ try {
+ reporter.removeHandler(failFastHandler);
+ getTarget("//objc:c.o");
+ fail("should have thrown");
+ } catch (NoSuchTargetException expected) {}
+ assertThat(baseArtifactNames(compileActionA.getOutputs())).containsExactly("a.o", "a.d");
+ assertThat(baseArtifactNames(compileActionA.getInputs()))
+ .containsExactly("a.m", "c.h", "private.h", XCRUNWRAPPER);
+ }
+
+ // Override required for distinct compiler path
+ @Override
+ @Test
+ public void testCompilationActions_device() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_minimum_os=1.0");
+ Platform platform = Platform.IOS_DEVICE;
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setAndCreateFiles("non_arc_srcs", "not_arc.m")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ CommandAction compileActionNotArc = compileAction("//objc:lib", "not_arc.o");
+
+ List<String> commonCompileFlags =
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(ObjcRuleClasses.CLANG)
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .add("-miphoneos-version-min=1.0")
+ .add("-arch", "armv7")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add("-F", AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")
+ .add("-F", frameworkDir(platform))
+ .addAll(FASTBUILD_COPTS)
+ .addAll(
+ iquoteArgs(
+ getConfiguredTarget("//objc:lib").getProvider(ObjcProvider.class),
+ getTargetConfiguration()))
+ .build();
+
+ assertThat(compileActionA.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .addAll(commonCompileFlags)
+ .add("-fobjc-arc")
+ .add("-c", "objc/a.m")
+ .addAll(outputArgs(compileActionA.getOutputs()))
+ .build());
+ assertThat(compileActionNotArc.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .addAll(commonCompileFlags)
+ .add("-fno-objc-arc")
+ .add("-c", "objc/not_arc.m")
+ .addAll(outputArgs(compileActionNotArc.getOutputs()))
+ .build());
+
+ assertRequiresDarwin(compileActionA);
+ try {
+ reporter.removeHandler(failFastHandler);
+ getTarget("//objc:c.o");
+ fail("should have thrown");
+ } catch (NoSuchTargetException expected) {}
+ assertThat(baseArtifactNames(compileActionA.getOutputs())).containsExactly("a.o", "a.d");
+ assertThat(baseArtifactNames(compileActionA.getInputs()))
+ .containsExactly("a.m", "c.h", "private.h", XCRUNWRAPPER);
+ }
+
+ // Test with ios device SDK version 9.0. Framework path differs from previous versions.
+ @Test
+ public void testCompilationActions_deviceSdk9() throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_minimum_os=1.0", "--ios_sdk_version=9.0");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileAction = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileAction.getArguments()).containsAllOf(
+ "-F", AppleToolchain.sdkDir() + AppleToolchain.SYSTEM_FRAMEWORK_PATH).inOrder();
+ }
+
+ @Test
+ public void testCompilationActionsWithPch() throws Exception {
+ Platform platform = Platform.IOS_SIMULATOR;
+ scratch.file("objc/foo.pch");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .set("pch", "'some.pch'")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments())
+ .containsExactlyElementsIn(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(ObjcRuleClasses.CLANG)
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .add("-fexceptions")
+ .add("-fasm-blocks")
+ .add("-fobjc-abi-version=2")
+ .add("-fobjc-legacy-dispatch")
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .add("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .add("-arch", "x86_64")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add("-F", AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")
+ .add("-F", frameworkDir(platform))
+ .addAll(FASTBUILD_COPTS)
+ .addAll(
+ iquoteArgs(
+ getConfiguredTarget("//objc:lib").getProvider(ObjcProvider.class),
+ getAppleCrosstoolConfiguration()))
+ .add("-include", "objc/some.pch")
+ .add("-fobjc-arc")
+ .add("-c", "objc/a.m")
+ .addAll(outputArgs(compileActionA.getOutputs()))
+ .build())
+ .inOrder();
+
+ assertThat(compileActionA.getInputs()).contains(
+ getFileConfiguredTarget("//objc:some.pch").getArtifact());
+ }
+
+ // Override required for distinct compiler path
+ @Override
+ @Test
+ public void testCompilationActionsWithCopts() throws Exception {
+ useConfiguration("--cpu=ios_i386");
+ Platform platform = Platform.IOS_SIMULATOR;
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setList("copts", "-Ifoo", "--monkeys=$(TARGET_CPU)")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments())
+ .containsExactlyElementsIn(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(ObjcRuleClasses.CLANG)
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .add("-fexceptions")
+ .add("-fasm-blocks")
+ .add("-fobjc-abi-version=2")
+ .add("-fobjc-legacy-dispatch")
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .add("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .add("-arch", "i386")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add("-F", AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")
+ .add("-F", frameworkDir(platform))
+ .addAll(FASTBUILD_COPTS)
+ .addAll(
+ iquoteArgs(
+ getConfiguredTarget("//objc:lib").getProvider(ObjcProvider.class),
+ getTargetConfiguration()))
+ .add("-fobjc-arc")
+ .add("-Ifoo")
+ .add("--monkeys=ios_i386")
+ .add("-c", "objc/a.m")
+ .addAll(outputArgs(compileActionA.getOutputs()))
+ .build())
+ .inOrder();
+ }
+
+ // Override required since module map is not included in action inputs for the crosstool case
+ @Override
+ @Test
+ public void testCompilationActionsWithModuleMapsEnabled() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_enable_module_maps");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(moduleMapArtifactArguments("//objc", "lib"));
+ assertThat(compileActionA.getArguments()).contains("-fmodule-maps");
+ assertThat(Artifact.toRootRelativePaths(compileActionA.getInputs()))
+ .contains("objc/lib.modulemaps/module.modulemap");
+ }
+
+ @Test
+ public void testCompilationActionsWithCoptFmodules() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setList("copts", "-fmodules")
+ .write();
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ assertThat(compileActionA.getArguments()).containsAllOf("-fmodules",
+ "-fmodules-cache-path=" + getModulesCachePath());
+ }
+
+ @Test
+ public void testCompilationActionsWithCoptFmodulesCachePath() throws Exception {
+ checkWarning("objc", "lib", CompilationSupport.MODULES_CACHE_PATH_WARNING,
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " copts = ['-fmodules', '-fmodules-cache-path=foobar']",
+ ")");
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ assertThat(compileActionA.getArguments()).containsAllOf("-fmodules",
+ "-fmodules-cache-path=" + getModulesCachePath());
+ }
+
+ // Override required for distinct libtool path
+ @Override
+ @Test
+ public void testArchiveAction_simulator() throws Exception {
+ useConfiguration("--cpu=ios_i386");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction archiveAction = archiveAction("//objc:lib");
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ MOCK_LIBTOOL_PATH,
+ "-static",
+ "-filelist",
+ getBinArtifact("lib-archive.objlist", "//objc:lib").getExecPathString(),
+ "-arch_only",
+ "i386",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsExactly("a.o", "b.o", "lib-archive.objlist", LIBTOOL);
+ assertThat(baseArtifactNames(archiveAction.getOutputs())).containsExactly("liblib.a");
+ assertRequiresDarwin(archiveAction);
+ }
+
+ // Override required for distinct libtool path
+ @Override
+ @Test
+ public void testArchiveAction_device() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction archiveAction = archiveAction("//objc:lib");
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ MOCK_LIBTOOL_PATH,
+ "-static",
+ "-filelist",
+ getBinArtifact("lib-archive.objlist", "//objc:lib").getExecPathString(),
+ "-arch_only",
+ "armv7",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsExactly("a.o", "b.o", "lib-archive.objlist", LIBTOOL);
+ assertThat(baseArtifactNames(archiveAction.getOutputs())).containsExactly("liblib.a");
+ assertRequiresDarwin(archiveAction);
+ }
+
+ // Override required for distinct libtool path
+ @Override
+ @Test
+ public void testFullyLinkArchiveAction_simulator() throws Exception {
+ useConfiguration("--cpu=ios_i386");
+ createLibraryTargetWriter("//objc:lib_dep")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib_dep")
+ .write();
+ SpawnAction archiveAction = (SpawnAction) getGeneratingActionForLabel(
+ "//objc2:lib_fully_linked.a");
+ assertRequiresDarwin(archiveAction);
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ MOCK_LIBTOOL_PATH,
+ "-static",
+ "-arch_only",
+ "i386",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString(),
+ getBinArtifact("liblib.a", "//objc2:lib").getExecPathString(),
+ getBinArtifact("liblib_dep.a", "//objc:lib_dep").getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsExactly("liblib_dep.a", "liblib.a", LIBTOOL);
+ }
+
+ // Override required for distinct libtool path
+ @Override
+ @Test
+ public void testFullyLinkArchiveAction_device() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ createLibraryTargetWriter("//objc:lib_dep")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib_dep")
+ .write();
+ SpawnAction archiveAction = (SpawnAction) getGeneratingActionForLabel(
+ "//objc2:lib_fully_linked.a");
+ assertRequiresDarwin(archiveAction);
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ MOCK_LIBTOOL_PATH,
+ "-static",
+ "-arch_only",
+ "armv7",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString(),
+ getBinArtifact("liblib.a", "//objc2:lib").getExecPathString(),
+ getBinArtifact("liblib_dep.a", "//objc:lib_dep").getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsExactly("liblib_dep.a", "liblib.a", LIBTOOL);
+ }
+
+ @Test
+ public void checkStoresCcLibsAsCc() throws Exception {
+ ScratchAttributeWriter.fromLabelString(this, "cc_library", "//cc:lib")
+ .setAndCreateFiles("srcs", "a.cc")
+ .write();
+ scratch.file(
+ "third_party/cc_lib/BUILD",
+ "licenses(['unencumbered'])",
+ "cc_library(",
+ " name = 'cc_lib_impl',",
+ " srcs = [",
+ " 'v1/a.c',",
+ " 'v1/a.h',",
+ " ],",
+ ")",
+ "",
+ "cc_inc_library(",
+ " name = 'cc_lib',",
+ " hdrs = ['v1/a.h'],",
+ " prefix = 'v1',",
+ " deps = [':cc_lib_impl'],",
+ ")");
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//cc:lib", "//third_party/cc_lib:cc_lib_impl")
+ .write();
+ ObjcProvider objcProvider = providerForTarget("//objc2:lib");
+
+ Iterable<Artifact> linkerInputArtifacts =
+ Iterables.transform(objcProvider.get(CC_LIBRARY), new Function<LinkerInput, Artifact>() {
+ @Override
+ public Artifact apply(LinkerInput library) {
+ return library.getArtifact();
+ }
+ });
+
+ assertThat(linkerInputArtifacts)
+ .containsAllOf(
+ getBinArtifact(
+ "liblib.a", getConfiguredTarget("//cc:lib", getAppleCrosstoolConfiguration())),
+ getBinArtifact(
+ "libcc_lib_impl.a",
+ getConfiguredTarget(
+ "//third_party/cc_lib:cc_lib_impl", getAppleCrosstoolConfiguration())));
+ }
+
+ @Test
+ public void testCollectsSdkFrameworksTransitively() throws Exception {
+ createLibraryTargetWriter("//base_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("sdk_frameworks", "foo")
+ .write();
+ createLibraryTargetWriter("//depender_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("sdk_frameworks", "bar")
+ .setList("deps", "//base_lib:lib")
+ .write();
+
+ ObjcProvider baseProvider = providerForTarget("//base_lib:lib");
+ ObjcProvider dependerProvider = providerForTarget("//depender_lib:lib");
+
+ Set<SdkFramework> baseFrameworks = ImmutableSet.of(new SdkFramework("foo"));
+ Set<SdkFramework> dependerFrameworks =
+ ImmutableSet.of(new SdkFramework("foo"), new SdkFramework("bar"));
+ assertThat(baseProvider.get(SDK_FRAMEWORK)).containsExactlyElementsIn(baseFrameworks);
+ assertThat(dependerProvider.get(SDK_FRAMEWORK)).containsExactlyElementsIn(dependerFrameworks);
+
+ // Make sure that the archive action does not actually include the frameworks. This is needed
+ // for creating binaries but is ignored for libraries.
+ CommandAction archiveAction = archiveAction("//depender_lib:lib");
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_LIBTOOL_PATH)
+ .add("-static")
+ .add("-filelist")
+ .add(
+ getBinArtifact("lib-archive.objlist", "//depender_lib:lib").getExecPathString())
+ .add("-arch_only", "x86_64")
+ .add("-syslibroot")
+ .add(AppleToolchain.sdkDir())
+ .add("-o")
+ .addAll(Artifact.toExecPaths(archiveAction.getOutputs()))
+ .build());
+ }
+
+ @Test
+ public void testMultipleRulesCompilingOneSourceGenerateUniqueObjFiles() throws Exception {
+ scratch.file("lib/a.m");
+ scratch.file("lib/BUILD",
+ "objc_library(name = 'lib1', srcs = ['a.m'], copts = ['-Ilib1flag'])",
+ "objc_library(name = 'lib2', srcs = ['a.m'], copts = ['-Ilib2flag'])");
+ Artifact obj1 = Iterables.getOnlyElement(
+ inputsEndingWith(archiveAction("//lib:lib1"), ".o"));
+ Artifact obj2 = Iterables.getOnlyElement(
+ inputsEndingWith(archiveAction("//lib:lib2"), ".o"));
+
+ // The exec paths of each obj file should be based on the objc_library target.
+ assertThat(obj1.getExecPathString()).contains("lib1");
+ assertThat(obj1.getExecPathString()).doesNotContain("lib2");
+ assertThat(obj2.getExecPathString()).doesNotContain("lib1");
+ assertThat(obj2.getExecPathString()).contains("lib2");
+
+ SpawnAction compile1 = (SpawnAction) getGeneratingAction(obj1);
+ SpawnAction compile2 = (SpawnAction) getGeneratingAction(obj2);
+ assertThat(compile1.getArguments()).contains("-Ilib1flag");
+ assertThat(compile2.getArguments()).contains("-Ilib2flag");
+ }
+
+ @Test
+ public void testIncludesDirsOfTransitiveDepsGetPassedToCompileAction() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("includes", "third_party/foo", "opensource/bar")
+ .write();
+
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("includes", "more_includes")
+ .setList("deps", "//lib1:lib1")
+ .write();
+ CommandAction compileAction = compileAction("//lib2:lib2", "a.o");
+ assertContainsSublist(
+ compileAction.getArguments(),
+ ImmutableList.copyOf(
+ Interspersing.beforeEach(
+ "-I",
+ rootedIncludePaths(
+ getAppleCrosstoolConfiguration(),
+ "lib2/more_includes",
+ "lib1/third_party/foo",
+ "lib1/opensource/bar"))));
+ }
+
+ @Test
+ public void testIncludesDirsOfTransitiveCcDepsGetPassedToCompileAction() throws Exception {
+ scratch.file("package/BUILD",
+ "cc_library(",
+ " name = 'cc_lib',",
+ " srcs = ['a.cc'],",
+ " includes = ['foo/bar'],",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['b.m'],",
+ " deps = [':cc_lib'],",
+ ")");
+
+ CommandAction compileAction = compileAction("//package:objc_lib", "b.o");
+ assertContainsSublist(
+ compileAction.getArguments(),
+ ImmutableList.copyOf(
+ Interspersing.beforeEach(
+ "-isystem",
+ rootedIncludePaths(getAppleCrosstoolConfiguration(), "package/foo/bar"))));
+ }
+
+ @Test
+ public void testIncludesDirsOfTransitiveCcIncDepsGetPassedToCompileAction() throws Exception {
+ scratch.file(
+ "third_party/cc_lib/BUILD",
+ "licenses(['unencumbered'])",
+ "cc_library(",
+ " name = 'cc_lib_impl',",
+ " srcs = [",
+ " 'v1/a.c',",
+ " 'v1/a.h',",
+ " ],",
+ ")",
+ "",
+ "cc_inc_library(",
+ " name = 'cc_lib',",
+ " hdrs = ['v1/a.h'],",
+ " prefix = 'v1',",
+ " deps = [':cc_lib_impl'],",
+ ")");
+
+ scratch.file(
+ "package/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['b.m'],",
+ " deps = ['//third_party/cc_lib:cc_lib'],",
+ ")");
+
+ CommandAction compileAction = compileAction("//package:objc_lib", "b.o");
+ String includeDir =
+ getAppleCrosstoolConfiguration()
+ .getIncludeDirectory(RepositoryName.MAIN)
+ .getExecPathString()
+ + "/third_party/cc_lib/_/cc_lib";
+ assertContainsSublist(compileAction.getArguments(), ImmutableList.of("-I", includeDir));
+ }
+
+ @Test
+ public void testIncludesIquoteFlagForGenFilesRoot() throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ CommandAction compileAction = compileAction("//lib:lib", "a.o");
+ BuildConfiguration config = getAppleCrosstoolConfiguration();
+ assertContainsSublist(compileAction.getArguments(), ImmutableList.of(
+ "-iquote", config.getGenfilesFragment().getSafePathString()));
+ assertThat(compileAction.getArguments()).doesNotContain(
+ config.getBinFragment().getSafePathString());
+ }
+
+ @Test
+ public void testProvidesHdrsAndIncludes() throws Exception {
+ checkProvidesHdrsAndIncludes(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesWithHdrs() throws Exception {
+ checkCompilesWithHdrs(RULE_TYPE);
+ }
+
+ @Test
+ public void testReceivesTransitivelyPropagatedDefines() throws Exception {
+ checkReceivesTransitivelyPropagatedDefines(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileAction() throws Exception {
+ checkSdkIncludesUsedInCompileAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSdkIncludesUsedInCompileActionsOfDependers() throws Exception {
+ checkSdkIncludesUsedInCompileActionsOfDependers(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilesAssemblyS() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.s")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileAction = compileAction("//objc:lib", "b.o");
+
+ assertThat(compileAction.getArguments()).doesNotContain("-x");
+ assertThat(compileAction.getArguments()).doesNotContain("assembler-with-cpp");
+ assertThat(baseArtifactNames(compileAction.getOutputs())).containsExactly("b.o", "b.d");
+ assertThat(baseArtifactNames(compileAction.getInputs()))
+ .containsExactly("c.h", "b.s", XCRUNWRAPPER);
+ }
+
+ @Test
+ public void testCompilesAssemblyAsm() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.asm")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileAction = compileAction("//objc:lib", "b.o");
+
+ assertThat(compileAction.getArguments()).doesNotContain("-x");
+ assertThat(compileAction.getArguments()).doesNotContain("assembler-with-cpp");
+ assertThat(baseArtifactNames(compileAction.getOutputs())).containsExactly("b.o", "b.d");
+ assertThat(baseArtifactNames(compileAction.getInputs()))
+ .containsExactly("c.h", "b.asm", XCRUNWRAPPER);
+ }
+
+ @Test
+ public void testCompilesAssemblyWithPreprocessing() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.S")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileAction = compileAction("//objc:lib", "b.o");
+
+ // Clang automatically preprocesses .S files, so the assembler-with-cpp flag is unnecessary.
+ // Regression test for b/22636858.
+ assertThat(compileAction.getArguments()).doesNotContain("-x");
+ assertThat(compileAction.getArguments()).doesNotContain("assembler-with-cpp");
+ assertThat(baseArtifactNames(compileAction.getOutputs())).containsExactly("b.o", "b.d");
+ assertThat(baseArtifactNames(compileAction.getInputs()))
+ .containsExactly("c.h", "b.S", XCRUNWRAPPER);
+ }
+
+ // Converts output artifacts into expected command-line arguments.
+ private List<String> outputArgs(Set<Artifact> outputs) {
+ ImmutableList.Builder<String> result = new ImmutableList.Builder<>();
+ for (String output : Artifact.toExecPaths(outputs)) {
+ if (output.endsWith(".o")) {
+ result.add("-o", output);
+ } else if (output.endsWith(".d")) {
+ result.add("-MD", "-MF", output);
+ } else {
+ throw new IllegalArgumentException(
+ "output " + output + " has unknown ending (not in (.d, .o)");
+ }
+ }
+ return result.build();
+ }
+
+ // Dotd pruning must be tested seperately for the legacy case, since it involves the
+ // ObjcCompileAction.
+ @Override
+ @Test
+ public void testUsesDotdPruning() throws Exception {
+ createLibraryTargetWriter("//lib:lib").setList("srcs", "a.m").write();
+ CommandAction compileAction = compileAction("//lib:lib", "a.o");
+ assertThat(compileAction).isInstanceOf(ObjcCompileAction.class);
+ assertThat(((ObjcCompileAction) compileAction).getDotdPruningPlan())
+ .isEqualTo(HeaderDiscovery.DotdPruningMode.USE);
+ }
+
+ @Override
+ @Test
+ public void testDoesNotUseDotdPruning() throws Exception {
+ useConfiguration("--objc_use_dotd_pruning=false");
+ createLibraryTargetWriter("//lib:lib").setList("srcs", "a.m").write();
+ CommandAction compileAction = compileAction("//lib:lib", "a.o");
+ assertThat(compileAction).isInstanceOf(ObjcCompileAction.class);
+ assertThat(((ObjcCompileAction) compileAction).getDotdPruningPlan())
+ .isEqualTo(HeaderDiscovery.DotdPruningMode.DO_NOT_USE);
+ }
+
+ // Override required because CppCompileAction#getPossibleInputsForTesting is not available to
+ // test for the presence of inputs that will be pruned.
+ @Override
+ @Test
+ public void testPrecompiledHeaders() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file("objc/a.m");
+ scratch.file("objc/c.pch");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch, "objc", "x", "srcs", "['a.m']", "non_arc_srcs", "['b.m']", "pch", "'c.pch'"));
+ CommandAction compileAction = compileAction("//objc:x", "a.o");
+ assertThat(Joiner.on(" ").join(compileAction.getArguments())).contains("-include objc/c.pch");
+ }
+
+ // Override required because CppCompileAction#getPossibleInputsForTesting is not available to
+ // test for the presence of inputs that will be pruned.
+ @Override
+ @Test
+ public void testCompilesSources() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//objc/lib1")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ createLibraryTargetWriter("//objc/lib2")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//objc/lib1")
+ .write();
+
+ createLibraryTargetWriter("//objc:x")
+ .setAndCreateFiles("srcs", "a.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//objc/lib2:lib2")
+ .write();
+
+ CommandAction compileA = compileAction("//objc:x", "a.o");
+
+ assertThat(Artifact.toRootRelativePaths(compileA.getInputs()))
+ .contains("objc/a.m");
+ assertThat(Artifact.toRootRelativePaths(compileA.getOutputs()))
+ .containsExactly("objc/_objs/x/objc/a.o", "objc/_objs/x/objc/a.d");
+ }
+
+
+ @Override
+ @Test
+ public void testCompilationModeDbg() throws Exception {
+ // Feature requires crosstool
+ }
+
+ @Override
+ @Test
+ public void testCompilationModeFastbuild() throws Exception {
+ // Feature requires crosstool
+ }
+
+ @Override
+ @Test
+ public void testCompilationModeOpt() throws Exception {
+ // Feature requires crosstool
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcProtoLibraryTest.java
new file mode 100644
index 0000000000..ff99cefb5e
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyObjcProtoLibraryTest.java
@@ -0,0 +1,125 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.Platform;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README.
+ */
+@RunWith(JUnit4.class)
+public class LegacyObjcProtoLibraryTest extends ObjcProtoLibraryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Test
+ public void testCompilationAction() throws Exception {
+ useConfiguration("--cpu=ios_i386");
+ Platform platform = Platform.IOS_SIMULATOR;
+
+ ConfiguredTarget target = getConfiguredTarget("//package:opl");
+ CommandAction linkAction =
+ (CommandAction) getGeneratingAction(getBinArtifact("libopl.a", target));
+
+ CommandAction compileAction =
+ (CommandAction)
+ getGeneratingAction(
+ ActionsTestUtil.getFirstArtifactEndingWith(linkAction.getInputs(), "/FileA.pb.o"));
+
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//package:opl")), "/FileA.pb.m");
+
+ Artifact objectFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(compileAction.getOutputs(), ".o");
+ Artifact dotdFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(compileAction.getOutputs(), ".d");
+ assertThat(compileAction.getArguments())
+ .containsExactlyElementsIn(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(ObjcRuleClasses.CLANG)
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .add("-fexceptions")
+ .add("-fasm-blocks")
+ .add("-fobjc-abi-version=2")
+ .add("-fobjc-legacy-dispatch")
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .add("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .add("-arch", "i386")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add("-F", AppleToolchain.sdkDir() + AppleToolchain.DEVELOPER_FRAMEWORK_PATH)
+ .add("-F", frameworkDir(platform))
+ .addAll(FASTBUILD_COPTS)
+ .addAll(
+ LegacyObjcLibraryTest.iquoteArgs(
+ target.getProvider(ObjcProvider.class), getTargetConfiguration()))
+ .add("-I")
+ .add(sourceFile.getExecPath().getParentDirectory().getParentDirectory().toString())
+ .add("-fno-objc-arc")
+ .add("-c", sourceFile.getExecPathString())
+ .add("-o")
+ .add(objectFile.getExecPathString())
+ .add("-MD")
+ .add("-MF")
+ .add(dotdFile.getExecPathString())
+ .build())
+ .inOrder();
+ assertRequiresDarwin(compileAction);
+ assertThat(Artifact.toRootRelativePaths(compileAction.getInputs())).containsAllOf(
+ "package/_generated_protos/opl/package/FileA.pb.m",
+ "package/_generated_protos/opl/package/FileA.pb.h",
+ "package/_generated_protos/opl/package/dir/FileB.pb.h",
+ "package/_generated_protos/opl/dep/File.pb.h"
+ );
+ }
+
+ @Test
+ public void testLibraryLinkAction() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ Artifact libFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//package:opl")), "/libopl.a");
+ CommandAction action = (CommandAction) getGeneratingAction(libFile);
+ assertThat(action.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ MOCK_LIBTOOL_PATH,
+ "-static",
+ "-filelist",
+ getBinArtifact("opl-archive.objlist", "//package:opl").getExecPathString(),
+ "-arch_only",
+ "armv7",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ libFile.getExecPathString()));
+ assertRequiresDarwin(action);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java
new file mode 100644
index 0000000000..c167d312b5
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java
@@ -0,0 +1,918 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.BinaryLinkingTargetFactory.REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableListMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultiset;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Multiset;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.MergeZip;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_binary. */
+@RunWith(JUnit4.class)
+public class ObjcBinaryTest extends ObjcRuleTestCase {
+ static final RuleType RULE_TYPE = new BinaryRuleType("objc_binary");
+
+ protected ConfiguredTarget addMockBinAndLibs(List<String> srcs) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ return createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", srcs)
+ .setList("deps", "//lib1:lib1", "//lib2:lib2")
+ .write();
+ }
+
+ @Before
+ public final void initializeToolsConfigMock() throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+ }
+
+ @Test
+ public void testCreate_runfiles() throws Exception {
+ ConfiguredTarget binary = addMockBinAndLibs(ImmutableList.of("a.m"));
+ RunfilesProvider runfiles = binary.getProvider(RunfilesProvider.class);
+ assertThat(runfiles.getDefaultRunfiles().getArtifacts()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts()))
+ .containsExactly(
+ "bin/bin.ipa",
+ "bin/bin_bin");
+ }
+
+ @Test
+ public void testFilesToRun() throws Exception {
+ checkFilesToRun(RULE_TYPE);
+ }
+
+ @Test
+ public void testNoRunfilesSupportForDevice() throws Exception {
+ checkNoRunfilesSupportForDevice(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenerateRunnerScriptAction() throws Exception {
+ checkGenerateRunnerScriptAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testGenerateRunnerScriptAction_escaped() throws Exception {
+ checkGenerateRunnerScriptAction_escaped(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionDuplicateInputs() throws Exception {
+ checkLinkActionDuplicateInputs(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ /**
+ * Tests that bitcode is disabled for simulator builds even if enabled by flag.
+ */
+ public void testLinkActionsWithBitcode_simulator() throws Exception {
+ useConfiguration("--xcode_version=7.1", "--apple_bitcode=embedded",
+ "--ios_multi_cpus=x86_64");
+ createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write();
+
+ CommandAction linkAction = linkAction("//objc:bin");
+
+ String commandLine = Joiner.on(" ").join(linkAction.getArguments());
+ assertThat(commandLine).doesNotContain("-fembed-bitcode");
+ assertThat(commandLine).doesNotContain("-fembed-bitcode-marker");
+ }
+
+ @Test
+ public void testLinkActionsWithNoBitcode() throws Exception {
+ useConfiguration("--xcode_version=7.1", "--apple_bitcode=none",
+ "--ios_multi_cpus=arm64");
+ createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write();
+
+ CommandAction linkAction = linkAction("//objc:bin");
+
+ String commandLine = Joiner.on(" ").join(linkAction.getArguments());
+ assertThat(commandLine).doesNotContain("-fembed-bitcode");
+ assertThat(commandLine).doesNotContain("-fembed-bitcode-marker");
+ }
+
+ @Test
+ public void testSigningAction() throws Exception {
+ checkDeviceSigningAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testSigningWithCertName() throws Exception {
+ checkSigningWithCertName(RULE_TYPE);
+ }
+
+ @Test
+ public void testProvisioningProfile_simulatorBuild() throws Exception {
+ useConfiguration("--cpu=ios_i386");
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+
+ Artifact provisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ SpawnAction spawnAction = bundleMergeAction("//bin:bin");
+ assertThat(spawnAction.getInputs()).doesNotContain(provisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//bin:bin");
+ assertThat(mobileProvisionProfiles(control)).isEmpty();
+ }
+
+ @Test
+ public void testProvisioningProfile_deviceBuild() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+
+ Artifact provisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ SpawnAction spawnAction = bundleMergeAction("//bin:bin");
+ assertThat(spawnAction.getInputs()).contains(provisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//bin:bin");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ ImmutableMap<String, String> expectedProfiles = ImmutableMap.of(
+ provisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ @Test
+ public void testUserSpecifiedProvisioningProfile_deviceBuild() throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ scratch.file("custom/BUILD", "exports_files(['pp.mobileprovision'])");
+ scratch.file("custom/pp.mobileprovision");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//lib1:lib1", "//lib2:lib2")
+ .set("provisioning_profile", "'//custom:pp.mobileprovision'")
+ .write();
+
+ Artifact defaultProvisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ Artifact customProvisioningProfile =
+ getFileConfiguredTarget("//custom:pp.mobileprovision").getArtifact();
+ SpawnAction spawnAction = bundleMergeAction("//bin:bin");
+ assertThat(spawnAction.getInputs()).contains(customProvisioningProfile);
+ assertThat(spawnAction.getInputs()).doesNotContain(defaultProvisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//bin:bin");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ Map<String, String> expectedProfiles = ImmutableMap.of(
+ customProvisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ @Test
+ public void testCreate_mergeControlAction() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//lib1:lib1", "//lib2:lib2")
+ .set("infoplist", "'bin-Info.plist'")
+ .write();
+
+ Action mergeAction = bundleMergeAction("//bin:bin");
+ Action action = bundleMergeControlAction("//bin:bin");
+ assertThat(action.getInputs()).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly(
+ "bin/bin.ipa-control");
+ assertThat(bundleMergeControl("//bin:bin"))
+ .isEqualTo(
+ BundleMergeProtos.Control.newBuilder()
+ .addBundleFile(
+ BundleFile.newBuilder()
+ .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "bin"))
+ .setBundlePath("bin")
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build())
+ .setBundleRoot("Payload/bin.app")
+ .setBundleInfoPlistFile(
+ execPathEndingWith(mergeAction.getInputs(), "bin-MergedInfo.plist"))
+ .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "bin.unprocessed.ipa"))
+ .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString())
+ .setPlatform("IOS_SIMULATOR")
+ .setFallbackBundleIdentifier("example.bin")
+ .build());
+ }
+
+ @Test
+ public void testCreate_mergeBundleAction() throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//lib1:lib1", "//lib2:lib2")
+ .set("infoplist", "'bin-Info.plist'")
+ .write();
+
+ SpawnAction action = bundleMergeAction("//bin:bin");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ "bin/bin_lipobin",
+ "bin/bin.ipa-control",
+ "bin/bin-MergedInfo.plist");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("bin/bin.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH, execPathEndingWith(action.getInputs(), "bin.ipa-control"))
+ .inOrder();
+ }
+
+ @Test
+ public void testCheckPrimaryBundleIdInMergedPlist() throws Exception {
+ checkPrimaryBundleIdInMergedPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testCheckFallbackBundleIdInMergedPlist() throws Exception {
+ checkFallbackBundleIdInMergedPlist(RULE_TYPE);
+ }
+
+ @Test
+ public void testCreate_errorForNoSourceOrDep() throws Exception {
+ scratch.file("x/Foo.plist");
+ checkError("x", "x", REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE,
+ "objc_binary(name='x')");
+ }
+
+ @Test
+ public void testCompileWithDotMFileInHeaders() throws Exception {
+ checkCompileWithDotMFileInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testCreate_NoDebugSymbolActionWithoutAppleFlag() throws Exception {
+ checkNoDebugSymbolFileWithoutAppleFlag(RULE_TYPE);
+ }
+
+ @Test
+ public void testErrorForLaunchImageGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, LAUNCH_IMAGE_ATTR);
+ }
+
+ @Test
+ public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception {
+ checkAssetCatalogAttributeError(RULE_TYPE, APP_ICON_ATTR);
+ }
+
+ @Test
+ public void testCollectsAssetCatalogsTransitively() throws Exception {
+ scratch.file("lib/ac.xcassets/foo");
+ scratch.file("lib/ac.xcassets/bar");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+ scratch.file("bin/ac.xcassets/baz");
+ scratch.file("bin/ac.xcassets/42");
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "src.m")
+ .setList("deps", "//lib:lib")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+
+ // Test that the actoolzip Action has arguments and inputs obtained from dependencies.
+ SpawnAction actoolZipAction = actoolZipActionForIpa("//bin:bin");
+ assertThat(Artifact.toExecPaths(actoolZipAction.getInputs())).containsExactly(
+ "lib/ac.xcassets/foo", "lib/ac.xcassets/bar", "bin/ac.xcassets/baz", "bin/ac.xcassets/42",
+ MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(actoolZipAction.getArguments(),
+ ImmutableList.of("lib/ac.xcassets", "bin/ac.xcassets"));
+ }
+
+ @Test
+ public void testCcDependencyLinkoptsArePropagatedToLinkAction() throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm", "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("bin/BUILD",
+ "cc_library(",
+ " name = 'cclib1',",
+ " srcs = ['dep1.c'],",
+ " linkopts = ['-framework F1', '-framework F2', '-Wl,--other-opt'],",
+ ")",
+ "cc_library(",
+ " name = 'cclib2',",
+ " srcs = ['dep2.c'],",
+ " linkopts = ['-another-opt', '-framework F2'],",
+ " deps = ['cclib1'],",
+ ")",
+ "cc_library(",
+ " name = 'cclib3',",
+ " srcs = ['dep2.c'],",
+ " linkopts = ['-one-more-opt', '-framework UIKit'],",
+ " deps = ['cclib1'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':cclib2', ':cclib3'],",
+ ")");
+
+ // Frameworks from the CROSSTOOL "apply_implicit_frameworks" feature should be present.
+ assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments()))
+ .contains("-framework Foundation -framework UIKit");
+ // Frameworks included in linkopts by the user should get placed together with no duplicates.
+ // (They may duplicate the ones inserted by the CROSSTOOL feature, but we don't test that here.)
+ assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments()))
+ .contains("-framework F2 -framework F1");
+ // Linkopts should also be grouped together.
+ assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments()))
+ .contains("-another-opt -Wl,--other-opt -one-more-opt");
+ }
+
+ @Test
+ public void testAlwaysLinkCcDependenciesAreForceLoaded() throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm", "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("bin/BUILD",
+ "cc_library(",
+ " name = 'cclib1',",
+ " srcs = ['dep1.c'],",
+ " alwayslink = 1,",
+ ")",
+ "cc_library(",
+ " name = 'cclib2',",
+ " srcs = ['dep2.c'],",
+ " deps = [':cclib1'],",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':cclib2'],",
+ ")");
+
+ // cclib1 is force loaded.
+ assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments()))
+ .containsMatch(Pattern.compile(" -force_load [^\\s]+/libcclib1.lo\\b"));
+ }
+
+ @Test
+ public void testSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency() throws Exception {
+ checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(RULE_TYPE);
+ }
+
+ @Test
+ public void testCreate_actoolAction() throws Exception {
+ addTargetWithAssetCatalogs(RULE_TYPE);
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testPassesFamiliesToActool() throws Exception {
+ checkPassesFamiliesToActool(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE);
+ }
+
+ @Test
+ public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE);
+ }
+
+ @SuppressWarnings("deprecation") // getMergeWithoutNamePrefixZipList is deprecated
+ @Test
+ public void testCreate_mergeActionsWithAssetCatalog() throws Exception {
+ // TODO(matvore): add this test to IosTestTest.java.
+ addTargetWithAssetCatalogs(RULE_TYPE);
+
+ Artifact actoolZipOut = getBinArtifact("x.actool.zip", "//x:x");
+ assertThat(bundleMergeAction("//x:x").getInputs()).contains(actoolZipOut);
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList()).containsExactly(MergeZip.newBuilder()
+ .setEntryNamePrefix("Payload/x.app/")
+ .setSourcePath(actoolZipOut.getExecPathString())
+ .build());
+ }
+
+ private void addBinAndLibWithRawResources() throws Exception {
+ addBinAndLibWithResources("resources", "resource1.txt", "ja.lproj/resource2.txt",
+ "objc_binary");
+ }
+
+ private void addBinAndLibWithStrings() throws Exception {
+ addBinAndLibWithResources("strings", "foo.strings", "ja.lproj/bar.strings",
+ "objc_binary");
+ }
+
+ @Test
+ public void testCollectsRawResourceFilesTransitively() throws Exception {
+ addBinAndLibWithRawResources();
+ checkCollectsResourceFilesTransitively(
+ "//bin:bin",
+ ImmutableList.of("lib/resource1.txt", "bin/ja.lproj/resource2.txt"),
+ ImmutableList.of("lib/resource1.txt"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin",
+ ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "bin_static_lib_bin",
+ ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"),
+ "lib_lib",
+ ImmutableMultiset.of("lib/resource1.txt")));
+ }
+
+ @Test
+ public void testCollectsStringsFilesTransitively() throws Exception {
+ addBinAndLibWithStrings();
+ checkCollectsResourceFilesTransitively(
+ "//bin:bin",
+ ImmutableList.of("bin/lib/foo.strings.binary", "bin/bin/ja.lproj/bar.strings.binary"),
+ ImmutableList.of("lib/foo.strings.binary"),
+ ImmutableSetMultimap.<String, Multiset<String>>of(
+ "bin_bin",
+ ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "bin_static_lib_bin",
+ ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"),
+ "lib_lib",
+ ImmutableMultiset.of("lib/foo.strings")));
+ }
+
+ @Test
+ public void testResourceFilesMergedInBundle() throws Exception {
+ addBinAndLibWithRawResources();
+ checkBundleablesAreMerged("//bin:bin",
+ ImmutableListMultimap.of(
+ "resource1.txt", "resource1.txt",
+ "ja.lproj/resource2.txt", "ja.lproj/resource2.txt"));
+ }
+
+ @Test
+ public void testStringsFilesMergedInBundle() throws Exception {
+ addBinAndLibWithStrings();
+ checkBundleablesAreMerged("//bin:bin",
+ ImmutableListMultimap.of(
+ "foo.strings.binary", "foo.strings",
+ "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings"));
+ }
+
+ @Test
+ public void testLinksFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksWeakFrameworksOfSelfAndTransitiveDependencies() throws Exception {
+ checkLinksWeakFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergesXcdatamodelZips() throws Exception {
+ checkMergesXcdatamodelZips(RULE_TYPE);
+ }
+
+ @Test
+ public void testPlistRequiresDotInName() throws Exception {
+ checkError("x", "x",
+ "'//x:Infoplist' does not produce any objc_binary infoplist files (expected .plist)",
+ "objc_binary(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ " infoplist = 'Infoplist'",
+ ")");
+ }
+
+ @Test
+ public void testLinkIncludeOrder_staticLibsFirst() throws Exception {
+ checkLinkIncludeOrderStaticLibsFirst(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkIncludeOrder_frameworksAndSystemLibsFirst() throws Exception {
+ checkLinkIncludeOrderFrameworksAndSystemLibsFirst(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinksDylibsTransitively() throws Exception {
+ checkLinksDylibsTransitively(RULE_TYPE);
+ }
+
+ @Test
+ public void testPopulatesCompilationArtifacts() throws Exception {
+ checkPopulatesCompilationArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testArchivesPrecompiledObjectFiles() throws Exception {
+ checkArchivesPrecompiledObjectFiles(RULE_TYPE);
+ }
+
+ @Test
+ public void testPopulatesBundling() throws Exception {
+ checkPopulatesBundling(RULE_TYPE);
+ }
+
+ @Test
+ public void testRegistersStoryboardCompilationActions() throws Exception {
+ checkRegistersStoryboardCompileActions(RULE_TYPE, "iphone");
+ }
+
+ @Test
+ public void testSwiftStdlibActions() throws Exception {
+ checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator");
+ }
+
+ @Test
+ public void testSwiftStdlibActionsWithToolchain() throws Exception {
+ useConfiguration("--xcode_toolchain=test_toolchain");
+ checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator", "test_toolchain");
+ }
+
+ @Test
+ public void testRegistersSwiftSupportActions() throws Exception {
+ checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator");
+ }
+
+ @Test
+ public void testRegistersSwiftSupportActionsWithToolchain() throws Exception {
+ useConfiguration("--xcode_toolchain=test_toolchain");
+ checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator", "test_toolchain");
+ }
+
+ @Test
+ public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception {
+ checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ checkObjcCopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ checkObjcCopts_argumentOrdering(RULE_TYPE);
+ }
+
+ @Test
+ public void testMergesActoolPartialInfoplist() throws Exception {
+ checkMergesPartialInfoplists(RULE_TYPE);
+ }
+
+ @Test
+ public void checkDefinesFromCcLibraryDep() throws Exception {
+ checkDefinesFromCcLibraryDep(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE);
+ }
+
+ @Test
+ public void testNibZipsMergedIntoBundle() throws Exception {
+ checkNibZipsMergedIntoBundle(RULE_TYPE);
+ }
+
+ @Test
+ public void testAllowVariousNonBlacklistedTypesInHeaders() throws Exception {
+ checkAllowVariousNonBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testWarningForBlacklistedTypesInHeaders() throws Exception {
+ checkWarningForBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testCppSourceCompilesWithCppFlags() throws Exception {
+ checkCppSourceCompilesWithCppFlags(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesFallbackBundleIdToBundleMerging() throws Exception {
+ checkBundleIdPassedAsFallbackId(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesPrimaryBundleIdToBundleMerging() throws Exception {
+ checkBundleIdPassedAsPrimaryId(RULE_TYPE);
+ }
+
+ @Test
+ public void testNestedBundleIdIsNotAffectedByParent() throws Exception {
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ ")");
+
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("hdrs", "lib.h")
+ .setList("bundles", "//bndl:bndl")
+ .write();
+
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//lib:lib")
+ .set("bundle_id", "'com.main.bundle'")
+ .write();
+
+ BundleMergeProtos.Control control = bundleMergeControl("//bin:bin");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.main.bundle");
+ // The nested bndl should not get its parent's bundle_id
+ assertThat(control.getNestedBundleList().get(0).getPrimaryBundleIdentifier())
+ .isNotEqualTo("com.main.bundle");
+ }
+
+ @Test
+ public void testAutomaticPlistEntries() throws Exception {
+ checkAutomaticPlistEntries(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleMergeInputContainsPlMergeOutput() throws Exception {
+ checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultipleInfoPlists() throws Exception {
+ checkMultipleInfoPlists(RULE_TYPE);
+ }
+
+ @Test
+ public void testInfoplistAndInfoplistsTogether() throws Exception {
+ checkInfoplistAndInfoplistsTogether(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkOpts() throws Exception {
+ checkLinkopts(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingAndLinking() throws Exception {
+ checkProtoBundlingAndLinking(RULE_TYPE);
+ }
+
+ @Test
+ public void testProtoBundlingWithTargetsWithNoDeps() throws Exception {
+ checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE);
+ }
+
+ @Test
+ public void testCanUseCrosstool() throws Exception {
+ checkLinkingRuleCanUseCrosstool(RULE_TYPE);
+ }
+
+ @Test
+ public void testBinaryStrippings() throws Exception {
+ checkBinaryStripAction(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+
+ assertAppleSdkVersionEnv(action);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ useConfiguration("--ios_sdk_version=8.1");
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+
+ assertAppleSdkVersionEnv(action, "8.1");
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneSimulator");
+ }
+
+ @Test
+ public void testAppleSdkDevicePlatformEnv() throws Exception {
+ useConfiguration("--cpu=ios_arm64");
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneOS");
+ }
+
+ @Test
+ public void testMergeBundleActionsWithNestedBundle() throws Exception {
+ checkMergeBundleActionsWithNestedBundle(RULE_TYPE);
+ }
+
+ @Test
+ public void testIncludesStoryboardOutputZipsAsMergeZips() throws Exception {
+ checkIncludesStoryboardOutputZipsAsMergeZips(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForDebug() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testClangCoptsForDebugModeWithoutGlib() throws Exception {
+ checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimized() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testCcDependency() throws Exception {
+ checkCcDependency(RULE_TYPE);
+ }
+
+ @Test
+ public void testLinkActionCorrect() throws Exception {
+ checkLinkActionCorrect(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testFrameworkDepLinkFlags() throws Exception {
+ checkFrameworkDepLinkFlags(RULE_TYPE, new ExtraLinkArgs());
+ }
+
+ @Test
+ public void testLinkActionsWithEmbeddedBitcode() throws Exception {
+ useConfiguration("--xcode_version=7.1", "--apple_bitcode=embedded", "--ios_multi_cpus=arm64");
+ createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write();
+
+ CommandAction linkAction = linkAction("//objc:bin");
+ String commandLine = Joiner.on(" ").join(linkAction.getArguments());
+
+ assertThat(commandLine).contains("-fembed-bitcode");
+ assertThat(commandLine).contains("-Xlinker -bitcode_verify");
+ assertThat(commandLine).contains("-Xlinker -bitcode_hide_symbols");
+ }
+
+ @Test
+ public void testLinkActionsWithEmbeddedBitcodeMarkers() throws Exception {
+ useConfiguration(
+ "--xcode_version=7.1", "--apple_bitcode=embedded_markers", "--ios_multi_cpus=arm64");
+ createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write();
+
+ CommandAction linkAction = linkAction("//objc:bin");
+
+ assertThat(Joiner.on(" ").join(linkAction.getArguments())).contains("-fembed-bitcode-marker");
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForDebugInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInGcovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.GCOV);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimizedInLlvmCovCoverage() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT,
+ CodeCoverageMode.LLVMCOV);
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ useConfiguration("--xcode_version=5.8");
+
+ addMockBinAndLibs(ImmutableList.of("a.m"));
+ CommandAction action = linkAction("//bin:bin");
+
+ assertXcodeVersionEnv(action, "5.8");
+ }
+
+ @Test
+ public void testCreate_debugSymbolActionWithAppleFlag() throws Exception {
+ useConfiguration("--apple_generate_dsym");
+ RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact artifact = getBinArtifact("x.app.dSYM.temp.zip", target);
+ String execPath = artifact.getExecPath().getParentDirectory().toString();
+ CommandAction linkAction = (CommandAction) getGeneratingAction(artifact);
+ assertThat(linkAction.getArguments()).containsAllOf(
+ "DSYM_HINT_LINKED_BINARY=" + execPath + "/x_bin",
+ "DSYM_HINT_DSYM_PATH=" + execPath + "/x.app.dSYM.temp",
+ "DSYM_HINT_DSYM_BUNDLE_ZIP=" + artifact.getExecPathString());
+
+ Artifact plistArtifact = getBinArtifact("x.app.dSYM/Contents/Info.plist", target);
+ Artifact debugSymbolArtifact =
+ getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_bin", target);
+ SpawnAction plistAction = (SpawnAction) getGeneratingAction(plistArtifact);
+ SpawnAction debugSymbolAction = (SpawnAction) getGeneratingAction(debugSymbolArtifact);
+ assertThat(debugSymbolAction).isEqualTo(plistAction);
+
+ String dsymUnzipActionArg =
+ "unzip -p "
+ + execPath
+ + "/x.app.dSYM.temp.zip"
+ + " Contents/Info.plist > "
+ + plistArtifact.getExecPathString()
+ + " && unzip -p "
+ + execPath
+ + "/x.app.dSYM.temp.zip"
+ + " Contents/Resources/DWARF/x_bin > "
+ + debugSymbolArtifact.getExecPathString();
+ assertThat(plistAction.getArguments()).contains(dsymUnzipActionArg);
+ }
+
+ @Test
+ public void testTargetHasDebugSymbols() throws Exception {
+ checkTargetHasDebugSymbols(RULE_TYPE);
+ }
+
+ @Test
+ public void testFilesToCompileOutputGroup() throws Exception {
+ checkFilesToCompileOutputGroup(RULE_TYPE);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibraryTest.java
new file mode 100644
index 0000000000..8f7e2862db
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleLibraryTest.java
@@ -0,0 +1,197 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.NESTED_BUNDLE;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.io.IOException;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_bundle_library. */
+@RunWith(JUnit4.class)
+public class ObjcBundleLibraryTest extends ObjcRuleTestCase {
+ protected static final RuleType RULE_TYPE =
+ new RuleType("objc_bundle_library") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) {
+ return ImmutableList.of();
+ }
+ };
+
+ private void addBundleWithResource() throws IOException {
+ scratch.file("bndl/foo.data");
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " resources = ['foo.data'],",
+ ")");
+ }
+
+ @Test
+ public void testDoesNotGenerateLinkActionWhenThereAreNoSources() throws Exception {
+ addBundleWithResource();
+ assertThat(linkAction("//bndl:bndl")).isNull();
+ ObjcProvider objcProvider = providerForTarget("//bndl:bndl");
+ Bundling providedBundle =
+ Iterables.getOnlyElement(objcProvider.get(NESTED_BUNDLE));
+ assertThat(providedBundle.getCombinedArchitectureBinary()).isAbsent();
+ }
+
+ @Test
+ public void testCreate_actoolAction() throws Exception {
+ addTargetWithAssetCatalogs(RULE_TYPE);
+ checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ @Test
+ public void testProvidesBundling() throws Exception {
+ addBundleWithResource();
+ scratch.file(
+ "bin/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " bundles = ['//bndl:bndl'],",
+ ")");
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//bin:bin");
+ BundleMergeProtos.Control nestedControl =
+ Iterables.getOnlyElement(mergeControl.getNestedBundleList());
+ BundleMergeProtos.BundleFile bundleFile =
+ BundleMergeProtos.BundleFile.newBuilder()
+ .setBundlePath("foo.data")
+ .setSourceFile(getSourceArtifact("bndl/foo.data").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build();
+
+ // Should put resource in .bundle directory, not bundle root (.app dir)
+ assertThat(nestedControl.getBundleFileList()).containsExactly(bundleFile);
+ assertThat(mergeControl.getBundleFileList()).doesNotContain(bundleFile);
+ }
+
+ @Test
+ public void testDoesNotMergeInfoplistOfNestedBundle() throws Exception {
+ scratch.file("bndl1/bndl1-Info.plist");
+ scratch.file("bndl1/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl1',",
+ " infoplist = 'bndl1-Info.plist',",
+ ")");
+ scratch.file("bndl2/bndl2-Info.plist");
+ scratch.file("bndl2/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl2',",
+ " bundles = ['//bndl1:bndl1'],",
+ " infoplist = 'bndl2-Info.plist',",
+ ")");
+ scratch.file("bin/bin-Info.plist");
+ scratch.file("bin/bin.m");
+ scratch.file("bin/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " bundles = ['//bndl2:bndl2'],",
+ " infoplist = 'bin-Info.plist'",
+ ")");
+ Artifact bundle1Infoplist = getSourceArtifact("bndl1/bndl1-Info.plist");
+ Artifact bundle2Infoplist = getSourceArtifact("bndl2/bndl2-Info.plist");
+ Artifact binaryInfoplist = getSourceArtifact("bin/bin-Info.plist");
+ Artifact binaryMergedInfoplist = getMergedInfoPlist(getConfiguredTarget("//bin:bin"));
+
+ PlMergeProtos.Control binaryPlMergeControl = plMergeControl("//bin:bin");
+
+ assertThat(binaryPlMergeControl.getSourceFileList())
+ .contains(binaryInfoplist.getExecPathString());
+ assertThat(binaryPlMergeControl.getSourceFileList())
+ .containsNoneOf(bundle1Infoplist.getExecPathString(), bundle2Infoplist.getExecPathString());
+
+ assertThat(bundleMergeAction("//bin:bin").getInputs())
+ .containsAllOf(bundle1Infoplist, bundle2Infoplist, binaryMergedInfoplist);
+
+ BundleMergeProtos.Control binControl = bundleMergeControl("//bin:bin");
+ assertThat(binControl.getBundleInfoPlistFile())
+ .isEqualTo(binaryMergedInfoplist.getExecPathString());
+
+ BundleMergeProtos.Control bundle2Control =
+ Iterables.getOnlyElement(binControl.getNestedBundleList());
+ assertThat(bundle2Control.getBundleInfoPlistFile())
+ .isEqualTo(bundle2Infoplist.getExecPathString());
+
+ BundleMergeProtos.Control bundle1Control =
+ Iterables.getOnlyElement(bundle2Control.getNestedBundleList());
+ assertThat(bundle1Control.getBundleInfoPlistFile())
+ .isEqualTo(bundle1Infoplist.getExecPathString());
+ }
+
+ @Test
+ public void testRegistersStoryboardCompilationActions() throws Exception {
+ checkRegistersStoryboardCompileActions(RULE_TYPE, "iphone");
+ }
+
+ @Test
+ public void testCompileXibActions() throws Exception {
+ checkCompileXibActions(RULE_TYPE);
+ }
+
+ @Test
+ public void testTwoStringsOneBundlePath() throws Exception {
+ checkTwoStringsOneBundlePath(RULE_TYPE);
+ }
+
+ @Test
+ public void testTwoResourcesOneBundlePath() throws Exception {
+ checkTwoResourcesOneBundlePath(RULE_TYPE);
+ }
+
+ @Test
+ public void testSameStringTwice() throws Exception {
+ checkSameStringsTwice(RULE_TYPE);
+ }
+
+ @Test
+ public void testPassesFamiliesToIbtool() throws Exception {
+ checkPassesFamiliesToIbtool(RULE_TYPE);
+ }
+
+ @Test
+ public void testMultipleInfoPlists() throws Exception {
+ checkMultipleInfoPlists(RULE_TYPE);
+ }
+
+ @Test
+ public void testInfoplistAndInfoplistsTogether() throws Exception {
+ checkInfoplistAndInfoplistsTogether(RULE_TYPE);
+ }
+
+ @Test
+ // Regression test for b/34770913.
+ public void testDeviceAndSimulatorBuilds() throws Exception {
+ addBundleWithResource();
+ useConfiguration("--ios_multi_cpus=i386,x86_64,arm64,armv7");
+
+ // Verifies this rule does not raise a rule error based on bundling platform flags.
+ providerForTarget("//bndl:bndl");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleTest.java
new file mode 100644
index 0000000000..cf23de0082
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBundleTest.java
@@ -0,0 +1,77 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcCommon.BUNDLE_CONTAINER_TYPE;
+import static com.google.devtools.build.lib.rules.objc.ObjcCommon.NOT_IN_CONTAINER_ERROR_FORMAT;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_bundle. */
+@RunWith(JUnit4.class)
+public class ObjcBundleTest extends ObjcRuleTestCase {
+ @Test
+ public void testErrorForImportArtifactNotInDotBundleDir() throws Exception {
+ scratch.file("x/foo/notinbundledir");
+ scratch.file("x/bar/x.bundle/isinbundledir");
+ checkError("x", "x",
+ String.format(NOT_IN_CONTAINER_ERROR_FORMAT,
+ "x/foo/notinbundledir",
+ ImmutableList.of(BUNDLE_CONTAINER_TYPE)),
+ "objc_bundle(",
+ " name = 'x',",
+ " bundle_imports = ['bar/x.bundle/isinbundledir', 'foo/notinbundledir'],",
+ ")");
+ }
+
+ @Test
+ public void testBundleFilesProvided() throws Exception {
+ scratch.file("bundle/bar/x.bundle/1");
+ scratch.file("bundle/bar/x.bundle/subdir/2");
+ scratch.file("bundle/bar/y.bundle/subdir/1");
+ scratch.file("bundle/bar/y.bundle/2");
+ scratch.file("bundle/BUILD",
+ "objc_bundle(",
+ " name = 'bundle',",
+ " bundle_imports = glob(['bar/**']),",
+ ")");
+ ObjcProvider provider = providerForTarget("//bundle:bundle");
+ assertThat(provider.get(BUNDLE_FILE)).containsExactly(
+ new BundleableFile(getSourceArtifact("bundle/bar/x.bundle/1"), "x.bundle/1"),
+ new BundleableFile(getSourceArtifact("bundle/bar/x.bundle/subdir/2"), "x.bundle/subdir/2"),
+ new BundleableFile(getSourceArtifact("bundle/bar/y.bundle/subdir/1"), "y.bundle/subdir/1"),
+ new BundleableFile(getSourceArtifact("bundle/bar/y.bundle/2"), "y.bundle/2"));
+ }
+
+ @Test
+ public void testBundleImportsUsesOuterMostDotBundleDirAsRoot() throws Exception {
+ scratch.file("bundle/bar/x.bundle/foo/y.bundle/baz");
+ scratch.file("bundle/BUILD",
+ "objc_bundle(",
+ " name = 'bundle',",
+ " bundle_imports = glob(['bar/**']),",
+ ")");
+ ObjcProvider provider = providerForTarget("//bundle:bundle");
+ assertThat(provider.get(BUNDLE_FILE))
+ .containsExactly(new BundleableFile(
+ getSourceArtifact("bundle/bar/x.bundle/foo/y.bundle/baz"), "x.bundle/foo/y.bundle/baz"))
+ .inOrder();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkTest.java
new file mode 100644
index 0000000000..e4a9dded52
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcFrameworkTest.java
@@ -0,0 +1,319 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.ObjcCommon.FRAMEWORK_CONTAINER_TYPE;
+import static com.google.devtools.build.lib.rules.objc.ObjcCommon.NOT_IN_CONTAINER_ERROR_FORMAT;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_FRAMEWORK;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STATIC_FRAMEWORK_DIR;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_framework. */
+@RunWith(JUnit4.class)
+public class ObjcFrameworkTest extends ObjcRuleTestCase {
+ @Test
+ public void testErrorForImportArtifactNotInDotFrameworkDir() throws Exception {
+ scratch.file("x/foo/notinframeworkdir");
+ scratch.file("x/bar/x.framework/isinframeworkdir");
+ checkError("x", "x",
+ String.format(NOT_IN_CONTAINER_ERROR_FORMAT,
+ "x/foo/notinframeworkdir",
+ ImmutableList.of(FRAMEWORK_CONTAINER_TYPE)),
+ "objc_framework(",
+ " name = 'x',",
+ " framework_imports = ['bar/x.framework/isinframeworkdir', 'foo/notinframeworkdir'],",
+ ")");
+ }
+
+ @Test
+ public void testProvidesFilesAndDirs_static() throws Exception {
+ addBinWithTransitiveDepOnFrameworkImport();
+ ObjcProvider provider = providerForTarget("//fx:fx");
+ assertThat(provider.get(STATIC_FRAMEWORK_DIR))
+ .containsExactly(
+ PathFragment.create("fx/fx1.framework"),
+ PathFragment.create("fx/fx2.framework"));
+ assertThat(provider.get(ObjcProvider.STATIC_FRAMEWORK_FILE))
+ .containsExactly(
+ getSourceArtifact("fx/fx1.framework/a"),
+ getSourceArtifact("fx/fx1.framework/b"),
+ getSourceArtifact("fx/fx2.framework/c"),
+ getSourceArtifact("fx/fx2.framework/d"));
+ assertThat(provider.get(ObjcProvider.DYNAMIC_FRAMEWORK_DIR)).isEmpty();
+ assertThat(provider.get(ObjcProvider.DYNAMIC_FRAMEWORK_FILE)).isEmpty();
+ }
+
+ @Test
+ public void testProvidesFilesAndDirs_dynamic() throws Exception {
+ scratch.file("fx/fx1.framework/a");
+ scratch.file("fx/fx1.framework/b");
+ scratch.file("fx/fx2.framework/c");
+ scratch.file("fx/fx2.framework/d");
+ scratch.file("fx/BUILD",
+ "objc_framework(",
+ " name = 'fx',",
+ " framework_imports = glob(['fx1.framework/*', 'fx2.framework/*']),",
+ " is_dynamic = 1,",
+ ")");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("deps", "//fx:fx")
+ .write();
+
+ ObjcProvider provider = providerForTarget("//fx:fx");
+ assertThat(provider.get(ObjcProvider.DYNAMIC_FRAMEWORK_DIR))
+ .containsExactly(
+ PathFragment.create("fx/fx1.framework"),
+ PathFragment.create("fx/fx2.framework"));
+ assertThat(provider.get(ObjcProvider.DYNAMIC_FRAMEWORK_FILE))
+ .containsExactly(
+ getSourceArtifact("fx/fx1.framework/a"),
+ getSourceArtifact("fx/fx1.framework/b"),
+ getSourceArtifact("fx/fx2.framework/c"),
+ getSourceArtifact("fx/fx2.framework/d"));
+ assertThat(provider.get(ObjcProvider.STATIC_FRAMEWORK_DIR)).isEmpty();
+ assertThat(provider.get(ObjcProvider.STATIC_FRAMEWORK_FILE)).isEmpty();
+ }
+
+ @Test
+ public void testSdkFrameworks_objcProvider() throws Exception {
+ ConfiguredTarget configuredTarget = addLibWithDepOnFrameworkImport();
+ ObjcProvider provider = providerForTarget(configuredTarget.getLabel().toString());
+
+ Set<SdkFramework> sdkFrameworks = ImmutableSet.of(new SdkFramework("CoreLocation"));
+
+ assertThat(provider.get(SDK_FRAMEWORK)).containsExactlyElementsIn(sdkFrameworks);
+ }
+
+ @Test
+ public void testWeakSdkFrameworks_objcProvider() throws Exception {
+ ConfiguredTarget configuredTarget = addLibWithDepOnFrameworkImport();
+ ObjcProvider provider = providerForTarget(configuredTarget.getLabel().toString());
+
+ assertThat(provider.get(WEAK_SDK_FRAMEWORK))
+ .containsExactly(new SdkFramework("MediaAccessibility"));
+ }
+
+ @Test
+ public void testDylibs_objcProvider() throws Exception {
+ ConfiguredTarget configuredTarget = addLibWithDepOnFrameworkImport();
+ ObjcProvider provider = providerForTarget(configuredTarget.getLabel().toString());
+
+ assertThat(provider.get(SDK_DYLIB)).containsExactly("libdy1");
+ }
+
+ @Test
+ public void testRequiresNonEmptyFrameworkImports()
+ throws Exception {
+ scratch.file("x/dir/x.framework/isinframeworkdir");
+ checkError("x", "empty_with_configuration",
+ getErrorMsgNonEmptyList(
+ "framework_imports", "objc_framework", "//x:empty_with_configuration"),
+ "objc_framework(",
+ " name = 'empty_with_configuration',",
+ " framework_imports = [],",
+ ")");
+ }
+
+ // This also serves as a regression test for non-empty attributes with configurable values. Please
+ // don't delete this.
+ @Test
+ public void testRequiresNonEmptyFrameworkImports_Configurable_EmptyWithConfiguration()
+ throws Exception {
+ scratch.file("x/dir/x.framework/isinframeworkdir");
+ useConfiguration("--test_arg=a");
+ checkError("x", "empty_with_configuration",
+ getErrorMsgNonEmptyList(
+ "framework_imports", "objc_framework", "//x:empty_with_configuration"),
+ "config_setting(",
+ " name = 'a',",
+ " values = {'test_arg': 'a'},",
+ ")",
+ "objc_framework(",
+ " name = 'empty_with_configuration',",
+ " framework_imports = select({",
+ " ':a': [],",
+ " '//conditions:default': ['dir/x.framework/isinframeworkdir']",
+ " })",
+ ")");
+ }
+
+ // This also serves as a regression test for non-empty attributes with configurable values. Please
+ // don't delete this.
+ @Test
+ public void testRequiresNonEmptyFrameworkImports_Configurable_NonEmptyWithConfiguration()
+ throws Exception {
+ scratch.file("x/dir/x.framework/isinframeworkdir");
+ useConfiguration("--test_arg=a");
+ scratchConfiguredTarget("x", "empty_with_configuration",
+ "config_setting(",
+ " name = 'a',",
+ " values = {'test_arg': 'a'},",
+ ")",
+ "objc_framework(",
+ " name = 'empty_with_configuration',",
+ " framework_imports = select({",
+ " ':a': ['dir/x.framework/isinframeworkdir'],",
+ " '//conditions:default': []",
+ " })",
+ ")");
+ }
+
+ // This also serves as a regression test for non-empty attributes with configurable values. Please
+ // don't delete this.
+ @Test
+ public void testRequiresNonEmptyFrameworkImports_Configurable_NonEmptyWithDefault()
+ throws Exception {
+ scratch.file("x/dir/x.framework/isinframeworkdir");
+ scratchConfiguredTarget("x", "empty_with_configuration",
+ "config_setting(",
+ " name = 'a',",
+ " values = {'test_arg': 'a'},",
+ ")",
+ "objc_framework(",
+ " name = 'empty_with_configuration',",
+ " framework_imports = select({",
+ " ':a': [],",
+ " '//conditions:default': ['dir/x.framework/isinframeworkdir']",
+ " })",
+ ")");
+ }
+
+ // This also serves as a regression test for non-empty attributes with configurable values. Please
+ // don't delete this.
+ @Test
+ public void testRequiresNonEmptyFrameworkImports_Configurable_EmptyWithDefault()
+ throws Exception {
+ scratch.file("x/dir/x.framework/isinframeworkdir");
+ checkError("x", "empty_with_configuration",
+ getErrorMsgNonEmptyList(
+ "framework_imports", "objc_framework", "//x:empty_with_configuration"),
+ "config_setting(",
+ " name = 'a',",
+ " values = {'test_arg': 'a'},",
+ ")",
+ "objc_framework(",
+ " name = 'empty_with_configuration',",
+ " framework_imports = select({",
+ " ':a': ['dir/x.framework/isinframeworkdir'],",
+ " '//conditions:default': []",
+ " })",
+ ")");
+ }
+
+ @Test
+ public void testDynamicFrameworkInFinalBundle() throws Exception {
+ scratch.file("x/Foo.framework/Foo");
+ scratch.file("x/Foo.framework/Info.plist");
+ scratch.file("x/Foo.framework/Headers/Foo.h");
+ scratch.file("x/Foo.framework/Resources/bar.png");
+ scratch.file(
+ "x/BUILD",
+ "objc_framework(",
+ " name = 'foo_framework',",
+ " framework_imports = glob(['Foo.framework/**']),",
+ " is_dynamic = 1,",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = [ 'a.m' ],",
+ " deps = [ ':foo_framework' ],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+
+ assertThat(mergeControl.getBundleFileList())
+ .containsAllOf(
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Foo")
+ .setSourceFile(getSourceArtifact("x/Foo.framework/Foo").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build(),
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Info.plist")
+ .setSourceFile(getSourceArtifact("x/Foo.framework/Info.plist").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE)
+ .build(),
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Resources/bar.png")
+ .setSourceFile(
+ getSourceArtifact("x/Foo.framework/Resources/bar.png").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+
+ assertThat(mergeControl.getBundleFileList())
+ .doesNotContain(
+ BundleFile.newBuilder()
+ .setBundlePath("Frameworks/Foo.framework/Headers/Foo.h")
+ .setSourceFile(
+ getSourceArtifact("x/Foo.framework/Headers/Foo.h").getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+ }
+
+ @Test
+ public void testDynamicFrameworkSigned() throws Exception {
+ useConfiguration("--ios_cpu=arm64");
+
+ scratch.file("x/Foo.framework/Foo");
+ scratch.file("x/Foo.framework/Info.plist");
+ scratch.file("x/Foo.framework/Headers/Foo.h");
+ scratch.file("x/Foo.framework/Resources/bar.png");
+ scratch.file(
+ "x/BUILD",
+ "objc_framework(",
+ " name = 'foo_framework',",
+ " framework_imports = glob(['Foo.framework/**']),",
+ " is_dynamic = 1,",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = [ 'a.m' ],",
+ " deps = [ ':foo_framework' ],",
+ ")",
+ "",
+ "ios_application(",
+ " name = 'x',",
+ " binary = ':bin',",
+ ")");
+
+ SpawnAction signingAction = (SpawnAction) ipaGeneratingAction();
+
+ assertThat(normalizeBashArgs(signingAction.getArguments()))
+ .containsAllOf("--sign", "${t}/Payload/x.app/Frameworks/*", "--sign", "${t}/Payload/x.app")
+ .inOrder();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcImportTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcImportTest.java
new file mode 100644
index 0000000000..3fea5129b8
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcImportTest.java
@@ -0,0 +1,131 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_import. */
+@RunWith(JUnit4.class)
+public class ObjcImportTest extends ObjcRuleTestCase {
+ protected static final RuleType RULE_TYPE =
+ new RuleType("objc_import") {
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ List<String> attributes = new ArrayList<>();
+ if (!alreadyAdded.contains("archives")) {
+ scratch.file(packageDir + "/precomp_library.a");
+ attributes.add("archives = ['precomp_library.a']");
+ }
+ return attributes;
+ }
+ };
+
+ private void addTrivialImportLibrary() throws IOException {
+ scratch.file("imp/precomp_lib.a");
+ scratch.file("imp/BUILD",
+ "objc_import(",
+ " name = 'imp',",
+ " archives = ['precomp_lib.a'],",
+ ")");
+ }
+
+ @Test
+ public void testImportLibrariesProvidedTransitively() throws Exception {
+ scratch.file("imp/this_library.a");
+ addTrivialImportLibrary();
+ scratch.file("lib/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " deps = ['//imp:imp'],",
+ ")");
+ ObjcProvider provider = providerForTarget("//lib:lib");
+ assertThat(Artifact.toExecPaths(provider.get(ObjcProvider.IMPORTED_LIBRARY)))
+ .containsExactly("imp/precomp_lib.a").inOrder();
+ }
+
+ @Test
+ public void testImportLibrariesLinkedToFinalBinary() throws Exception {
+ addTrivialImportLibrary();
+ createBinaryTargetWriter("//bin:bin").setList("deps", "//imp:imp").write();
+ CommandAction linkBinAction = linkAction("//bin:bin");
+ verifyObjlist(linkBinAction, "bin-linker.objlist", "imp/precomp_lib.a");
+ assertThat(Artifact.toExecPaths(linkBinAction.getInputs()))
+ .contains("imp/precomp_lib.a");
+ }
+
+ @Test
+ public void testNoDepsAllowed() throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ checkError("imp", "imp",
+ "//imp:imp: no such attribute 'deps' in 'objc_import' rule",
+ "objc_import(",
+ " name = 'imp',",
+ " archives = ['library.a'],",
+ " deps = ['//lib:lib'],",
+ ")");
+ }
+
+ @Test
+ public void testArchiveRequiresDotInName() throws Exception {
+ checkError("x", "x", "'//x:fooa' does not produce any objc_import archives files (expected .a)",
+ "objc_import(",
+ " name = 'x',",
+ " archives = ['fooa'],",
+ ")");
+ }
+
+ @Test
+ public void testDylibsProvided() throws Exception {
+ scratch.file("imp/imp.a");
+ scratch.file("imp/BUILD",
+ "objc_import(",
+ " name = 'imp',",
+ " archives = ['imp.a'],",
+ " sdk_dylibs = ['libdy1', 'libdy2'],",
+ ")");
+ ObjcProvider provider = providerForTarget("//imp:imp");
+ assertThat(provider.get(ObjcProvider.SDK_DYLIB)).containsExactly("libdy1", "libdy2").inOrder();
+ }
+
+ @Test
+ public void testProvidesHdrsAndIncludes() throws Exception {
+ checkProvidesHdrsAndIncludes(RULE_TYPE);
+ }
+
+ @Test
+ public void testProvidesStoryboardObjects() throws Exception {
+ checkProvidesStoryboardObjects(RULE_TYPE);
+ }
+
+ @Test
+ public void testNestedBundleInformationPropagatedToDependers() throws Exception {
+ checkNestedBundleInformationPropagatedToDependers(RULE_TYPE);
+ }
+
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcLibraryTest.java
new file mode 100644
index 0000000000..40a2c83edc
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcLibraryTest.java
@@ -0,0 +1,1542 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.baseArtifactNames;
+import static com.google.devtools.build.lib.rules.objc.CompilationSupport.ABSOLUTE_INCLUDES_PATH_FORMAT;
+import static com.google.devtools.build.lib.rules.objc.CompilationSupport.FILE_IN_SRCS_AND_HDRS_WARNING_FORMAT;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.ASSET_CATALOG;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.BUNDLE_FILE;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.CC_LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.LIBRARY;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.SDK_DYLIB;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.WEAK_SDK_FRAMEWORK;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.XCASSETS_DIR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.NON_ARC_SRCS_TYPE;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SRCS_TYPE;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.ActionExecutionException;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.RunfilesProvider;
+import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.packages.NoSuchTargetException;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.Platform;
+import com.google.devtools.build.lib.rules.cpp.CppCompileAction;
+import com.google.devtools.build.lib.rules.cpp.CppModuleMapAction;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.common.options.OptionsParsingException;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_library. */
+@RunWith(JUnit4.class)
+public class ObjcLibraryTest extends ObjcRuleTestCase {
+
+ static final RuleType RULE_TYPE = new OnlyNeedsSourcesRuleType("objc_library");
+ private static final String WRAPPED_CLANG = "wrapped_clang";
+
+ /**
+ * Middleman artifact arising from //tools/osx/crosstool:link, containing tools that should be
+ * inputs to link actions.
+ */
+ private static final String CROSSTOOL_LINK_MIDDLEMAN = "tools_Sosx_Scrosstool_Clink";
+
+ /** Creates an {@code objc_library} target writer. */
+ @Override
+ protected ScratchAttributeWriter createLibraryTargetWriter(String labelString) {
+ return ScratchAttributeWriter.fromLabelString(this, "objc_library", labelString);
+ }
+
+ @Test
+ public void testFilesToBuild() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:One")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+
+ Iterable<Artifact> files = getFilesToBuild(target);
+ assertThat(Artifact.toRootRelativePaths(files)).containsExactly("objc/libOne.a");
+ }
+
+ @Test
+ public void testCompilesSources() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//objc/lib1")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ createLibraryTargetWriter("//objc/lib2")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//objc/lib1")
+ .write();
+
+ createLibraryTargetWriter("//objc:x")
+ .setAndCreateFiles("srcs", "a.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//objc/lib2:lib2")
+ .write();
+
+ CppCompileAction compileA = (CppCompileAction) compileAction("//objc:x", "a.o");
+
+ assertThat(Artifact.toRootRelativePaths(compileA.getPossibleInputsForTesting()))
+ .containsAllOf("objc/a.m", "objc/hdr.h", "objc/private.h");
+ assertThat(Artifact.toRootRelativePaths(compileA.getOutputs()))
+ .containsExactly("objc/_objs/x/objc/a.o", "objc/_objs/x/objc/a.d");
+ }
+
+ @Test
+ public void testObjcPlusPlusCompile() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386",
+ "--ios_minimum_os=9.10.11");
+ createLibraryTargetWriter("//objc:lib")
+ .setList("srcs", "a.mm")
+ .write();
+ CommandAction compileAction = compileAction("//objc:lib", "a.o");
+ assertThat(compileAction.getArguments())
+ .containsAllOf("-stdlib=libc++", "-std=gnu++11", "-mios-simulator-version-min=9.10.11");
+ }
+
+ @Test
+ public void testObjcPlusPlusCompileDarwin() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=darwin_x86_64",
+ "--macos_minimum_os=9.10.11",
+ // TODO(b/36126423): Darwin should imply macos, so the
+ // following line should not be necessary.
+ "--apple_platform_type=macos",
+ "--experimental_objc_crosstool=all");
+ createLibraryTargetWriter("//objc:lib")
+ .setList("srcs", "a.mm")
+ .write();
+ CommandAction compileAction = compileAction("//objc:lib", "a.o");
+ assertThat(compileAction.getArguments())
+ .containsAllOf("-stdlib=libc++", "-std=gnu++11", "-mmacosx-version-min=9.10.11");
+ }
+
+ @Test
+ public void testCompilationModeDbg() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386",
+ "--compilation_mode=dbg");
+ scratch.file("objc/a.m");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch,
+ "objc",
+ "lib",
+ "srcs",
+ "['a.m']"));
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).contains("--DBG_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).doesNotContain("--FASTBUILD_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).doesNotContain("--OPT_ONLY_FLAG");
+ }
+
+ @Test
+ public void testCompilationModeFastbuild() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386",
+ "--compilation_mode=fastbuild");
+ scratch.file("objc/a.m");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch,
+ "objc",
+ "lib",
+ "srcs",
+ "['a.m']"));
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).doesNotContain("--DBG_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).contains("--FASTBUILD_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).doesNotContain("--OPT_ONLY_FLAG");
+ }
+
+ @Test
+ public void testCompilationModeOpt() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386",
+ "--compilation_mode=opt");
+ scratch.file("objc/a.m");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch,
+ "objc",
+ "lib",
+ "srcs",
+ "['a.m']"));
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).doesNotContain("--DBG_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).doesNotContain("--FASTBUILD_ONLY_FLAG");
+ assertThat(compileActionA.getArguments()).contains("--OPT_ONLY_FLAG");
+ }
+
+ @Test
+ public void testCreate_runfilesWithSourcesOnly() throws Exception {
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:One")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ RunfilesProvider provider = target.getProvider(RunfilesProvider.class);
+ assertThat(baseArtifactNames(provider.getDefaultRunfiles().getArtifacts())).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(provider.getDataRunfiles().getArtifacts()))
+ .containsExactly("objc/libOne.a");
+ }
+
+ @Test
+ public void testCreate_noErrorForEmptySourcesButHasDependency() throws Exception {
+ createLibraryTargetWriter("//baselib:baselib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("hdrs", "a.h")
+ .setList("deps", "//baselib:baselib")
+ .write();
+ ObjcProvider provider = providerForTarget("//lib:lib");
+ assertThat(provider.get(LIBRARY))
+ .containsExactlyElementsIn(archiveAction("//baselib:baselib").getOutputs());
+ }
+
+ @Test
+ public void testCreate_errorForEmptyFilegroupSources() throws Exception {
+ checkError(
+ "x",
+ "x",
+ "does not produce any objc_library srcs files (expected " + SRCS_TYPE + ")",
+ "filegroup(name = 'fg', srcs = [])",
+ "objc_library(name = 'x', srcs = ['fg'])");
+ }
+
+ @Test
+ public void testCreate_srcsContainingHeaders() throws Exception {
+ scratch.file("x/a.m", "dummy source file");
+ scratch.file("x/a.h", "dummy header file");
+ scratch.file("x/BUILD", "objc_library(name = 'Target', srcs = ['a.m', 'a.h'])");
+ assertThat(view.hasErrors(getConfiguredTarget("//x:Target"))).isFalse();
+ }
+
+ @Test
+ public void testCreate_warningForOverlappingSrcsAndHdrs() throws Exception {
+ scratch.file("/x/a.h", "dummy header file");
+ checkWarning(
+ "x",
+ "x",
+ String.format(FILE_IN_SRCS_AND_HDRS_WARNING_FORMAT, "x/a.h"),
+ "objc_library(name = 'x', srcs = ['a.h'], hdrs = ['a.h'])");
+ }
+
+ @Test
+ public void testCreate_headerAndCompiledSourceWithSameName() throws Exception {
+ scratch.file("objc/BUILD", "objc_library(name = 'Target', srcs = ['a.m'], hdrs = ['a.h'])");
+ assertThat(view.hasErrors(getConfiguredTarget("//objc:Target"))).isFalse();
+ }
+
+ @Test
+ public void testCreate_errorForCcInNonArcSources() throws Exception {
+ scratch.file("x/cc.cc");
+ checkError(
+ "x",
+ "x",
+ "'//x:cc.cc' does not produce any objc_library non_arc_srcs files (expected "
+ + NON_ARC_SRCS_TYPE
+ + ")",
+ "objc_library(name = 'x', non_arc_srcs = ['cc.cc'])");
+ }
+
+ @Test
+ public void testFileInSrcsAndNonArcSources() throws Exception {
+ checkError(
+ "x",
+ "x",
+ String.format(CompilationSupport.FILE_IN_SRCS_AND_NON_ARC_SRCS_ERROR_FORMAT, "x/foo.m"),
+ "objc_library(name = 'x', srcs = ['foo.m'], non_arc_srcs = ['foo.m'])");
+ }
+
+ @Test
+ public void testCreate_headerContainingDotMAndDotCFiles() throws Exception {
+ scratch.file("x/a.m", "dummy source file");
+ scratch.file("x/a.h", "dummy header file");
+ scratch.file("x/b.m", "dummy source file");
+ scratch.file("x/a.c", "dummy source file");
+ scratch.file(
+ "x/BUILD", "objc_library(name = 'Target', srcs = ['a.m'], hdrs = ['a.h', 'b.m', 'a.c'])");
+ assertThat(view.hasErrors(getConfiguredTarget("//x:Target"))).isFalse();
+ }
+
+ @Test
+ public void testProvidesObjcHeadersWithDotMFiles() throws Exception {
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h", "f.m")
+ .write();
+ ConfiguredTarget depender =
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "d.h", "e.m")
+ .setList("deps", "//objc:lib")
+ .write();
+ assertThat(Artifact.toRootRelativePaths(target.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc/a.h", "objc/b.h", "objc/f.m");
+ assertThat(Artifact.toRootRelativePaths(depender.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc/a.h", "objc/b.h", "objc/f.m", "objc2/d.h", "objc2/e.m");
+ }
+
+ @Test
+ public void testNonPropagatedDepsProvider() throws Exception {
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("non_propagated_deps", "//objc:lib")
+ .write();
+ ConfiguredTarget transitiveDepender =
+ createLibraryTargetWriter("//objc3:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "e.h", "f.h")
+ .setList("non_propagated_deps", "//objc2:lib")
+ .write();
+
+ assertThat(Artifact.toRootRelativePaths(target.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc/a.h", "objc/b.h");
+ assertThat(
+ Artifact.toRootRelativePaths(
+ transitiveDepender.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc2/c.h", "objc2/d.h", "objc3/e.h", "objc3/f.h");
+ }
+
+ @Test
+ public void testMultiPlatformLibrary() throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64,armv7,arm64", "--ios_cpu=armv7");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h")
+ .write();
+
+ assertThat(view.hasErrors(getConfiguredTarget("//objc:lib"))).isFalse();
+ }
+
+ @Test
+ public void testCompilationActions_simulator() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386");
+
+ scratch.file("objc/a.m");
+ scratch.file("objc/non_arc.m");
+ scratch.file("objc/private.h");
+ scratch.file("objc/c.h");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch,
+ "objc",
+ "lib",
+ "srcs",
+ "['a.m', 'private.h']",
+ "hdrs",
+ "['c.h']",
+ "non_arc_srcs",
+ "['non_arc.m']"));
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ CommandAction compileActionNonArc = compileAction("//objc:lib", "non_arc.o");
+
+ assertRequiresDarwin(compileActionA);
+ assertThat(compileActionA.getArguments())
+ .contains("tools/osx/crosstool/iossim/" + WRAPPED_CLANG);
+ assertThat(compileActionA.getArguments())
+ .containsAllOf("-isysroot", AppleToolchain.sdkDir()).inOrder();
+ assertThat(Collections.frequency(compileActionA.getArguments(),
+ "-F" + AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")).isEqualTo(1);
+ assertThat(Collections.frequency(compileActionA.getArguments(),
+ "-F" + frameworkDir(Platform.IOS_SIMULATOR))).isEqualTo(1);
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(AppleToolchain.DEFAULT_WARNINGS.values());
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(CompilationSupport.DEFAULT_COMPILER_FLAGS);
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(CompilationSupport.SIMULATOR_COMPILE_FLAGS);
+ assertThat(compileActionA.getArguments()).contains("-fobjc-arc");
+ assertThat(compileActionA.getArguments()).containsAllOf("-c", "objc/a.m");
+ assertThat(compileActionNonArc.getArguments()).contains("-fno-objc-arc");
+ assertThat(compileActionA.getArguments()).containsAllIn(FASTBUILD_COPTS);
+ assertThat(compileActionA.getArguments())
+ .contains("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION);
+ assertThat(compileActionA.getArguments()).contains("-arch i386");
+ }
+
+ @Test
+ public void testCompilationActions_device() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+
+ scratch.file("objc/a.m");
+ scratch.file("objc/non_arc.m");
+ scratch.file("objc/private.h");
+ scratch.file("objc/c.h");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch,
+ "objc",
+ "lib",
+ "srcs",
+ "['a.m', 'private.h']",
+ "hdrs",
+ "['c.h']",
+ "non_arc_srcs",
+ "['non_arc.m']"));
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ CommandAction compileActionNonArc = compileAction("//objc:lib", "non_arc.o");
+
+ assertRequiresDarwin(compileActionA);
+ assertThat(compileActionA.getArguments()).contains("tools/osx/crosstool/ios/" + WRAPPED_CLANG);
+ assertThat(compileActionA.getArguments())
+ .containsAllOf("-isysroot", AppleToolchain.sdkDir()).inOrder();
+ assertThat(Collections.frequency(compileActionA.getArguments(),
+ "-F" + AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")).isEqualTo(1);
+ assertThat(Collections.frequency(compileActionA.getArguments(),
+ "-F" + frameworkDir(Platform.IOS_DEVICE))).isEqualTo(1);
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(AppleToolchain.DEFAULT_WARNINGS.values());
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(CompilationSupport.DEFAULT_COMPILER_FLAGS);
+ assertThat(compileActionA.getArguments())
+ .containsNoneIn(CompilationSupport.SIMULATOR_COMPILE_FLAGS);
+
+ assertThat(compileActionA.getArguments()).contains("-fobjc-arc");
+ assertThat(compileActionA.getArguments()).containsAllOf("-c", "objc/a.m");
+
+ assertThat(compileActionNonArc.getArguments()).contains("-fno-objc-arc");
+ assertThat(compileActionA.getArguments()).containsAllIn(FASTBUILD_COPTS);
+ assertThat(compileActionA.getArguments())
+ .contains("-miphoneos-version-min=" + DEFAULT_IOS_SDK_VERSION);
+ assertThat(compileActionA.getArguments()).contains("-arch armv7");
+ }
+
+ @Test
+ public void testArchivesPrecompiledObjectFiles() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file("objc/a.m");
+ scratch.file("objc/b.o");
+ scratch.file("objc/BUILD", RULE_TYPE.target(scratch, "objc", "x", "srcs", "['a.m', 'b.o']"));
+ assertThat(Artifact.toRootRelativePaths(archiveAction("//objc:x").getInputs()))
+ .contains("objc/b.o");
+ }
+
+ @Test
+ public void testCompileWithFrameworkImportsIncludesFlagsAndInputArtifacts() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ addBinWithTransitiveDepOnFrameworkImport();
+ CommandAction compileAction = compileAction("//lib:lib", "a.o");
+
+ assertThat(compileAction.getArguments()).doesNotContain("-framework");
+ assertThat(Joiner.on("").join(compileAction.getArguments())).contains("-Ffx");
+ assertThat(compileAction.getInputs())
+ .containsAllOf(
+ getSourceArtifact("fx/fx1.framework/a"),
+ getSourceArtifact("fx/fx1.framework/b"),
+ getSourceArtifact("fx/fx2.framework/c"),
+ getSourceArtifact("fx/fx2.framework/d"));
+ }
+
+ @Test
+ public void testPrecompiledHeaders() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file("objc/a.m");
+ scratch.file("objc/c.pch");
+ scratch.file(
+ "objc/BUILD",
+ RULE_TYPE.target(
+ scratch, "objc", "x", "srcs", "['a.m']", "non_arc_srcs", "['b.m']", "pch", "'c.pch'"));
+ CppCompileAction compileAction = (CppCompileAction) compileAction("//objc:x", "a.o");
+ assertThat(Joiner.on(" ").join(compileAction.getArguments()))
+ .contains("-include objc/c.pch");
+ assertThat(Artifact.toRootRelativePaths(compileAction.getPossibleInputsForTesting()))
+ .contains("objc/c.pch");
+ }
+
+ @Test
+ public void testCompilationActionsWithCopts() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--cpu=ios_i386",
+ "--ios_cpu=i386",
+ "--experimental_disable_go");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setList("copts", "-Ifoo", "--monkeys=$(TARGET_CPU)")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ assertThat(compileActionA.getArguments()).containsAllOf("-Ifoo", "--monkeys=ios_i386");
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--objccopt=-foo");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ List<String> args = compileAction("//lib:lib", "a.o").getArguments();
+ assertThat(args).contains("-foo");
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--objccopt=-foo");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("copts", "-bar")
+ .write();
+ List<String> args = compileAction("//lib:lib", "a.o").getArguments();
+ assertThat(args).containsAllOf("-fobjc-arc", "-foo", "-bar").inOrder();
+ }
+
+ @Test
+ public void testCompilationActionsWithModuleMapsEnabled() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_enable_module_maps");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(moduleMapArtifactArguments("//objc", "lib"));
+ assertThat(compileActionA.getArguments()).contains("-fmodule-maps");
+ assertThat(Artifact.toRootRelativePaths(compileActionA.getInputs()))
+ .doesNotContain("objc/lib.modulemaps/module.modulemap");
+ }
+
+ @Test
+ public void testCompilationActionsWithEmbeddedBitcode() throws Exception {
+ useConfiguration(
+ "--xcode_version=7.1",
+ "--ios_multi_cpus=arm64",
+ "--apple_bitcode=embedded");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).contains("-fembed-bitcode");
+ }
+
+ @Test
+ public void testCompilationActionsWithEmbeddedBitcodeMarkers() throws Exception {
+ useConfiguration(
+ "--xcode_version=7.1",
+ "--ios_multi_cpus=arm64",
+ "--apple_bitcode=embedded_markers");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).contains("-fembed-bitcode-marker");
+ }
+
+ @Test
+ public void testCompilationActionsWithNoBitcode() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--xcode_version=7.1",
+ "--ios_multi_cpus=arm64",
+ "--apple_bitcode=none");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).doesNotContain("-fembed-bitcode");
+ assertThat(compileActionA.getArguments()).doesNotContain("-fembed-bitcode-marker");
+ }
+
+ /**
+ * Tests that bitcode is disabled for simulator builds even if enabled by flag.
+ */
+ @Test
+ public void testCompilationActionsWithBitcode_simulator() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--xcode_version=7.1",
+ "--ios_multi_cpus=x86_64",
+ "--apple_bitcode=embedded");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+
+ assertThat(compileActionA.getArguments()).doesNotContain("-fembed-bitcode");
+ assertThat(compileActionA.getArguments()).doesNotContain("-fembed-bitcode-marker");
+ }
+
+ @Test
+ public void testModuleMapActionFiltersHeaders() throws Exception {
+ RULE_TYPE.scratchTarget(
+ scratch,
+ "srcs",
+ "['a.m', 'b.m', 'private.h', 'private.inc']",
+ "hdrs",
+ "['a.h', 'x.inc', 'foo.m', 'bar.mm']");
+
+ ConfiguredTarget configuredTarget = getConfiguredTarget("//x:x");
+ Artifact moduleMap = getGenfilesArtifact("x.modulemaps/module.modulemap", configuredTarget);
+
+ CppModuleMapAction genMap = (CppModuleMapAction) getGeneratingAction(moduleMap);
+
+ assertThat(Artifact.toRootRelativePaths(genMap.getPrivateHeaders())).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(genMap.getPublicHeaders())).containsExactly("x/a.h");
+ }
+
+ @Test
+ public void testArchiveAction_simulator() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+
+ CommandAction archiveAction = archiveAction("//objc:lib");
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ "tools/osx/crosstool/iossim/libtool",
+ "-static",
+ "-filelist",
+ getBinArtifact("lib-archive.objlist", "//objc:lib").getExecPathString(),
+ "-arch_only",
+ "i386",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsAllOf("a.o", "b.o", "lib-archive.objlist", CROSSTOOL_LINK_MIDDLEMAN);
+ assertThat(baseArtifactNames(archiveAction.getOutputs())).containsExactly("liblib.a");
+ assertRequiresDarwin(archiveAction);
+ }
+
+ @Test
+ public void testArchiveAction_device() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction archiveAction = archiveAction("//objc:lib");
+
+ assertThat(archiveAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ "tools/osx/crosstool/ios/libtool",
+ "-static",
+ "-filelist",
+ getBinArtifact("lib-archive.objlist", "//objc:lib").getExecPathString(),
+ "-arch_only",
+ "armv7",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(archiveAction.getOutputs()).getExecPathString()));
+ assertThat(baseArtifactNames(archiveAction.getInputs()))
+ .containsAllOf("a.o", "b.o", "lib-archive.objlist");
+ assertThat(baseArtifactNames(archiveAction.getOutputs())).containsExactly("liblib.a");
+ assertRequiresDarwin(archiveAction);
+ }
+
+ @Test
+ public void testFullyLinkArchiveAction_simulator() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386");
+ createLibraryTargetWriter("//objc:lib_dep")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib_dep")
+ .write();
+ CommandAction linkAction =
+ (CommandAction) getGeneratingActionForLabel("//objc2:lib_fully_linked.a");
+ assertRequiresDarwin(linkAction);
+ assertThat(linkAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ "tools/osx/crosstool/iossim/libtool",
+ "-static",
+ "-arch_only",
+ "i386",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(linkAction.getOutputs()).getExecPathString(),
+ getBinArtifact("liblib.a", "//objc2:lib").getExecPathString(),
+ getBinArtifact("liblib_dep.a", "//objc:lib_dep").getExecPathString()));
+ // TODO(hlopko): make containsExactly once crosstools are updated so
+ // link_dynamic_library.sh is not needed anymore
+ assertThat(baseArtifactNames(linkAction.getInputs())).containsAllOf(
+ "liblib_dep.a",
+ "liblib.a",
+ CROSSTOOL_LINK_MIDDLEMAN);
+ }
+
+ @Test
+ public void testFullyLinkArchiveAction_device() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_armv7",
+ "--ios_cpu=armv7");
+ createLibraryTargetWriter("//objc:lib_dep")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib_dep")
+ .write();
+ CommandAction linkAction =
+ (CommandAction) getGeneratingActionForLabel("//objc2:lib_fully_linked.a");
+ assertRequiresDarwin(linkAction);
+ assertThat(linkAction.getArguments())
+ .isEqualTo(
+ ImmutableList.of(
+ "tools/osx/crosstool/ios/libtool",
+ "-static",
+ "-arch_only",
+ "armv7",
+ "-syslibroot",
+ AppleToolchain.sdkDir(),
+ "-o",
+ Iterables.getOnlyElement(linkAction.getOutputs()).getExecPathString(),
+ getBinArtifact("liblib.a", "//objc2:lib").getExecPathString(),
+ getBinArtifact("liblib_dep.a", "//objc:lib_dep").getExecPathString()));
+ // TODO(hlopko): make containsExactly once crosstools are updated so
+ // link_dynamic_library.sh is not needed anymore
+ assertThat(baseArtifactNames(linkAction.getInputs())).containsAllOf(
+ "liblib_dep.a",
+ "liblib.a",
+ CROSSTOOL_LINK_MIDDLEMAN);
+ }
+
+ @Test
+ public void checkDoesNotStoreObjcLibsAsCC() throws Exception {
+ createLibraryTargetWriter("//objc:lib_dep")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib_dep")
+ .write();
+ ObjcProvider objcProvider = providerForTarget("//objc2:lib");
+ assertThat(objcProvider.get(CC_LIBRARY)).isEmpty();
+ }
+
+ @Test
+ public void testIncludesDirsGetPassedToCompileAction() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("includes", "../third_party/foo", "opensource/bar")
+ .write();
+ CommandAction compileAction = compileAction("//lib:lib", "a.o");
+
+ for (String path :
+ rootedIncludePaths(
+ getAppleCrosstoolConfiguration(), "third_party/foo", "lib/opensource/bar")) {
+ assertThat(Joiner.on("").join(compileAction.getArguments())).contains("-I" + path);
+ }
+ }
+
+ @Test
+ public void testPropagatesDefinesToDependersTransitively() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_x86_64",
+ "--ios_cpu=x86_64");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("non_arc_srcs", "b.m")
+ .setList("defines", "A=foo", "B", "MONKEYS=$(TARGET_CPU)")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m")
+ .setAndCreateFiles("non_arc_srcs", "b.m")
+ .setList("deps", "//lib1:lib1")
+ .setList("defines", "C=bar", "D")
+ .write();
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "c.m")
+ .setList("deps", "//lib2:lib2")
+ .write();
+
+ assertThat(compileAction("//lib1:lib1", "a.o").getArguments())
+ .containsAllOf("-DA=foo", "-DB", "-DMONKEYS=ios_x86_64")
+ .inOrder();
+ assertThat(compileAction("//lib1:lib1", "b.o").getArguments())
+ .containsAllOf("-DA=foo", "-DB", "-DMONKEYS=ios_x86_64")
+ .inOrder();
+ assertThat(compileAction("//lib2:lib2", "a.o").getArguments())
+ .containsAllOf("-DA=foo", "-DB", "-DMONKEYS=ios_x86_64", "-DC=bar", "-DD")
+ .inOrder();
+ assertThat(compileAction("//lib2:lib2", "b.o").getArguments())
+ .containsAllOf("-DA=foo", "-DB", "-DMONKEYS=ios_x86_64", "-DC=bar", "-DD")
+ .inOrder();
+ // TODO: Add tests for //bin:bin once experimental_objc_binary is implemented
+ }
+
+ @Test
+ public void testDuplicateDefines() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("defines", "foo=bar", "foo=bar")
+ .write();
+ int timesDefinesAppear = 0;
+ for (String arg : compileAction("//lib:lib", "a.o").getArguments()) {
+ if (arg.equals("-Dfoo=bar")) {
+ timesDefinesAppear++;
+ }
+ }
+ assertWithMessage("Duplicate define \"foo=bar\" should occur only once in command line")
+ .that(timesDefinesAppear)
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void checkDefinesFromCcLibraryDep() throws Exception {
+ checkDefinesFromCcLibraryDep(RULE_TYPE);
+ }
+
+ @Test
+ public void testCppSourceCompilesWithCppFlags() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//objc:x")
+ .setAndCreateFiles("srcs", "a.mm", "b.cc", "c.mm", "d.cxx", "e.c", "f.m", "g.C")
+ .write();
+ assertThat(compileAction("//objc:x", "a.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "b.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "c.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "d.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "e.o").getArguments()).doesNotContain("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "f.o").getArguments()).doesNotContain("-std=gnu++11");
+ assertThat(compileAction("//objc:x", "g.o").getArguments()).contains("-std=gnu++11");
+ }
+
+ @Test
+ public void testAssetCatalogsAttributeErrorForNotInXcAssetsDir() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file("lib/ac/notinxcassets1");
+ scratch.file("lib/ac/notinxcassets2");
+ scratch.file("lib/ac/foo.xcassets/isinxcassets");
+ checkError("lib", "lib",
+ String.format(ObjcCommon.NOT_IN_CONTAINER_ERROR_FORMAT,
+ "lib/ac/notinxcassets2", ImmutableList.of(ObjcCommon.ASSET_CATALOG_CONTAINER_TYPE)),
+ "objc_library(name = 'lib', srcs = ['src.m'], asset_catalogs = glob(['ac/**']))");
+ }
+
+ @Test
+ public void testXcdatamodelsAttributeErrorForNotInXcdatamodelDir() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file("lib/xcd/notinxcdatamodel1");
+ scratch.file("lib/xcd/notinxcdatamodel2");
+ scratch.file("lib/xcd/foo.xcdatamodel/isinxcdatamodel");
+ scratch.file("lib/xcd/bar.xcdatamodeld/isinxcdatamodeld");
+ checkError("lib", "lib",
+ String.format(ObjcCommon.NOT_IN_CONTAINER_ERROR_FORMAT,
+ "lib/xcd/notinxcdatamodel1", Xcdatamodels.CONTAINER_TYPES),
+ "objc_library(name = 'lib', srcs = ['src.m'], datamodels = glob(['xcd/**']))");
+ }
+
+ @Test
+ public void testProvidesStoryboardOptions() throws Exception {
+ checkProvidesStoryboardObjects(RULE_TYPE);
+ }
+
+ @Test
+ public void testDoesNotUseCxxUnfilteredFlags() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createLibraryTargetWriter("//lib:lib")
+ .setList("srcs", "a.m")
+ .write();
+ // -pthread is an unfiltered_cxx_flag in the osx crosstool.
+ assertThat(compileAction("//lib:lib", "a.o").getArguments()).doesNotContain("-pthread");
+ }
+
+ @Test
+ public void testDoesNotUseDotdPruning() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--objc_use_dotd_pruning=false");
+ createLibraryTargetWriter("//lib:lib")
+ .setList("srcs", "a.m")
+ .write();
+ CppCompileAction compileAction = (CppCompileAction) compileAction("//lib:lib", "a.o");
+ assertThat(compileAction.discoverInputsFromDotdFiles(null, null, null)).isEmpty();
+ }
+
+ @Test
+ public void testProvidesObjcLibraryAndHeaders() throws Exception {
+ ConfiguredTarget target =
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "a.h", "b.h")
+ .write();
+ ConfiguredTarget depender =
+ createLibraryTargetWriter("//objc2:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h", "d.h")
+ .setList("deps", "//objc:lib")
+ .write();
+ assertThat(Artifact.toRootRelativePaths(target.getProvider(ObjcProvider.class).get(LIBRARY)))
+ .containsExactly("objc/liblib.a");
+ assertThat(Artifact.toRootRelativePaths(depender.getProvider(ObjcProvider.class).get(LIBRARY)))
+ .containsExactly("objc/liblib.a", "objc2/liblib.a");
+ assertThat(Artifact.toRootRelativePaths(target.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc/a.h", "objc/b.h");
+ assertThat(Artifact.toRootRelativePaths(depender.getProvider(ObjcProvider.class).get(HEADER)))
+ .containsExactly("objc/a.h", "objc/b.h", "objc2/c.h", "objc2/d.h");
+ }
+
+ @Test
+ public void testWeakSdkFrameworks_objcProvider() throws Exception {
+ createLibraryTargetWriter("//base_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("weak_sdk_frameworks", "foo")
+ .write();
+ createLibraryTargetWriter("//depender_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("weak_sdk_frameworks", "bar")
+ .setList("deps", "//base_lib:lib")
+ .write();
+
+ ObjcProvider baseProvider = providerForTarget("//base_lib:lib");
+ ObjcProvider dependerProvider = providerForTarget("//depender_lib:lib");
+
+ assertThat(baseProvider.get(WEAK_SDK_FRAMEWORK)).containsExactly(new SdkFramework("foo"));
+ assertThat(dependerProvider.get(WEAK_SDK_FRAMEWORK))
+ .containsExactly(new SdkFramework("foo"), new SdkFramework("bar"));
+ }
+
+ @Test
+ public void testErrorIfDepDoesNotExist() throws Exception {
+ checkErrorIfNotExist("deps", "[':nonexistent']");
+ }
+
+ @Test
+ public void testArIsNotImplicitOutput() throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .write();
+ try {
+ reporter.removeHandler(failFastHandler);
+ getTarget("//lib:liblib.a");
+ fail("should have thrown");
+ } catch (NoSuchTargetException expected) {
+ }
+ }
+
+ @Test
+ public void testErrorForAbsoluteIncludesPath() throws Exception {
+ scratch.file("x/a.m");
+ checkError(
+ "x",
+ "x",
+ String.format(ABSOLUTE_INCLUDES_PATH_FORMAT, "/absolute/path"),
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ " includes = ['/absolute/path'],",
+ ")");
+ }
+
+ @Test
+ public void testExportsBundleDependencies() throws Exception {
+ scratch.file("bundle/bar/x.bundle/1");
+ scratch.file(
+ "bundle/BUILD",
+ "objc_bundle(",
+ " name = 'bundle',",
+ " bundle_imports = glob(['bar/**']),",
+ ")");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("bundles", "//bundle:bundle")
+ .write();
+ ObjcProvider provider = providerForTarget("//lib:lib");
+ assertThat(provider.get(BUNDLE_FILE))
+ .contains(new BundleableFile(getSourceArtifact("bundle/bar/x.bundle/1"), "x.bundle/1"));
+ }
+
+ @Test
+ public void testDylibsProvided() throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("sdk_dylibs", "libdy1", "libdy2")
+ .write();
+ ObjcProvider provider = providerForTarget("//lib:lib");
+ assertThat(provider.get(SDK_DYLIB)).containsExactly("libdy1", "libdy2").inOrder();
+ }
+
+ @Test
+ public void testPopulatesCompilationArtifacts() throws Exception {
+ checkPopulatesCompilationArtifacts(RULE_TYPE);
+ }
+
+ @Test
+ public void testProvidesXcassetCatalogsTransitively() throws Exception {
+ scratch.file("lib1/ac.xcassets/foo");
+ scratch.file("lib1/ac.xcassets/bar");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+ scratch.file("lib2/ac.xcassets/baz");
+ scratch.file("lib2/ac.xcassets/42");
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .setList("deps", "//lib1:lib1")
+ .write();
+
+ ObjcProvider lib2Provider = providerForTarget("//lib2:lib2");
+ assertThat(Artifact.toExecPaths(lib2Provider.get(ASSET_CATALOG)))
+ .containsExactly(
+ "lib1/ac.xcassets/foo",
+ "lib1/ac.xcassets/bar",
+ "lib2/ac.xcassets/baz",
+ "lib2/ac.xcassets/42");
+ assertThat(lib2Provider.get(XCASSETS_DIR))
+ .containsExactly(
+ PathFragment.create("lib1/ac.xcassets"), PathFragment.create("lib2/ac.xcassets"));
+
+ ObjcProvider lib1Provider = providerForTarget("//lib1:lib1");
+ assertThat(Artifact.toExecPaths(lib1Provider.get(ASSET_CATALOG)))
+ .containsExactly("lib1/ac.xcassets/foo", "lib1/ac.xcassets/bar");
+ assertThat(lib1Provider.get(XCASSETS_DIR))
+ .containsExactly(PathFragment.create("lib1/ac.xcassets"))
+ .inOrder();
+ }
+
+ @Test
+ public void testObjcListFileInArchiveGeneration() throws Exception {
+ scratch.file("lib/a.m");
+ scratch.file("lib/b.m");
+ scratch.file("lib/BUILD", "objc_library(name = 'lib1', srcs = ['a.m', 'b.m'])");
+ ConfiguredTarget target = getConfiguredTarget("//lib:lib1");
+ Artifact objlist = getBinArtifact("lib1-archive.objlist", target);
+ ParameterFileWriteAction action = (ParameterFileWriteAction) getGeneratingAction(objlist);
+ assertThat(action.getContents())
+ .containsExactlyElementsIn(
+ Artifact.toExecPaths(inputsEndingWith(archiveAction("//lib:lib1"), ".o")));
+ }
+
+ @Test
+ public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception {
+ checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForDebug() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testClangCoptsForDebugModeWithoutGlib() throws Exception {
+ checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE);
+ }
+
+ @Test
+ public void testCompilationActionsForOptimized() throws Exception {
+ checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE);
+ }
+
+ @Test
+ public void testUsesDefinesFromTransitiveCcDeps() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "cc_library(",
+ " name = 'cc_lib',",
+ " srcs = ['a.cc'],",
+ " defines = ['FOO'],",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['b.m'],",
+ " deps = [':cc_lib'],",
+ ")");
+
+ CommandAction compileAction = compileAction("//package:objc_lib", "b.o");
+ assertThat(compileAction.getArguments()).contains("-DFOO");
+ }
+
+ @Test
+ public void testAllowVariousNonBlacklistedTypesInHeaders() throws Exception {
+ checkAllowVariousNonBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testWarningForBlacklistedTypesInHeaders() throws Exception {
+ checkWarningForBlacklistedTypesInHeaders(RULE_TYPE);
+ }
+
+ @Test
+ public void testBundleInformationPropagatedThroughLibraries() throws Exception {
+ checkNestedBundleInformationPropagatedToDependers(RULE_TYPE);
+ }
+
+ @Test
+ public void testAppleSdkVersionEnv() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction action = compileAction("//objc:lib", "a.o");
+
+ assertAppleSdkVersionEnv(action);
+ }
+
+ @Test
+ public void testNonDefaultAppleSdkVersionEnv() throws Exception {
+ useConfiguration("--ios_sdk_version=8.1");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction action = compileAction("//objc:lib", "a.o");
+
+ assertAppleSdkVersionEnv(action, "8.1");
+ }
+
+ @Test
+ public void testXcodeVersionEnv() throws Exception {
+ useConfiguration("--xcode_version=5.8");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction action = compileAction("//objc:lib", "a.o");
+
+ assertXcodeVersionEnv(action, "5.8");
+ }
+
+ @Test
+ public void testIosSdkVersionCannotBeDefinedButEmpty() throws Exception {
+ try {
+ useConfiguration("--ios_sdk_version=");
+ fail("Should fail for empty ios_sdk_version");
+ } catch (OptionsParsingException e) {
+ assertThat(e).hasMessageThat().contains("--ios_sdk_version");
+ }
+ }
+
+ private void checkErrorIfNotExist(String attribute, String value) throws Exception {
+ scratch.file("x/a.m");
+ checkError(
+ "x",
+ "x",
+ "in "
+ + attribute
+ + " attribute of objc_library rule //x:x: rule '//x:nonexistent' does not exist",
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['a.m'],",
+ attribute + " = " + value,
+ ")");
+ }
+
+ @Test
+ public void testUsesDotdPruning() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL, "--objc_use_dotd_pruning");
+ createLibraryTargetWriter("//lib:lib").setList("srcs", "a.m").write();
+ CppCompileAction compileAction = (CppCompileAction) compileAction("//lib:lib", "a.o");
+ try {
+ compileAction.discoverInputsFromDotdFiles(null, null, null);
+ fail("Expected ActionExecutionException");
+ } catch (ActionExecutionException expected) {
+ assertThat(expected).hasMessageThat().contains("error while parsing .d file");
+ }
+ }
+
+ @Test
+ public void testAppleSdkDefaultPlatformEnv() throws Exception {
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction action = compileAction("//objc:lib", "a.o");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneSimulator");
+ }
+
+ @Test
+ public void testAppleSdkDevicePlatformEnv() throws Exception {
+ useConfiguration("--cpu=ios_arm64");
+
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .write();
+ CommandAction action = compileAction("//objc:lib", "a.o");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneOS");
+ }
+
+ @Test
+ public void testApplePlatformEnvForCcLibraryDep() throws Exception {
+ useConfiguration(
+ "--experimental_disable_go", "--experimental_disable_jvm", "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("package/BUILD",
+ "cc_library(",
+ " name = 'cc_lib',",
+ " srcs = ['a.cc'],",
+ ")",
+ "",
+ "objc_binary(",
+ " name = 'objc_bin',",
+ " srcs = ['b.m'],",
+ " deps = [':cc_lib'],",
+ ")");
+
+ Action binLinkAction = linkAction("//package:objc_bin");
+ Artifact artifact =
+ ActionsTestUtil.getFirstArtifactEndingWith(binLinkAction.getInputs(), "libcc_lib.a");
+ Action cppLibLinkAction = getGeneratingAction(artifact);
+ Artifact cppLibArtifact =
+ ActionsTestUtil.getFirstArtifactEndingWith(cppLibLinkAction.getInputs(), ".o");
+
+ CppCompileAction action = (CppCompileAction) getGeneratingAction(cppLibArtifact);
+ assertAppleSdkVersionEnv(action.getEnvironment());
+ }
+
+ @Test
+ public void testDoesNotPropagateProtoIncludes() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ scratch.file(
+ "x/BUILD",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_lib',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")");
+ createLibraryTargetWriter("//a:lib")
+ .setList("srcs", "a.m")
+ .setList("deps", "//x:objc_proto_lib")
+ .write();
+ createLibraryTargetWriter("//b:lib").setList("srcs", "b.m").setList("deps", "//a:lib").write();
+
+ CommandAction compileAction1 = compileAction("//a:lib", "a.o");
+ CommandAction compileAction2 = compileAction("//b:lib", "b.o");
+
+ assertThat(Joiner.on(" ").join(compileAction1.getArguments())).contains("objc_proto_lib");
+ assertThat(Joiner.on(" ").join(compileAction2.getArguments())).doesNotContain("objc_proto_lib");
+ }
+
+ @Test
+ public void testExportsJ2ObjcProviders() throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ ConfiguredTarget lib = createLibraryTargetWriter("//a:lib").write();
+ assertThat(lib.getProvider(J2ObjcEntryClassProvider.class)).isNotNull();
+ assertThat(lib.getProvider(J2ObjcMappingFileProvider.class)).isNotNull();
+ }
+
+ @Test
+ public void testObjcProtoLibraryDoesNotCrash() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'objc',",
+ " srcs = ['source.m'],",
+ " deps = [':objc_proto_lib'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_lib',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")");
+ assertThat(getConfiguredTarget("//x:objc")).isNotNull();
+ }
+
+ @Test
+ public void testLegacyObjcProtoLibraryDoesNotCrash() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'objc',",
+ " srcs = ['source.m'],",
+ " deps = [':objc_proto_lib'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_lib',",
+ " deps = [':protos'],",
+ ")");
+ assertThat(getConfiguredTarget("//x:objc")).isNotNull();
+ }
+
+ @Test
+ public void testObjcImportDoesNotCrash() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'objc',",
+ " srcs = ['source.m'],",
+ " deps = [':import'],",
+ ")",
+ "objc_import(",
+ " name = 'import',",
+ " archives = ['archive.a'],",
+ ")");
+ assertThat(getConfiguredTarget("//x:objc")).isNotNull();
+ }
+
+ @Test
+ public void testCompilationActionsWithIQuotesInCopts() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--ios_cpu=i386");
+ createLibraryTargetWriter("//objc:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "c.h")
+ .setList("copts", "-iquote foo/bar", "-iquote bam/baz")
+ .write();
+
+ CommandAction compileActionA = compileAction("//objc:lib", "a.o");
+ String action = String.join(" ", compileActionA.getArguments());
+ assertThat(action).contains("-iquote foo/bar");
+ assertThat(action).contains("-iquote bam/baz");
+ }
+ @Test
+ public void testCollectCodeCoverageWithGCOVFlags() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL, "--collect_code_coverage");
+ createLibraryTargetWriter("//objc:x")
+ .setAndCreateFiles("srcs", "a.mm", "b.cc", "c.mm", "d.cxx", "e.c", "f.m", "g.C")
+ .write();
+ List<String> copts = ImmutableList.of("-fprofile-arcs", "-ftest-coverage");
+ assertThat(compileAction("//objc:x", "a.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "b.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "c.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "d.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "e.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "f.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "g.o").getArguments()).containsAllIn(copts);
+ }
+
+ @Test
+ public void testCollectCodeCoverageWithLLVMCOVFlags() throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--collect_code_coverage",
+ "--experimental_use_llvm_covmap");
+ createLibraryTargetWriter("//objc:x")
+ .setAndCreateFiles("srcs", "a.mm", "b.cc", "c.mm", "d.cxx", "e.c", "f.m", "g.C")
+ .write();
+ List<String> copts = ImmutableList.of("-fprofile-instr-generate", "-fcoverage-mapping");
+ assertThat(compileAction("//objc:x", "a.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "b.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "c.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "d.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "e.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "f.o").getArguments()).containsAllIn(copts);
+ assertThat(compileAction("//objc:x", "g.o").getArguments()).containsAllIn(copts);
+ }
+
+ @Test
+ public void testNoG0IfGeneratesDsym() throws Exception {
+ useConfiguration("--apple_generate_dsym", "-c", "opt");
+ createLibraryTargetWriter("//x:x").setList("srcs", "a.m").write();
+ CommandAction compileAction = compileAction("//x:x", "a.o");
+ assertThat(compileAction.getArguments()).doesNotContain("-g0");
+ }
+
+ @Test
+ public void testFilesToCompileOutputGroup() throws Exception {
+ checkFilesToCompileOutputGroup(RULE_TYPE);
+ }
+
+ @Test
+ public void testSysrootArgSpecifiedWithGrteTopFlag() throws Exception {
+ MockObjcSupport.setup(mockToolsConfig, "default_grte_top : '//x'");
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--experimental_objc_crosstool=all",
+ "--cpu=ios_x86_64",
+ "--ios_cpu=x86_64");
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'objc',",
+ " srcs = ['source.m'],",
+ ")",
+ "filegroup(",
+ " name = 'everything',",
+ " srcs = ['header.h'],",
+ ")");
+ CommandAction compileAction = compileAction("//x:objc", "source.o");
+ assertThat(compileAction.getArguments()).contains("--sysroot=x");
+ }
+
+ @Test
+ public void testDefaultEnabledFeatureIsUsed() throws Exception {
+ MockObjcSupport.setup(mockToolsConfig,
+ "feature {",
+ " name: 'default'",
+ " enabled : true",
+ " flag_set {",
+ " action: 'objc-compile'",
+ " flag_group {",
+ " flag: '-dummy'",
+ " }",
+ " }",
+ "}");
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--experimental_objc_crosstool=all",
+ "--cpu=ios_x86_64",
+ "--ios_cpu=x86_64");
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'objc',",
+ " srcs = ['source.m'],",
+ ")");
+ CommandAction compileAction = compileAction("//x:objc", "source.o");
+ assertThat(compileAction.getArguments()).contains("-dummy");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspectTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspectTest.java
new file mode 100644
index 0000000000..83611a5b4b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoAspectTest.java
@@ -0,0 +1,227 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for the objc_proto_library aspect. */
+@RunWith(JUnit4.class)
+public final class ObjcProtoAspectTest extends BuildViewTestCase {
+
+ @Before
+ public final void initializeToolsConfigMock() throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+ }
+
+ @Test
+ public void testObjcProtoAspectPropagatesProvider() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNotNull();
+ }
+
+ @Test
+ public void testObjcProtoAspectPropagatesProtobufProvider() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNotNull();
+ assertThat(Artifact.toExecPaths(objcProtoProvider.getProtobufHeaders()))
+ .containsExactly("objcproto/include/header.h");
+
+ Artifact header = Iterables.getOnlyElement(objcProtoProvider.getProtobufHeaders());
+ PathFragment includePath = header.getExecPath().getParentDirectory();
+ PathFragment genIncludePath =
+ PathFragment.create(
+ getConfiguration(targetConfig, AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION)
+ .getGenfilesFragment()
+ + "/"
+ + includePath);
+
+ assertThat(objcProtoProvider.getProtobufHeaderSearchPaths())
+ .containsExactly(includePath, genIncludePath);
+ }
+
+ @Test
+ public void testObjcProtoAspectDoesNotPropagateProviderWhenNoProtos() throws Exception {
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['A.m'],",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNull();
+ }
+
+ @Test
+ public void testObjcProtoAspectBundlesDuplicateSymbols() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['A.m'],",
+ " deps = [",
+ " ':objc_proto',",
+ " ':objc_proto_duplicate',",
+ " ],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_duplicate',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['data_filter.pbascii'],",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNotNull();
+
+ assertThat(Artifact.toExecPaths(Iterables.concat(objcProtoProvider.getProtoGroups())))
+ .containsExactly("x/data.proto");
+ assertThat(Artifact.toExecPaths(objcProtoProvider.getPortableProtoFilters()))
+ .containsExactly("x/data_filter.pbascii");
+ }
+
+ @Test
+ public void testObjcProtoAspectPropagatesGeneratedFilter() throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['A.m'],",
+ " deps = [",
+ " ':objc_proto',",
+ " ],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto',",
+ " deps = [':protos'],",
+ " uses_protobuf = 1,",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNotNull();
+
+ assertThat(Artifact.toExecPaths(objcProtoProvider.getPortableProtoFilters()))
+ .containsExactly(
+ getConfiguration(targetConfig, AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION)
+ .getGenfilesFragment()
+ + "/x/_proto_filters/objc_proto/generated_filter_file.pbascii");
+ }
+
+ @Test
+ public void testObjcProtoAspectPropagatesFiltersFromDependenciesOfObjcProtoLibrary()
+ throws Exception {
+ scratch.file(
+ "x/BUILD",
+ "objc_library(",
+ " name = 'x',",
+ " srcs = ['A.m'],",
+ " deps = [",
+ " ':objc_proto_all',",
+ " ],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_all',",
+ " deps = [':objc_proto_1', ':objc_proto_2'],",
+ " uses_protobuf = 1,",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_1',",
+ " deps = [':protos'],",
+ " portable_proto_filters = ['filter.pbascii'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_proto_2',",
+ " deps = [':protos'],",
+ " uses_protobuf = 1,",
+ ")");
+ ConfiguredTarget topTarget = getObjcProtoAspectConfiguredTarget("//x:x");
+ ObjcProtoProvider objcProtoProvider = topTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(objcProtoProvider).isNotNull();
+
+ assertThat(Artifact.toExecPaths(objcProtoProvider.getPortableProtoFilters()))
+ .containsAllOf(
+ "x/filter.pbascii",
+ getConfiguration(targetConfig, AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION)
+ .getGenfilesFragment()
+ + "/x/_proto_filters/objc_proto_2/generated_filter_file.pbascii");
+ }
+
+ private ConfiguredTarget getObjcProtoAspectConfiguredTarget(String label) throws Exception {
+ scratch.file("bin/BUILD",
+ "objc_binary(",
+ " name = 'link_target',",
+ " deps = ['" + label + "'],",
+ ")");
+
+ return view.getPrerequisiteConfiguredTargetForTesting(
+ reporter,
+ getConfiguredTarget("//bin:link_target"),
+ Label.parseAbsoluteUnchecked(label),
+ masterConfig);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java
new file mode 100644
index 0000000000..a2689cd8fc
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java
@@ -0,0 +1,854 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.collect.nestedset.NestedSet;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.rules.cpp.CppModuleMapAction;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Test case for objc_proto_library. */
+@RunWith(JUnit4.class)
+public class ObjcProtoLibraryTest extends ObjcRuleTestCase {
+
+ @Before
+ public final void initializeToolsConfigMock() throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+ }
+
+ @Before
+ public final void createFiles() throws Exception {
+ scratch.file(
+ "package/BUILD",
+ "apple_binary(",
+ " name = 'opl_binary',",
+ " deps = [':opl_protobuf'],",
+ " platform_type = 'tvos'",
+ ")",
+ "objc_library(",
+ " name = 'non_strict_lib',",
+ " deps = [':strict_lib'],",
+ ")",
+ "",
+ "objc_library(",
+ " name = 'strict_lib',",
+ " deps = [':opl_protobuf'],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'opl',",
+ " deps = [':protolib'],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'nested_opl',",
+ " deps = [':opl_protobuf'],",
+ " portable_proto_filters = ['nested_filter.txt'],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'opl_protobuf',",
+ " deps = [':protolib'],",
+ " portable_proto_filters = [",
+ " 'proto_filter.txt',",
+ " ':portable_proto_filters',",
+ " ],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'opl_protobuf_well_known_types',",
+ " deps = [':protolib_well_known_types'],",
+ " portable_proto_filters = [",
+ " 'proto_filter.txt',",
+ " ],",
+ ")",
+ "objc_proto_library(",
+ " name = 'opl_well_known_types',",
+ " deps = [':protolib_well_known_types'],",
+ ")",
+ "",
+ "filegroup(",
+ " name = 'portable_proto_filters',",
+ " srcs = [",
+ " 'proto_filter2.txt',",
+ " 'proto_filter3.txt',",
+ " ],",
+ ")",
+ "",
+ "proto_library(",
+ " name = 'protolib',",
+ " srcs = ['file_a.proto', 'dir/file_b.proto'],",
+ " deps = ['//dep:dep_lib'],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'opl_protobuf_special_names',",
+ " deps = [':protolib_special_names'],",
+ " portable_proto_filters = [",
+ " 'proto_filter.txt',",
+ " ],",
+ ")",
+ "objc_proto_library(",
+ " name = 'opl_pb2_special_names',",
+ " deps = [':protolib_special_names'],",
+ ")",
+ "",
+ "proto_library(",
+ " name = 'protolib_special_names',",
+ " srcs = [",
+ " 'j2objc-descriptor.proto',",
+ " 'http.proto',",
+ " 'https.proto',",
+ " 'some_url_blah.proto',",
+ " 'thumbnail_url.proto',",
+ " 'url.proto',",
+ " 'url2https.proto',",
+ " 'urlbar.proto',",
+ " ],",
+ " deps = ['//dep:dep_lib'],",
+ ")",
+ "",
+ "proto_library(",
+ " name = 'protolib_well_known_types',",
+ " srcs = ['file_a.proto'],",
+ " deps = ['//objcproto:well_known_type_proto'],",
+ ")",
+ "",
+ "genrule(",
+ " name = 'gen_proto',",
+ " srcs = ['file_a.proto'],",
+ " outs = ['file_a_genfile.proto'],",
+ " cmd = 'cp $(location file_a.proto) $(location file_a_genfile.proto)')",
+ "",
+ "proto_library(",
+ " name = 'gen_protolib',",
+ " srcs = ['file_a_genfile.proto'],",
+ " deps = ['//dep:dep_lib'],",
+ ")",
+ "",
+ "objc_proto_library(",
+ " name = 'gen_opl',",
+ " deps = [':gen_protolib'],",
+ ")");
+ scratch.file("dep/BUILD",
+ "proto_library(",
+ " name = 'dep_lib',",
+ " srcs = ['file.proto'],",
+ ")");
+ scratch.file("package/file_a.proto");
+ scratch.file("package/dir/file_b.proto");
+ scratch.file("dep/file.proto");
+ scratch.file("package/proto_filter.txt");
+ scratch.file("package/proto_filter2.txt");
+ scratch.file("package/proto_filter3.txt");
+ }
+
+ @Test
+ public void testOutputs() throws Exception {
+ NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:opl"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/libopl.a",
+ "package/_generated_protos/opl/package/FileA.pb.h",
+ "package/_generated_protos/opl/package/FileA.pb.m",
+ "package/_generated_protos/opl/package/dir/FileB.pb.h",
+ "package/_generated_protos/opl/package/dir/FileB.pb.m",
+ "package/_generated_protos/opl/dep/File.pb.h");
+ }
+
+ @Test
+ public void testOutputsProtobuf() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.h",
+ "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.m",
+ "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.h",
+ "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.m",
+ "package/_generated_protos/opl_protobuf/dep/File.pbobjc.h");
+ }
+
+ @Test
+ public void testOutputsWithAutoUnionExperiment() throws Exception {
+ NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:opl"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/libopl.a",
+ "package/_generated_protos/opl/package/FileA.pb.h",
+ "package/_generated_protos/opl/package/FileA.pb.m",
+ "package/_generated_protos/opl/package/dir/FileB.pb.h",
+ "package/_generated_protos/opl/package/dir/FileB.pb.m",
+ "package/_generated_protos/opl/dep/File.pb.h");
+ }
+
+ @Test
+ public void testDependingOnProtobufObjcProtoLibrary() throws Exception {
+ NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:nested_opl"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/nested_opl/package/FileA.pbobjc.h",
+ "package/_generated_protos/nested_opl/package/FileA.pbobjc.m",
+ "package/_generated_protos/nested_opl/package/dir/FileB.pbobjc.h",
+ "package/_generated_protos/nested_opl/package/dir/FileB.pbobjc.m");
+ }
+
+ @Test
+ public void testOutputsProtobufWithAutoUnionExperiment() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .doesNotContain("package/libopl_protobuf.a");
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.h",
+ "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.m",
+ "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.h",
+ "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.m",
+ "package/_generated_protos/opl_protobuf/dep/File.pbobjc.h");
+ }
+
+ @Test
+ public void testPB2GeneratedFileNames() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_pb2_special_names"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/opl_pb2_special_names/package/J2ObjcDescriptor.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/J2ObjcDescriptor.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/Http.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/Http.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/Https.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/Https.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/SomeUrlBlah.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/SomeUrlBlah.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/ThumbnailUrl.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/ThumbnailUrl.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/Url.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/Url.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/Url2Https.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/Url2Https.pb.m",
+ "package/_generated_protos/opl_pb2_special_names/package/Urlbar.pb.h",
+ "package/_generated_protos/opl_pb2_special_names/package/Urlbar.pb.m");
+ }
+
+ @Test
+ public void testProtobufGeneratedFileNames() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_special_names"));
+ String outputPath = "package/_generated_protos/opl_protobuf_special_names/package/";
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ outputPath + "J2ObjcDescriptor.pbobjc.h",
+ outputPath + "J2ObjcDescriptor.pbobjc.m",
+ outputPath + "HTTP.pbobjc.h",
+ outputPath + "HTTP.pbobjc.m",
+ outputPath + "HTTPS.pbobjc.h",
+ outputPath + "HTTPS.pbobjc.m",
+ outputPath + "SomeURLBlah.pbobjc.h",
+ outputPath + "SomeURLBlah.pbobjc.m",
+ outputPath + "ThumbnailURL.pbobjc.h",
+ outputPath + "ThumbnailURL.pbobjc.m",
+ outputPath + "URL.pbobjc.h",
+ outputPath + "URL.pbobjc.m",
+ outputPath + "URL2HTTPS.pbobjc.h",
+ outputPath + "URL2HTTPS.pbobjc.m",
+ outputPath + "Urlbar.pbobjc.h",
+ outputPath + "Urlbar.pbobjc.m");
+ }
+
+ @Test
+ public void testOutputsPB2WithWellKnownTypes() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_well_known_types"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/opl_well_known_types/package/FileA.pb.h",
+ "package/_generated_protos/opl_well_known_types/package/FileA.pb.m");
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsNoneOf(
+ "package/_generated_protos/opl_well_known_types/objcproto/WellKnownType.pb.h",
+ "package/_generated_protos/opl_well_known_types/objcproto/WellKnownType.pb.m");
+ }
+
+ @Test
+ public void testOutputsProtobufWithWellKnownTypes() throws Exception {
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_well_known_types"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/_generated_protos/opl_protobuf_well_known_types/package/FileA.pbobjc.h",
+ "package/_generated_protos/opl_protobuf_well_known_types/package/FileA.pbobjc.m");
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .doesNotContain(
+ "package/_generated_protos/opl_protobuf_well_known_types/objcproto/WellKnownType.pbobjc.h");
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .doesNotContain(
+ "package/_generated_protos/opl_protobuf_well_known_types/objcproto/WellKnownType.pbobjc.m");
+ }
+
+ @Test
+ public void testOutputsGenfile() throws Exception {
+ NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:gen_opl"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild))
+ .containsAllOf(
+ "package/libgen_opl.a",
+ "package/_generated_protos/gen_opl/package/FileAGenfile.pb.h",
+ "package/_generated_protos/gen_opl/package/FileAGenfile.pb.m");
+ }
+
+ @Test
+ public void testSourceGenerationAction() throws Exception {
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//package:opl")), "/FileA.pb.m");
+ SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile);
+
+ Artifact inputFileList =
+ ActionsTestUtil.getFirstArtifactEndingWith(action.getInputs(), "/_proto_input_files");
+
+ ImmutableList<String> protoInputs =
+ ImmutableList.of("dep/file.proto", "package/file_a.proto", "package/dir/file_b.proto");
+
+ assertThat(action.getArguments())
+ .containsExactly(
+ "/usr/bin/python",
+ "tools/objc/compile_protos.py",
+ "--input-file-list",
+ inputFileList.getExecPathString(),
+ "--output-dir",
+ // 2x parent directory because the package has one element ("package")
+ sourceFile.getExecPath().getParentDirectory().getParentDirectory().toString(),
+ "--working-dir", ".")
+ .inOrder();
+ assertRequiresDarwin(action);
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllOf(
+ "tools/objc/compile_protos.py",
+ "tools/objc/proto_support");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs);
+ assertThat(action.getInputs()).contains(inputFileList);
+
+ FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList);
+ assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs));
+ }
+
+ @Test
+ public void testProtobufSourceGenerationAction() throws Exception {
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf")), "/FileA.pbobjc.m");
+ SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile);
+
+ Artifact inputFileList =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ action.getInputs(), "/_proto_input_files_BundledProtos_0");
+
+ ImmutableList<String> protoInputs =
+ ImmutableList.of("dep/file.proto", "package/file_a.proto", "package/dir/file_b.proto");
+
+ BuildConfiguration topLevelConfig = getAppleCrosstoolConfiguration();
+ assertThat(action.getArguments())
+ .containsExactly(
+ "tools/objc/protobuf_compiler_wrapper.sh",
+ "--input-file-list",
+ inputFileList.getExecPathString(),
+ "--output-dir",
+ // 2x parent directory because the package has one element ("package")
+ sourceFile.getExecPath().getParentDirectory().getParentDirectory().toString(),
+ "--force",
+ "--proto-root-dir",
+ topLevelConfig.getGenfilesFragment().toString(),
+ "--proto-root-dir",
+ ".",
+ "--config",
+ "package/proto_filter.txt",
+ "--config",
+ "package/proto_filter2.txt",
+ "--config",
+ "package/proto_filter3.txt")
+ .inOrder();
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsAllOf(
+ "tools/objc/protobuf_compiler_wrapper.sh",
+ "tools/objc/protobuf_compiler_helper.py",
+ "tools/objc/proto_support");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs);
+ assertThat(action.getInputs()).contains(inputFileList);
+
+ FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList);
+ assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs));
+ }
+
+ @Test
+ public void testProtobufWithWellKnownTypesProtoListInput() throws Exception {
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_well_known_types")),
+ "/FileA.pbobjc.m");
+ SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile);
+
+ Artifact inputFileList =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ action.getInputs(), "/_proto_input_files_BundledProtos_0");
+
+ ImmutableList<String> protoInputs = ImmutableList.of("package/file_a.proto");
+
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs);
+ assertThat(action.getInputs()).contains(inputFileList);
+
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .contains("objcproto/well_known_type.proto");
+
+ FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList);
+ assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs));
+ }
+
+ @Test
+ public void testUseObjcHeaders() throws Exception {
+ scratch.file("objcheaderpackage/BUILD",
+ "objc_proto_library(",
+ " name = 'opl',",
+ " deps = ['//package:protolib'],",
+ " use_objc_header_names = 1,",
+ ")");
+
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(getConfiguredTarget("//objcheaderpackage:opl")), "/FileA.pb.m");
+ SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile);
+
+ assertThat(action.getArguments()).contains("--use-objc-header-names");
+
+ NestedSet<Artifact> filesToBuild =
+ getFilesToBuild(getConfiguredTarget("//objcheaderpackage:opl"));
+ assertThat(Artifact.toRootRelativePaths(filesToBuild)).containsAllOf(
+ "objcheaderpackage/_generated_protos/opl/package/FileA.pbobjc.h",
+ "objcheaderpackage/_generated_protos/opl/package/FileA.pb.m",
+ "objcheaderpackage/_generated_protos/opl/package/dir/FileB.pbobjc.h",
+ "objcheaderpackage/_generated_protos/opl/package/dir/FileB.pb.m"
+ );
+ }
+
+ @Test
+ public void testProtobufCompilationAction() throws Exception {
+ useConfiguration("--ios_cpu=i386");
+
+ ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf");
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.m");
+ SpawnAction generateAction = (SpawnAction) getGeneratingAction(sourceFile);
+
+ assertThat(generateAction).isNotNull();
+ }
+
+
+ @Test
+ public void testProtobufObjcProviderWithAutoUnionExperiment() throws Exception {
+ ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf");
+ Artifact headerFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.h");
+
+ ObjcProvider provider = providerForTarget("//package:opl_protobuf");
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet())
+ .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory());
+
+ assertThat(provider.get(ObjcProvider.LIBRARY).toSet())
+ .doesNotContain(getBinArtifact("libopl_protobuf.a", target));
+
+ assertThat(provider.get(ObjcProvider.HEADER).toSet()).contains(headerFile);
+ }
+
+ @Test
+ public void testPerProtoIncludes() throws Exception {
+ ConfiguredTarget target = getConfiguredTarget("//package:opl");
+ Artifact headerFile = ActionsTestUtil.getFirstArtifactEndingWith(
+ getFilesToBuild(target), "/FileA.pb.h");
+
+ ObjcProvider provider = providerForTarget("//package:opl");
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet()).containsExactly(
+ // 2x parent directory because the package has one element ("package")
+ headerFile.getExecPath().getParentDirectory().getParentDirectory()
+ );
+ }
+
+ @Test
+ public void testErrorForNoDepsAttribute() throws Exception {
+ checkError(
+ "x", "x", ProtoAttributes.NO_PROTOS_ERROR, "objc_proto_library(", " name = 'x',", ")");
+ }
+
+ @Test
+ public void testErrorForEmptyDepsAttribute() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.NO_PROTOS_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [],",
+ ")");
+ }
+
+ // This is a test for deprecated functionality.
+ @Test
+ public void testErrorForDepWithFilegroupWithoutProtoFiles() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.NO_PROTOS_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [':fg'],",
+ ")",
+ "filegroup(",
+ " name = 'fg',",
+ " srcs = ['file.dat'],",
+ ")");
+ }
+
+ @Test
+ public void testWarningForProtoSourceDeps() throws Exception {
+ checkWarning(
+ "x",
+ "x",
+ ProtoAttributes.FILES_DEPRECATED_WARNING,
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = ['foo.proto'],",
+ ")");
+ }
+
+ @Test
+ public void testWarningForFilegroupDeps() throws Exception {
+ checkWarning(
+ "x",
+ "x",
+ ProtoAttributes.FILES_DEPRECATED_WARNING,
+ "filegroup(",
+ " name = 'protos',",
+ " srcs = ['foo.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [':protos'],",
+ ")");
+ }
+
+ @Test
+ public void testObjcCopts() throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ List<String> args = compileAction("//package:opl", "FileA.pb.o").getArguments();
+ assertThat(args).contains("-foo");
+ }
+
+ @Test
+ public void testObjcCopts_argumentOrdering() throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ List<String> args = compileAction("//package:opl", "FileA.pb.o").getArguments();
+ assertThat(args).containsAllOf("-fno-objc-arc", "-foo").inOrder();
+ }
+
+ @Test
+ public void testErrorForPortableProtoFiltersEmpty() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.PORTABLE_PROTO_FILTERS_EMPTY_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " portable_proto_filters = [],",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['file.proto'],",
+ ")");
+ }
+
+ @Test
+ public void testErrorWhenDependingOnPB2FromProtobufTarget() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.PROTOCOL_BUFFERS2_IN_PROTOBUF_DEPS_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " portable_proto_filters = ['filter.pbascii'],",
+ " deps = [':pb2', ':protos_b'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'pb2',",
+ " deps = [':protos_a'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_a',",
+ " srcs = ['a.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_b',",
+ " srcs = ['b.proto'],",
+ ")");
+ }
+
+ @Test
+ public void testErrorWhenDependingOnPB2FromPB2Target() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.OBJC_PROTO_LIB_DEP_IN_PROTOCOL_BUFFERS2_DEPS_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " deps = [':pb2', ':protos_b'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'pb2',",
+ " deps = [':protos_a'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_a',",
+ " srcs = ['a.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_b',",
+ " srcs = ['b.proto'],",
+ ")");
+ }
+
+ @Test
+ public void testErrorForPortableProtoFiltersWithUseObjcHeaderNames() throws Exception {
+ checkErrorForPortableProtoFilterWithPb2Option("use_objc_header_names = 1");
+ }
+
+ @Test
+ public void testErrorForPortableProtoFiltersWithPerProtoIncludes() throws Exception {
+ checkErrorForPortableProtoFilterWithPb2Option("per_proto_includes = 1");
+ }
+
+ @Test
+ public void testErrorForPortableProtoFiltersWithOptionsFile() throws Exception {
+ checkErrorForPortableProtoFilterWithPb2Option("options_file = 'options_file.txt'");
+ }
+
+ @Test
+ public void testErrorForUsesProtobufWithUseObjcHeaderNames() throws Exception {
+ checkErrorForUsesProtobufWithPb2Option("use_objc_header_names = 1");
+ }
+
+ @Test
+ public void testErrorForUsesProtobufWithPerProtoIncludes() throws Exception {
+ checkErrorForUsesProtobufWithPb2Option("per_proto_includes = 1");
+ }
+
+ @Test
+ public void testErrorForUsesProtobufWithOptionsFile() throws Exception {
+ checkErrorForUsesProtobufWithPb2Option("options_file = 'options_file.txt'");
+ }
+
+ @Test
+ public void testModulemapCreatedForNonLinkingTargets() throws Exception {
+ checkOnlyLibModuleMapsArePresentForTarget("//package:opl_protobuf");
+ }
+
+ @Test
+ public void testModulemapNotCreatedForLinkingTargets() throws Exception {
+ checkOnlyLibModuleMapsArePresentForTarget("//package:opl_binary");
+ }
+
+ @Test
+ public void testErrorForPortableProtoFilterFilesInDeps() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.FILES_NOT_ALLOWED_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " portable_proto_filters = ['proto_filter.txt'],",
+ " deps = [':protos'],",
+ ")",
+ "filegroup(",
+ " name = 'protos',",
+ " srcs = ['file.proto'],",
+ ")");
+ }
+
+ @Test
+ public void testErrorForUsesProtobufAsFalseWithFilters() throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.USES_PROTOBUF_CANT_BE_SPECIFIED_AS_FALSE,
+ "objc_proto_library(",
+ " name = 'x',",
+ " uses_protobuf = 0,",
+ " portable_proto_filters = ['myfilter.pbascii'],",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['file.proto'],",
+ ")");
+ }
+
+ private void checkErrorForPortableProtoFilterWithPb2Option(String pb2Option) throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.PROTOBUF_ATTRIBUTES_NOT_EXCLUSIVE_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " portable_proto_filters = ['proto_filter.txt'],",
+ " " + pb2Option + ",",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['file.proto'],",
+ ")");
+ }
+
+ private void checkErrorForUsesProtobufWithPb2Option(String pb2Option) throws Exception {
+ checkError(
+ "x",
+ "x",
+ ProtoAttributes.PROTOBUF_ATTRIBUTES_NOT_EXCLUSIVE_ERROR,
+ "objc_proto_library(",
+ " name = 'x',",
+ " uses_protobuf = 1,",
+ " " + pb2Option + ",",
+ " deps = [':protos'],",
+ ")",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['file.proto'],",
+ ")");
+ }
+
+ private static String sortedJoin(Iterable<String> elements) {
+ return Joiner.on('\n').join(Ordering.natural().immutableSortedCopy(elements));
+ }
+
+ private void checkOnlyLibModuleMapsArePresentForTarget(String target) throws Exception {
+ Artifact libModuleMap =
+ getGenfilesArtifact(
+ "opl_protobuf.modulemaps/module.modulemap",
+ getConfiguredTarget("//package:opl_protobuf"));
+ Artifact protolibModuleMap =
+ getGenfilesArtifact(
+ "protobuf_lib.modulemaps/module.modulemap",
+ getConfiguredTarget("//objcproto:protobuf_lib"));
+
+ ObjcProvider provider = providerForTarget(target);
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.MODULE_MAP).toSet()))
+ .containsExactlyElementsIn(
+ Artifact.toRootRelativePaths(ImmutableSet.of(libModuleMap, protolibModuleMap)));
+ }
+
+ @Test
+ public void testObjcProvider() throws Exception {
+ ConfiguredTarget target = getConfiguredTarget("//package:opl");
+ Artifact headerFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pb.h");
+ Artifact sourceFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pb.m");
+
+ ObjcProvider provider = providerForTarget("//package:opl");
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet())
+ .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory());
+
+ ConfiguredTarget libProtoBufTarget = getConfiguredTarget("//objcproto:ProtocolBuffers_lib");
+ assertThat(provider.get(ObjcProvider.LIBRARY).toSet())
+ .containsExactly(
+ getBinArtifact("libopl.a", target),
+ getBinArtifact("libProtocolBuffers_lib.a", libProtoBufTarget));
+
+ assertThat(provider.get(ObjcProvider.HEADER).toSet()).containsAllOf(headerFile, sourceFile);
+
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet())
+ .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory());
+ }
+
+ @Test
+ public void testProtobufObjcProvider() throws Exception {
+ ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf");
+ Artifact headerFile =
+ ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.h");
+ ObjcProvider provider = providerForTarget("//package:opl_protobuf");
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet())
+ .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory());
+
+ ConfiguredTarget libProtoBufTarget = getConfiguredTarget("//objcproto:protobuf_lib");
+ assertThat(provider.get(ObjcProvider.LIBRARY).toSet())
+ .containsExactly(getBinArtifact("libprotobuf_lib.a", libProtoBufTarget));
+
+ assertThat(provider.get(ObjcProvider.HEADER).toSet()).contains(headerFile);
+
+ assertThat(provider.get(ObjcProvider.INCLUDE).toSet())
+ .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory());
+ }
+
+ @Test
+ public void testCompilationActionInCoverageMode() throws Exception {
+ useConfiguration("--collect_code_coverage");
+
+ ConfiguredTarget target = getConfiguredTarget("//package:opl");
+ CommandAction linkAction =
+ (CommandAction) getGeneratingAction(getBinArtifact("libopl.a", target));
+
+ CommandAction compileAction =
+ (CommandAction)
+ getGeneratingAction(
+ ActionsTestUtil.getFirstArtifactEndingWith(linkAction.getInputs(), "/FileA.pb.o"));
+
+ assertThat(Artifact.toRootRelativePaths(compileAction.getOutputs()))
+ .containsAllOf(
+ "package/_objs/opl/package/_generated_protos/opl/package/FileA.pb.o",
+ "package/_objs/opl/package/_generated_protos/opl/package/FileA.pb.gcno");
+ }
+
+ @Test
+ public void testModuleMapActionFiltersHeaders() throws Exception {
+ ConfiguredTarget configuredTarget = getConfiguredTarget("//package:opl");
+ Artifact moduleMap = getGenfilesArtifact("opl.modulemaps/module.modulemap", configuredTarget);
+
+ CppModuleMapAction genMap = (CppModuleMapAction) getGeneratingAction(moduleMap);
+ assertThat(Artifact.toRootRelativePaths(genMap.getPrivateHeaders())).isEmpty();
+ assertThat(Artifact.toRootRelativePaths(genMap.getPublicHeaders()))
+ .containsExactly(
+ "package/_generated_protos/opl/package/FileA.pb.h",
+ "package/_generated_protos/opl/package/dir/FileB.pb.h",
+ "package/_generated_protos/opl/dep/File.pb.h");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProviderTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProviderTest.java
new file mode 100644
index 0000000000..031a9516bd
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoProviderTest.java
@@ -0,0 +1,95 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link ObjcProvider}. */
+@RunWith(JUnit4.class)
+public class ObjcProtoProviderTest extends BuildViewTestCase {
+
+ @Before
+ public final void setup() throws Exception {
+ // Empty target just so artifacts can be created.
+ scratch.file("x/BUILD",
+ "objc_library(",
+ " name = 'x',",
+ ")");
+ }
+
+ @Test
+ public void emptyProvider() {
+ ObjcProtoProvider empty = new ObjcProtoProvider.Builder().build();
+ assertThat(empty.getProtoGroups()).isEmpty();
+ }
+
+ @Test
+ public void onlyPropagatesProvider() throws Exception {
+ Artifact foo = getTestArtifact("foo");
+ ObjcProtoProvider onlyPropagates =
+ new ObjcProtoProvider.Builder()
+ .addProtoGroup(NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER, foo))
+ .build();
+ assertThat(Iterables.concat(onlyPropagates.getProtoGroups())).containsExactly(foo);
+ }
+
+ @Test
+ public void propagatesThroughDependers() throws Exception {
+ Artifact foo = getTestArtifact("foo");
+ Artifact bar = getTestArtifact("bar");
+ Artifact baz = getTestArtifact("baz");
+ Artifact header = getTestArtifact("protobuf");
+ PathFragment searchPath = header.getExecPath().getParentDirectory();
+
+ ObjcProtoProvider base1 =
+ new ObjcProtoProvider.Builder()
+ .addProtoGroup(NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER, foo))
+ .addPortableProtoFilters(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER, baz))
+ .addProtobufHeaders(NestedSetBuilder.<Artifact>create(Order.STABLE_ORDER, header))
+ .build();
+
+ ObjcProtoProvider base2 =
+ new ObjcProtoProvider.Builder()
+ .addProtoGroup(NestedSetBuilder.<Artifact>create(Order.NAIVE_LINK_ORDER, bar))
+ .addProtobufHeaderSearchPaths(
+ NestedSetBuilder.<PathFragment>create(Order.LINK_ORDER, searchPath))
+ .build();
+
+ ObjcProtoProvider depender =
+ new ObjcProtoProvider.Builder().addTransitive(ImmutableList.of(base1, base2)).build();
+ assertThat(Iterables.concat(depender.getProtoGroups())).containsExactly(foo, bar);
+ assertThat(depender.getPortableProtoFilters()).containsExactly(baz);
+ assertThat(depender.getProtobufHeaders()).containsExactly(header);
+ assertThat(depender.getProtobufHeaderSearchPaths()).containsExactly(searchPath);
+ }
+
+ private Artifact getTestArtifact(String name) throws Exception {
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ return getBinArtifact(name, target);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java
new file mode 100644
index 0000000000..2b7f3fe6a3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProviderTest.java
@@ -0,0 +1,159 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.rules.objc.ObjcProvider.Key;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for {@link ObjcProvider}. */
+@RunWith(JUnit4.class)
+public class ObjcProviderTest {
+
+ @Test
+ public void emptyProvider() {
+ ObjcProvider empty = new ObjcProvider.Builder().build();
+ assertThat(empty.get(ObjcProvider.SDK_DYLIB)).isEmpty();
+ }
+
+ @Test
+ public void onlyPropagatesProvider() {
+ ObjcProvider onlyPropagates = new ObjcProvider.Builder()
+ .add(ObjcProvider.SDK_DYLIB, "foo")
+ .build();
+ assertThat(onlyPropagates.get(ObjcProvider.SDK_DYLIB)).containsExactly("foo");
+ }
+
+ @Test
+ public void onlyNonPropagatesProvider() {
+ ObjcProvider dep = new ObjcProvider.Builder()
+ .add(ObjcProvider.SDK_DYLIB, "foo")
+ .build();
+ ObjcProvider notPropagates = new ObjcProvider.Builder()
+ .addTransitiveWithoutPropagating(ImmutableList.of(dep))
+ .build();
+ assertThat(notPropagates.get(ObjcProvider.SDK_DYLIB)).containsExactly("foo");
+ }
+
+ @Test
+ public void propagatesAndNonPropagatesProvider() {
+ ObjcProvider dep = new ObjcProvider.Builder()
+ .add(ObjcProvider.SDK_DYLIB, "foo")
+ .build();
+ ObjcProvider provider = new ObjcProvider.Builder()
+ .addTransitiveWithoutPropagating(ImmutableList.of(dep))
+ .add(ObjcProvider.SDK_DYLIB, "bar")
+ .build();
+ assertThat(provider.get(ObjcProvider.SDK_DYLIB)).containsExactly("foo", "bar").inOrder();
+ }
+
+ @Test
+ public void doesNotPropagate() {
+ ObjcProvider dep = new ObjcProvider.Builder()
+ .add(ObjcProvider.SDK_DYLIB, "foo")
+ .build();
+ ObjcProvider provider = new ObjcProvider.Builder()
+ .addTransitiveWithoutPropagating(ImmutableList.of(dep))
+ .add(ObjcProvider.SDK_DYLIB, "bar")
+ .build();
+ ObjcProvider depender = new ObjcProvider.Builder()
+ .addTransitiveAndPropagate(provider)
+ .build();
+ assertThat(depender.get(ObjcProvider.SDK_DYLIB)).containsExactly("bar");
+ }
+
+ @Test
+ public void strictDependencyDoesNotPropagateMoreThanOneLevel() {
+ PathFragment strictInclude = PathFragment.create("strict_path");
+ PathFragment propagatedInclude = PathFragment.create("propagated_path");
+
+ ObjcProvider strictDep =
+ new ObjcProvider.Builder()
+ .addForDirectDependents(ObjcProvider.INCLUDE, strictInclude)
+ .build();
+ ObjcProvider propagatedDep =
+ new ObjcProvider.Builder().add(ObjcProvider.INCLUDE, propagatedInclude).build();
+
+ ObjcProvider provider =
+ new ObjcProvider.Builder()
+ .addTransitiveAndPropagate(ImmutableList.of(strictDep, propagatedDep))
+ .build();
+ ObjcProvider depender = new ObjcProvider.Builder().addTransitiveAndPropagate(provider).build();
+
+ assertThat(provider.get(ObjcProvider.INCLUDE))
+ .containsExactly(strictInclude, propagatedInclude);
+ assertThat(depender.get(ObjcProvider.INCLUDE)).containsExactly(propagatedInclude);
+ }
+
+ @Test
+ public void strictDependencyDoesNotPropagateMoreThanOneLevelOnSkylark() {
+ PathFragment strictInclude = PathFragment.create("strict_path");
+ PathFragment propagatedInclude = PathFragment.create("propagated_path");
+
+ ObjcProvider strictDep =
+ new ObjcProvider.Builder()
+ .addForDirectDependents(ObjcProvider.INCLUDE, strictInclude)
+ .build();
+ ObjcProvider propagatedDep =
+ new ObjcProvider.Builder().add(ObjcProvider.INCLUDE, propagatedInclude).build();
+
+ ObjcProvider provider =
+ new ObjcProvider.Builder()
+ .addTransitiveAndPropagate(ImmutableList.of(strictDep, propagatedDep))
+ .build();
+ ObjcProvider depender = new ObjcProvider.Builder().addTransitiveAndPropagate(provider).build();
+
+ assertThat(
+ ((SkylarkNestedSet) provider.getValue(ObjcProvider.INCLUDE.getSkylarkKeyName()))
+ .toCollection())
+ .containsExactly(strictInclude.toString(), propagatedInclude.toString());
+ assertThat(
+ ((SkylarkNestedSet) depender.getValue(ObjcProvider.INCLUDE.getSkylarkKeyName()))
+ .toCollection())
+ .containsExactly(propagatedInclude.toString());
+ }
+
+ @Test
+ public void keysExportedToSkylark() throws Exception {
+ List<Field> keyFields = new ArrayList<>();
+ for (Field field : ObjcProvider.class.getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers()) && field.getType() == ObjcProvider.Key.class) {
+ keyFields.add(field);
+ }
+ }
+ ImmutableSet<Key<?>> allRegisteredKeys = ImmutableSet.<Key<?>>builder()
+ .addAll(ObjcProvider.KEYS_FOR_SKYLARK)
+ .addAll(ObjcProvider.KEYS_NOT_IN_SKYLARK)
+ .build();
+
+ for (Field field : keyFields) {
+ ObjcProvider.Key<?> key = (Key<?>) field.get(null);
+ assertWithMessage("Key %s must either be exposed to skylark or explicitly blacklisted",
+ key.getSkylarkKeyName()).that(allRegisteredKeys).contains(key);
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
new file mode 100644
index 0000000000..2fb8a81a48
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcRuleTestCase.java
@@ -0,0 +1,4852 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.baseArtifactNames;
+import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+import static com.google.devtools.build.lib.rules.objc.LegacyCompilationSupport.AUTOMATIC_SDK_FRAMEWORKS;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.GENERAL_RESOURCE_FILE;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.HEADER;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.INCLUDE;
+import static com.google.devtools.build.lib.rules.objc.ObjcProvider.STORYBOARD;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.FAMILIES_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.BundlingRule.INFOPLIST_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.CLANG;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.CLANG_PLUSPLUS;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.DSYMUTIL;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.LIPO;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.BUNDLE_ID_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.ENTITLEMENTS_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.PROVISIONING_PROFILE_ATTR;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.SRCS_TYPE;
+import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.STRIP;
+import static com.google.devtools.build.lib.rules.objc.ReleaseBundlingSupport.NO_ASSET_CATALOG_ERROR_FORMAT;
+import static org.junit.Assert.fail;
+
+import com.dd.plist.NSDictionary;
+import com.dd.plist.PropertyListParser;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.ListMultimap;
+import com.google.common.collect.Multiset;
+import com.google.devtools.build.lib.actions.Action;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.actions.ExecutionInfoSpecifier;
+import com.google.devtools.build.lib.actions.ExecutionRequirements;
+import com.google.devtools.build.lib.actions.FailAction;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.FileProvider;
+import com.google.devtools.build.lib.analysis.FilesToRunProvider;
+import com.google.devtools.build.lib.analysis.OutputGroupProvider;
+import com.google.devtools.build.lib.analysis.RunfilesSupport;
+import com.google.devtools.build.lib.analysis.actions.BinaryFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
+import com.google.devtools.build.lib.analysis.actions.FileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction;
+import com.google.devtools.build.lib.analysis.actions.TemplateExpansionAction.Substitution;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.analysis.config.BuildOptions;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.Attribute.SplitTransition;
+import com.google.devtools.build.lib.packages.util.MockJ2ObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import com.google.devtools.build.lib.rules.apple.AppleCommandLineOptions;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration.ConfigurationDistinguisher;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.rules.apple.Platform;
+import com.google.devtools.build.lib.rules.apple.Platform.PlatformType;
+import com.google.devtools.build.lib.rules.apple.XcodeVersionProperties;
+import com.google.devtools.build.lib.rules.cpp.CppLinkAction;
+import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.Control;
+import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.MergeZip;
+import com.google.devtools.build.xcode.plmerge.proto.PlMergeProtos;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import org.junit.Before;
+
+/**
+ * Superclass for all Obj-C rule tests.
+ *
+ * <p>TODO(matvore): split this up into more helper classes, especially the check... methods, which
+ * are many and not shared by all objc_ rules.
+ * <p>TODO(matvore): find a more concise way to repeat common tests (in particular, those which
+ * simply call a check... method) across several rule types.
+ */
+public abstract class ObjcRuleTestCase extends BuildViewTestCase {
+ protected static final String MOCK_ACTOOLWRAPPER_PATH = "tools/objc/actoolwrapper";
+ protected static final String MOCK_IBTOOLWRAPPER_PATH = "tools/objc/ibtoolwrapper";
+ protected static final String MOCK_BUNDLEMERGE_PATH = "tools/objc/bundlemerge";
+ protected static final String MOCK_MOMCWRAPPER_PATH = "tools/objc/momcwrapper";
+ protected static final String MOCK_SWIFTSTDLIBTOOLWRAPPER_PATH =
+ "tools/objc/swiftstdlibtoolwrapper";
+ protected static final String MOCK_LIBTOOL_PATH = "tools/objc/libtool";
+ protected static final String MOCK_XCRUNWRAPPER_PATH = "tools/objc/xcrunwrapper";
+ protected static final ImmutableList<String> FASTBUILD_COPTS =
+ ImmutableList.of("-O0", "-DDEBUG=1");
+
+ protected static final DottedVersion DEFAULT_IOS_SDK_VERSION =
+ DottedVersion.fromString(AppleCommandLineOptions.DEFAULT_IOS_SDK_VERSION);
+
+ private String artifactPrefix;
+
+ /**
+ * Returns the configuration obtained by applying the apple crosstool configuration transtion to
+ * this {@code BuildViewTestCase}'s target configuration.
+ */
+ protected BuildConfiguration getAppleCrosstoolConfiguration() throws InterruptedException {
+ return getConfiguration(targetConfig, AppleCrosstoolTransition.APPLE_CROSSTOOL_TRANSITION);
+ }
+
+ /** Specification of code coverage behavior. */
+ public enum CodeCoverageMode {
+ // No code coverage information.
+ NONE,
+ // Code coverage in gcov format.
+ GCOV,
+ // Code coverage in llvm-covmap format.
+ LLVMCOV;
+ }
+
+ /**
+ * Returns the bin dir for artifacts built for a given Apple architecture and minimum OS
+ * version (as set by a configuration transition) and configuration distinguisher but the global
+ * default for {@code --cpu}.
+ *
+ * @param arch the given Apple architecture which artifacts are built under this configuration.
+ * Note this will likely be different than the value of {@code --cpu}.
+ * @param configurationDistinguisher the configuration distinguisher used to describe the
+ * a configuration transition
+ * @param minOsVersion the minimum os version for which to compile artifacts in the
+ * configuration
+ */
+ protected String configurationBin(
+ String arch, ConfigurationDistinguisher configurationDistinguisher,
+ DottedVersion minOsVersion) {
+ return configurationDir(arch, configurationDistinguisher, minOsVersion) + "bin/";
+ }
+
+ /**
+ * Returns the genfiles dir for artifacts built for a given Apple architecture and minimum OS
+ * version (as set by a configuration transition) and configuration distinguisher but the global
+ * default for {@code --cpu}.
+ *
+ * @param arch the given Apple architecture which artifacts are built under this configuration.
+ * Note this will likely be different than the value of {@code --cpu}.
+ * @param configurationDistinguisher the configuration distinguisher used to describe the
+ * a configuration transition
+ * @param minOsVersion the minimum os version for which to compile artifacts in the
+ * configuration
+ */
+ protected String configurationGenfiles(
+ String arch, ConfigurationDistinguisher configurationDistinguisher,
+ DottedVersion minOsVersion) {
+ return configurationDir(arch, configurationDistinguisher, minOsVersion) + "genfiles";
+ }
+
+ private String configurationDir(
+ String arch, ConfigurationDistinguisher configurationDistinguisher,
+ DottedVersion minOsVersion) {
+ switch (configurationDistinguisher) {
+ case UNKNOWN:
+ return String.format("blaze-out/ios_%s-fastbuild/", arch);
+ case IOS_EXTENSION: // Intentional fall-through.
+ case IOS_APPLICATION:
+ case WATCH_OS1_EXTENSION:
+ case APPLEBIN_IOS:
+ return String.format("blaze-out/ios-%1$s-min%3$s-%2$s-ios_%1$s-fastbuild/",
+ arch, configurationDistinguisher.toString().toLowerCase(Locale.US), minOsVersion);
+ case APPLEBIN_WATCHOS:
+ return String.format("blaze-out/watchos-%1$s-min%3$s-%2$s-watchos_%1$s-fastbuild/",
+ arch, configurationDistinguisher.toString().toLowerCase(Locale.US), minOsVersion);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the bin dir for artifacts built for a given Apple architecture (as set by a
+ * configuration transition) and configuration distinguisher but the global default for
+ * {@code --cpu} and the platform default for minimum OS.
+ *
+ * @param arch the given Apple architecture which artifacts are built under this configuration.
+ * Note this will likely be different than the value of {@code --cpu}
+ * @param configurationDistinguisher the configuration distinguisher used to describe the
+ * a configuration transition
+ */
+ protected String configurationBin(
+ String arch, ConfigurationDistinguisher configurationDistinguisher) {
+ return configurationBin(arch, configurationDistinguisher,
+ defaultMinimumOs(configurationDistinguisher));
+ }
+
+ /**
+ * Returns the bin dir for artifacts with the given iOS architecture as set through {@code --cpu}
+ * and configuration distinguisher, assuming {@code --ios_multi_cpus} isn't set.
+ */
+ protected static String iosConfigurationCcDepsBin(
+ String arch, ConfigurationDistinguisher configurationDistinguisher) {
+ switch (configurationDistinguisher) {
+ case IOS_EXTENSION:
+ case WATCH_OS1_EXTENSION:
+ case APPLEBIN_IOS:
+ return String.format("blaze-out/%s-ios_%s-fastbuild/bin/",
+ configurationDistinguisher.toString().toLowerCase(Locale.US), arch);
+ case UNKNOWN: // Intentional fall-through.
+ case IOS_APPLICATION:
+ return String.format("blaze-out/ios_%s-fastbuild/bin/", arch);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the default minimum os version that dependencies under a given configuration
+ * distinguisher (and thus a given platform type) will be compiled for.
+ */
+ protected static DottedVersion defaultMinimumOs(
+ ConfigurationDistinguisher configurationDistinguisher) {
+ switch (configurationDistinguisher) {
+ case UNKNOWN:
+ case IOS_EXTENSION:
+ return IosExtension.EXTENSION_MINIMUM_OS_VERSION;
+ case IOS_APPLICATION:
+ case APPLEBIN_IOS:
+ return DEFAULT_IOS_SDK_VERSION;
+ case WATCH_OS1_EXTENSION:
+ return WatchUtils.MINIMUM_OS_VERSION;
+ case APPLEBIN_WATCHOS:
+ return DottedVersion.fromString(XcodeVersionProperties.DEFAULT_WATCHOS_SDK_VERSION);
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Returns the genfiles dir for iOS builds in the root architecture.
+ */
+ protected static String rootConfigurationGenfiles() {
+ return "blaze-out/gcc-4.4.0-glibc-2.3.6-grte-k8-fastbuild/genfiles/";
+ }
+
+ protected String execPathEndingWith(Iterable<Artifact> artifacts, String suffix) {
+ return getFirstArtifactEndingWith(artifacts, suffix).getExecPathString();
+ }
+
+ @Before
+ public final void initializeMockToolsConfig() throws Exception {
+ MockObjcSupport.setup(mockToolsConfig);
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+ }
+
+ protected static String frameworkDir(ConfiguredTarget target) {
+ AppleConfiguration configuration =
+ target.getConfiguration().getFragment(AppleConfiguration.class);
+ return frameworkDir(configuration.getSingleArchPlatform());
+ }
+
+ protected static String frameworkDir(Platform platform) {
+ return AppleToolchain.platformDir(
+ platform.getNameInPlist()) + AppleToolchain.DEVELOPER_FRAMEWORK_PATH;
+ }
+
+ /**
+ * Creates an {@code objc_library} target writer for the label indicated by the given String.
+ */
+ protected ScratchAttributeWriter createLibraryTargetWriter(String labelString) {
+ return ScratchAttributeWriter.fromLabelString(this, "objc_library", labelString);
+ }
+
+ /**
+ * Creates an {@code objc_binary} target writer for the label indicated by the given String.
+ */
+ protected ScratchAttributeWriter createBinaryTargetWriter(String labelString) {
+ return ScratchAttributeWriter.fromLabelString(this, "objc_binary", labelString);
+ }
+
+ private static String compilationModeFlag(CompilationMode mode) {
+ switch (mode) {
+ case DBG:
+ return "dbg";
+ case OPT:
+ return "opt";
+ case FASTBUILD:
+ return "fastbuild";
+ }
+ throw new AssertionError();
+ }
+
+ private static List<String> compilationModeCopts(CompilationMode mode) {
+ switch (mode) {
+ case DBG:
+ return ImmutableList.<String>builder()
+ .addAll(ObjcConfiguration.DBG_COPTS)
+ .addAll(ObjcConfiguration.GLIBCXX_DBG_COPTS)
+ .build();
+ case OPT:
+ return ObjcConfiguration.OPT_COPTS;
+ case FASTBUILD:
+ return FASTBUILD_COPTS;
+ }
+ throw new AssertionError();
+ }
+
+ protected static String listAttribute(String name, Iterable<String> values) {
+ StringBuilder result = new StringBuilder();
+ for (String value : values) {
+ if (result.length() == 0) {
+ result.append(name).append(" = [");
+ }
+ result.append(String.format("'%s',", value));
+ }
+ if (result.length() != 0) {
+ result.append("],");
+ }
+ return result.toString();
+ }
+
+ /** Returns the treatment of the crosstool for this test case. */
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.ALL;
+ }
+
+ @Override
+ protected void useConfiguration(String... args) throws Exception {
+ // By default, objc tests assume the case of --experimental_objc_crosstool=all. The "Legacy"
+ // subclasses explicitly override to test --experimental_objc_crosstool=off.
+ useConfiguration(getObjcCrosstoolMode(), args);
+ }
+
+ protected void useConfiguration(ObjcCrosstoolMode objcCrosstoolMode, String... args)
+ throws Exception {
+ ImmutableList.Builder<String> extraArgsBuilder = ImmutableList.builder();
+ if (objcCrosstoolMode != ObjcCrosstoolMode.OFF) {
+ String crosstoolModeFlag =
+ objcCrosstoolMode == ObjcCrosstoolMode.ALL
+ ? "--experimental_objc_crosstool=all"
+ : "--experimental_objc_crosstool=library";
+ extraArgsBuilder.add(crosstoolModeFlag);
+ }
+ extraArgsBuilder
+ .add("--experimental_disable_go")
+ .add("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+
+ ImmutableList<String> extraArgs = extraArgsBuilder.build();
+ args = Arrays.copyOf(args, args.length + extraArgs.size());
+ for (int i = 0; i < extraArgs.size(); i++) {
+ args[(args.length - extraArgs.size()) + i] = extraArgs.get(i);
+ }
+
+ super.useConfiguration(args);
+ }
+
+ /**
+ * @param extraAttributes individual strings which contain a whole attribute to be added to the
+ * generated target, e.g. "deps = ['foo']"
+ */
+ protected ConfiguredTarget addBinaryBasedTarget(
+ String ruleType,
+ String packageName,
+ String targetName,
+ List<String> srcs,
+ List<String> deps,
+ String... extraAttributes)
+ throws Exception {
+ for (String source : srcs) {
+ scratch.file(String.format("%s/%s", packageName, source));
+ }
+ scratch.file(String.format("%s/BUILD", packageName),
+ ruleType + "(name = '" + targetName + "',",
+ listAttribute("srcs", srcs),
+ listAttribute("deps", deps),
+ Joiner.on(",\n").join(extraAttributes),
+ ")");
+ return getConfiguredTarget(String.format("//%s:%s", packageName, targetName));
+ }
+
+ /**
+ * @param extraAttributes individual strings which contain a whole attribute to be added to the
+ * generated target, e.g. "deps = ['foo']"
+ */
+ protected ConfiguredTarget addSimpleIosTest(
+ String packageName,
+ String targetName,
+ List<String> srcs,
+ List<String> deps,
+ String... extraAttributes)
+ throws Exception {
+ return addBinaryBasedTarget(
+ "ios_test", packageName, targetName, srcs, deps, extraAttributes);
+ }
+
+ /**
+ * Returns the arguments to pass to clang for specifying module map artifact location and
+ * module name.
+ *
+ * @param packagePath the path to the package this target is in
+ * @param targetName the name of the target
+ */
+ protected List<String> moduleMapArtifactArguments(String packagePath, String targetName) {
+ Artifact moduleMapArtifact =
+ getGenfilesArtifact(
+ targetName + ".modulemaps/module.modulemap", packagePath + ":" + targetName);
+ String moduleName = packagePath.replace("//", "").replace("/", "_") + "_" + targetName;
+
+ return ImmutableList.of("-iquote",
+ moduleMapArtifact.getExecPath().getParentDirectory().toString(),
+ "-fmodule-name=" + moduleName);
+ }
+
+ /**
+ * Returns all child configurations resulting from a given split transition on a given
+ * configuration.
+ */
+ protected List<BuildConfiguration> getSplitConfigurations(BuildConfiguration configuration,
+ SplitTransition<BuildOptions> splitTransition) throws InterruptedException {
+ ImmutableList.Builder<BuildConfiguration> splitConfigs = ImmutableList.builder();
+
+ for (BuildOptions splitOptions : splitTransition.split(configuration.getOptions())) {
+ splitConfigs.add(getSkyframeExecutor().getConfigurationForTesting(
+ reporter, configuration.fragmentClasses(), splitOptions));
+ }
+
+ return splitConfigs.build();
+ }
+
+ protected void checkLinkActionCorrect(RuleType ruleType, ExtraLinkArgs extraLinkArgs)
+ throws Exception {
+ useConfiguration(
+ "--cpu=ios_i386",
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go");
+
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']", "deps", "['//lib1:lib1', '//lib2:lib2']");
+ CommandAction action = linkAction("//x:x");
+ assertRequiresDarwin(action);
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsAllOf("x/libx.a", "lib1/liblib1.a", "lib2/liblib2.a", "x/x-linker.objlist");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x_bin");
+
+ verifyLinkAction(Iterables.getOnlyElement(action.getOutputs()),
+ getBinArtifact("x-linker.objlist", "//x:x"), "i386",
+ ImmutableList.of("libx.a", "liblib1.a", "liblib2.a"), ImmutableList.<PathFragment>of(),
+ extraLinkArgs);
+ }
+
+ // Regression test for b/29094356.
+ protected void checkLinkActionDuplicateInputs(RuleType ruleType, ExtraLinkArgs extraLinkArgs)
+ throws Exception {
+ useConfiguration(
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("lib/BUILD",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ " deps = ['//lib2:lib2'],",
+ ")");
+
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.m']", "deps", "['//lib:cclib', '//lib1:lib1', '//lib2:lib2']");
+ CommandAction action = linkAction("//x:x");
+ assertRequiresDarwin(action);
+
+ verifyObjlist(action, "x-linker.objlist",
+ execPathEndingWith(action.getInputs(), "x/libx.a"),
+ execPathEndingWith(action.getInputs(), "lib2/liblib2.a"),
+ execPathEndingWith(action.getInputs(), "lib1/liblib1.a"),
+ execPathEndingWith(action.getInputs(), "lib/libcclib.a"));
+ }
+
+ /**
+ * Verifies a {@code -filelist} file's contents.
+ *
+ * @param originalAction the action which uses the filelist artifact
+ * @param objlistName the path suffix of the filelist artifact
+ * @param inputArchives path suffixes of the expected contents of the filelist
+ */
+ protected void verifyObjlist(Action originalAction, String objlistName,
+ String... inputArchives) {
+ Artifact filelistArtifact =
+ getFirstArtifactEndingWith(originalAction.getInputs(), objlistName);
+
+ ParameterFileWriteAction fileWriteAction =
+ (ParameterFileWriteAction) getGeneratingAction(filelistArtifact);
+ ImmutableList.Builder<String> execPaths = ImmutableList.builder();
+ for (String inputArchive : inputArchives) {
+ execPaths.add(execPathEndingWith(originalAction.getInputs(), inputArchive));
+ }
+
+ assertThat(fileWriteAction.getContents()).containsExactlyElementsIn(execPaths.build());
+ }
+
+ /**
+ * Verifies a link action is registered correctly.
+ *
+ * @param binArtifact the output artifact which a link action should be registered to generate
+ * @param filelistArtifact the input filelist artifact
+ * @param arch the architecture (for example, "i386") which the binary is to be created for
+ * @param inputArchives the suffixes (basenames or relative paths with basenames) of the input
+ * archive files for the link action
+ * @param importedFrameworks custom framework path fragments
+ * @param extraLinkArgs extra link arguments expected on the link action
+ */
+ protected void verifyLinkAction(Artifact binArtifact, Artifact filelistArtifact, String arch,
+ List<String> inputArchives, List<PathFragment> importedFrameworks,
+ ExtraLinkArgs extraLinkArgs) {
+ final CommandAction binAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ for (String inputArchive : inputArchives) {
+ // Verify each input archive is present in the action inputs.
+ getFirstArtifactEndingWith(binAction.getInputs(), inputArchive);
+ }
+ ImmutableList.Builder<String> frameworkPathFragmentParents = ImmutableList.builder();
+ ImmutableList.Builder<String> frameworkPathBaseNames = ImmutableList.builder();
+ for (PathFragment importedFramework : importedFrameworks) {
+ frameworkPathFragmentParents.add(importedFramework.getParentDirectory().toString());
+ frameworkPathBaseNames.add(importedFramework.getBaseName());
+ }
+
+ ImmutableList<String> expectedCommandLineFragments = ImmutableList.<String>builder()
+ .add("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .add("-arch " + arch)
+ .add("-isysroot " + AppleToolchain.sdkDir())
+ .add(AppleToolchain.sdkDir() + AppleToolchain.DEVELOPER_FRAMEWORK_PATH)
+ .add(frameworkDir(Platform.forTarget(PlatformType.IOS, arch)))
+ .addAll(frameworkPathFragmentParents.build())
+ .add("-Xlinker -objc_abi_version -Xlinker 2")
+ .add("-Xlinker -rpath -Xlinker @executable_path/Frameworks")
+ .add("-fobjc-link-runtime")
+ .add("-ObjC")
+ .addAll(
+ Interspersing.beforeEach(
+ "-framework", SdkFramework.names(AUTOMATIC_SDK_FRAMEWORKS)))
+ .addAll(
+ Interspersing.beforeEach(
+ "-framework", frameworkPathBaseNames.build()))
+ .add("-filelist")
+ .add(filelistArtifact.getExecPathString())
+ .add("-o")
+ .addAll(Artifact.toExecPaths(binAction.getOutputs()))
+ .addAll(extraLinkArgs)
+ .build();
+
+ String linkArgs = Joiner.on(" ").join(binAction.getArguments());
+ for (String expectedCommandLineFragment : expectedCommandLineFragments) {
+ assertThat(linkArgs).contains(expectedCommandLineFragment);
+ }
+ }
+
+ protected void checkLinkActionWithTransitiveCppDependency(
+ RuleType ruleType, ExtraLinkArgs extraLinkArgs) throws Exception {
+
+ createLibraryTargetWriter("//lib1:lib1").setAndCreateFiles("srcs", "a.mm").write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("deps", "//lib1")
+ .write();
+
+ scratch.file("x/c.m");
+ ruleType.scratchTarget(scratch, "srcs", "['c.m']", "deps", "['//lib2:lib2']");
+
+ CommandAction action = linkAction("//x:x");
+ assertThat(action.getArguments().get(2))
+ .startsWith(
+ MOCK_XCRUNWRAPPER_PATH + " " + CLANG_PLUSPLUS + " -stdlib=libc++ -std=gnu++11");
+ }
+
+ protected Map<String, String> mobileProvisionProfiles(BundleMergeProtos.Control control) {
+ Map<String, String> profiles = new HashMap<>();
+ for (BundleFile bundleFile : control.getBundleFileList()) {
+ if (bundleFile.getBundlePath()
+ .endsWith(ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE)) {
+ assertWithMessage("Should not have multiple entries for same source file")
+ .that(profiles.put(bundleFile.getSourceFile(), bundleFile.getBundlePath()))
+ .isNull();
+ }
+ }
+ return profiles;
+ }
+
+ protected void checkFilesToRun(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ FilesToRunProvider filesToRun = target.getProvider(FilesToRunProvider.class);
+ assertThat(filesToRun.getExecutable().getRootRelativePathString())
+ .isEqualTo("x/x_runner.sh");
+ RunfilesSupport runfilesSupport = filesToRun.getRunfilesSupport();
+ assertThat(Artifact.toRootRelativePaths(runfilesSupport.getRunfiles().getArtifacts()))
+ .containsExactly(
+ "x/x.ipa",
+ "x/x_runner.sh",
+ "tools/objc/StdRedirect.dylib");
+ }
+
+ protected void assertAppleSdkVersionEnv(Map<String, String> env) throws Exception {
+ assertAppleSdkVersionEnv(env, DEFAULT_IOS_SDK_VERSION);
+ }
+
+ protected void assertAppleSdkVersionEnv(Map<String, String> env, DottedVersion versionNumber)
+ throws Exception {
+ assertThat(env).containsEntry("APPLE_SDK_VERSION_OVERRIDE", versionNumber.toString());
+ }
+
+ protected void assertAppleSdkPlatformEnv(
+ Map<String, String> env, String platformName) throws Exception {
+ assertThat(env).containsEntry("APPLE_SDK_PLATFORM", platformName);
+ }
+
+ protected void assertAppleSdkVersionEnv(CommandAction action) throws Exception {
+ assertAppleSdkVersionEnv(action, DEFAULT_IOS_SDK_VERSION.toString());
+ }
+
+ protected void assertAppleSdkVersionEnv(CommandAction action, String versionString)
+ throws Exception {
+ assertThat(action.getEnvironment())
+ .containsEntry("APPLE_SDK_VERSION_OVERRIDE", versionString);
+ }
+
+ protected void assertAppleSdkPlatformEnv(CommandAction action, String platformName)
+ throws Exception {
+ assertThat(action.getEnvironment()).containsEntry("APPLE_SDK_PLATFORM", platformName);
+ }
+
+ protected void assertXcodeVersionEnv(CommandAction action, String versionNumber)
+ throws Exception {
+ assertThat(action.getEnvironment()).containsEntry("XCODE_VERSION_OVERRIDE", versionNumber);
+ }
+
+ protected void checkNoRunfilesSupportForDevice(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ ruleType.scratchTarget(scratch);
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ FilesToRunProvider filesToRun = target.getProvider(FilesToRunProvider.class);
+ assertThat(filesToRun.getRunfilesSupport()).isNull();
+ }
+
+ protected void checkGenerateRunnerScriptAction(RuleType ruleType) throws Exception {
+ useConfiguration(
+ "--cpu=ios_i386", "--ios_simulator_device=iPhone X", "--ios_simulator_version=3");
+
+ ruleType.scratchTarget(scratch);
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Artifact runnerScript = getBinArtifact("x_runner.sh", target);
+ TemplateExpansionAction action = (TemplateExpansionAction) getGeneratingAction(runnerScript);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("ios_runner.sh.mac_template");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x_runner.sh");
+ assertThat(action.getSubstitutions())
+ .containsExactly(
+ Substitution.of("%ipa_file%", "x/x.ipa"),
+ Substitution.of("%sim_device%", "'iPhone X'"),
+ Substitution.of("%sdk_version%", "3"),
+ Substitution.of("%app_name%", "x"),
+ Substitution.of("%std_redirect_dylib_path%", "tools/objc/StdRedirect.dylib"));
+ }
+
+ protected void checkGenerateRunnerScriptAction_escaped(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_i386", "--ios_simulator_device=iPhone X'");
+
+ ruleType.scratchTarget(scratch);
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Artifact runnerScript = getBinArtifact("x_runner.sh", target);
+ TemplateExpansionAction action = (TemplateExpansionAction) getGeneratingAction(runnerScript);
+ assertThat(action.getSubstitutions())
+ .contains(Substitution.of("%sim_device%", "'iPhone X'\\'''"));
+ }
+
+ protected void checkDeviceSigningAction(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+
+ scratch.file("x/entitlements.entitlements");
+ ruleType.scratchTarget(scratch, ENTITLEMENTS_ATTR, "'entitlements.entitlements'");
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ protected void checkSigningWithCertName(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--ios_signing_cert_name=Foo Bar");
+
+ scratch.file("x/entitlements.entitlements");
+ ruleType.scratchTarget(scratch, ENTITLEMENTS_ATTR, "'entitlements.entitlements'");
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("--sign \"Foo Bar\"");
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ protected void checkPostProcessingAction(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "ipa_post_processor", "'tool.sh'");
+
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("tool.sh", "x.unprocessed.ipa");
+
+ assertThat(Joiner.on(' ').join(action.getArguments())).contains("x/tool.sh ${t}");
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly("x/x.ipa");
+ }
+
+ protected void checkSigningAndPostProcessing(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ ruleType.scratchTarget(
+ scratch, "ipa_post_processor", "'tool.sh'", ENTITLEMENTS_ATTR,
+ "'entitlements.entitlements'");
+
+ SpawnAction action = (SpawnAction) ipaGeneratingAction();
+ assertRequiresDarwin(action);
+ assertThat(ActionsTestUtil.baseArtifactNames(action.getInputs()))
+ .containsExactly("tool.sh", "x.entitlements", "foo.mobileprovision", "x.unprocessed.ipa");
+
+ assertThat(normalizeBashArgs(action.getArguments()))
+ .containsAllOf("x/tool.sh", "--sign")
+ .inOrder();
+ }
+
+ protected void checkNoEntitlementsDefined(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--nodevice_debug_entitlements");
+
+ ruleType.scratchTarget(scratch);
+
+ SpawnAction ipaAction = (SpawnAction) ipaGeneratingAction();
+ Artifact entitlements = getFirstArtifactEndingWith(ipaAction.getInputs(), ".entitlements");
+ SpawnAction substitutionAction = (SpawnAction) getGeneratingAction(entitlements);
+ assertThat(Joiner.on(' ').join(substitutionAction.getArguments())).contains("sed");
+
+ Artifact prefix =
+ getFirstArtifactEndingWith(substitutionAction.getInputs(), ".team_prefix_file");
+ SpawnAction prefixAction = (SpawnAction) getGeneratingAction(prefix);
+ assertThat(baseArtifactNames(prefixAction.getInputs())).containsExactly("foo.mobileprovision");
+ assertThat(Joiner.on(' ').join(prefixAction.getArguments()))
+ .contains("Print ApplicationIdentifierPrefix:0");
+
+ Artifact extractedEntitlements =
+ getFirstArtifactEndingWith(substitutionAction.getInputs(), ".entitlements_with_variables");
+ SpawnAction extractionAction = (SpawnAction) getGeneratingAction(extractedEntitlements);
+ assertThat(baseArtifactNames(extractionAction.getInputs()))
+ .containsExactly("foo.mobileprovision");
+ assertThat(Joiner.on(' ').join(extractionAction.getArguments())).contains("Print Entitlements");
+ }
+
+ protected void checkEntitlementsDefined(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--nodevice_debug_entitlements");
+
+ ruleType.scratchTarget(scratch, ENTITLEMENTS_ATTR, "'bar.entitlements'");
+
+ SpawnAction ipaAction = (SpawnAction) ipaGeneratingAction();
+ Artifact entitlements = getFirstArtifactEndingWith(ipaAction.getInputs(), ".entitlements");
+ SpawnAction substitutionAction = (SpawnAction) getGeneratingAction(entitlements);
+
+ Artifact prefix =
+ getFirstArtifactEndingWith(substitutionAction.getInputs(), ".team_prefix_file");
+ SpawnAction prefixAction = (SpawnAction) getGeneratingAction(prefix);
+ assertThat(prefixAction).isNotNull();
+
+ assertThat(Artifact.toExecPaths(substitutionAction.getInputs())).contains("x/bar.entitlements");
+ assertThat(
+ getFirstArtifactEndingWith(
+ substitutionAction.getInputs(), ".entitlements_with_variables"))
+ .isNull();
+ }
+
+ protected void checkExtraEntitlements(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--extra_entitlements=//foo:extra.entitlements");
+
+ ruleType.scratchTarget(scratch);
+
+ scratch.file("foo/extra.entitlements");
+ scratch.file("foo/BUILD", "exports_files(['extra.entitlements'])");
+
+ SpawnAction ipaAction = (SpawnAction) ipaGeneratingAction();
+ Artifact entitlements = getFirstArtifactEndingWith(ipaAction.getInputs(), ".entitlements");
+ SpawnAction mergeAction = (SpawnAction) getGeneratingAction(entitlements);
+
+ assertThat(Artifact.toExecPaths(mergeAction.getInputs())).contains("foo/extra.entitlements");
+
+ Artifact mergeControl =
+ getFirstArtifactEndingWith(mergeAction.getInputs(), ".merge-entitlements-control");
+ BinaryFileWriteAction mergeControleAction =
+ (BinaryFileWriteAction) getGeneratingAction(mergeControl);
+
+ PlMergeProtos.Control mergeControlProto;
+ try (InputStream in = mergeControleAction.getSource().openStream()) {
+ mergeControlProto = PlMergeProtos.Control.parseFrom(in);
+ }
+
+ assertThat(mergeControlProto.getSourceFileList()).contains("foo/extra.entitlements");
+ }
+
+ protected void checkFastbuildDebugEntitlements(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7");
+ assertDebugEntitlements(ruleType);
+ }
+
+ protected void checkDebugEntitlements(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--compilation_mode=dbg");
+ assertDebugEntitlements(ruleType);
+ }
+
+ protected void checkOptNoDebugEntitlements(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--compilation_mode=opt");
+ assertNoDebugEntitlements(ruleType);
+ }
+
+ protected void checkExplicitNoDebugEntitlements(RuleType ruleType) throws Exception {
+ useConfiguration("--cpu=ios_armv7", "--nodevice_debug_entitlements");
+ assertNoDebugEntitlements(ruleType);
+ }
+
+ private void assertDebugEntitlements(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+
+ SpawnAction ipaAction = (SpawnAction) ipaGeneratingAction();
+ Artifact entitlements = getFirstArtifactEndingWith(ipaAction.getInputs(), ".entitlements");
+ SpawnAction mergeAction = (SpawnAction) getGeneratingAction(entitlements);
+
+ assertThat(Artifact.toExecPaths(mergeAction.getInputs()))
+ .contains("tools/objc/device_debug_entitlements.plist");
+
+ Artifact mergeControl =
+ getFirstArtifactEndingWith(mergeAction.getInputs(), ".merge-entitlements-control");
+ BinaryFileWriteAction mergeControleAction =
+ (BinaryFileWriteAction) getGeneratingAction(mergeControl);
+
+ PlMergeProtos.Control mergeControlProto;
+ try (InputStream in = mergeControleAction.getSource().openStream()) {
+ mergeControlProto = PlMergeProtos.Control.parseFrom(in);
+ }
+
+ assertThat(mergeControlProto.getSourceFileList())
+ .contains("tools/objc/device_debug_entitlements.plist");
+ }
+
+ private void assertNoDebugEntitlements(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+
+ SpawnAction ipaAction = (SpawnAction) ipaGeneratingAction();
+ Artifact entitlements = getFirstArtifactEndingWith(ipaAction.getInputs(), ".entitlements");
+ SpawnAction entitlementsAction = (SpawnAction) getGeneratingAction(entitlements);
+
+ assertThat(Artifact.toExecPaths(entitlementsAction.getInputs()))
+ .doesNotContain("tools/objc/device_debug_entitlements.plist");
+ }
+
+ protected void checkCompilesSources(RuleType ruleType) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//lib1:lib1")
+ .write();
+ scratch.file("x/a.m");
+ scratch.file("x/b.m");
+ scratch.file("x/a.h");
+ scratch.file("x/private.h");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m', 'b.m', 'private.h']", "hdrs", "['a.h']",
+ "deps", "['//lib2:lib2']");
+ CommandAction compileA = compileAction("//x:x", "a.o");
+
+ assertThat(Artifact.toRootRelativePaths(compileA.getInputs()))
+ .containsExactly("x/a.m", "x/a.h", "x/private.h", "lib1/hdr.h", "lib2/hdr.h",
+ MOCK_XCRUNWRAPPER_PATH);
+ assertThat(Artifact.toRootRelativePaths(compileA.getOutputs()))
+ .containsExactly("x/_objs/x/x/a.o", "x/_objs/x/x/a.d");
+ }
+
+ protected void checkCompilesSourcesWithModuleMapsEnabled(RuleType ruleType) throws Exception {
+ useConfiguration("--experimental_objc_enable_module_maps");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .setList("deps", "//lib1:lib1")
+ .write();
+
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.m', 'b.m']", "hdrs", "['a.h']", "deps", "['//lib2:lib2']");
+ CommandAction compileA = compileAction("//x:x", "a.o");
+
+ assertThat(Artifact.toRootRelativePaths(compileA.getInputs()))
+ .containsAllOf(
+ "lib1/lib1.modulemaps/module.modulemap",
+ "lib2/lib2.modulemaps/module.modulemap",
+ "x/x.modulemaps/module.modulemap");
+ }
+
+ protected void checkCompileWithDotMFileInHeaders(RuleType ruleType) throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/b.m");
+ scratch.file("bin/h.m");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m', 'b.m']",
+ "hdrs", "['h.m']",
+ "deps", "['//lib1:lib1', '//lib2:lib2']");
+ Action linkAction = linkAction("//x:x");
+ Artifact libBin = getFirstArtifactEndingWith(linkAction.getInputs(), "libx.a");
+ Action linkBinAFile = getGeneratingAction(libBin);
+ Artifact aObjFile = getFirstArtifactEndingWith(linkBinAFile.getInputs(), "a.o");
+ CommandAction compileA = (CommandAction) getGeneratingAction(aObjFile);
+
+ assertThat(compileA.getArguments()).contains("x/a.m");
+ assertThat(compileA.getArguments()).doesNotContain("x/h.m");
+ assertThat(getFirstArtifactEndingWith(linkBinAFile.getInputs(), "h.o")).isNull();
+ }
+
+ protected void checkCompileWithTextualHeaders(RuleType ruleType) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "textual_hdrs", "['t.h']",
+ "deps", "['//lib1:lib1', '//lib2:lib2']");
+ CommandAction compileA = compileAction("//x:x", "a.o");
+
+ assertThat(Artifact.toRootRelativePaths(compileA.getInputs()))
+ .containsAllOf("x/a.m", "x/t.h", "lib1/hdr.h", "lib2/hdr.h");
+ }
+
+ protected void checkLinksFrameworksOfSelfAndTransitiveDependencies(RuleType ruleType)
+ throws Exception {
+ createLibraryTargetWriter("//base_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("sdk_frameworks", "foo")
+ .write();
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "deps", "['//base_lib:lib']",
+ "sdk_frameworks", "['bar']");
+
+ assertThat(Joiner.on(" ").join(linkAction("//x:x").getArguments()))
+ .contains("-framework foo -framework bar");
+ }
+
+ protected void checkLinksWeakFrameworksOfSelfAndTransitiveDependencies(RuleType ruleType)
+ throws Exception {
+ createLibraryTargetWriter("//base_lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("weak_sdk_frameworks", "foo")
+ .write();
+
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.m']", "deps", "['//base_lib:lib']", "weak_sdk_frameworks", "['bar']");
+
+ assertThat(Joiner.on(" ").join(linkAction("//x:x").getArguments()))
+ .contains("-weak_framework foo -weak_framework bar");
+ }
+
+ protected void checkLinkWithFrameworkImportsIncludesFlagsAndInputArtifacts(RuleType ruleType)
+ throws Exception {
+ ConfiguredTarget lib = addLibWithDepOnFrameworkImport();
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "deps", "['" + lib.getLabel() + "']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ String linkActionArgs = Joiner.on(" ").join(linkAction.getArguments());
+ assertThat(linkActionArgs).contains("-framework fx1 -framework fx2");
+ assertThat(linkActionArgs).contains("-F fx");
+ assertThat(linkAction.getInputs()).containsAllOf(
+ getSourceArtifact("fx/fx1.framework/a"),
+ getSourceArtifact("fx/fx1.framework/b"),
+ getSourceArtifact("fx/fx2.framework/c"),
+ getSourceArtifact("fx/fx2.framework/d"));
+ }
+
+ protected void checkLinkIncludeOrderFrameworksAndSystemLibsFirst(RuleType ruleType)
+ throws Exception {
+ useConfiguration("--noobjc_includes_prioritize_static_libs");
+ scratch.file("fx/fx1.framework");
+ scratch.file("fx/BUILD", "objc_framework(name = 'fx')");
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.m']", "sdk_frameworks", "['fx']", "sdk_dylibs", "['libdy1']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ String linkActionArgs = Joiner.on(" ").join(linkAction.getArguments());
+
+ assertThat(linkActionArgs.indexOf("-F")).isLessThan(linkActionArgs.indexOf("-filelist"));
+ assertThat(linkActionArgs.indexOf("-l")).isLessThan(linkActionArgs.indexOf("-filelist"));
+ }
+
+ protected void checkLinkIncludeOrderStaticLibsFirst(RuleType ruleType) throws Exception {
+ scratch.file("fx/fx1.framework");
+ scratch.file("fx/BUILD", "objc_framework(name = 'fx')");
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.m']", "sdk_frameworks", "['fx']", "sdk_dylibs", "['libdy1']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ String linkActionArgs = Joiner.on(" ").join(linkAction.getArguments());
+
+ assertThat(linkActionArgs.indexOf(".a")).isLessThan(linkActionArgs.indexOf("-F"));
+ assertThat(linkActionArgs.indexOf(".a")).isLessThan(linkActionArgs.indexOf("-l"));
+ }
+
+ protected ObjcProvider providerForTarget(String label) throws Exception {
+ return getConfiguredTarget(label).getProvider(ObjcProvider.class);
+ }
+
+ protected CommandAction archiveAction(String label) throws Exception {
+ ConfiguredTarget target = getConfiguredTarget(label);
+ return (CommandAction)
+ getGeneratingAction(getBinArtifact("lib" + target.getLabel().getName() + ".a", target));
+ }
+
+ protected Iterable<Artifact> inputsEndingWith(Action action, final String suffix) {
+ return Iterables.filter(action.getInputs(), new Predicate<Artifact>() {
+ @Override
+ public boolean apply(Artifact artifact) {
+ return artifact.getExecPathString().endsWith(suffix);
+ }
+ });
+ }
+
+ /**
+ * Asserts that the given action can specify execution requirements, and requires execution on
+ * darwin.
+ */
+ protected void assertRequiresDarwin(ExecutionInfoSpecifier action) {
+ assertThat(action.getExecutionInfo()).containsKey(ExecutionRequirements.REQUIRES_DARWIN);
+ }
+
+ /**
+ * Asserts that the given action can specify execution requirements, but does not require
+ * execution on darwin.
+ */
+ protected void assertNotRequiresDarwin(Action action) {
+ ExecutionInfoSpecifier executionInfoSpecifier = (ExecutionInfoSpecifier) action;
+ assertThat(executionInfoSpecifier.getExecutionInfo())
+ .doesNotContainKey(ExecutionRequirements.REQUIRES_DARWIN);
+ }
+
+ protected ConfiguredTarget addBinWithTransitiveDepOnFrameworkImport() throws Exception {
+ ConfiguredTarget lib = addLibWithDepOnFrameworkImport();
+ return createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", lib.getLabel().toString())
+ .write();
+
+ }
+
+ protected ConfiguredTarget addLibWithDepOnFrameworkImport() throws Exception {
+ scratch.file("fx/fx1.framework/a");
+ scratch.file("fx/fx1.framework/b");
+ scratch.file("fx/fx2.framework/c");
+ scratch.file("fx/fx2.framework/d");
+ scratch.file("fx/BUILD",
+ "objc_framework(",
+ " name = 'fx',",
+ " framework_imports = glob(['fx1.framework/*', 'fx2.framework/*']),",
+ " sdk_frameworks = ['CoreLocation'],",
+ " weak_sdk_frameworks = ['MediaAccessibility'],",
+ " sdk_dylibs = ['libdy1'],",
+ ")");
+ return createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("deps", "//fx:fx")
+ .write();
+ }
+
+ protected CommandAction compileAction(String ownerLabel, String objFileName) throws Exception {
+ Action archiveAction = archiveAction(ownerLabel);
+ return (CommandAction)
+ getGeneratingAction(
+ getFirstArtifactEndingWith(archiveAction.getInputs(), "/" + objFileName));
+ }
+
+ /**
+ * Verifies simply that some rule type creates the {@link CompilationArtifacts} object
+ * successfully; in particular, makes sure it is not ignoring attributes. If the scope of
+ * {@link CompilationArtifacts} expands, make sure this method tests it properly.
+ *
+ * <p>This test only makes sure the attributes are not being ignored - it does not test any
+ * other functionality in depth, which is covered by other unit tests.
+ */
+ protected void checkPopulatesCompilationArtifacts(RuleType ruleType) throws Exception {
+ scratch.file("x/a.m");
+ scratch.file("x/b.m");
+ scratch.file("x/c.pch");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "non_arc_srcs", "['b.m']",
+ "pch", "'c.pch'");
+ ImmutableList<String> includeFlags = ImmutableList.of("-include", "x/c.pch");
+ assertContainsSublist(compileAction("//x:x", "a.o").getArguments(), includeFlags);
+ assertContainsSublist(compileAction("//x:x", "b.o").getArguments(), includeFlags);
+ }
+
+ protected void checkProvidesHdrsAndIncludes(RuleType ruleType) throws Exception {
+ scratch.file("x/a.h");
+ ruleType.scratchTarget(scratch,
+ "hdrs", "['a.h']",
+ "includes", "['incdir']");
+ ObjcProvider provider =
+ getConfiguredTarget("//x:x", getAppleCrosstoolConfiguration())
+ .getProvider(ObjcProvider.class);
+ assertThat(provider.get(HEADER)).containsExactly(getSourceArtifact("x/a.h"));
+ assertThat(provider.get(INCLUDE))
+ .containsExactly(
+ PathFragment.create("x/incdir"),
+ getAppleCrosstoolConfiguration().getGenfilesFragment().getRelative("x/incdir"));
+ }
+
+ protected void checkCompilesWithHdrs(RuleType ruleType) throws Exception {
+ scratch.file("x/a.m");
+ scratch.file("x/a.h");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "hdrs", "['a.h']");
+ assertThat(compileAction("//x:x", "a.o").getInputs()).contains(getSourceArtifact("x/a.h"));
+ }
+
+ protected void checkArchivesPrecompiledObjectFiles(RuleType ruleType) throws Exception {
+ scratch.file("x/a.m");
+ scratch.file("x/b.o");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m', 'b.o']");
+ assertThat(Artifact.toRootRelativePaths(archiveAction("//x:x").getInputs())).contains("x/b.o");
+ }
+
+ protected void checkPopulatesBundling(RuleType ruleType) throws Exception {
+ scratch.file("x/a.m");
+ scratch.file("x/info.plist");
+ scratch.file("x/assets.xcassets/1");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ INFOPLIST_ATTR, "'info.plist'",
+ "asset_catalogs", "['assets.xcassets/1']");
+ String targetName = "//x:x";
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/info.plist").getExecPathString());
+
+ assertThat(linkAction("//x:x").getInputs())
+ .contains(getBinArtifact("libx.a", target));
+
+ Artifact actoolzipOutput = getBinArtifact("x.actool.zip", target);
+ assertThat(getGeneratingAction(actoolzipOutput).getInputs())
+ .contains(getSourceArtifact("x/assets.xcassets/1"));
+ }
+
+ /**
+ * Checks that a target at {@code //x:x}, which is already created, registered a correct merge
+ * bundle action based on certain arbitrary and default values which include nested bundles.
+ */
+ private void checkMergeBundleActionsWithNestedBundle(
+ String bundleDir, BuildConfiguration bundleConfiguration) throws Exception {
+ BundleFile fooResource = BundleFile.newBuilder()
+ .setSourceFile("bndl/foo.data")
+ .setBundlePath("foo.data")
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build();
+
+ BundleMergeProtos.Control topControl = bundleMergeControl("//x:x");
+ BundleMergeProtos.Control nestedControl =
+ Iterables.getOnlyElement(topControl.getNestedBundleList());
+ assertThat(topControl.getBundleRoot()).isEqualTo(bundleDir);
+ assertThat(nestedControl.getBundleRoot()).isEqualTo("bndl.bundle");
+ assertThat(topControl.getBundleFileList()).doesNotContain(fooResource);
+ assertThat(nestedControl.getBundleFileList()).contains(fooResource);
+
+ ConfiguredTarget bndlTarget = getConfiguredTarget("//bndl:bndl", bundleConfiguration);
+ Artifact bundlePlist = getBinArtifact("bndl-MergedInfo.plist", bndlTarget);
+ assertThat(nestedControl.getBundleInfoPlistFile()).isEqualTo(bundlePlist.getExecPathString());
+
+ Artifact actoolzipOutput = getBinArtifact("bndl.actool.zip", bndlTarget);
+ assertThat(nestedControl.getMergeZipList())
+ .containsExactly(MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/bndl.bundle/")
+ .setSourcePath(actoolzipOutput.getExecPathString())
+ .build());
+
+ assertThat(bundleMergeAction("//x:x").getInputs())
+ .containsAllOf(getSourceArtifact("bndl/foo.data"), bundlePlist, actoolzipOutput);
+ }
+
+ protected SpawnAction bundleMergeAction(String target) throws Exception {
+ Label targetLabel = Label.parseAbsolute(target);
+ ConfiguredTarget binary = getConfiguredTarget(target);
+ return (SpawnAction)
+ getGeneratingAction(getBinArtifact(targetLabel.getName() + artifactName(".unprocessed.ipa"),
+ binary));
+ }
+
+ protected void checkMergeBundleActionsWithNestedBundle(RuleType ruleType) throws Exception {
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " resources = ['foo.data'],",
+ " infoplist = 'bndl-Info.plist',",
+ " asset_catalogs = ['bar.xcassets/1'],",
+ ")");
+ ruleType.scratchTarget(scratch,
+ "bundles", "['//bndl:bndl']");
+ checkMergeBundleActionsWithNestedBundle(
+ getBundlePathInsideIpa(ruleType), targetConfig);
+ }
+
+ // This checks that the proto bundling and grouping behavior works as expected. Grouping is based
+ // on the proto_library targets, given that each proto_library is complete in its closure (all
+ // the required deps are captured inside a proto_library).
+ //
+ // This particular tests sets up 3 proto groups, defined as [A, B], [B, C], [A, C, D]. The proto
+ // grouping support detects that, for example, since A doesn't appear in all groups with B or C,
+ // then it doesn't need any dependencies other than itself to be built. The same applies for B and
+ // C, The same cannot be said about D, which only appears with A and C, so we have to assume that
+ // D depends on A and C.
+ //
+ // These dependencies describe what the inputs will be to each of the generation/compilation
+ // actions. Denoting {[in] -> [out]} as an action with "in" being the required inputs, and "out"
+ // being the expected outputs, given the layout of the groups for this test, the actions should
+ // be:
+ //
+ // {[A] -> [A]}
+ // {[B] -> [B]}
+ // {[C] -> [C]}
+ // {[A, C, D] -> [D]}
+ //
+ // This test ensures that, for example, to generate DataA.pbobjc.{h,m}, only data_a.proto should
+ // be provided as an input, while the inputs to generate DataD.pbobjc.{h,m} should be
+ // data_a.proto, data_c.proto and data_d.proto. The same applies for the compilation actions,
+ // where the inputs are interpreted as .pbobjc.h files, and the output is a .pbobjc.o file.
+ protected void checkProtoBundlingAndLinking(RuleType ruleType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_1',",
+ " srcs = ['data_a.proto', 'data_b.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_2',",
+ " srcs = ['data_b.proto', 'data_c.proto'],",
+ ")",
+ "proto_library(",
+ " name = 'protos_3',",
+ " srcs = ['data_c.proto', 'data_a.proto', 'data_d.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_a',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_1'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_b',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos_2', ':protos_3'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_a', '//protos:objc_protos_b']",
+ ")");
+
+ ruleType.scratchTarget(
+ scratch,
+ "srcs", "['main.m']",
+ "deps", "['//libs:objc_lib']",
+ "defines", "['SHOULDNOTBEINPROTOS']",
+ "copts", "['-ISHOULDNOTBEINPROTOS']");
+
+ BuildConfiguration childConfig =
+ Iterables.getOnlyElement(
+ getSplitConfigurations(
+ targetConfig,
+ new MultiArchSplitTransitionProvider.AppleBinaryTransition(
+ PlatformType.IOS, Optional.<DottedVersion>absent())));
+
+ ConfiguredTarget topTarget = getConfiguredTarget("//x:x", childConfig);
+
+ assertObjcProtoProviderArtifactsArePropagated(topTarget);
+ assertBundledGenerationActionsAreDifferent(topTarget);
+ assertOnlyRequiredInputsArePresentForBundledGeneration(topTarget);
+ assertOnlyRequiredInputsArePresentForBundledCompilation(topTarget);
+ assertCoptsAndDefinesForBundlingTarget(topTarget);
+ assertBundledGroupsGetCreatedAndLinked(topTarget);
+ }
+
+ protected ImmutableList<Artifact> getAllObjectFilesLinkedInBin(Artifact bin) {
+ ImmutableList.Builder<Artifact> objects = ImmutableList.builder();
+ CommandAction binAction = (CommandAction) getGeneratingAction(bin);
+ for (Artifact binActionArtifact : binAction.getInputs()) {
+ if (binActionArtifact.getRootRelativePath().getPathString().endsWith(".a")) {
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binActionArtifact);
+ for (Artifact linkActionArtifact : linkAction.getInputs()) {
+ if (linkActionArtifact.getRootRelativePath().getPathString().endsWith(".o")) {
+ objects.add(linkActionArtifact);
+ }
+ }
+ }
+ }
+ return objects.build();
+ }
+
+ private void assertObjcProtoProviderArtifactsArePropagated(ConfiguredTarget topTarget)
+ throws Exception {
+ ConfiguredTarget libTarget =
+ view.getPrerequisiteConfiguredTargetForTesting(
+ reporter, topTarget, Label.parseAbsoluteUnchecked("//libs:objc_lib"), masterConfig);
+
+ ObjcProtoProvider protoProvider = libTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(protoProvider).isNotNull();
+ assertThat(protoProvider.getProtoGroups().toSet()).hasSize(3);
+ assertThat(
+ Artifact.toExecPaths(
+ ImmutableSet.copyOf(Iterables.concat(protoProvider.getProtoGroups()))))
+ .containsExactly(
+ "protos/data_a.proto",
+ "protos/data_b.proto",
+ "protos/data_c.proto",
+ "protos/data_d.proto");
+ assertThat(Artifact.toExecPaths(protoProvider.getPortableProtoFilters()))
+ .containsExactly("protos/filter_a.pbascii", "protos/filter_b.pbascii");
+ }
+
+ private void assertBundledGenerationActionsAreDifferent(ConfiguredTarget topTarget) {
+ Artifact protoHeaderA = getBinArtifact("_generated_protos/x/protos/DataA.pbobjc.h", topTarget);
+ Artifact protoHeaderB = getBinArtifact("_generated_protos/x/protos/DataB.pbobjc.h", topTarget);
+ Artifact protoHeaderC = getBinArtifact("_generated_protos/x/protos/DataC.pbobjc.h", topTarget);
+ Artifact protoHeaderD = getBinArtifact("_generated_protos/x/protos/DataD.pbobjc.h", topTarget);
+ CommandAction protoActionA = (CommandAction) getGeneratingAction(protoHeaderA);
+ CommandAction protoActionB = (CommandAction) getGeneratingAction(protoHeaderB);
+ CommandAction protoActionC = (CommandAction) getGeneratingAction(protoHeaderC);
+ CommandAction protoActionD = (CommandAction) getGeneratingAction(protoHeaderD);
+ assertThat(protoActionA).isNotNull();
+ assertThat(protoActionB).isNotNull();
+ assertThat(protoActionC).isNotNull();
+ assertThat(protoActionD).isNotNull();
+ assertThat(protoActionA).isNotEqualTo(protoActionB);
+ assertThat(protoActionB).isNotEqualTo(protoActionC);
+ assertThat(protoActionC).isNotEqualTo(protoActionD);
+ }
+
+ private void assertOnlyRequiredInputsArePresentForBundledGeneration(ConfiguredTarget topTarget)
+ throws Exception {
+ ConfiguredTarget libTarget =
+ view.getPrerequisiteConfiguredTargetForTesting(
+ reporter, topTarget, Label.parseAbsoluteUnchecked("//libs:objc_lib"), masterConfig);
+ ObjcProtoProvider protoProvider = libTarget.getProvider(ObjcProtoProvider.class);
+
+ Artifact protoHeaderA = getBinArtifact("_generated_protos/x/protos/DataA.pbobjc.h", topTarget);
+ Artifact protoHeaderB = getBinArtifact("_generated_protos/x/protos/DataB.pbobjc.h", topTarget);
+ Artifact protoHeaderC = getBinArtifact("_generated_protos/x/protos/DataC.pbobjc.h", topTarget);
+ Artifact protoHeaderD = getBinArtifact("_generated_protos/x/protos/DataD.pbobjc.h", topTarget);
+
+ CommandAction protoActionA = (CommandAction) getGeneratingAction(protoHeaderA);
+ CommandAction protoActionB = (CommandAction) getGeneratingAction(protoHeaderB);
+ CommandAction protoActionC = (CommandAction) getGeneratingAction(protoHeaderC);
+ CommandAction protoActionD = (CommandAction) getGeneratingAction(protoHeaderD);
+
+ assertThat(protoActionA.getInputs()).containsAllIn(protoProvider.getPortableProtoFilters());
+ assertThat(protoActionB.getInputs()).containsAllIn(protoProvider.getPortableProtoFilters());
+ assertThat(protoActionC.getInputs()).containsAllIn(protoProvider.getPortableProtoFilters());
+ assertThat(protoActionD.getInputs()).containsAllIn(protoProvider.getPortableProtoFilters());
+
+ assertThat(Artifact.toExecPaths(protoActionA.getInputs())).contains("protos/data_a.proto");
+ assertThat(Artifact.toExecPaths(protoActionA.getInputs()))
+ .containsNoneOf("protos/data_b.proto", "protos/data_c.proto", "protos/data_d.proto");
+
+ assertThat(Artifact.toExecPaths(protoActionB.getInputs())).contains("protos/data_b.proto");
+ assertThat(Artifact.toExecPaths(protoActionB.getInputs()))
+ .containsNoneOf("protos/data_a.proto", "protos/data_c.proto", "protos/data_d.proto");
+
+ assertThat(Artifact.toExecPaths(protoActionC.getInputs())).contains("protos/data_c.proto");
+ assertThat(Artifact.toExecPaths(protoActionC.getInputs()))
+ .containsNoneOf("protos/data_a.proto", "protos/data_b.proto", "protos/data_d.proto");
+
+ assertThat(Artifact.toExecPaths(protoActionD.getInputs())).contains("protos/data_d.proto");
+ assertThat(Artifact.toExecPaths(protoActionD.getInputs()))
+ .containsAllOf("protos/data_a.proto", "protos/data_c.proto");
+ assertThat(Artifact.toExecPaths(protoActionD.getInputs()))
+ .doesNotContain("protos/data_b.proto");
+ }
+
+ private void assertOnlyRequiredInputsArePresentForBundledCompilation(ConfiguredTarget topTarget) {
+ Artifact protoHeaderA = getBinArtifact("_generated_protos/x/protos/DataA.pbobjc.h", topTarget);
+ Artifact protoHeaderB = getBinArtifact("_generated_protos/x/protos/DataB.pbobjc.h", topTarget);
+ Artifact protoHeaderC = getBinArtifact("_generated_protos/x/protos/DataC.pbobjc.h", topTarget);
+ Artifact protoHeaderD = getBinArtifact("_generated_protos/x/protos/DataD.pbobjc.h", topTarget);
+
+ Artifact protoObjectA =
+ getBinArtifact("_objs/x/x/_generated_protos/x/protos/DataA.pbobjc.o", topTarget);
+ Artifact protoObjectB =
+ getBinArtifact("_objs/x/x/_generated_protos/x/protos/DataB.pbobjc.o", topTarget);
+ Artifact protoObjectC =
+ getBinArtifact("_objs/x/x/_generated_protos/x/protos/DataC.pbobjc.o", topTarget);
+ Artifact protoObjectD =
+ getBinArtifact("_objs/x/x/_generated_protos/x/protos/DataD.pbobjc.o", topTarget);
+
+ CommandAction protoObjectActionA = (CommandAction) getGeneratingAction(protoObjectA);
+ CommandAction protoObjectActionB = (CommandAction) getGeneratingAction(protoObjectB);
+ CommandAction protoObjectActionC = (CommandAction) getGeneratingAction(protoObjectC);
+ CommandAction protoObjectActionD = (CommandAction) getGeneratingAction(protoObjectD);
+
+ assertThat(protoObjectActionA).isNotNull();
+ assertThat(protoObjectActionB).isNotNull();
+ assertThat(protoObjectActionC).isNotNull();
+ assertThat(protoObjectActionD).isNotNull();
+
+ assertThat(protoObjectActionA.getInputs())
+ .containsNoneOf(protoHeaderB, protoHeaderC, protoHeaderD);
+ assertThat(protoObjectActionB.getInputs())
+ .containsNoneOf(protoHeaderA, protoHeaderC, protoHeaderD);
+ assertThat(protoObjectActionC.getInputs())
+ .containsNoneOf(protoHeaderA, protoHeaderB, protoHeaderD);
+ assertThat(protoObjectActionD.getInputs())
+ .containsAllOf(protoHeaderA, protoHeaderC, protoHeaderD);
+ assertThat(protoObjectActionD.getInputs())
+ .doesNotContain(protoHeaderB);
+ }
+
+ private void assertCoptsAndDefinesForBundlingTarget(ConfiguredTarget topTarget) {
+ Artifact protoObject =
+ getBinArtifact("_objs/x/x/_generated_protos/x/protos/DataA.pbobjc.o", topTarget);
+ CommandAction protoObjectAction = (CommandAction) getGeneratingAction(protoObject);
+ assertThat(protoObjectAction).isNotNull();
+ assertThat(protoObjectAction.getArguments())
+ .containsNoneOf("-DSHOULDNOTBEINPROTOS", "-ISHOULDNOTBEINPROTOS");
+
+ Artifact binLib = getBinArtifact("libx.a", topTarget);
+ CommandAction binLibAction = (CommandAction) getGeneratingAction(binLib);
+ assertThat(binLibAction).isNotNull();
+
+ Artifact binSrcObject = getFirstArtifactEndingWith(binLibAction.getInputs(), "main.o");
+ CommandAction binSrcObjectAction = (CommandAction) getGeneratingAction(binSrcObject);
+ assertThat(binSrcObjectAction).isNotNull();
+ assertThat(binSrcObjectAction.getArguments())
+ .containsAllOf("-DSHOULDNOTBEINPROTOS", "-ISHOULDNOTBEINPROTOS");
+ }
+
+ private void assertBundledGroupsGetCreatedAndLinked(ConfiguredTarget topTarget) {
+ Artifact protosGroup0Lib = getBinArtifact("libx_BundledProtos_0.a", topTarget);
+ Artifact protosGroup1Lib = getBinArtifact("libx_BundledProtos_1.a", topTarget);
+ Artifact protosGroup2Lib = getBinArtifact("libx_BundledProtos_2.a", topTarget);
+ Artifact protosGroup3Lib = getBinArtifact("libx_BundledProtos_3.a", topTarget);
+
+ CommandAction protosLib0Action = (CommandAction) getGeneratingAction(protosGroup0Lib);
+ CommandAction protosLib1Action = (CommandAction) getGeneratingAction(protosGroup1Lib);
+ CommandAction protosLib2Action = (CommandAction) getGeneratingAction(protosGroup2Lib);
+ CommandAction protosLib3Action = (CommandAction) getGeneratingAction(protosGroup3Lib);
+ assertThat(protosLib0Action).isNotNull();
+ assertThat(protosLib1Action).isNotNull();
+ assertThat(protosLib2Action).isNotNull();
+ assertThat(protosLib3Action).isNotNull();
+
+ Artifact bin = getBinArtifact("x_bin", topTarget);
+ CommandAction binAction = (CommandAction) getGeneratingAction(bin);
+ assertThat(binAction.getInputs())
+ .containsAllOf(protosGroup0Lib, protosGroup1Lib, protosGroup2Lib, protosGroup3Lib);
+ }
+
+ protected void checkProtoBundlingDoesNotHappen(RuleType ruleType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos',",
+ " srcs = ['data_a.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos',",
+ " portable_proto_filters = ['filter_b.pbascii'],",
+ " deps = [':protos'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos']",
+ ")");
+
+ ruleType.scratchTarget(
+ scratch,
+ "srcs", "['main.m']",
+ "deps", "['//libs:objc_lib']");
+
+ ConfiguredTarget topTarget = getConfiguredTarget("//x:x");
+ Artifact protoHeader = getBinArtifact("_generated_protos/x/protos/DataA.pbobjc.h", topTarget);
+ CommandAction protoAction = (CommandAction) getGeneratingAction(protoHeader);
+ assertThat(protoAction).isNull();
+ }
+
+ protected void checkProtoBundlingWithTargetsWithNoDeps(RuleType ruleType) throws Exception {
+ scratch.file(
+ "protos/BUILD",
+ "proto_library(",
+ " name = 'protos_a',",
+ " srcs = ['data_a.proto'],",
+ ")",
+ "objc_proto_library(",
+ " name = 'objc_protos_a',",
+ " portable_proto_filters = ['filter_a.pbascii'],",
+ " deps = [':protos_a'],",
+ ")");
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ " deps = ['//protos:objc_protos_a', ':no_deps_target'],",
+ ")",
+ "objc_framework(",
+ " name = 'no_deps_target',",
+ " framework_imports = ['x.framework'],",
+ ")");
+
+ ruleType.scratchTarget(scratch, "deps", "['//libs:objc_lib']");
+
+ ConfiguredTarget topTarget = getConfiguredTarget("//x:x");
+
+ ConfiguredTarget libTarget =
+ view.getPrerequisiteConfiguredTargetForTesting(
+ reporter, topTarget, Label.parseAbsoluteUnchecked("//libs:objc_lib"), masterConfig);
+
+ ObjcProtoProvider protoProvider = libTarget.getProvider(ObjcProtoProvider.class);
+ assertThat(protoProvider).isNotNull();
+ }
+
+ protected void checkFrameworkDepLinkFlags(RuleType ruleType,
+ ExtraLinkArgs extraLinkArgs) throws Exception {
+ scratch.file(
+ "libs/BUILD",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ " deps = [':my_framework'],",
+ ")",
+ "objc_framework(",
+ " name = 'my_framework',",
+ " framework_imports = ['buzzbuzz.framework'],",
+ ")");
+
+ ruleType.scratchTarget(scratch, "deps", "['//libs:objc_lib']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ Artifact binArtifact = getFirstArtifactEndingWith(linkAction.getOutputs(), "x_bin");
+ Artifact objList = getFirstArtifactEndingWith(linkAction.getInputs(), "x-linker.objlist");
+
+ verifyLinkAction(
+ binArtifact,
+ objList,
+ "x86_64",
+ ImmutableList.of("x/libx.a", "libobjc_lib.a"),
+ ImmutableList.of(PathFragment.create("libs/buzzbuzz")),
+ extraLinkArgs);
+ }
+
+ protected void checkBundleLoaderIsCorrectlyPassedToTheLinker(RuleType ruleType) throws Exception {
+ scratch.file("bin/BUILD",
+ "apple_binary(",
+ " name = 'bin',",
+ " srcs = ['a.m'],",
+ " platform_type = 'ios',",
+ ")");
+
+ ruleType.scratchTarget(scratch, "binary_type", "'loadable_bundle'", "bundle_loader",
+ "'//bin:bin'");
+ ConfiguredTarget binTarget = getConfiguredTarget("//bin:bin");
+
+ CommandAction linkAction = linkAction("//x:x");
+ assertThat(Joiner.on(" ").join(linkAction.getArguments()))
+ .contains("-bundle_loader " + getBinArtifact("bin_lipobin", binTarget).getExecPath());
+ assertThat(Joiner.on(" ").join(linkAction.getArguments()))
+ .contains("-Xlinker -rpath -Xlinker @loader_path/Frameworks");
+ }
+
+ /**
+ * @param bundleConfiguration the configuration in which the bundle is expected to be executed
+ */
+ protected void checkMergeBundleActionsWithNestedBundle(BinaryRuleTypePair ruleTypePair,
+ BuildConfiguration bundleConfiguration) throws Exception {
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " resources = ['foo.data'],",
+ " infoplist = 'bndl-Info.plist',",
+ " asset_catalogs = ['bar.xcassets/1'],",
+ ")");
+ ruleTypePair.scratchTargets(scratch,
+ "bundles", "['//bndl:bndl']");
+ checkMergeBundleActionsWithNestedBundle(ruleTypePair.getBundleDir(), bundleConfiguration);
+ }
+
+ protected Action lipoLibAction(String libLabel) throws Exception {
+ return actionProducingArtifact(libLabel, "_lipo.a");
+ }
+
+ protected Action lipoBinAction(String binLabel) throws Exception {
+ return actionProducingArtifact(binLabel, "_lipobin");
+ }
+
+ protected CommandAction linkAction(String binLabel) throws Exception {
+ CommandAction linkAction = (CommandAction) actionProducingArtifact(binLabel, "_bin");
+ if (linkAction == null) {
+ // For multi-architecture rules, the link action is not in the target configuration, but
+ // across a configuration transition.
+ Action lipoAction = lipoBinAction(binLabel);
+ if (lipoAction != null) {
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "_bin");
+ linkAction = (CommandAction) getGeneratingAction(binArtifact);
+ }
+ }
+ return linkAction;
+ }
+
+ protected CommandAction linkLibAction(String libLabel) throws Exception {
+ CommandAction linkAction = (CommandAction) actionProducingArtifact(libLabel, "-fl.a");
+
+ if (linkAction == null) {
+ // For multi-architecture rules, the link action is not in the target configuration, but
+ // across a configuration transition.
+ Action lipoAction = lipoLibAction(libLabel);
+ if (lipoAction != null) {
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), "-fl.a");
+ linkAction = (CommandAction) getGeneratingAction(binArtifact);
+ }
+ }
+ return linkAction;
+ }
+
+ protected Action actionProducingArtifact(String targetLabel,
+ String artifactSuffix) throws Exception {
+ ConfiguredTarget libraryTarget = getConfiguredTarget(targetLabel);
+ Label parsedLabel = Label.parseAbsolute(targetLabel);
+ Artifact linkedLibrary = getBinArtifact(
+ parsedLabel.getName() + artifactSuffix,
+ libraryTarget);
+ return getGeneratingAction(linkedLibrary);
+ }
+
+ protected void addTargetWithAssetCatalogs(RuleType ruleType) throws Exception {
+ scratch.file("x/foo.xcassets/foo");
+ scratch.file("x/bar.xcassets/bar");
+ ruleType.scratchTarget(scratch,
+ "asset_catalogs", "['foo.xcassets/foo', 'bar.xcassets/bar']");
+ }
+
+ /**
+ * Checks that a target at {@code //x:x}, which is already created, registered a correct actool
+ * action based on the given targetDevice and platform, setting certain arbitrary and default
+ * values.
+ */
+ protected void checkActoolActionCorrectness(DottedVersion minimumOsVersion, String targetDevice,
+ String platform) throws Exception {
+ Artifact actoolZipOut = getBinArtifact("x" + artifactName(".actool.zip"),
+ getConfiguredTarget("//x:x"));
+ Artifact actoolPartialInfoplist =
+ getBinArtifact("x" + artifactName(".actool-PartialInfo.plist"), "//x:x");
+ SpawnAction actoolZipAction = (SpawnAction) getGeneratingAction(actoolZipOut);
+ assertThat(actoolZipAction.getArguments())
+ .containsExactly(
+ MOCK_ACTOOLWRAPPER_PATH,
+ actoolZipOut.getExecPathString(),
+ "--platform", platform,
+ "--output-partial-info-plist", actoolPartialInfoplist.getExecPathString(),
+ "--minimum-deployment-target", minimumOsVersion.toString(),
+ "--target-device", targetDevice,
+ "x/foo.xcassets", "x/bar.xcassets")
+ .inOrder();
+ assertRequiresDarwin(actoolZipAction);
+
+ assertThat(Artifact.toExecPaths(actoolZipAction.getInputs()))
+ .containsExactly(
+ "x/foo.xcassets/foo",
+ "x/bar.xcassets/bar",
+ MOCK_ACTOOLWRAPPER_PATH);
+ assertThat(Artifact.toExecPaths(actoolZipAction.getOutputs()))
+ .containsExactly(
+ actoolZipOut.getExecPathString(),
+ actoolPartialInfoplist.getExecPathString());
+ }
+
+ /**
+ * Checks that a target at {@code //x:x}, which is already created, registered a correct actool
+ * action based on certain arbitrary and default values for iphone simulator.
+ */
+ protected void checkActoolActionCorrectness(DottedVersion minimumOsVersion) throws Exception {
+ checkActoolActionCorrectness(minimumOsVersion, "iphone", "iphonesimulator");
+ }
+
+ protected void checkAssetCatalogAttributeError(RuleType ruleType, String attribute)
+ throws Exception {
+ checkAssetCatalogAttributeError(ruleType, attribute, INFOPLIST_ATTR, "'pl.plist'");
+ }
+
+ protected void checkAssetCatalogAttributeError(RuleType ruleType, String attribute,
+ String infoplistAttribute, String infoPlists) throws Exception {
+ scratch.file("x/pl.plist");
+ checkError("x", "x", String.format(NO_ASSET_CATALOG_ERROR_FORMAT, "3.1415926"),
+ ruleType.target(scratch, "x", "x",
+ infoplistAttribute, infoPlists,
+ attribute, "'3.1415926'"));
+ }
+
+ protected SpawnAction actoolZipActionForIpa(String target) throws Exception {
+ Artifact binActoolZipOut =
+ getFirstArtifactEndingWith(bundleMergeAction(target).getInputs(), ".actool.zip");
+ return (SpawnAction) getGeneratingAction(binActoolZipOut);
+ }
+
+ /**
+ * Checks that a target at {@code //x:x}, which is already created, registered an actool with
+ * correct arguments based on certain arbitrary and default values.
+ */
+ private void checkActoolZipInvocationCorrectness(DottedVersion minimumOsVersion)
+ throws Exception {
+ SpawnAction actoolZipAction = actoolZipActionForIpa("//x:x");
+ assertThat(actoolZipAction.getArguments())
+ .containsExactly(
+ MOCK_ACTOOLWRAPPER_PATH,
+ execPathEndingWith(actoolZipAction.getOutputs(), "x.actool.zip"),
+ "--platform", "iphonesimulator",
+ "--output-partial-info-plist",
+ execPathEndingWith(actoolZipAction.getOutputs(), "actool-PartialInfo.plist"),
+ "--minimum-deployment-target", minimumOsVersion.toString(),
+ "--target-device", "iphone",
+ "lib/ac.xcassets",
+ "--app-icon", "foo",
+ "--launch-image", "bar")
+ .inOrder();
+ }
+
+ protected void checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(RuleType ruleType)
+ throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("asset_catalogs", "ac.xcassets/foo")
+ .write();
+ ruleType.scratchTarget(scratch,
+ "srcs", "['src.m']",
+ "deps", "['//lib:lib']",
+ APP_ICON_ATTR, "'foo'",
+ LAUNCH_IMAGE_ATTR, "'bar'");
+ checkActoolZipInvocationCorrectness(DEFAULT_IOS_SDK_VERSION);
+ }
+
+ protected void checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(
+ BinaryRuleTypePair ruleTypePair, DottedVersion minimumOsVersion) throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("asset_catalogs", "ac.xcassets/foo")
+ .write();
+ ruleTypePair.scratchTargets(scratch,
+ "deps", "['//lib:lib']",
+ APP_ICON_ATTR, "'foo'",
+ LAUNCH_IMAGE_ATTR, "'bar'");
+ checkActoolZipInvocationCorrectness(minimumOsVersion);
+ }
+
+ /**
+ * Verifies that targeted device family information is passed to actoolzip for the given targeted
+ * families.
+ *
+ * @param packageName where to place the rule during testing - this should be different every time
+ * the method is invoked
+ * @param buildFileContents contents of the BUILD file for the {@code packageName} package
+ * @param targetDevices the values to {@code --target-device} expected in the actoolzip invocation
+ */
+ private void checkPassesFamiliesToActool(String packageName, String buildFileContents,
+ String... targetDevices) throws Exception {
+ scratch.file(String.format("%s/BUILD", packageName), buildFileContents);
+ ConfiguredTarget target = getConfiguredTarget(String.format("//%s:x", packageName));
+ Artifact actoolZipOut = getBinArtifact("x.actool.zip", target);
+ SpawnAction actoolZipAction = (SpawnAction) getGeneratingAction(actoolZipOut);
+
+ List<String> arguments = actoolZipAction.getArguments();
+ for (String targetDevice : targetDevices) {
+ assertContainsSublist(arguments, ImmutableList.of("--target-device", targetDevice));
+ }
+
+ assertWithMessage("Incorrect number of --target-device flags in arguments [" + arguments + "]")
+ .that(Collections.frequency(arguments, "--target-device"))
+ .isEqualTo(targetDevices.length);
+ }
+
+ private void checkPassesFamiliesToActool(RuleType ruleType, String packageName,
+ String familiesAttribute, String... actoolFlags) throws Exception {
+ String buildFileContents = ruleType.target(scratch, packageName, "x",
+ FAMILIES_ATTR, familiesAttribute,
+ "asset_catalogs", "['foo.xcassets/1']");
+ checkPassesFamiliesToActool(packageName, buildFileContents, actoolFlags);
+ }
+
+ protected void checkPassesFamiliesToActool(RuleType ruleType) throws Exception {
+ checkPassesFamiliesToActool(ruleType, "iphone", "['iphone']", "iphone");
+ checkPassesFamiliesToActool(ruleType, "ipad", "['ipad']", "ipad");
+ checkPassesFamiliesToActool(ruleType, "both", "['iphone', 'ipad']", "ipad", "iphone");
+ checkPassesFamiliesToActool(ruleType, "both_reverse", "['ipad', 'iphone']", "ipad", "iphone");
+ }
+
+ private void checkPassesFamiliesToActool(BinaryRuleTypePair ruleTypePair, String packageName,
+ String familiesAttribute, String families, String... actoolFlags) throws Exception {
+ String buildFileContents = ruleTypePair.targets(scratch, packageName,
+ "asset_catalogs", "['foo.xcassets/1']",
+ familiesAttribute, families);
+ checkPassesFamiliesToActool(packageName, buildFileContents, actoolFlags);
+ }
+
+ protected void checkPassesFamiliesToActool(BinaryRuleTypePair ruleTypePair) throws Exception {
+ checkPassesFamiliesToActool(ruleTypePair, FAMILIES_ATTR);
+ }
+
+ protected void checkPassesFamiliesToActool(BinaryRuleTypePair ruleTypePair,
+ String familiesAttribute) throws Exception {
+ checkPassesFamiliesToActool(ruleTypePair, "iphone", familiesAttribute, "['iphone']", "iphone");
+ checkPassesFamiliesToActool(ruleTypePair, "ipad", familiesAttribute, "['ipad']", "ipad");
+ checkPassesFamiliesToActool(ruleTypePair, "both", familiesAttribute, "['iphone', 'ipad']",
+ "ipad", "iphone");
+ checkPassesFamiliesToActool(ruleTypePair, "both_reverse", familiesAttribute,
+ "['ipad', 'iphone']", "ipad", "iphone");
+ }
+
+ /**
+ * Verifies that targeted device family information is passed to ibtool for the given targeted
+ * families.
+ *
+ * @param packageName where to place the rule during testing - this should be different every time
+ * the method is invoked
+ * @param buildFileContents contents of the BUILD file for the {@code packageName} package
+ * @param targetDevices the values to {@code --target-device} expected in the ibtool invocation
+ */
+ private void checkPassesFamiliesToIbtool(String packageName, String buildFileContents,
+ String... targetDevices) throws Exception {
+ scratch.file(String.format("%s/BUILD", packageName), buildFileContents);
+ ConfiguredTarget target = getConfiguredTarget(String.format("//%s:x", packageName));
+
+ Artifact storyboardZipOut = getBinArtifact("x/foo.storyboard.zip", target);
+ SpawnAction storyboardZipAction = (SpawnAction) getGeneratingAction(storyboardZipOut);
+
+ List<String> arguments = storyboardZipAction.getArguments();
+ for (String targetDevice : targetDevices) {
+ assertContainsSublist(arguments, ImmutableList.of("--target-device", targetDevice));
+ }
+
+ assertWithMessage("Incorrect number of --target-device flags in arguments [" + arguments + "]")
+ .that(Collections.frequency(arguments, "--target-device"))
+ .isEqualTo(targetDevices.length);
+ }
+
+ private void checkPassesFamiliesToIbtool(RuleType ruleType, String packageName,
+ String families, String... targetDevices) throws Exception {
+ String buildFileContents = ruleType.target(scratch, packageName, "x",
+ FAMILIES_ATTR, families,
+ "storyboards", "['foo.storyboard']");
+ checkPassesFamiliesToIbtool(packageName, buildFileContents, targetDevices);
+ }
+
+ protected void checkPassesFamiliesToIbtool(RuleType ruleType) throws Exception {
+ checkPassesFamiliesToIbtool(ruleType, "iphone", "['iphone']", "iphone");
+ checkPassesFamiliesToIbtool(ruleType, "ipad", "['ipad']", "ipad");
+ checkPassesFamiliesToIbtool(ruleType, "both", "['iphone', 'ipad']",
+ "ipad", "iphone");
+ checkPassesFamiliesToIbtool(ruleType, "both_reverse", "['ipad', 'iphone']",
+ "ipad", "iphone");
+ }
+
+ private void checkPassesFamiliesToIbtool(BinaryRuleTypePair ruleTypePair, String packageName,
+ String familyAttribute, String families, String... targetDevices) throws Exception {
+ String buildFileContents = ruleTypePair.targets(scratch, packageName,
+ familyAttribute, families,
+ "storyboards", "['foo.storyboard']");
+ checkPassesFamiliesToIbtool(packageName, buildFileContents, targetDevices);
+ }
+
+ protected void checkPassesFamiliesToIbtool(BinaryRuleTypePair ruleTypePair) throws Exception {
+ checkPassesFamiliesToIbtool(ruleTypePair, FAMILIES_ATTR);
+ }
+
+ protected void checkPassesFamiliesToIbtool(BinaryRuleTypePair ruleTypePair,
+ String familyAttribute) throws Exception {
+ checkPassesFamiliesToIbtool(ruleTypePair, "iphone", familyAttribute, "['iphone']",
+ "iphone");
+ checkPassesFamiliesToIbtool(ruleTypePair, "ipad", familyAttribute, "['ipad']",
+ "ipad");
+ checkPassesFamiliesToIbtool(ruleTypePair, "both", familyAttribute,
+ "['iphone', 'ipad']", "ipad", "iphone");
+ checkPassesFamiliesToIbtool(ruleTypePair, "both_reverse", familyAttribute,
+ "['ipad', 'iphone']", "ipad", "iphone");
+ }
+
+ private void checkReportsErrorsForInvalidFamiliesAttribute(
+ RuleType ruleType, String packageName, String familyAttribute, String families)
+ throws Exception {
+ checkError(packageName, "x", ReleaseBundling.INVALID_FAMILIES_ERROR,
+ ruleType.target(scratch, packageName, "x", familyAttribute, families));
+ }
+
+ protected void checkReportsErrorsForInvalidFamiliesAttribute(RuleType ruleType)
+ throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(ruleType, FAMILIES_ATTR);
+ }
+
+ protected void checkReportsErrorsForInvalidFamiliesAttribute(RuleType ruleType,
+ String familyAttribute) throws Exception {
+ checkReportsErrorsForInvalidFamiliesAttribute(ruleType, "a", familyAttribute, "['foo']");
+ checkReportsErrorsForInvalidFamiliesAttribute(ruleType, "b", familyAttribute, "[]");
+ checkReportsErrorsForInvalidFamiliesAttribute(ruleType, "c", familyAttribute,
+ "['iphone', 'ipad', 'iphone']");
+ checkReportsErrorsForInvalidFamiliesAttribute(ruleType, "d", familyAttribute,
+ "['iphone', 'bar']");
+ }
+
+ /**
+ * @param extraAttributes individual strings which contain a whole attribute to be added to the
+ * generated target, e.g. "deps = ['foo']"
+ */
+ protected void addBinAndLibWithResources(
+ String attributeName,
+ String libFile,
+ String binFile,
+ String binaryType,
+ String... extraAttributes)
+ throws Exception {
+ scratch.file("lib/" + libFile);
+
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set(attributeName, "['" + libFile + "']")
+ .write();
+
+ scratch.file("bin/" + binFile);
+ scratch.file(
+ "bin/BUILD",
+ binaryType + "(",
+ " name = 'bin',",
+ " srcs = ['src.m'],",
+ " deps = ['//lib:lib'],",
+ " " + attributeName + " = ['" + binFile + "'],",
+ Joiner.on(',').join(extraAttributes),
+ ")");
+ }
+
+ protected void checkCollectsResourceFilesTransitively(
+ String targetLabel,
+ Collection<String> binBundleMergeInputs,
+ Collection<String> libBundleMergeInputs,
+ ImmutableSetMultimap<String, Multiset<String>> filesByTarget)
+ throws Exception {
+ Action mergeBundleAction = bundleMergeAction(targetLabel);
+
+ assertThat(Artifact.toRootRelativePaths(mergeBundleAction.getInputs()))
+ .containsAllIn(binBundleMergeInputs);
+ }
+
+ protected void checkLinksDylibsTransitively(RuleType ruleType)
+ throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("sdk_dylibs", "libdy1", "libdy2")
+ .write();
+ ruleType.scratchTarget(scratch,
+ "sdk_dylibs", "['libdy3']",
+ "deps", "['//lib:lib']");
+
+ CommandAction action = linkAction("//x:x");
+ assertThat(Joiner.on(" ").join(action.getArguments())).contains("-ldy1 -ldy2 -ldy3");
+ }
+
+ protected BinaryFileWriteAction bundleMergeControlAction(String binaryLabelString)
+ throws Exception {
+ Label binaryLabel = Label.parseAbsolute(binaryLabelString);
+ ConfiguredTarget binary = getConfiguredTarget(binaryLabelString);
+ return (BinaryFileWriteAction) getGeneratingAction(
+ getBinArtifact(binaryLabel.getName() + artifactName(".ipa-control"), binary));
+ }
+
+ protected BundleMergeProtos.Control bundleMergeControl(String binaryLabel)
+ throws Exception {
+ try (InputStream in = bundleMergeControlAction(binaryLabel).getSource()
+ .openStream()) {
+ return BundleMergeProtos.Control.parseFrom(in);
+ }
+ }
+
+ protected void checkNoDebugSymbolFileWithoutAppleFlag(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact plistArtifact = getBinArtifact("bin.app.dSYM/Contents/Info.plist", target);
+ Artifact debugSymbolArtifact =
+ getBinArtifact("bin.app.dSYM/Contents/Resources/DWARF/bin", target);
+ CommandAction plistAction = (CommandAction) getGeneratingAction(plistArtifact);
+ CommandAction debugSymbolAction = (CommandAction) getGeneratingAction(debugSymbolArtifact);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(getBinArtifact("x_bin", target));
+
+ assertThat(linkAction.getArguments().get(2)).doesNotContain(DSYMUTIL);
+ assertThat(plistAction).isNull();
+ assertThat(debugSymbolAction).isNull();
+ }
+
+ protected ConfiguredTarget createTargetWithStoryboards(RuleType ruleType) throws Exception {
+ scratch.file("x/1.storyboard");
+ scratch.file("x/2.storyboard");
+ scratch.file("x/subdir_for_no_reason/en.lproj/loc.storyboard");
+ scratch.file("x/ja.lproj/loc.storyboard");
+ ruleType.scratchTarget(scratch, "storyboards", "glob(['*.storyboard', '**/*.storyboard'])");
+ return getConfiguredTarget("//x:x");
+ }
+
+ private ConfiguredTarget createTargetWithStoryboards(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ scratch.file("x/1.storyboard");
+ scratch.file("x/2.storyboard");
+ scratch.file("x/subdir_for_no_reason/en.lproj/loc.storyboard");
+ scratch.file("x/ja.lproj/loc.storyboard");
+ ruleTypePair.scratchTargets(scratch, "storyboards",
+ "glob(['*.storyboard', '**/*.storyboard'])");
+ return getConfiguredTarget("//x:x");
+ }
+
+ private ConfiguredTarget createTargetWithSwift(RuleType ruleType) throws Exception {
+ scratch.file("x/main.m");
+
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_rule_impl(ctx):",
+ " return struct(objc=apple_common.new_objc_provider(uses_swift=True))",
+ "swift_rule = rule(implementation = swift_rule_impl, attrs = {})");
+
+ scratch.file(
+ "x/BUILD",
+ "load('//examples/rule:apple_rules.bzl', 'swift_rule')",
+ "swift_rule(name='swift_bin')",
+ ruleType.getRuleTypeName() + "(",
+ " name = 'x',",
+ " srcs = ['main.m'],",
+ " deps = [':swift_bin'],",
+ ")");
+
+ return getConfiguredTarget("//x:x");
+ }
+
+ protected void checkProvidesStoryboardObjects(RuleType ruleType) throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ createTargetWithStoryboards(ruleType);
+ ObjcProvider provider = providerForTarget("//x:x");
+ ImmutableList<Artifact> storyboardInputs = ImmutableList.of(
+ getSourceArtifact("x/1.storyboard"),
+ getSourceArtifact("x/2.storyboard"),
+ getSourceArtifact("x/subdir_for_no_reason/en.lproj/loc.storyboard"),
+ getSourceArtifact("x/ja.lproj/loc.storyboard"));
+
+ assertThat(provider.get(GENERAL_RESOURCE_FILE))
+ .containsExactlyElementsIn(storyboardInputs);
+ assertThat(provider.get(STORYBOARD))
+ .containsExactlyElementsIn(storyboardInputs);
+ }
+
+ protected void checkRegistersStoryboardCompileActions(
+ BinaryRuleTypePair ruleTypePair, DottedVersion minimumOsVersion,
+ String platformName) throws Exception {
+ checkRegistersStoryboardCompileActions(
+ createTargetWithStoryboards(ruleTypePair), minimumOsVersion,
+ ImmutableList.of(platformName));
+ }
+
+ protected void checkRegistersStoryboardCompileActions(RuleType ruleType,
+ String platformName) throws Exception {
+ checkRegistersStoryboardCompileActions(
+ createTargetWithStoryboards(ruleType), DEFAULT_IOS_SDK_VERSION,
+ ImmutableList.of(platformName));
+ }
+
+ private void checkRegistersStoryboardCompileActions(
+ ConfiguredTarget target, DottedVersion minimumOsVersion, List<String> targetDevices) {
+ Artifact storyboardZip = getBinArtifact("x/1.storyboard.zip", target);
+ CommandAction compileAction = (CommandAction) getGeneratingAction(storyboardZip);
+ assertThat(compileAction.getInputs()).containsExactly(
+ getSourceArtifact(MOCK_IBTOOLWRAPPER_PATH),
+ getSourceArtifact("x/1.storyboard")
+ );
+ String archiveRoot = targetDevices.contains("watch") ? "." : "1.storyboardc";
+ assertThat(compileAction.getOutputs()).containsExactly(storyboardZip);
+ assertThat(compileAction.getArguments())
+ .containsExactlyElementsIn(new CustomCommandLine.Builder()
+ .add(MOCK_IBTOOLWRAPPER_PATH)
+ .add(storyboardZip.getExecPathString())
+ .add(archiveRoot) // archive root
+ .add("--minimum-deployment-target").add(minimumOsVersion.toString())
+ .add("--module").add("x")
+ .addBeforeEach("--target-device", targetDevices)
+ .add("x/1.storyboard")
+ .build()
+ .arguments())
+ .inOrder();
+
+ storyboardZip = getBinArtifact("x/ja.lproj/loc.storyboard.zip", target);
+ compileAction = (CommandAction) getGeneratingAction(storyboardZip);
+ assertThat(compileAction.getInputs()).containsExactly(
+ getSourceArtifact(MOCK_IBTOOLWRAPPER_PATH),
+ getSourceArtifact("x/ja.lproj/loc.storyboard")
+ );
+ assertThat(compileAction.getOutputs()).containsExactly(storyboardZip);
+ archiveRoot = targetDevices.contains("watch") ? "ja.lproj/" : "ja.lproj/loc.storyboardc";
+ assertThat(compileAction.getArguments())
+ .containsExactlyElementsIn(new CustomCommandLine.Builder()
+ .add(MOCK_IBTOOLWRAPPER_PATH)
+ .add(storyboardZip.getExecPathString())
+ .add(archiveRoot) // archive root
+ .add("--minimum-deployment-target").add(minimumOsVersion.toString())
+ .add("--module").add("x")
+ .addBeforeEach("--target-device", targetDevices)
+ .add("x/ja.lproj/loc.storyboard")
+ .build().arguments())
+ .inOrder();
+ }
+
+ protected void assertSwiftStdlibToolAction(
+ ConfiguredTarget target,
+ String platformName,
+ String zipName,
+ String bundlePath,
+ String toolchain)
+ throws Exception {
+ String zipArtifactName = String.format("%s.%s.zip", target.getTarget().getName(), zipName);
+ Artifact swiftLibsZip = getBinArtifact(zipArtifactName, target);
+ Artifact binary = getBinArtifact("x_lipobin", target);
+ SpawnAction toolAction = (SpawnAction) getGeneratingAction(swiftLibsZip);
+
+ assertThat(toolAction.getInputs()).containsExactly(
+ binary,
+ getSourceArtifact(MOCK_SWIFTSTDLIBTOOLWRAPPER_PATH));
+ assertThat(toolAction.getOutputs()).containsExactly(swiftLibsZip);
+
+ CustomCommandLine.Builder expectedCommandLine =
+ CustomCommandLine.builder().add(MOCK_SWIFTSTDLIBTOOLWRAPPER_PATH);
+
+ if (toolchain != null) {
+ expectedCommandLine.add("--toolchain").add(toolchain);
+ }
+
+ expectedCommandLine
+ .add("--output_zip_path")
+ .add(swiftLibsZip.getExecPathString())
+ .add("--bundle_path")
+ .add(bundlePath)
+ .add("--platform")
+ .add(platformName)
+ .add("--scan-executable")
+ .add(binary.getExecPathString());
+
+ assertThat(toolAction.getArguments()).isEqualTo(expectedCommandLine.build().arguments());
+ }
+
+ protected void checkRegisterSwiftSupportActions(
+ RuleType ruleType, String platformName, String toolchain) throws Exception {
+ checkRegisterSwiftSupportActions(createTargetWithSwift(ruleType), platformName, toolchain);
+ }
+
+ protected void checkRegisterSwiftSupportActions(
+ RuleType ruleType, String platformName) throws Exception {
+ checkRegisterSwiftSupportActions(createTargetWithSwift(ruleType), platformName, null);
+ }
+
+ protected void checkRegisterSwiftSupportActions(
+ ConfiguredTarget target, String platformName, String toolchain) throws Exception {
+ assertSwiftStdlibToolAction(
+ target, platformName, "swiftsupport", "SwiftSupport/" + platformName, toolchain);
+ }
+
+ protected void checkRegisterSwiftSupportActions(
+ ConfiguredTarget target, String platformName) throws Exception {
+ assertSwiftStdlibToolAction(
+ target, platformName, "swiftsupport", "SwiftSupport/" + platformName, null);
+ }
+
+ protected void checkRegisterSwiftStdlibActions(
+ RuleType ruleType, String platformName, String toolchain) throws Exception {
+ checkRegisterSwiftStdlibActions(createTargetWithSwift(ruleType), platformName, toolchain);
+ }
+
+ protected void checkRegisterSwiftStdlibActions(
+ RuleType ruleType, String platformName) throws Exception {
+ checkRegisterSwiftStdlibActions(createTargetWithSwift(ruleType), platformName, null);
+ }
+
+ protected void checkRegisterSwiftStdlibActions(
+ ConfiguredTarget target, String platformName, String toolchain) throws Exception {
+ assertSwiftStdlibToolAction(target, platformName, "swiftstdlib", "Frameworks", toolchain);
+ }
+
+ protected void checkRegisterSwiftStdlibActions(
+ ConfiguredTarget target, String platformName) throws Exception {
+ assertSwiftStdlibToolAction(target, platformName, "swiftstdlib", "Frameworks", null);
+ }
+
+ /**
+ * Checks that a target at {@code //x:x}, which is already created, merges xcdatamodel zips
+ * properly based on certain arbitrary and default values.
+ */
+ private void checkMergesXcdatamodelZips(String bundleDir, String binarysMergeZip)
+ throws Exception {
+ Action mergeBundleAction = bundleMergeAction("//x:x");
+ Iterable<Artifact> mergeInputs = mergeBundleAction.getInputs();
+ assertThat(Artifact.toRootRelativePaths(mergeInputs))
+ .containsAllOf("x/x/foo.zip", binarysMergeZip);
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ assertThat(control.getMergeZipList())
+ .containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(
+ getFirstArtifactEndingWith(mergeInputs, "x/foo.zip").getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(
+ getFirstArtifactEndingWith(mergeInputs, binarysMergeZip).getExecPathString())
+ .build());
+ }
+
+ protected void checkMergesXcdatamodelZips(RuleType ruleType) throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("datamodels", "foo.xcdatamodel/1")
+ .write();
+ ruleType.scratchTarget(scratch,
+ "deps", "['//lib:lib']",
+ "datamodels", "['bar.xcdatamodeld/barx.xcdatamodel/2']");
+ checkMergesXcdatamodelZips(getBundlePathInsideIpa(ruleType), "x/x/bar.zip");
+ }
+
+ protected void checkMergesXcdatamodelZips(BinaryRuleTypePair ruleTypePair) throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("datamodels", "foo.xcdatamodel/1")
+ .write();
+ ruleTypePair.scratchTargets(scratch,
+ "deps", "['//lib:lib']",
+ "datamodels", "['bar.xcdatamodeld/barx.xcdatamodel/2']");
+ checkMergesXcdatamodelZips(ruleTypePair.getBundleDir(), "x/x/bar.zip");
+ }
+
+ protected void checkIncludesStoryboardOutputZipsAsMergeZips(RuleType ruleType) throws Exception {
+ scratch.file("lib/libsb.storyboard");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("storyboards", "libsb.storyboard")
+ .write();
+ scratch.file("bndl/bndlsb.storyboard");
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " storyboards = ['bndlsb.storyboard'],",
+ ")");
+
+ scratch.file("x/xsb.storyboard");
+ ruleType.scratchTarget(scratch,
+ "storyboards", "['xsb.storyboard']",
+ "deps", "['//lib:lib']",
+ "bundles", "['//bndl:bndl']");
+
+ Artifact libsbOutputZip = getBinArtifact("x/libsb.storyboard.zip", "//x:x");
+ Artifact bndlsbOutputZip = getBinArtifact("bndl/bndlsb.storyboard.zip", "//bndl:bndl");
+ Artifact xsbOutputZip = getBinArtifact("x/xsb.storyboard.zip", "//x:x");
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+ String prefix = getBundlePathInsideIpa(ruleType) + "/";
+ assertThat(mergeControl.getMergeZipList()).containsExactly(
+ BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(prefix)
+ .setSourcePath(libsbOutputZip.getExecPathString())
+ .build(),
+ BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(prefix)
+ .setSourcePath(xsbOutputZip.getExecPathString())
+ .build());
+
+ BundleMergeProtos.Control nestedMergeControl =
+ Iterables.getOnlyElement(mergeControl.getNestedBundleList());
+ assertThat(nestedMergeControl.getMergeZipList()).containsExactly(
+ BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(prefix + "bndl.bundle/")
+ .setSourcePath(bndlsbOutputZip.getExecPathString())
+ .build());
+
+ Action mergeAction = bundleMergeAction("//x:x");
+ assertThat(mergeAction.getInputs())
+ .containsAllOf(libsbOutputZip, xsbOutputZip, bndlsbOutputZip);
+ }
+
+ protected void checkIncludesStoryboardOutputZipsAsMergeZips(BinaryRuleTypePair ruleTypePair,
+ BuildConfiguration nestedConfiguration) throws Exception {
+ scratch.file("lib/libsb.storyboard");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("storyboards", "libsb.storyboard")
+ .write();
+
+ scratch.file("bndl/bndlsb.storyboard");
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " storyboards = ['bndlsb.storyboard'],",
+ ")");
+
+ scratch.file("x/xsb.storyboard");
+ ruleTypePair.scratchTargets(scratch,
+ "storyboards", "['xsb.storyboard']",
+ "deps", "['//lib:lib']",
+ "bundles", "['//bndl:bndl']");
+
+ Artifact libsbOutputZip = getBinArtifact("x/libsb.storyboard.zip", "//x:x");
+ Artifact bndlsbOutputZip = getBinArtifact(
+ "bndl/bndlsb.storyboard.zip", getConfiguredTarget("//bndl:bndl", nestedConfiguration));
+ Artifact xsbOutputZip = getBinArtifact("x/xsb.storyboard.zip", "//x:x");
+
+ String bundleDir = ruleTypePair.getBundleDir();
+ Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList()).containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(libsbOutputZip.getExecPathString())
+ .build(),
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/")
+ .setSourcePath(xsbOutputZip.getExecPathString())
+ .build());
+
+ Control nestedMergeControl =
+ Iterables.getOnlyElement(mergeControl.getNestedBundleList());
+ assertThat(nestedMergeControl.getMergeZipList()).containsExactly(
+ MergeZip.newBuilder()
+ .setEntryNamePrefix(bundleDir + "/bndl.bundle/")
+ .setSourcePath(bndlsbOutputZip.getExecPathString())
+ .build());
+ }
+
+ protected List<String> rootedIncludePaths(
+ BuildConfiguration configuration, String... unrootedPaths) {
+ ImmutableList.Builder<String> rootedPaths = new ImmutableList.Builder<>();
+ for (String unrootedPath : unrootedPaths) {
+ rootedPaths.add(unrootedPath)
+ .add(configuration.getGenfilesFragment().getRelative(unrootedPath).getSafePathString());
+ }
+ return rootedPaths.build();
+ }
+
+ protected void checkErrorsWrongFileTypeForSrcsWhenCompiling(RuleType ruleType)
+ throws Exception {
+ scratch.file("fg/BUILD",
+ "filegroup(",
+ " name = 'fg',",
+ " srcs = ['non_matching', 'matchingh.h', 'matchingc.c'],",
+ ")");
+ checkError("x1", "x1",
+ "does not match expected type: " + SRCS_TYPE,
+ ruleType.target(scratch, "x1", "x1",
+ "srcs", "['//fg:fg']"));
+ }
+
+ protected void prepareAlwayslinkCheck(RuleType ruleType) throws Exception {
+ scratch.file(
+ "imp1/BUILD",
+ "objc_import(",
+ " name = 'imp1',",
+ " archives = ['imp1.a'],",
+ " alwayslink = 1,",
+ ")");
+ scratch.file("imp2/BUILD",
+ "objc_import(",
+ " name = 'imp2',",
+ " archives = ['imp2.a'],",
+ ")");
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("alwayslink", 1)
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("alwayslink", 0)
+ .write();
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "deps", "['//imp1:imp1', '//imp2:imp2', '//lib1:lib1', '//lib2:lib2']");
+ }
+
+ protected void checkForceLoadsAlwayslinkTargets(RuleType ruleType, ExtraLinkArgs extraLinkArgs)
+ throws Exception {
+ prepareAlwayslinkCheck(ruleType);
+ CommandAction action = linkAction("//x:x");
+
+ verifyObjlist(action, "x-linker.objlist",
+ execPathEndingWith(action.getInputs(), "x/libx.a"),
+ execPathEndingWith(action.getInputs(), "lib2.a"),
+ execPathEndingWith(action.getInputs(), "imp2.a"));
+ Iterable<String> forceLoadArchives = ImmutableList.of(
+ execPathEndingWith(action.getInputs(), "imp1.a"),
+ execPathEndingWith(action.getInputs(), "lib1.a"));
+ assertThat(action.getArguments())
+ .containsExactly(
+ "/bin/bash",
+ "-c",
+ Joiner.on(" ")
+ .join(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(CLANG)
+ .add("-filelist")
+ .add(execPathEndingWith(action.getInputs(), "x-linker.objlist"))
+ .add("-mios-simulator-version-min=" + DEFAULT_IOS_SDK_VERSION)
+ .add("-arch")
+ .add("x86_64")
+ .add("-isysroot", AppleToolchain.sdkDir())
+ .add(
+ "-F", AppleToolchain.sdkDir() + AppleToolchain.DEVELOPER_FRAMEWORK_PATH)
+ .add("-F", frameworkDir(getConfiguredTarget("//x:x")))
+ .add("-Xlinker", "-objc_abi_version", "-Xlinker", "2")
+ .add("-Xlinker", "-rpath", "-Xlinker", "@executable_path/Frameworks")
+ .add("-fobjc-link-runtime")
+ .add("-ObjC")
+ .addAll(
+ Interspersing.beforeEach(
+ "-framework", SdkFramework.names(AUTOMATIC_SDK_FRAMEWORKS)))
+ .add("-o")
+ .addAll(Artifact.toExecPaths(action.getOutputs()))
+ .addAll(Interspersing.beforeEach("-force_load", forceLoadArchives))
+ .addAll(extraLinkArgs)
+ .build()))
+ .inOrder();
+ }
+
+ protected void checkObjcCopts(RuleType ruleType) throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+ List<String> args = compileAction("//x:x", "a.o").getArguments();
+ assertThat(args).contains("-foo");
+ }
+
+ protected void checkObjcCopts_argumentOrdering(RuleType ruleType) throws Exception {
+ useConfiguration("--objccopt=-foo");
+
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "copts", "['-bar']");
+ List<String> args = compileAction("//x:x", "a.o").getArguments();
+ assertThat(args).containsAllOf("-fobjc-arc", "-foo", "-bar").inOrder();
+ }
+
+ protected void checkClangCoptsForCompilationMode(RuleType ruleType, CompilationMode mode,
+ CodeCoverageMode codeCoverageMode) throws Exception {
+ ImmutableList.Builder<String> allExpectedCoptsBuilder = ImmutableList.<String>builder()
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .addAll(compilationModeCopts(mode));
+
+ switch (codeCoverageMode) {
+ case NONE:
+ useConfiguration("--compilation_mode=" + compilationModeFlag(mode));
+ break;
+ case GCOV:
+ allExpectedCoptsBuilder.addAll(CompilationSupport.CLANG_GCOV_COVERAGE_FLAGS);
+ useConfiguration("--collect_code_coverage",
+ "--compilation_mode=" + compilationModeFlag(mode));
+ break;
+ case LLVMCOV:
+ allExpectedCoptsBuilder.addAll(CompilationSupport.CLANG_LLVM_COVERAGE_FLAGS);
+ useConfiguration("--collect_code_coverage", "--experimental_use_llvm_covmap",
+ "--compilation_mode=" + compilationModeFlag(mode));
+ break;
+ }
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']");
+
+ CommandAction compileActionA = compileAction("//x:x", "a.o");
+
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(allExpectedCoptsBuilder.build());
+ }
+
+ protected void checkClangCoptsForDebugModeWithoutGlib(RuleType ruleType) throws Exception {
+ ImmutableList.Builder<String> allExpectedCoptsBuilder = ImmutableList.<String>builder()
+ .addAll(CompilationSupport.DEFAULT_COMPILER_FLAGS)
+ .addAll(ObjcConfiguration.DBG_COPTS);
+
+ useConfiguration("--compilation_mode=dbg", "--objc_debug_with_GLIBCXX=false");
+ scratch.file("x/a.m");
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']");
+
+ CommandAction compileActionA = compileAction("//x:x", "a.o");
+
+ assertThat(compileActionA.getArguments())
+ .containsAllIn(allExpectedCoptsBuilder.build()).inOrder();
+
+ }
+
+ protected void checkLinkopts(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "linkopts", "['foo', 'bar']");
+
+ CommandAction linkAction = linkAction("//x:x");
+ String linkArgs = Joiner.on(" ").join(linkAction.getArguments());
+ assertThat(linkArgs).contains("-Wl,foo");
+ assertThat(linkArgs).contains("-Wl,bar");
+ }
+
+ protected void checkMergesPartialInfoplists(RuleType ruleType) throws Exception {
+ scratch.file("x/primary-Info.plist");
+ ruleType.scratchTarget(scratch,
+ INFOPLIST_ATTR, "'primary-Info.plist'",
+ "asset_catalogs", "['foo.xcassets/bar']");
+
+ String targetName = "//x:x";
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+
+ PlMergeProtos.Control control = plMergeControl(targetName);
+ Artifact actoolPartial = getBinArtifact("x.actool-PartialInfo.plist", "//x:x");
+ Artifact versionInfoplist = getBinArtifact("plists/x-version.plist", target);
+ Artifact environmentInfoplist = getBinArtifact("plists/x-environment.plist", target);
+ Artifact automaticInfoplist = getBinArtifact("plists/x-automatic.plist", target);
+
+ assertPlistMergeControlUsesSourceFiles(
+ control,
+ ImmutableList.<String>of(
+ "x/primary-Info.plist",
+ versionInfoplist.getExecPathString(),
+ environmentInfoplist.getExecPathString(),
+ automaticInfoplist.getExecPathString(),
+ actoolPartial.getExecPathString()));
+ }
+
+ protected void checkMergesPartialInfoplists(BinaryRuleTypePair ruleTypePair) throws Exception {
+ scratch.file("x/primary-Info.plist");
+ ruleTypePair.scratchTargets(scratch,
+ "asset_catalogs", "['foo.xcassets/bar']",
+ INFOPLIST_ATTR, "'primary-Info.plist'");
+
+ String targetName = "//x:x";
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+
+ Artifact merged = getBinArtifact("x-MergedInfo.plist", target);
+ Artifact actoolPartial = getBinArtifact("x.actool-PartialInfo.plist", "//x:x");
+
+ Artifact versionInfoplist = getBinArtifact("plists/x-version.plist", target);
+ Artifact environmentInfoplist = getBinArtifact("plists/x-environment.plist", target);
+ Artifact automaticInfoplist = getBinArtifact("plists/x-automatic.plist", target);
+
+ assertPlistMergeControlUsesSourceFiles(
+ control,
+ ImmutableList.<String>of(
+ "x/primary-Info.plist",
+ versionInfoplist.getExecPathString(),
+ environmentInfoplist.getExecPathString(),
+ automaticInfoplist.getExecPathString(),
+ actoolPartial.getExecPathString()));
+ assertThat(control.getOutFile()).isEqualTo(merged.getExecPathString());
+ assertThat(control.getVariableSubstitutionMapMap())
+ .containsExactlyEntriesIn(getVariableSubstitutionArguments(ruleTypePair));
+ assertThat(control.getFallbackBundleId()).isEqualTo("example.x");
+ }
+
+ private void addTransitiveDefinesUsage(RuleType topLevelRuleType) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("defines", "A=foo", "B")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//lib1:lib1")
+ .setList("defines", "C=bar", "D")
+ .write();
+
+ topLevelRuleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "non_arc_srcs", "['b.m']",
+ "deps", "['//lib2:lib2']",
+ "defines", "['E=baz']",
+ "copts", "['explicit_copt']");
+ }
+
+ protected void checkReceivesTransitivelyPropagatedDefines(RuleType ruleType) throws Exception {
+ addTransitiveDefinesUsage(ruleType);
+ assertContainsSublist(compileAction("//x:x", "a.o").getArguments(),
+ ImmutableList.of("-DA=foo", "-DB", "-DC=bar", "-DD", "-DE=baz", "explicit_copt"));
+ assertContainsSublist(compileAction("//x:x", "b.o").getArguments(),
+ ImmutableList.of("-DA=foo", "-DB", "-DC=bar", "-DD", "-DE=baz", "explicit_copt"));
+ }
+
+ protected void checkDefinesFromCcLibraryDep(RuleType ruleType) throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+ ScratchAttributeWriter.fromLabelString(this, "cc_library", "//dep:lib")
+ .setList("srcs", "a.cc")
+ .setList("defines", "foo", "bar")
+ .write();
+
+ ScratchAttributeWriter.fromLabelString(this, ruleType.getRuleTypeName(), "//objc:x")
+ .setList("srcs", "a.m")
+ .setList("deps", "//dep:lib")
+ .write();
+
+ CommandAction compileAction = compileAction("//objc:x", "a.o");
+ assertThat(compileAction.getArguments()).containsAllOf("-Dfoo", "-Dbar");
+ }
+
+ protected void checkSdkIncludesUsedInCompileAction(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "sdk_includes", "['foo', 'bar/baz']",
+ "srcs", "['a.m', 'b.m']");
+ String sdkIncludeDir = AppleToolchain.sdkDir() + "/usr/include";
+ assertThat(compileAction("//x:x", "a.o").getArguments())
+ .containsAllOf(
+ "-I", sdkIncludeDir + "/foo",
+ "-I", sdkIncludeDir + "/bar/baz")
+ .inOrder();
+ assertThat(compileAction("//x:x", "b.o").getArguments())
+ .containsAllOf(
+ "-I", sdkIncludeDir + "/foo",
+ "-I", sdkIncludeDir + "/bar/baz")
+ .inOrder();
+ }
+
+ protected void checkSdkIncludesUsedInCompileActionsOfDependers(RuleType ruleType)
+ throws Exception {
+ ruleType.scratchTarget(scratch, "sdk_includes", "['foo', 'bar/baz']");
+ // Add some dependers (including transitive depender //bin:bin) and make sure they use the flags
+ // as well.
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m")
+ .setList("deps", "//x:x")
+ .setList("sdk_includes", "from_lib")
+ .write();
+ createBinaryTargetWriter("//bin:bin")
+ .setAndCreateFiles("srcs", "b.m")
+ .setList("deps", "//lib:lib")
+ .setList("sdk_includes", "from_bin")
+ .write();
+ String sdkIncludeDir = AppleToolchain.sdkDir() + "/usr/include";
+ assertThat(compileAction("//lib:lib", "a.o").getArguments())
+ .containsAllOf(
+ "-I", sdkIncludeDir + "/from_lib",
+ "-I", sdkIncludeDir + "/foo",
+ "-I", sdkIncludeDir + "/bar/baz")
+ .inOrder();
+ assertThat(compileAction("//bin:bin", "b.o").getArguments())
+ .containsAllOf(
+ "-I", sdkIncludeDir + "/from_bin",
+ "-I", sdkIncludeDir + "/from_lib",
+ "-I", sdkIncludeDir + "/foo",
+ "-I", sdkIncludeDir + "/bar/baz")
+ .inOrder();
+ }
+
+ protected void checkCompileXibActions(
+ BinaryRuleTypePair ruleTypePair, DottedVersion minimumOsVersion,
+ String platformType) throws Exception {
+ ruleTypePair.scratchTargets(scratch, "xibs", "['foo.xib', 'es.lproj/bar.xib']");
+ checkCompileXibActions(minimumOsVersion, platformType);
+ }
+
+ protected void checkCompileXibActions(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "xibs", "['foo.xib', 'es.lproj/bar.xib']");
+ checkCompileXibActions(DEFAULT_IOS_SDK_VERSION, "iphone");
+ }
+
+ private void checkCompileXibActions(DottedVersion minimumOsVersion,
+ String platformType) throws Exception {
+ scratch.file("x/foo.xib");
+ scratch.file("x/es.lproj/bar.xib");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Artifact fooNibZip = getBinArtifact("x/x/foo.nib.zip", target);
+ Artifact barNibZip = getBinArtifact("x/x/es.lproj/bar.nib.zip", target);
+ CommandAction fooCompile = (CommandAction) getGeneratingAction(fooNibZip);
+ CommandAction barCompile = (CommandAction) getGeneratingAction(barNibZip);
+
+ assertThat(Artifact.toExecPaths(fooCompile.getInputs()))
+ .containsExactly(MOCK_IBTOOLWRAPPER_PATH, "x/foo.xib");
+ assertThat(Artifact.toExecPaths(barCompile.getInputs()))
+ .containsExactly(MOCK_IBTOOLWRAPPER_PATH, "x/es.lproj/bar.xib");
+
+ assertThat(fooCompile.getArguments())
+ .containsExactly(
+ MOCK_IBTOOLWRAPPER_PATH,
+ fooNibZip.getExecPathString(),
+ "foo.nib", // archive root
+ "--minimum-deployment-target", minimumOsVersion.toString(),
+ "--module", "x",
+ "--target-device", platformType,
+ "x/foo.xib")
+ .inOrder();
+ assertThat(barCompile.getArguments())
+ .containsExactly(
+ MOCK_IBTOOLWRAPPER_PATH,
+ barNibZip.getExecPathString(),
+ "es.lproj/bar.nib", // archive root
+ "--minimum-deployment-target", minimumOsVersion.toString(),
+ "--module", "x",
+ "--target-device", platformType,
+ "x/es.lproj/bar.xib")
+ .inOrder();
+ }
+
+ protected void checkNibZipsMergedIntoBundle(RuleType ruleType) throws Exception {
+ scratch.file("lib/a.m");
+ scratch.file("lib/lib.xib");
+ scratch.file("lib/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " xibs = ['lib.xib'],",
+ ")");
+ scratch.file("x/foo.xib");
+ scratch.file("x/es.lproj/x.xib");
+ ruleType.scratchTarget(scratch,
+ "xibs", "['foo.xib', 'es.lproj/x.xib']",
+ "deps", "['//lib:lib']");
+
+ ConfiguredTarget xTarget = getConfiguredTarget("//x:x");
+ List<Artifact> nibZips = ImmutableList.of(
+ getBinArtifact("x/lib/lib.nib.zip", xTarget),
+ getBinArtifact("x/x/foo.nib.zip", xTarget),
+ getBinArtifact("x/x/es.lproj/x.nib.zip", xTarget));
+ List<BundleMergeProtos.MergeZip> mergeZips = new ArrayList<>();
+ for (Artifact nibZip : nibZips) {
+ mergeZips.add(BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(getBundlePathInsideIpa(ruleType) + "/")
+ .setSourcePath(nibZip.getExecPathString())
+ .build());
+ }
+
+ assertThat(bundleMergeAction("//x:x").getInputs()).containsAllIn(nibZips);
+ assertThat(bundleMergeControl("//x:x").getMergeZipList())
+ .containsAllIn(mergeZips);
+ }
+
+ protected void checkNibZipsMergedIntoBundle(BinaryRuleTypePair ruleTypePair) throws Exception {
+ scratch.file("lib/a.m");
+ scratch.file("lib/lib.xib");
+ scratch.file("lib/BUILD",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " xibs = ['lib.xib'],",
+ ")");
+ scratch.file("x/foo.xib");
+ scratch.file("x/es.lproj/bar.xib");
+ ruleTypePair.scratchTargets(scratch,
+ "xibs", "['foo.xib', 'es.lproj/bar.xib']",
+ "deps", "['//lib:lib']");
+
+ ConfiguredTarget bundlingTarget = getConfiguredTarget("//x:x");
+ List<Artifact> nibZips = ImmutableList.of(
+ getBinArtifact("x/lib/lib.nib.zip", bundlingTarget),
+ getBinArtifact("x/x/foo.nib.zip", bundlingTarget),
+ getBinArtifact("x/x/es.lproj/bar.nib.zip", bundlingTarget));
+ List<BundleMergeProtos.MergeZip> mergeZips = new ArrayList<>();
+ for (Artifact nibZip : nibZips) {
+ mergeZips.add(BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(ruleTypePair.getBundleDir() + "/")
+ .setSourcePath(nibZip.getExecPathString())
+ .build());
+ }
+
+ assertThat(bundleMergeAction("//x:x").getInputs()).containsAllIn(nibZips);
+ assertThat(bundleMergeControl("//x:x").getMergeZipList())
+ .containsAllIn(mergeZips);
+ }
+
+ protected void checkBinaryLipoActionMultiCpu(
+ BinaryRuleTypePair ruleTypePair, ConfigurationDistinguisher configurationDistinguisher)
+ throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--cpu=ios_armv7");
+ ruleTypePair.scratchTargets(scratch);
+
+ CommandAction action = (CommandAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x")));
+
+ String i386Prefix = configurationBin("i386", configurationDistinguisher);
+ String x8664Prefix = configurationBin("x86_64", configurationDistinguisher);
+ assertThat(Artifact.toExecPaths(action.getInputs()))
+ .containsExactly(
+ i386Prefix + "x/bin_bin",
+ x8664Prefix + "x/bin_bin",
+ MOCK_XCRUNWRAPPER_PATH);
+
+ assertThat(action.getArguments())
+ .containsExactly(MOCK_XCRUNWRAPPER_PATH, LIPO,
+ "-create", i386Prefix + "x/bin_bin", x8664Prefix + "x/bin_bin",
+ "-o", execPathEndingWith(action.getOutputs(), "x_lipobin"))
+ .inOrder();
+ }
+
+ protected void checkBinaryActionMultiPlatform_fails(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ useConfiguration(
+ "--ios_multi_cpus=i386,x86_64,armv7,arm64", "--watchos_cpus=armv7k", "--cpu=ios_armv7");
+ ruleTypePair.scratchTargets(scratch);
+
+ try {
+ getConfiguredTarget("//x:x");
+ fail("Multiplatform binary should have failed");
+ } catch (AssertionError expected) {
+ assertThat(expected)
+ .hasMessageThat()
+ .contains(
+ "--ios_multi_cpus does not currently allow values for both simulator and device "
+ + "builds.");
+ }
+ }
+
+ protected void checkMultiCpuResourceInheritance(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ ruleTypePair.scratchTargets(scratch, "resources", "['foo.png']");
+
+ assertThat(Artifact.toRootRelativePaths(bundleMergeAction("//x:x").getInputs()))
+ .containsExactly(
+ "x/foo.png",
+ "x/x_lipobin",
+ "tools/objc/bundlemerge",
+ "x/x.ipa-control",
+ "x/x-MergedInfo.plist");
+ }
+
+ public void checkAllowVariousNonBlacklistedTypesInHeaders(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "hdrs", "['foo.foo', 'NoExtension', 'bar.inc', 'baz.hpp']");
+ assertThat(view.hasErrors(getConfiguredTarget("//x:x"))).isFalse();
+ }
+
+ public void checkWarningForBlacklistedTypesInHeaders(RuleType ruleType) throws Exception {
+ checkWarning("x1", "x1",
+ "file 'foo.a' from target '//x1:foo.a' is not allowed in hdrs",
+ ruleType.target(scratch, "x1", "x1", "hdrs", "['foo.a']"));
+ checkWarning("x2", "x2",
+ "file 'bar.o' from target '//x2:bar.o' is not allowed in hdrs",
+ ruleType.target(scratch, "x2", "x2", "hdrs", "['bar.o']"));
+ }
+
+ public void checkCppSourceCompilesWithCppFlags(RuleType ruleType) throws Exception {
+ useConfiguration("--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL);
+
+ ruleType.scratchTarget(
+ scratch, "srcs", "['a.mm', 'b.cc', 'c.mm', 'd.cxx', 'e.c', 'f.m', 'g.C']");
+ assertThat(compileAction("//x:x", "a.o").getArguments()).contains("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "b.o").getArguments()).contains("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "c.o").getArguments()).contains("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "d.o").getArguments()).contains("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "e.o").getArguments()).doesNotContain("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "f.o").getArguments()).doesNotContain("-stdlib=libc++");
+ assertThat(compileAction("//x:x", "g.o").getArguments()).contains("-stdlib=libc++");
+
+ // Also test that --std=gnu++11 is provided whenever -stdlib=libc++ is.
+ assertThat(compileAction("//x:x", "a.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//x:x", "b.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//x:x", "c.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//x:x", "d.o").getArguments()).contains("-std=gnu++11");
+ assertThat(compileAction("//x:x", "e.o").getArguments()).doesNotContain("-std=gnu++11");
+ assertThat(compileAction("//x:x", "f.o").getArguments()).doesNotContain("-std=gnu++11");
+ assertThat(compileAction("//x:x", "g.o").getArguments()).contains("-std=gnu++11");
+ }
+
+ public void checkBundleIdPassedAsFallbackId(RuleType ruleType) throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Info.plist");
+
+ ruleType.scratchTarget(scratch,
+ INFOPLIST_ATTR, "'Info.plist'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.hasPrimaryBundleIdentifier()).isFalse();
+ assertThat(control.getFallbackBundleIdentifier()).isEqualTo("example.x");
+ }
+
+ public void checkBundleIdPassedAsPrimaryId(RuleType ruleType) throws Exception {
+ scratch.file("bin/a.m");
+ scratch.file("bin/Info.plist");
+
+ ruleType.scratchTarget(scratch,
+ INFOPLIST_ATTR, "'Info.plist'",
+ BUNDLE_ID_ATTR, "'com.bundle.id'");
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+
+ assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.bundle.id");
+ assertThat(control.hasFallbackBundleIdentifier()).isFalse();
+ }
+
+ protected void checkPrimaryBundleIdInMergedPlist(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ INFOPLIST_ATTR, "'Info.plist'",
+ BUNDLE_ID_ATTR, "'com.bundle.id'");
+ scratch.file("bin/Info.plist");
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.bundle.id"), getVariableSubstitutionArgumentsDefaultFormat(ruleType));
+ }
+
+ protected void checkPrimaryBundleIdInMergedPlist(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ ruleTypePair.scratchTargets(scratch,
+ INFOPLIST_ATTR, "'Info.plist'",
+ BUNDLE_ID_ATTR, "'com.bundle.id'");
+ scratch.file("bin/Info.plist");
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.of("com.bundle.id"), getVariableSubstitutionArguments(ruleTypePair));
+ }
+
+ protected void checkFallbackBundleIdInMergedPlist(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ INFOPLIST_ATTR, "'Info.plist'");
+ scratch.file("bin/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(), getVariableSubstitutionArgumentsDefaultFormat(ruleType));
+ }
+
+ protected void checkFallbackBundleIdInMergedPlist(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ ruleTypePair.scratchTargets(scratch,
+ INFOPLIST_ATTR, "'Info.plist'");
+ scratch.file("bin/Info.plist");
+
+ checkBundleIdFlagsInPlistMergeAction(
+ Optional.<String>absent(), getVariableSubstitutionArguments(ruleTypePair));
+ }
+
+ protected void checkBundleIdFlagsInPlistMergeAction(
+ Optional<String> specifiedBundleId, Map<String, String> variableSubstitutions)
+ throws Exception {
+ checkBundleIdFlagsInPlistMergeAction(specifiedBundleId, variableSubstitutions,
+ "example.x");
+ }
+ protected void checkBundleIdFlagsInPlistMergeAction(
+ Optional<String> specifiedBundleId, Map<String, String> variableSubstitutions,
+ String defaultBundleId) throws Exception {
+ String targetName = "//x:x";
+ PlMergeProtos.Control control = plMergeControl(targetName);
+ ConfiguredTarget target = getConfiguredTarget(targetName);
+ Artifact mergedPlist = getMergedInfoPlist(target);
+ String bundleIdToCheck = specifiedBundleId.or(defaultBundleId);
+ Artifact versionInfoplist = getBinArtifact("plists/x" + artifactName("-version.plist"), target);
+ Artifact environmentInfoplist = getBinArtifact("plists/x" + artifactName("-environment.plist"),
+ target);
+ Artifact automaticInfoplist = getBinArtifact("plists/x" + artifactName("-automatic.plist"),
+ target);
+
+ assertPlistMergeControlUsesSourceFiles(
+ control,
+ ImmutableList.<String>of(
+ "x/Info.plist",
+ versionInfoplist.getExecPathString(),
+ environmentInfoplist.getExecPathString(),
+ automaticInfoplist.getExecPathString()));
+ assertThat(control.getOutFile()).isEqualTo(mergedPlist.getExecPathString());
+ assertThat(control.getVariableSubstitutionMapMap())
+ .containsExactlyEntriesIn(variableSubstitutions);
+
+ if (specifiedBundleId.isPresent()) {
+ assertThat(control.hasPrimaryBundleId()).isTrue();
+ assertThat(control.getPrimaryBundleId()).isEqualTo(bundleIdToCheck);
+ } else {
+ assertThat(control.hasFallbackBundleId()).isTrue();
+ assertThat(control.getFallbackBundleId()).isEqualTo(bundleIdToCheck);
+ }
+ }
+
+ protected void checkSigningSimulatorBuild(BinaryRuleTypePair ruleTypePair, boolean useMultiCpu)
+ throws Exception {
+ if (useMultiCpu) {
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--cpu=ios_i386");
+ } else {
+ useConfiguration("--cpu=ios_i386");
+ }
+
+ ruleTypePair.scratchTargets(scratch);
+
+ SpawnAction ipaGeneratingAction = (SpawnAction) ipaGeneratingAction();
+ assertThat(ActionsTestUtil.baseArtifactNames(ipaGeneratingAction.getInputs()))
+ .containsExactly("x.unprocessed.ipa");
+
+ assertThat(normalizeBashArgs(ipaGeneratingAction.getArguments()))
+ .containsAllOf("/usr/bin/codesign", "--sign", "\"-\"")
+ .inOrder();
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ assertThat(mobileProvisionProfiles(control)).isEmpty();
+ }
+
+ protected Action ipaGeneratingAction() throws Exception {
+ return getGeneratingActionForLabel("//x:x.ipa");
+ }
+
+ protected void checkProvisioningProfileDeviceBuild(
+ BinaryRuleTypePair ruleTypePair, boolean useMultiCpu) throws Exception {
+ if (useMultiCpu) {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--cpu=ios_i386", "--watchos_cpus=armv7k");
+ } else {
+ useConfiguration("--cpu=ios_armv7", "--watchos_cpus=armv7k");
+ }
+
+ ruleTypePair.scratchTargets(scratch);
+
+ Artifact provisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ assertThat(ipaGeneratingAction().getInputs()).contains(provisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ ImmutableMap<String, String> expectedProfiles = ImmutableMap.of(
+ provisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ protected void addCustomProvisioningProfile(BinaryRuleTypePair ruleTypePair,
+ String provisioningProfileAttribute) throws Exception {
+ scratch.file("custom/BUILD", "exports_files(['pp.mobileprovision'])");
+ scratch.file("custom/pp.mobileprovision");
+ ruleTypePair.scratchTargets(
+ scratch, provisioningProfileAttribute, "'//custom:pp.mobileprovision'");
+ }
+
+ protected void checkProvisioningProfileUserSpecified(
+ BinaryRuleTypePair ruleTypePair, boolean useMultiCpu) throws Exception {
+ checkProvisioningProfileUserSpecified(ruleTypePair, useMultiCpu, PROVISIONING_PROFILE_ATTR);
+ }
+ protected void checkProvisioningProfileUserSpecified(
+ BinaryRuleTypePair ruleTypePair, boolean useMultiCpu,
+ String provisioningProfileAttribute) throws Exception {
+ if (useMultiCpu) {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--cpu=ios_i386", "--watchos_cpus=armv7k");
+ } else {
+ useConfiguration("--cpu=ios_armv7", "--watchos_cpus=armv7k");
+ }
+ addCustomProvisioningProfile(ruleTypePair, provisioningProfileAttribute);
+
+ Artifact defaultProvisioningProfile =
+ getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact();
+ Artifact customProvisioningProfile =
+ getFileConfiguredTarget("//custom:pp.mobileprovision").getArtifact();
+ Action signingAction = ipaGeneratingAction();
+ assertThat(signingAction.getInputs()).contains(customProvisioningProfile);
+ assertThat(signingAction.getInputs()).doesNotContain(defaultProvisioningProfile);
+
+ BundleMergeProtos.Control control = bundleMergeControl("//x:x");
+ Map<String, String> profiles = mobileProvisionProfiles(control);
+ Map<String, String> expectedProfiles = ImmutableMap.of(
+ customProvisioningProfile.getExecPathString(),
+ ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE);
+ assertThat(profiles).isEqualTo(expectedProfiles);
+ }
+
+ protected void checkMergeBundleAction(BinaryRuleTypePair ruleTypePair) throws Exception {
+ ruleTypePair.scratchTargets(scratch,
+ INFOPLIST_ATTR, "'Info.plist'");
+ SpawnAction action = bundleMergeAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs()))
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ "x/x_lipobin",
+ "x/x.ipa-control",
+ "x/x-MergedInfo.plist");
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x.unprocessed.ipa");
+ assertNotRequiresDarwin(action);
+ assertThat(action.getEnvironment()).isEmpty();
+ assertThat(action.getArguments())
+ .containsExactly(
+ MOCK_BUNDLEMERGE_PATH,
+ execPathEndingWith(action.getInputs(), "x.ipa-control"))
+ .inOrder();
+ }
+
+ protected void checkCollectsAssetCatalogsTransitively(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ scratch.file("lib/ac.xcassets/foo");
+ scratch.file("lib/ac.xcassets/bar");
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .set("asset_catalogs", "glob(['ac.xcassets/**'])")
+ .write();
+
+ scratch.file("x/ac.xcassets/baz");
+ scratch.file("x/ac.xcassets/42");
+ ruleTypePair.scratchTargets(scratch,
+ "deps", "['//lib:lib']",
+ "asset_catalogs", "glob(['ac.xcassets/**'])");
+
+ // Test that the actoolzip Action has arguments and inputs obtained from dependencies.
+ SpawnAction actoolZipAction = actoolZipActionForIpa("//x:x");
+ assertThat(Artifact.toExecPaths(actoolZipAction.getInputs())).containsExactly(
+ "lib/ac.xcassets/foo", "lib/ac.xcassets/bar", "x/ac.xcassets/baz", "x/ac.xcassets/42",
+ MOCK_ACTOOLWRAPPER_PATH);
+ assertContainsSublist(actoolZipAction.getArguments(),
+ ImmutableList.of("lib/ac.xcassets", "x/ac.xcassets"));
+ }
+
+ protected void checkMergeActionsWithAssetCatalog(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ Artifact actoolZipOut = getBinArtifact("x.actool.zip", "//x:x");
+ assertThat(bundleMergeAction("//x:x").getInputs()).contains(actoolZipOut);
+
+ BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x");
+ assertThat(mergeControl.getMergeZipList())
+ .containsExactly(MergeZip.newBuilder()
+ .setEntryNamePrefix(ruleTypePair.getBundleDir() + "/")
+ .setSourcePath(actoolZipOut.getExecPathString())
+ .build());
+ }
+
+ protected void checkBundleablesAreMerged(
+ String bundlingTarget, ListMultimap<String, String> artifactAndBundlePaths) throws Exception {
+ BundleMergeProtos.Control control = bundleMergeControl(bundlingTarget);
+ Action mergeBundleAction = bundleMergeAction(bundlingTarget);
+ List<BundleFile> expectedBundleFiles = new ArrayList<>();
+ for (Map.Entry<String, String> path : artifactAndBundlePaths.entries()) {
+ Artifact artifact = getFirstArtifactEndingWith(mergeBundleAction.getInputs(), path.getKey());
+ expectedBundleFiles.add(BundleFile.newBuilder()
+ .setBundlePath(path.getValue())
+ .setSourceFile(artifact.getExecPathString())
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+ }
+ assertThat(control.getBundleFileList()).containsAllIn(expectedBundleFiles);
+ }
+
+ protected void checkNestedBundleInformationPropagatedToDependers(RuleType ruleType)
+ throws Exception {
+ scratch.file("bndl/bndl-Info.plist");
+ scratch.file("bndl/bndl.png");
+ scratch.file("bndl/BUILD",
+ "objc_bundle_library(",
+ " name = 'bndl',",
+ " infoplist = 'bndl-Info.plist',",
+ " resources = ['bndl.png'],",
+ ")");
+
+ ruleType.scratchTarget(scratch, "bundles", "['//bndl:bndl']");
+
+ scratch.file("bin/bin.m");
+ scratch.file("bin/BUILD",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = ['//x:x'],",
+ ")");
+
+ assertThat(bundleMergeAction("//bin:bin").getInputs())
+ .containsAllOf(
+ getSourceArtifact("bndl/bndl-Info.plist"), getSourceArtifact("bndl/bndl.png"));
+
+ BundleMergeProtos.Control binControl = bundleMergeControl("//bin:bin");
+ BundleMergeProtos.Control bundleControl =
+ Iterables.getOnlyElement(binControl.getNestedBundleList());
+
+ assertThat(bundleControl.getBundleInfoPlistFile()).isEqualTo("bndl/bndl-Info.plist");
+
+ assertThat(bundleControl.getBundleFileList())
+ .containsExactly(BundleMergeProtos.BundleFile.newBuilder()
+ .setBundlePath("bndl.png")
+ .setSourceFile("bndl/bndl.png")
+ .setExternalFileAttribute(BundleableFile.DEFAULT_EXTERNAL_FILE_ATTRIBUTE)
+ .build());
+ }
+
+ protected void checkConvertStringsAction(BinaryRuleTypePair ruleTypePair) throws Exception {
+ scratch.file("lib/foo.strings");
+ scratch.file("lib/es.lproj/bar.strings");
+ ruleTypePair.scratchTargets(scratch, "strings", "['foo.strings', 'es.lproj/bar.strings']");
+
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Artifact binaryFoo = getBinArtifact("x/foo.strings.binary", target);
+ Artifact binaryBar = getBinArtifact("x/es.lproj/bar.strings.binary", target);
+
+ CommandAction fooAction = (CommandAction) getGeneratingAction(binaryFoo);
+ CommandAction barAction = (CommandAction) getGeneratingAction(binaryBar);
+
+ assertThat(fooAction.getOutputs())
+ .containsExactly(binaryFoo);
+ assertThat(Artifact.toExecPaths(fooAction.getInputs()))
+ .containsExactly("x/foo.strings", MOCK_XCRUNWRAPPER_PATH);
+
+ assertThat(barAction.getOutputs())
+ .containsExactly(binaryBar);
+ assertThat(Artifact.toExecPaths(barAction.getInputs()))
+ .containsExactly("x/es.lproj/bar.strings", MOCK_XCRUNWRAPPER_PATH);
+ }
+
+ protected void checkMomczipActions(
+ BinaryRuleTypePair ruleTypePair, DottedVersion minimumOsVersion) throws Exception {
+ createLibraryTargetWriter("//lib:lib")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setList("datamodels", "foo.xcdatamodel/1")
+ .write();
+ ruleTypePair.scratchTargets(scratch,
+ "deps", "['//lib:lib']",
+ "datamodels", "['bar.xcdatamodeld/barx.xcdatamodel/2']");
+
+ AppleConfiguration configuration =
+ getTargetConfiguration().getFragment(AppleConfiguration.class);
+
+ Action mergeBundleAction = bundleMergeAction("//x:x");
+ Artifact fooMomZip = getFirstArtifactEndingWith(mergeBundleAction.getInputs(), "x/foo.zip");
+ CommandAction fooMomczipAction = (CommandAction) getGeneratingAction(fooMomZip);
+ Artifact barMomZip = getFirstArtifactEndingWith(mergeBundleAction.getInputs(), "x/bar.zip");
+ CommandAction barMomczipAction = (CommandAction) getGeneratingAction(barMomZip);
+
+ assertThat(Artifact.toExecPaths(fooMomczipAction.getInputs()))
+ .containsExactly("lib/foo.xcdatamodel/1", MOCK_MOMCWRAPPER_PATH);
+ assertThat(fooMomczipAction.getOutputs()).containsExactly(fooMomZip);
+ assertThat(Artifact.toExecPaths(barMomczipAction.getInputs()))
+ .containsExactly("x/bar.xcdatamodeld/barx.xcdatamodel/2", MOCK_MOMCWRAPPER_PATH);
+ assertThat(barMomczipAction.getOutputs()).containsExactly(barMomZip);
+
+ ImmutableList<String> commonMomcZipArguments = ImmutableList.of(
+ "-XD_MOMC_SDKROOT=" + AppleToolchain.sdkDir(),
+ "-XD_MOMC_IOS_TARGET_VERSION=" + minimumOsVersion,
+ "-MOMC_PLATFORMS",
+ configuration.getMultiArchPlatform(PlatformType.IOS).getLowerCaseNameInPlist(),
+ "-XD_MOMC_TARGET_VERSION=10.6");
+
+ assertThat(fooMomczipAction.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_MOMCWRAPPER_PATH)
+ .add(fooMomZip.getExecPathString())
+ .add("foo.mom")
+ .addAll(commonMomcZipArguments)
+ .add("lib/foo.xcdatamodel")
+ .build());
+ assertThat(barMomczipAction.getArguments())
+ .isEqualTo(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_MOMCWRAPPER_PATH)
+ .add(barMomZip.getExecPathString())
+ .add("bar.momd")
+ .addAll(commonMomcZipArguments)
+ .add("x/bar.xcdatamodeld")
+ .build());
+ }
+
+ protected void addCommonResources(BinaryRuleTypePair ruleTypePair) throws Exception {
+ scratch.file("x/Model.xcdatamodeld/Model-1.0.xcdatamodel/contents");
+ ruleTypePair.scratchTargets(scratch,
+ "strings", "['foo.strings']",
+ "xibs", "['bar.xib']",
+ "storyboards", "['baz.storyboard']",
+ "datamodels", "glob(['Model.xcdatamodeld/**'])");
+ }
+
+ protected void checkMultiCpuCompiledResources(BinaryRuleTypePair ruleTypePair) throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--watchos_cpus=armv7k");
+ addCommonResources(ruleTypePair);
+
+ BundleMergeProtos.Control topControl = bundleMergeControl("//x:x");
+ ImmutableList.Builder<String> bundlePaths = ImmutableList.builder();
+ for (BundleMergeProtos.BundleFile file : topControl.getBundleFileList()) {
+ bundlePaths.add(file.getBundlePath());
+ }
+ assertThat(bundlePaths.build()).containsNoDuplicates();
+
+ ImmutableList.Builder<String> mergeZipNames = ImmutableList.builder();
+ for (BundleMergeProtos.MergeZip zip : topControl.getMergeZipList()) {
+ mergeZipNames.add(Iterables.getLast(Splitter.on('/').split(zip.getSourcePath())));
+ }
+ assertThat(mergeZipNames.build()).containsNoDuplicates();
+ }
+
+ protected void checkMultiCpuCompiledResourcesFromGenrule(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--watchos_cpus=armv7k");
+
+ String targets =
+ ruleTypePair.targets(scratch, "x", "strings", "['Resources/en.lproj/foo.strings']");
+ scratch.file("x/foo.strings");
+ scratch.file("x/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = ['foo.strings'],",
+ " outs = ['Resources/en.lproj/foo.strings'],",
+ " cmd = 'cp $(location foo.strings) $(location Resources/en.lproj/foo.strings)'",
+ ")",
+ targets);
+
+ BundleMergeProtos.Control topControl = bundleMergeControl("//x:x");
+ ImmutableList.Builder<String> bundlePaths = ImmutableList.builder();
+ for (BundleMergeProtos.BundleFile file : topControl.getBundleFileList()) {
+ bundlePaths.add(file.getBundlePath());
+ }
+ assertThat(bundlePaths.build()).containsNoDuplicates();
+ }
+
+ protected void checkMultiCpuGeneratedResourcesFromGenrule(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--watchos_cpus=armv7k");
+
+ String targets = ruleTypePair.targets(scratch, "x", "resources", "[':gen']");
+ scratch.file(
+ "x/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = ['foo'],",
+ " outs = ['foo.res'],",
+ " cmd = 'cp $(location foo) $(location foo.res)'",
+ ")",
+ targets);
+
+ BundleMergeProtos.Control topControl = bundleMergeControl("//x:x");
+ ImmutableList.Builder<String> bundlePaths = ImmutableList.builder();
+ for (BundleMergeProtos.BundleFile file : topControl.getBundleFileList()) {
+ bundlePaths.add(file.getBundlePath());
+ }
+ assertThat(bundlePaths.build()).containsNoDuplicates();
+ }
+
+ protected void checkTwoStringsOneBundlePath(BinaryRuleTypePair ruleTypePair, String errorTarget)
+ throws Exception {
+ String targets = ruleTypePair.targets(scratch, "x",
+ "strings", "['Resources/en.lproj/foo.strings', 'FooBar/en.lproj/foo.strings']");
+ checkTwoStringsOneBundlePath(targets, errorTarget);
+ }
+
+ protected void checkTwoStringsOneBundlePath(RuleType ruleType) throws Exception {
+ String targets = ruleType.target(scratch, "x", "bndl",
+ "strings", "['Resources/en.lproj/foo.strings', 'FooBar/en.lproj/foo.strings']");
+ checkTwoStringsOneBundlePath(targets, "bndl");
+ }
+
+ private void checkTwoStringsOneBundlePath(String targets, String errorTarget) throws Exception {
+ checkError(
+ "x",
+ errorTarget,
+ "Two files map to the same path [en.lproj/foo.strings] in this bundle but come from "
+ + "different locations: //x:Resources/en.lproj/foo.strings and "
+ + "//x:FooBar/en.lproj/foo.strings",
+ targets);
+ }
+
+ protected void checkTwoResourcesOneBundlePath(RuleType ruleType) throws Exception {
+ String targets = ruleType.target(scratch, "x", "bndl", "resources", "['baz/foo', 'bar/foo']");
+ checkTwoResourcesOneBundlePath(targets, "bndl");
+ }
+
+ protected void checkTwoResourcesOneBundlePath(BinaryRuleTypePair ruleTypePair, String errorTarget)
+ throws Exception {
+ String targets = ruleTypePair.targets(scratch, "x", "resources", "['baz/foo', 'bar/foo']");
+ checkTwoResourcesOneBundlePath(targets, errorTarget);
+ }
+
+ private void checkTwoResourcesOneBundlePath(String targets, String errorTarget) throws Exception {
+ checkError(
+ "x",
+ errorTarget,
+ "Two files map to the same path [foo] in this bundle but come from "
+ + "different locations: //x:baz/foo and //x:bar/foo",
+ targets);
+ }
+
+ protected void checkSameStringsTwice(RuleType ruleType) throws Exception {
+ String targets =
+ ruleType.target(
+ scratch,
+ "x",
+ "bndl",
+ "resources",
+ "['Resources/en.lproj/foo.strings']",
+ "strings",
+ "['Resources/en.lproj/foo.strings']");
+ checkSameStringsTwice(targets, "bndl");
+ }
+
+ protected void checkSameStringsTwice(BinaryRuleTypePair ruleTypePair, String errorTarget)
+ throws Exception {
+ String targets =
+ ruleTypePair.targets(
+ scratch,
+ "x",
+ "resources",
+ "['Resources/en.lproj/foo.strings']",
+ "strings",
+ "['Resources/en.lproj/foo.strings']");
+ checkSameStringsTwice(targets, errorTarget);
+ }
+
+ private void checkSameStringsTwice(String targets, String errorTarget) throws Exception {
+ checkError(
+ "x",
+ errorTarget,
+ "The same file was included multiple times in this rule: x/Resources/en.lproj/foo.strings",
+ targets);
+ }
+
+ protected Artifact getMergedInfoPlist(ConfiguredTarget target) {
+ return getBinArtifact(target.getLabel().getName() + artifactName("-MergedInfo.plist"),
+ target);
+ }
+
+ protected void checkTargetHasDebugSymbols(RuleType ruleType) throws Exception {
+ useConfiguration("--apple_generate_dsym");
+ ruleType.scratchTarget(scratch);
+
+ Iterable<Artifact> filesToBuild =
+ getConfiguredTarget("//x:x").getProvider(FileProvider.class).getFilesToBuild();
+ assertThat(filesToBuild)
+ .containsAllOf(
+ getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_bin", "//x:x"),
+ getBinArtifact("x.app.dSYM/Contents/Info.plist", "//x:x"));
+ }
+
+ protected void checkTargetHasCpuSpecificDsymFiles(RuleType ruleType) throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--apple_generate_dsym");
+ ruleType.scratchTarget(scratch);
+
+ List<Artifact> debugArtifacts = new ArrayList<>();
+ debugArtifacts.add(getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_armv7", "//x:x"));
+ debugArtifacts.add(getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_arm64", "//x:x"));
+
+ Iterable<Artifact> filesToBuild =
+ getConfiguredTarget("//x:x").getProvider(FileProvider.class).getFilesToBuild();
+ assertThat(filesToBuild).containsAllIn(debugArtifacts);
+ }
+
+ protected void checkTargetHasDsymPlist(RuleType ruleType) throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64", "--apple_generate_dsym");
+ ruleType.scratchTarget(scratch);
+
+ Iterable<Artifact> filesToBuild =
+ getConfiguredTarget("//x:x").getProvider(FileProvider.class).getFilesToBuild();
+ assertThat(filesToBuild).contains(getBinArtifact("x.app.dSYM/Contents/Info.plist", "//x:x"));
+ }
+
+ protected void checkCcDependency(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ ruleTypePair.scratchTargets(scratch, "deps", "['//lib:cclib']");
+ checkCcDependency(configurationDistinguisher, "bin");
+ }
+
+ /**
+ * @param extraAttrs pairs of key-value strings (must be an even number) which will be added as
+ * extra attributes to the target generated for this test
+ */
+ protected void checkCcDependency(RuleType ruleType, String... extraAttrs) throws Exception {
+ List<String> attrs =
+ ImmutableList.<String>builder()
+ .add("deps")
+ .add("['//lib:cclib']")
+ .add(extraAttrs)
+ .build();
+ ruleType.scratchTarget(scratch, attrs.toArray(new String[0]));
+ checkCcDependency(ConfigurationDistinguisher.UNKNOWN, "x");
+ }
+
+ private void checkCcDependency(
+ ConfigurationDistinguisher configurationDistinguisher, String targetName) throws Exception {
+ useConfiguration(
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("lib/BUILD",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ ")");
+
+ Action appLipoAction = lipoBinAction("//x:x");
+
+ CommandAction binBinAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(appLipoAction.getInputs(), targetName + "_bin"));
+
+ verifyObjlist(
+ binBinAction, String.format("%s-linker.objlist", targetName),
+ "lib/libcclib.a", String.format("x/lib%s.a", targetName));
+
+ assertThat(Artifact.toExecPaths(binBinAction.getInputs()))
+ .containsAllOf(
+ iosConfigurationCcDepsBin("i386", configurationDistinguisher) + "lib/libcclib.a",
+ iosConfigurationCcDepsBin("i386", configurationDistinguisher)
+ + String.format("x/lib%s.a", targetName),
+ iosConfigurationCcDepsBin("i386", configurationDistinguisher)
+ + String.format("x/%s-linker.objlist", targetName));
+ }
+
+ protected void checkCcDependencyMultiArch(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm",
+ "--ios_multi_cpus=armv7,arm64", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("lib/BUILD",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ ")");
+ ruleTypePair.scratchTargets(scratch, "deps", "['//lib:cclib']");
+
+ CommandAction appLipoAction = (CommandAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x", targetConfig)));
+
+ assertThat(Artifact.toExecPaths(appLipoAction.getInputs()))
+ .containsAllOf(
+ configurationBin("armv7", configurationDistinguisher) + "x/bin_bin",
+ configurationBin("arm64", configurationDistinguisher) + "x/bin_bin");
+
+ ImmutableSet.Builder<Artifact> binInputs = ImmutableSet.builder();
+ for (Artifact bin : appLipoAction.getInputs()) {
+ CommandAction binAction = (CommandAction) getGeneratingAction(bin);
+ if (binAction != null) {
+ binInputs.addAll(binAction.getInputs());
+ verifyObjlist(binAction, "x/bin-linker.objlist",
+ "x/libbin.a", "lib/libcclib.a");
+ }
+ }
+
+ assertThat(Artifact.toExecPaths(binInputs.build()))
+ .containsAllOf(
+ configurationBin("armv7", configurationDistinguisher) + "x/libbin.a",
+ configurationBin("arm64", configurationDistinguisher) + "x/libbin.a",
+ configurationBin("armv7", configurationDistinguisher)
+ + "lib/libcclib.a",
+ configurationBin("arm64", configurationDistinguisher)
+ + "lib/libcclib.a",
+ configurationBin("armv7", configurationDistinguisher)
+ + "x/bin-linker.objlist",
+ configurationBin("arm64", configurationDistinguisher)
+ + "x/bin-linker.objlist");
+ }
+
+ protected void checkGenruleDependency(BinaryRuleTypePair ruleTypePair) throws Exception {
+ checkGenruleDependency(ruleTypePair.targets(scratch, "x", "srcs", "['gen.m']"));
+ }
+
+ protected void checkGenruleDependency(RuleType ruleType) throws Exception {
+ checkGenruleDependency(ruleType.target(scratch, "x", "bin", "srcs", "['gen.m']"));
+ }
+
+ private void checkGenruleDependency(String targets) throws Exception {
+ scratch.file("x/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = [],",
+ " outs = ['gen.m'],",
+ " cmd = '\\'\\' > $(location gen.m)'",
+ ")",
+ targets);
+
+ CommandAction binBinAction = (CommandAction)
+ getGeneratingAction(getConfiguredTarget("//x:bin"), "x/bin_bin");
+ Artifact libBin = getFirstArtifactEndingWith(binBinAction.getInputs(), "libbin.a");
+ Action libBinAction = getGeneratingAction(libBin);
+ Action genOAction =
+ getGeneratingAction(Iterables.getOnlyElement(inputsEndingWith(libBinAction, ".o")));
+
+ assertThat(Artifact.toExecPaths(genOAction.getInputs()))
+ .containsExactly(
+ configurationGenfiles(
+ "x86_64",
+ ConfigurationDistinguisher.UNKNOWN,
+ defaultMinimumOs(ConfigurationDistinguisher.UNKNOWN))
+ + "/x/gen.m",
+ MOCK_XCRUNWRAPPER_PATH);
+ }
+
+ protected void checkGenruleDependencyMultiArch(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ useConfiguration("--ios_multi_cpus=armv7,arm64");
+ String targets = ruleTypePair.targets(scratch, "x", "srcs", "['gen.m']");
+ scratch.file("x/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = [],",
+ " outs = ['gen.m'],",
+ " cmd = '\\'\\' > $(location gen.m)'",
+ ")",
+ targets);
+
+ CommandAction appLipoAction = (CommandAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x", targetConfig)));
+
+ assertThat(Artifact.toExecPaths(appLipoAction.getInputs()))
+ .containsExactly(
+ configurationBin("armv7", configurationDistinguisher) + "x/bin_bin",
+ configurationBin("arm64", configurationDistinguisher) + "x/bin_bin",
+ MOCK_XCRUNWRAPPER_PATH);
+ }
+
+ protected void checkGenruleWithoutJavaCcDependency(BinaryRuleTypePair ruleTypePair)
+ throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm",
+ "--ios_multi_cpus=armv7,arm64", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ String targets = ruleTypePair.targets(scratch, "x", "srcs", "['gen.m']");
+ scratch.file("x/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = [],",
+ " outs = ['gen.m'],",
+ " cmd = 'echo \"\" > $(location gen.m)'",
+ ")",
+ targets);
+
+ CommandAction appLipoAction = (CommandAction) getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x", targetConfig)));
+
+ for (Artifact binBin : appLipoAction.getInputs()) {
+ CommandAction binBinAction = (CommandAction) getGeneratingAction(binBin);
+ if (binBinAction == null) {
+ continue;
+ }
+ Action libBinAction =
+ getGeneratingAction(getFirstArtifactEndingWith(binBinAction.getInputs(), "libbin.a"));
+ Action genOAction =
+ getGeneratingAction(Iterables.getOnlyElement(inputsEndingWith(libBinAction, ".o")));
+ Action genMAction =
+ getGeneratingAction(getFirstArtifactEndingWith(genOAction.getInputs(), "gen.m"));
+ assertThat(genMAction).isNotInstanceOf(FailAction.class);
+ }
+ }
+
+ protected void checkCcDependencyWithProtoDependency(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ useConfiguration(
+ "--experimental_disable_go",
+ "--experimental_disable_jvm",
+ "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+ scratch.file("lib/BUILD",
+ "proto_library(",
+ " name = 'protolib',",
+ " srcs = ['foo.proto'],",
+ " cc_api_version = 1,",
+ ")",
+ "",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ " deps = [':protolib'],",
+ ")");
+ ruleTypePair.scratchTargets(scratch, "deps", "['//lib:cclib']");
+
+ Action appLipoAction = lipoBinAction("//x:x");
+
+ CommandAction binBinAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(appLipoAction.getInputs(), "bin_bin"));
+
+ String i386Prefix = iosConfigurationCcDepsBin("i386", configurationDistinguisher);
+ ImmutableList<String> archiveFilenames = ImmutableList.of(
+ i386Prefix + "lib/libcclib.a",
+ i386Prefix + "x/libbin.a",
+ i386Prefix + "lib/libprotolib.a",
+ i386Prefix + "net/proto/libproto.a");
+
+ verifyObjlist(binBinAction, "x/bin-linker.objlist",
+ archiveFilenames.toArray(new String[archiveFilenames.size()]));
+
+ assertThat(Artifact.toExecPaths(binBinAction.getInputs()))
+ .containsAllIn(
+ ImmutableList.builder()
+ .addAll(archiveFilenames)
+ .add(i386Prefix + "x/bin-linker.objlist")
+ .build());
+ }
+
+ protected void checkCcDependencyAndJ2objcDependency(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ MockJ2ObjcSupport.setup(mockToolsConfig);
+ useConfiguration(
+ "--experimental_disable_go",
+ "--cpu=ios_i386",
+ "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("lib/BUILD",
+ "java_library(",
+ " name = 'javalib',",
+ " srcs = ['foo.java'],",
+ ")",
+ "",
+ "j2objc_library(",
+ " name = 'j2objclib',",
+ " deps = [':javalib'],",
+ ")",
+ "",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ ")");
+ ruleTypePair.scratchTargets(scratch, "deps", "['//lib:cclib', '//lib:j2objclib']");
+
+ Action appLipoAction = getGeneratingAction(
+ getBinArtifact("x_lipobin", getConfiguredTarget("//x:x", targetConfig)));
+
+ CommandAction binBinAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(appLipoAction.getInputs(), "bin_bin"));
+
+ String i386Prefix = iosConfigurationCcDepsBin("i386", configurationDistinguisher);
+ ImmutableList<String> archiveFilenames = ImmutableList.of(
+ i386Prefix + "lib/libcclib.a",
+ i386Prefix + "x/libbin.a",
+ i386Prefix + "lib/libjavalib_j2objc.a",
+ i386Prefix + "third_party/java/j2objc/libjre_core_lib.a");
+
+ verifyObjlist(binBinAction, "x/bin-linker.objlist",
+ archiveFilenames.toArray(new String[archiveFilenames.size()]));
+
+ assertThat(Artifact.toExecPaths(binBinAction.getInputs()))
+ .containsAllIn(
+ ImmutableList.builder()
+ .addAll(archiveFilenames)
+ .add(i386Prefix + "x/bin-linker.objlist")
+ .build());
+ }
+
+ protected void checkCcDependencyWithProtoDependencyMultiArch(BinaryRuleTypePair ruleTypePair,
+ ConfigurationDistinguisher configurationDistinguisher) throws Exception {
+ MockProtoSupport.setup(mockToolsConfig);
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm",
+ "--ios_multi_cpus=armv7,arm64", "--crosstool_top=//tools/osx/crosstool:crosstool");
+ scratch.file("lib/BUILD",
+ "proto_library(",
+ " name = 'protolib',",
+ " srcs = ['foo.proto'],",
+ " cc_api_version = 1,",
+ ")",
+ "",
+ "cc_library(",
+ " name = 'cclib',",
+ " srcs = ['dep.c'],",
+ " deps = [':protolib'],",
+ ")");
+ ruleTypePair.scratchTargets(scratch, "deps", "['//lib:cclib']");
+
+ Action appLipoAction = lipoBinAction("//x:x");
+
+ assertThat(Artifact.toExecPaths(appLipoAction.getInputs()))
+ .containsExactly(
+ configurationBin("armv7", configurationDistinguisher) + "x/bin_bin",
+ configurationBin("arm64", configurationDistinguisher) + "x/bin_bin",
+ MOCK_XCRUNWRAPPER_PATH);
+ }
+
+ protected void checkBinaryStripAction(RuleType ruleType, String... extraItems) throws Exception {
+ ruleType.scratchTarget(scratch);
+
+ useConfiguration("--compilation_mode=opt", "--objc_enable_binary_stripping");
+ ConfiguredTarget binaryTarget = getConfiguredTarget("//x:x");
+ Artifact strippedBinary = getBinArtifact("x_bin", binaryTarget);
+ Artifact unstrippedBinary = getBinArtifact("x_bin_unstripped", binaryTarget);
+ CommandAction symbolStripAction = (CommandAction) getGeneratingAction(strippedBinary);
+ boolean isTestRule = ruleType.getRuleTypeName().endsWith("_test");
+
+ ImmutableList.Builder<String> expectedSymbolStripArgs = ImmutableList.<String>builder()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add(STRIP);
+
+ expectedSymbolStripArgs.add(extraItems);
+
+ expectedSymbolStripArgs.add(
+ "-o", strippedBinary.getExecPathString(), unstrippedBinary.getExecPathString());
+
+ assertThat(symbolStripAction.getArguments())
+ .containsExactlyElementsIn(expectedSymbolStripArgs.build())
+ .inOrder();
+
+ CommandAction linkAction = (CommandAction) getGeneratingAction(unstrippedBinary);
+
+ String args = Joiner.on(" ").join(linkAction.getArguments());
+ if (isTestRule) {
+ assertThat(args).doesNotContain("-dead_strip");
+ assertThat(args).doesNotContain("-no_dead_strip_inits_and_terms");
+ } else {
+ assertThat(args).contains("-dead_strip");
+ assertThat(args).contains("-no_dead_strip_inits_and_terms");
+ }
+
+ assertThat(compileAction("//x:x", "a.o").getArguments()).contains("-g");
+ }
+
+ protected void checkLaunchStoryboardIncluded(BinaryRuleTypePair ruleTypePair) throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ ruleTypePair.scratchTargets(scratch, "launch_storyboard", "'launch.storyboard'");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact storyboardZip = getBinArtifact("x/launch.storyboard.zip", target);
+ CommandAction storyboardCompile = (CommandAction) getGeneratingAction(storyboardZip);
+
+ assertThat(storyboardCompile.getInputs())
+ .containsExactly(
+ getSourceArtifact(MOCK_IBTOOLWRAPPER_PATH),
+ getSourceArtifact("x/launch.storyboard"));
+
+ assertThat(storyboardCompile.getArguments())
+ .isEqualTo(
+ new CustomCommandLine.Builder()
+ .add(MOCK_IBTOOLWRAPPER_PATH)
+ .add(storyboardZip.getExecPathString())
+ .add("launch.storyboardc")
+ .add("--minimum-deployment-target")
+ .add("8.1")
+ .add("--module")
+ .add("x")
+ .add("--target-device")
+ .add("iphone")
+ .add("x/launch.storyboard")
+ .build()
+ .arguments());
+
+ assertGeneratesLaunchStoryboardPlist(target, "launch");
+ assertUsesLaunchStoryboardPlist(target);
+ assertMergesLaunchStoryboard(ruleTypePair, storyboardZip);
+ }
+
+ protected void checkLaunchStoryboardXib(BinaryRuleTypePair ruleTypePair) throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ ruleTypePair.scratchTargets(scratch, "launch_storyboard", "'launch.xib'");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact nibZip = getBinArtifact("x/x/launch.nib.zip", target);
+ CommandAction nibCompile = (CommandAction) getGeneratingAction(nibZip);
+
+ assertThat(Artifact.toExecPaths(nibCompile.getInputs()))
+ .containsExactly(MOCK_IBTOOLWRAPPER_PATH, "x/launch.xib");
+
+ assertThat(nibCompile.getArguments())
+ .containsExactly(
+ MOCK_IBTOOLWRAPPER_PATH,
+ nibZip.getExecPathString(),
+ "launch.nib",
+ "--minimum-deployment-target", "8.1",
+ "--module", "x",
+ "--target-device", "iphone",
+ "x/launch.xib")
+ .inOrder();
+
+ assertGeneratesLaunchStoryboardPlist(target, "launch");
+ assertUsesLaunchStoryboardPlist(target);
+ assertMergesLaunchStoryboard(ruleTypePair, nibZip);
+ }
+
+ private void assertGeneratesLaunchStoryboardPlist(ConfiguredTarget target, String baseName)
+ throws Exception {
+ Artifact storyboardPlist =
+ getBinArtifact("plists/" + target.getLabel().getName() + "-launchstoryboard.plist", target);
+
+ FileWriteAction plistAction = (FileWriteAction) getGeneratingAction(storyboardPlist);
+
+ assertThat(plistAction.getFileContents())
+ .contains("\"UILaunchStoryboardName\" = \"" + baseName + "\"");
+ }
+
+ private void assertUsesLaunchStoryboardPlist(ConfiguredTarget target) throws Exception {
+ Artifact storyboardPlist =
+ getBinArtifact("plists/" + target.getLabel().getName() + "-launchstoryboard.plist", target);
+ PlMergeProtos.Control plMergeControl = plMergeControl(target.getLabel().getCanonicalForm());
+
+ assertThat(plMergeControl.getSourceFileList()).contains(storyboardPlist.getExecPathString());
+ }
+
+ private void assertMergesLaunchStoryboard(BinaryRuleTypePair ruleTypePair, Artifact storyboardZip)
+ throws Exception {
+ assertThat(bundleMergeAction("//x:x").getInputs()).contains(storyboardZip);
+ assertThat(bundleMergeControl("//x:x").getMergeZipList())
+ .contains(
+ BundleMergeProtos.MergeZip.newBuilder()
+ .setEntryNamePrefix(ruleTypePair.getBundleDir() + "/")
+ .setSourcePath(storyboardZip.getExecPathString())
+ .build());
+ }
+
+ protected void checkLaunchStoryboardLproj(BinaryRuleTypePair ruleTypePair) throws Exception {
+ useConfiguration("--ios_minimum_os=8.1");
+ ruleTypePair.scratchTargets(
+ scratch, "launch_storyboard", "'superfluous_dir/en.lproj/launch.storyboard'");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ Artifact storyboardZip = getBinArtifact("x/en.lproj/launch.storyboard.zip", target);
+ CommandAction storyboardCompile = (CommandAction) getGeneratingAction(storyboardZip);
+
+ assertThat(storyboardCompile.getInputs())
+ .contains(getSourceArtifact("x/superfluous_dir/en.lproj/launch.storyboard"));
+
+ assertThat(storyboardCompile.getArguments())
+ .containsAllOf(
+ "en.lproj/launch.storyboardc", "x/superfluous_dir/en.lproj/launch.storyboard");
+
+ assertGeneratesLaunchStoryboardPlist(target, "launch");
+ assertMergesLaunchStoryboard(ruleTypePair, storyboardZip);
+ }
+
+ protected void checkAutomaticPlistEntries(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, INFOPLIST_ATTR, RuleType.OMIT_REQUIRED_ATTR);
+
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ Artifact automaticInfoplist = getBinArtifact("plists/x-automatic.plist", target);
+ FileWriteAction automaticInfoplistAction =
+ (FileWriteAction) getGeneratingAction(automaticInfoplist);
+
+ NSDictionary foundAutomaticEntries =
+ (NSDictionary)
+ PropertyListParser.parse(
+ automaticInfoplistAction.getFileContents().getBytes(Charset.defaultCharset()));
+
+ assertThat(foundAutomaticEntries.keySet())
+ .containsExactly(
+ "UIDeviceFamily",
+ "DTPlatformName",
+ "DTSDKName",
+ "CFBundleSupportedPlatforms",
+ "MinimumOSVersion");
+ }
+
+ protected void checkMultipleInfoPlists(RuleType ruleType) throws Exception {
+ scratch.file("x/a.plist");
+ scratch.file("x/b.plist");
+ ruleType.scratchTarget(scratch, "infoplists", "['a.plist', 'b.plist']");
+
+ String targetName = "//x:x";
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/a.plist").getExecPathString());
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/b.plist").getExecPathString());
+ }
+
+ protected void checkInfoplistAndInfoplistsTogether(RuleType ruleType) throws Exception {
+ scratch.file("x/a.plist");
+ scratch.file("x/b.plist");
+ scratch.file("x/c.plist");
+ ruleType.scratchTarget(scratch, "infoplists", "['a.plist', 'b.plist']", INFOPLIST_ATTR,
+ "'c.plist'");
+
+ String targetName = "//x:x";
+ PlMergeProtos.Control control = plMergeControl(targetName);
+
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/a.plist").getExecPathString());
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/b.plist").getExecPathString());
+ assertThat(control.getSourceFileList())
+ .contains(getSourceArtifact("x/c.plist").getExecPathString());
+ }
+
+ protected void checkBundleMergeInputContainsPlMergeOutput(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, INFOPLIST_ATTR, RuleType.OMIT_REQUIRED_ATTR);
+
+ Artifact mergedPlist = getMergedInfoPlist(getConfiguredTarget("//x:x"));
+ CommandAction mergeAction = (CommandAction) getGeneratingAction(mergedPlist);
+
+ assertThat(bundleMergeAction("//x:x").getInputs()).containsAllIn(mergeAction.getOutputs());
+ }
+
+ /**
+ * Computes expected variable substitutions for "x" with full bundle name.
+ */
+ protected Map<String, String> getVariableSubstitutionArgumentsDefaultFormat(RuleType ruleType) {
+ return constructVariableSubstitutions("x", getBundlePathInsideIpa(ruleType));
+ }
+
+ /**
+ * Return the expected name for the bundle.
+ */
+ protected String getBundleNameWithExtension(RuleType ruleType) {
+ return "x." + ruleType.bundleExtension();
+ }
+
+ /**
+ * Return the expected bundle path inside an Ipa.
+ */
+ protected String getBundlePathInsideIpa(RuleType ruleType) {
+ return "Payload/" + getBundleNameWithExtension(ruleType);
+ }
+
+ /**
+ * Computes expected variable substitutions from a ruleTypePair
+ */
+ protected Map<String, String> getVariableSubstitutionArguments(BinaryRuleTypePair ruleTypePair) {
+ return constructVariableSubstitutions(
+ ruleTypePair.getBundleName(), ruleTypePair.getBundleDir());
+ }
+
+ private Map<String, String> constructVariableSubstitutions(String bundleName, String bundleDir) {
+ return new ImmutableMap.Builder<String, String>()
+ .put("EXECUTABLE_NAME", bundleName)
+ .put("BUNDLE_NAME", bundleDir.split("/")[1])
+ .put("PRODUCT_NAME", bundleName)
+ .build();
+ }
+
+ protected void assertPlistMergeControlUsesSourceFiles(
+ PlMergeProtos.Control control, Iterable<String> sourceFilePaths) throws Exception {
+ Iterable<String> allSourceFiles =
+ Iterables.concat(control.getSourceFileList(), control.getImmutableSourceFileList());
+ assertThat(allSourceFiles).containsAllIn(sourceFilePaths);
+ }
+
+ private BinaryFileWriteAction plMergeAction(String binaryLabelString) throws Exception {
+ Label binaryLabel = Label.parseAbsolute(binaryLabelString);
+ ConfiguredTarget binary = getConfiguredTarget(binaryLabelString);
+ return (BinaryFileWriteAction)
+ getGeneratingAction(getBinArtifact(binaryLabel.getName()
+ + artifactName(".plmerge-control"), binary));
+ }
+
+ protected PlMergeProtos.Control plMergeControl(String binaryLabelString) throws Exception {
+ InputStream in = plMergeAction(binaryLabelString).getSource().openStream();
+ return PlMergeProtos.Control.parseFrom(in);
+ }
+
+ protected void setArtifactPrefix(String artifactPrefix) {
+ this.artifactPrefix = artifactPrefix;
+ }
+
+ private String artifactName(String artifactName) {
+ if (artifactPrefix != null) {
+ return String.format("-%s%s", artifactPrefix, artifactName);
+ }
+ return artifactName;
+ }
+
+ /**
+ * Normalizes arguments to a bash action into a space-separated list.
+ *
+ * <p>Bash actions' arguments have two parts, the bash invocation ({@code "/bin/bash", "-c"}) and
+ * the command executed in the bash shell, as a single string. This method merges all these
+ * arguments and splits them on {@code ' '}.
+ */
+ protected List<String> normalizeBashArgs(List<String> args) {
+ return Splitter.on(' ').splitToList(Joiner.on(' ').join(args));
+ }
+
+ /** Returns the directory where objc modules will be cached. */
+ protected String getModulesCachePath() throws InterruptedException {
+ return getAppleCrosstoolConfiguration().getGenfilesFragment()
+ + "/"
+ + CompilationSupport.OBJC_MODULE_CACHE_DIR_NAME;
+ }
+
+ /**
+ * Verifies that the given rule supports the minimum_os attribute, and adds compile and link
+ * args to set the minimum os appropriately, including compile args for dependencies.
+ *
+ * @param ruleType the rule to test
+ */
+ protected void checkMinimumOsLinkAndCompileArg(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "minimum_os_version", "'5.4'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction linkAction = linkAction("//x:x");
+ CommandAction objcLibArchiveAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+ CommandAction objcLibCompileAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(objcLibArchiveAction.getInputs(), "b.o"));
+
+ String linkArgs = Joiner.on(" ").join(linkAction.getArguments());
+ String compileArgs = Joiner.on(" ").join(objcLibCompileAction.getArguments());
+ assertThat(linkArgs).contains("-mios-simulator-version-min=5.4");
+ assertThat(compileArgs).contains("-mios-simulator-version-min=5.4");
+ }
+
+ /**
+ * Verifies that the given rule supports the minimum_os attribute under the watchOS platform
+ * type, and adds compile and link args to set the minimum os appropriately for watchos,
+ * including compile args for dependencies.
+ *
+ * @param ruleType the rule to test
+ */
+ protected void checkMinimumOsLinkAndCompileArg_watchos(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "platform_type", "'watchos'",
+ "minimum_os_version", "'5.4'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction linkAction = linkAction("//x:x");
+ CommandAction objcLibArchiveAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+ CommandAction objcLibCompileAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(objcLibArchiveAction.getInputs(), "b.o"));
+
+ String linkArgs = Joiner.on(" ").join(linkAction.getArguments());
+ String compileArgs = Joiner.on(" ").join(objcLibCompileAction.getArguments());
+ assertThat(linkArgs).contains("-mwatchos-simulator-version-min=5.4");
+ assertThat(compileArgs).contains("-mwatchos-simulator-version-min=5.4");
+ }
+
+ /**
+ * Verifies that the given rule throws a sensible error if the minimum_os attribute has a bad
+ * value.
+ */
+ protected void checkMinimumOs_invalid_nonVersion(RuleType ruleType) throws Exception {
+ checkError("x", "x",
+ String.format(
+ MultiArchSplitTransitionProvider.INVALID_VERSION_STRING_ERROR_FORMAT,
+ "foobar"),
+ ruleType.target(scratch, "x", "x", "minimum_os_version", "'foobar'"));
+ }
+
+ /**
+ * Verifies that the given rule throws a sensible error if the minimum_os attribute has a bad
+ * value.
+ */
+ protected void checkMinimumOs_invalid_containsAlphabetic(RuleType ruleType) throws Exception {
+ checkError("x", "x",
+ String.format(
+ MultiArchSplitTransitionProvider.INVALID_VERSION_STRING_ERROR_FORMAT,
+ "4.3alpha"),
+ ruleType.target(scratch, "x", "x", "minimum_os_version", "'4.3alpha'"));
+ }
+
+ /**
+ * Verifies that the given rule throws a sensible error if the minimum_os attribute has a bad
+ * value.
+ */
+ protected void checkMinimumOs_invalid_tooManyComponents(RuleType ruleType) throws Exception {
+ checkError("x", "x",
+ String.format(
+ MultiArchSplitTransitionProvider.INVALID_VERSION_STRING_ERROR_FORMAT,
+ "4.3.1"),
+ ruleType.target(scratch, "x", "x", "minimum_os_version", "'4.3.1'"));
+ }
+
+ protected void checkDylibDependencies(RuleType ruleType,
+ ExtraLinkArgs extraLinkArgs) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "dylibs", "['//fx:framework_import']");
+
+ scratch.file("fx/MyFramework.framework/MyFramework");
+ scratch.file("fx/BUILD",
+ "objc_framework(",
+ " name = 'framework_import',",
+ " framework_imports = glob(['MyFramework.framework/*']),",
+ " is_dynamic = 1,",
+ ")");
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--experimental_disable_go",
+ "--experimental_disable_jvm", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ Action lipobinAction = lipoBinAction("//x:x");
+
+ String i386Bin =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x_bin";
+ String i386Filelist =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x-linker.objlist";
+ String x8664Bin =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x_bin";
+ String x8664Filelist =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x-linker.objlist";
+
+ Artifact i386BinArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), i386Bin);
+ Artifact i386FilelistArtifact =
+ getFirstArtifactEndingWith(getGeneratingAction(i386BinArtifact).getInputs(), i386Filelist);
+ Artifact x8664BinArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), x8664Bin);
+ Artifact x8664FilelistArtifact =
+ getFirstArtifactEndingWith(getGeneratingAction(x8664BinArtifact).getInputs(),
+ x8664Filelist);
+
+ ImmutableList<String> archiveNames =
+ ImmutableList.of("x/libx.a", "lib1/liblib1.a", "lib2/liblib2.a");
+ verifyLinkAction(i386BinArtifact, i386FilelistArtifact, "i386", archiveNames,
+ ImmutableList.of(PathFragment.create("fx/MyFramework")), extraLinkArgs);
+ verifyLinkAction(x8664BinArtifact, x8664FilelistArtifact,
+ "x86_64", archiveNames, ImmutableList.of(PathFragment.create("fx/MyFramework")),
+ extraLinkArgs);
+ }
+
+ protected void checkLipoBinaryAction(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']");
+
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+
+ CommandAction action = (CommandAction) lipoBinAction("//x:x");
+ String i386Bin =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS) + "x/x_bin";
+ String x8664Bin =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS) + "x/x_bin";
+
+ assertThat(Artifact.toExecPaths(action.getInputs()))
+ .containsExactly(i386Bin, x8664Bin, MOCK_XCRUNWRAPPER_PATH);
+
+ assertThat(action.getArguments())
+ .containsExactly(MOCK_XCRUNWRAPPER_PATH, LIPO,
+ "-create", i386Bin, x8664Bin,
+ "-o", execPathEndingWith(action.getOutputs(), "x_lipobin"))
+ .inOrder();
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x_lipobin");
+ assertRequiresDarwin(action);
+ }
+
+ protected void checkMultiarchCcDep(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']", "deps", "['//package:cclib']");
+ scratch.file("package/BUILD",
+ "cc_library(name = 'cclib', srcs = ['dep.c'])");
+
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--experimental_disable_go",
+ "--experimental_disable_jvm", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ Action appLipoAction = actionProducingArtifact("//x:x", "_lipobin");
+ String i386Prefix =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS);
+ String x8664Prefix =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS);
+
+ CommandAction i386BinAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(appLipoAction.getInputs(), i386Prefix + "x/x_bin"));
+
+ CommandAction x8664BinAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(appLipoAction.getInputs(), x8664Prefix + "x/x_bin"));
+
+ verifyObjlist(
+ i386BinAction, "x/x-linker.objlist",
+ "x/libx.a", "package/libcclib.a");
+ verifyObjlist(
+ x8664BinAction, "x/x-linker.objlist",
+ "x/libx.a", "package/libcclib.a");
+
+ assertThat(Artifact.toExecPaths(i386BinAction.getInputs()))
+ .containsAllOf(
+ i386Prefix + "x/libx.a",
+ i386Prefix + "package/libcclib.a",
+ i386Prefix + "x/x-linker.objlist");
+ assertThat(Artifact.toExecPaths(x8664BinAction.getInputs()))
+ .containsAllOf(
+ x8664Prefix + "x/libx.a",
+ x8664Prefix + "package/libcclib.a",
+ x8664Prefix + "x/x-linker.objlist");
+ }
+
+ protected void checkLinkActionsWithSrcs(RuleType ruleType,
+ ExtraLinkArgs extraLinkArgs) throws Exception {
+ createLibraryTargetWriter("//lib1:lib1")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ createLibraryTargetWriter("//lib2:lib2")
+ .setAndCreateFiles("srcs", "a.m", "b.m", "private.h")
+ .setAndCreateFiles("hdrs", "hdr.h")
+ .write();
+ ruleType.scratchTarget(scratch,
+ "srcs", "['a.m']",
+ "deps", "['//lib1:lib1', '//lib2:lib2']");
+ useConfiguration("--ios_multi_cpus=i386,x86_64", "--experimental_disable_go",
+ "--experimental_disable_jvm", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ Action lipobinAction = lipoBinAction("//x:x");
+
+ String i386Bin =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x_bin";
+ String i386Filelist =
+ configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x-linker.objlist";
+ String x8664Bin =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x_bin";
+ String x8664Filelist =
+ configurationBin("x86_64", ConfigurationDistinguisher.APPLEBIN_IOS)
+ + "x/x-linker.objlist";
+
+ Artifact i386BinArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), i386Bin);
+ Artifact i386FilelistArtifact =
+ getFirstArtifactEndingWith(getGeneratingAction(i386BinArtifact).getInputs(), i386Filelist);
+ Artifact x8664BinArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), x8664Bin);
+ Artifact x8664FilelistArtifact =
+ getFirstArtifactEndingWith(getGeneratingAction(x8664BinArtifact).getInputs(),
+ x8664Filelist);
+
+ ImmutableList<String> archiveNames =
+ ImmutableList.of("x/libx.a", "lib1/liblib1.a", "lib2/liblib2.a");
+ verifyLinkAction(i386BinArtifact, i386FilelistArtifact, "i386", archiveNames,
+ ImmutableList.<PathFragment>of(), extraLinkArgs);
+ verifyLinkAction(x8664BinArtifact, x8664FilelistArtifact,
+ "x86_64", archiveNames, ImmutableList.<PathFragment>of(), extraLinkArgs);
+ }
+
+ // Regression test for b/32310268.
+ protected void checkAliasedLinkoptsThroughObjcLibrary(RuleType ruleType) throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm",
+ "--cpu=ios_i386", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("bin/BUILD",
+ "objc_library(",
+ " name = 'objclib',",
+ " srcs = ['objcdep.c'],",
+ " deps = ['cclib'],",
+ ")",
+ "alias(",
+ " name = 'cclib',",
+ " actual = 'cclib_real',",
+ ")",
+ "cc_library(",
+ " name = 'cclib_real',",
+ " srcs = ['ccdep.c'],",
+ " linkopts = ['-somelinkopt'],",
+ ")");
+
+ ruleType.scratchTarget(scratch,
+ "srcs", "['main.m']",
+ "deps", "['//bin:objclib']");
+
+ // Frameworks should get placed together with no duplicates.
+ assertThat(Joiner.on(" ").join(linkAction("//x").getArguments()))
+ .contains("-somelinkopt");
+ }
+
+ protected void checkCcDependencyLinkoptsArePropagatedToLinkAction(
+ RuleType ruleType) throws Exception {
+ useConfiguration("--experimental_disable_go", "--experimental_disable_jvm",
+ "--cpu=ios_i386", "--crosstool_top=//tools/osx/crosstool:crosstool");
+
+ scratch.file("bin/BUILD",
+ "cc_library(",
+ " name = 'cclib1',",
+ " srcs = ['dep1.c'],",
+ " linkopts = ['-framework F1', '-framework F2', '-Wl,--other-opt'],",
+ ")",
+ "cc_library(",
+ " name = 'cclib2',",
+ " srcs = ['dep2.c'],",
+ " linkopts = ['-another-opt', '-framework F2'],",
+ " deps = ['cclib1'],",
+ ")",
+ "cc_library(",
+ " name = 'cclib3',",
+ " srcs = ['dep2.c'],",
+ " linkopts = ['-one-more-opt', '-framework UIKit'],",
+ " deps = ['cclib1'],",
+ ")");
+
+ ruleType.scratchTarget(scratch,
+ "srcs", "['main.m']",
+ "deps", "['//bin:cclib2', '//bin:cclib3']");
+
+ // Frameworks from the CROSSTOOL "apply_implicit_frameworks" feature should be present.
+ assertThat(Joiner.on(" ").join(linkAction("//x").getArguments()))
+ .contains("-framework Foundation -framework UIKit");
+ // Frameworks included in linkopts by the user should get placed together with no duplicates.
+ // (They may duplicate the ones inserted by the CROSSTOOL feature, but we don't test that here.)
+ assertThat(Joiner.on(" ").join(linkAction("//x").getArguments()))
+ .contains("-framework F2 -framework F1");
+ // Linkopts should also be grouped together.
+ assertThat(Joiner.on(" ").join(linkAction("//x").getArguments()))
+ .contains("-another-opt -Wl,--other-opt -one-more-opt");
+ }
+
+ protected void checkAppleSdkVersionEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+
+ CommandAction action = linkAction("//x:x");
+
+ assertAppleSdkVersionEnv(action);
+ }
+
+ protected void checkNonDefaultAppleSdkVersionEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+ useConfiguration("--ios_sdk_version=8.1");
+
+ CommandAction action = linkAction("//x:x");
+
+ assertAppleSdkVersionEnv(action, "8.1");
+ }
+
+ protected void checkAppleSdkDefaultPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+ CommandAction action = linkAction("//x:x");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneSimulator");
+ }
+
+ protected void checkAppleSdkIphoneosPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_disable_go",
+ "--cpu=ios_arm64");
+
+ CommandAction action = linkAction("//x:x");
+
+ assertAppleSdkPlatformEnv(action, "iPhoneOS");
+ }
+
+ protected void checkAppleSdkWatchsimulatorPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "platform_type", "'watchos'");
+ useConfiguration("--watchos_cpus=i386");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+
+ String i386Bin = configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchSimulator");
+ }
+
+ protected void checkAppleSdkWatchosPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "platform_type", "'watchos'");
+ useConfiguration("--watchos_cpus=armv7k");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+
+ String armv7kBin =
+ configurationBin("armv7k", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), armv7kBin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchOS");
+ }
+
+ protected void checkAppleSdkTvsimulatorPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "platform_type", "'tvos'");
+ useConfiguration("--tvos_cpus=x86_64");
+
+ CommandAction linkAction = linkAction("//x:x");
+
+ assertAppleSdkPlatformEnv(linkAction, "AppleTVSimulator");
+ }
+
+ protected void checkAppleSdkTvosPlatformEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "platform_type", "'tvos'");
+ useConfiguration("--tvos_cpus=arm64");
+
+ CommandAction linkAction = linkAction("//x:x");
+
+ assertAppleSdkPlatformEnv(linkAction, "AppleTVOS");
+ }
+
+ protected void checkLinkMinimumOSVersion(ConfigurationDistinguisher distinguisher, String arch,
+ String minOSVersionOption) throws Exception {
+ CommandAction linkAction = linkAction("//x:x");
+
+ assertThat(Joiner.on(" ").join(linkAction.getArguments())).contains(minOSVersionOption);
+ }
+
+ protected void checkWatchSimulatorDepCompile(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "platform_type", "'watchos'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+
+ String i386Bin = configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+ CommandAction objcLibCompileAction = (CommandAction) getGeneratingAction(
+ getFirstArtifactEndingWith(linkAction.getInputs(), "libobjcLib.a"));
+
+ assertAppleSdkPlatformEnv(objcLibCompileAction, "WatchSimulator");
+ assertThat(objcLibCompileAction.getArguments()).containsAllOf("-arch_only", "i386").inOrder();
+ }
+
+ protected void checkWatchSimulatorLinkAction(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "platform_type", "'watchos'");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+
+ // Tests that ios_multi_cpus and cpu are completely ignored.
+ useConfiguration("--ios_multi_cpus=x86_64", "--cpu=ios_x86_64", "--watchos_cpus=i386");
+
+ Action lipoAction = actionProducingArtifact("//x:x", "_lipobin");
+
+ String i386Bin = configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+ Artifact binArtifact = getFirstArtifactEndingWith(lipoAction.getInputs(), i386Bin);
+ CommandAction linkAction = (CommandAction) getGeneratingAction(binArtifact);
+
+ assertAppleSdkPlatformEnv(linkAction, "WatchSimulator");
+ assertThat(normalizeBashArgs(linkAction.getArguments()))
+ .containsAllOf("-arch", "i386").inOrder();
+ }
+
+ protected void checkWatchSimulatorLipoAction(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "platform_type", "'watchos'");
+
+ // Tests that ios_multi_cpus and cpu are completely ignored.
+ useConfiguration("--ios_multi_cpus=x86_64", "--cpu=ios_x86_64", "--watchos_cpus=i386,armv7k");
+
+ CommandAction action = (CommandAction) lipoBinAction("//x:x");
+ String i386Bin = configurationBin("i386", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+ String armv7kBin = configurationBin("armv7k", ConfigurationDistinguisher.APPLEBIN_WATCHOS)
+ + "x/x_bin";
+
+ assertThat(Artifact.toExecPaths(action.getInputs()))
+ .containsExactly(i386Bin, armv7kBin, MOCK_XCRUNWRAPPER_PATH);
+
+ assertContainsSublist(action.getArguments(), ImmutableList.of(
+ MOCK_XCRUNWRAPPER_PATH, LIPO, "-create"));
+ assertThat(action.getArguments()).containsAllOf(armv7kBin, i386Bin);
+ assertContainsSublist(action.getArguments(), ImmutableList.of(
+ "-o", execPathEndingWith(action.getOutputs(), "x_lipobin")));
+
+ assertThat(Artifact.toRootRelativePaths(action.getOutputs()))
+ .containsExactly("x/x_lipobin");
+ assertAppleSdkPlatformEnv(action, "WatchOS");
+ assertRequiresDarwin(action);
+ }
+
+ protected void checkXcodeVersionEnv(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch);
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction action = linkAction("//x:x");
+
+ assertXcodeVersionEnv(action, "5.8");
+ }
+
+ protected void checkNoSrcs(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']");
+ scratch.file("package/BUILD",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ])");
+ useConfiguration("--xcode_version=5.8");
+
+ CommandAction action = linkAction("//x:x");
+ assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllOf(
+ "x/libx.a", "package/libobjcLib.a", "x/x-linker.objlist");
+ }
+
+ public void checkLinkingRuleCanUseCrosstool(RuleType ruleType) throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+
+ // If bin is indeed using the c++ backend, then its archive action should be a CppLinkAction.
+ Action action =
+ getGeneratingAction(getBinArtifact("lib" + target.getLabel().getName() + ".a", target));
+ assertThat(action).isInstanceOf(CppLinkAction.class);
+ }
+
+ public void checkLinkingRuleCanUseCrosstool_singleArch(RuleType ruleType) throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+
+ // If bin is indeed using the c++ backend, then its archive action should be a CppLinkAction.
+ Action lipobinAction = lipoBinAction("//x:x");
+ Artifact bin = getFirstArtifactEndingWith(lipobinAction.getInputs(), "_bin");
+ Action linkAction = getGeneratingAction(bin);
+ Artifact archive = getFirstArtifactEndingWith(linkAction.getInputs(), ".a");
+ Action archiveAction = getGeneratingAction(archive);
+ assertThat(archiveAction).isInstanceOf(CppLinkAction.class);
+ }
+
+ public void checkLinkingRuleCanUseCrosstool_multiArch(RuleType ruleType) throws Exception {
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all",
+ "--ios_multi_cpus=i386,x86_64");
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+
+ // If bin is indeed using the c++ backend, then its archive action should be a CppLinkAction.
+ Action lipobinAction = lipoBinAction("//x:x");
+ Artifact bin = getFirstArtifactEndingWith(lipobinAction.getInputs(), "_bin");
+ Action linkAction = getGeneratingAction(bin);
+ Artifact archive = getFirstArtifactEndingWith(linkAction.getInputs(), ".a");
+ Action archiveAction = getGeneratingAction(archive);
+ assertThat(archiveAction).isInstanceOf(CppLinkAction.class);
+ }
+
+ protected void scratchFrameworkSkylarkStub(String bzlPath) throws Exception {
+ PathFragment pathFragment = PathFragment.create(bzlPath);
+ scratch.file(pathFragment.getParentDirectory() + "/BUILD");
+ scratch.file(
+ bzlPath,
+ "def framework_stub_impl(ctx):",
+ " bin_provider = ctx.attr.binary[apple_common.AppleDylibBinary]",
+ " my_provider = apple_common.new_dynamic_framework_provider(",
+ " objc = bin_provider.objc,",
+ " binary = bin_provider.binary,",
+ " framework_files = depset([bin_provider.binary]),",
+ " framework_dirs = depset(['_frameworks/stubframework.framework']))",
+ " return struct(providers = [my_provider])",
+ "framework_stub_rule = rule(",
+ " framework_stub_impl,",
+ // Both 'binary' and 'deps' are needed because ObjcProtoAspect is applied transitively
+ // along attribute 'deps' only.
+ " attrs = {'binary': attr.label(mandatory=True,",
+ " providers=[apple_common.AppleDylibBinary]),",
+ " 'deps': attr.label_list(providers=[apple_common.AppleDylibBinary])},",
+ " fragments = ['apple', 'objc'],",
+ ")");
+ }
+
+ private void assertAvoidDepsObjects(RuleType ruleType) throws Exception {
+ /*
+ * The target tree for ease of understanding:
+ * x depends on "avoidLib" as a dylib and "objcLib" as a static dependency.
+ *
+ * ( objcLib )
+ * / \
+ * ( avoidLib ) ( baseLib )
+ * / / \
+ * (avoidLibDep) / (baseLibDep)
+ * \ /
+ * ( avoidLibDepTwo )
+ *
+ * All libraries prefixed with "avoid" shouldn't be statically linked in the top level target.
+ */
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "dylibs", "['//package:avoidLib']");
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file("package/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ],",
+ " deps = [':avoidLibDep', ':baseLib'])",
+ "objc_library(name = 'baseLib', srcs = [ 'base.m' ],",
+ " deps = [':baseLibDep', ':avoidLibDepTwo'])",
+ "objc_library(name = 'baseLibDep', srcs = [ 'basedep.m' ],",
+ " sdk_frameworks = ['BaseSDK'], resources = [':base.png'])",
+ "framework_stub_rule(name = 'avoidLib', binary = ':avoidLibBinary')",
+ "apple_binary(name = 'avoidLibBinary', binary_type = 'dylib', srcs = [ 'c.m' ],",
+ " platform_type = 'ios',",
+ " deps = [':avoidLibDep'])",
+ "objc_library(name = 'avoidLibDep', srcs = [ 'd.m' ], deps = [':avoidLibDepTwo'])",
+ "objc_library(name = 'avoidLibDepTwo', srcs = [ 'e.m' ],",
+ " sdk_frameworks = ['AvoidSDK'], resources = [':avoid.png'])");
+
+ Action lipobinAction = lipoBinAction("//x:x");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), "x/x_bin");
+
+ Action action = getGeneratingAction(binArtifact);
+
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "x/libx.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libobjcLib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libbaseLib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libbaseLibDep.a"))
+ .isNotNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libavoidLib.a")).isNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libavoidLibDepTwo.a"))
+ .isNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libavoidLibDep.a")).isNull();
+ }
+
+ public void checkAvoidDepsObjectsWithCrosstool(RuleType ruleType) throws Exception {
+ useConfiguration(ObjcCrosstoolMode.ALL, "--ios_multi_cpus=i386,x86_64");
+ assertAvoidDepsObjects(ruleType);
+ }
+
+ public void checkAvoidDepsObjects(RuleType ruleType) throws Exception {
+ useConfiguration("--ios_multi_cpus=i386,x86_64");
+ assertAvoidDepsObjects(ruleType);
+ }
+
+ /**
+ * Verifies that if apple_binary A depends on a dylib B1 which then depends on a dylib B2,
+ * that the symbols from B2 are not present in A.
+ */
+ public void checkAvoidDepsThroughDylib(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:ObjcLib']",
+ "dylibs", "['//package:dylib1']");
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file("package/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "objc_library(name = 'ObjcLib', srcs = [ 'ObjcLib.m' ],",
+ " deps = [':Dylib1Lib', ':Dylib2Lib'])",
+ "objc_library(name = 'Dylib1Lib', srcs = [ 'Dylib1Lib.m' ])",
+ "objc_library(name = 'Dylib2Lib', srcs = [ 'Dylib2Lib.m' ])",
+ "framework_stub_rule(name = 'dylib1', binary = ':dylib1Binary')",
+ "apple_binary(name = 'dylib1Binary', binary_type = 'dylib', srcs = [ 'Dylib1Bin.m' ],",
+ " platform_type = 'ios',",
+ " deps = [':Dylib1Lib'], dylibs = ['//package:dylib2'])",
+ "framework_stub_rule(name = 'dylib2', binary = ':dylib2Binary')",
+ "apple_binary(name = 'dylib2Binary', binary_type = 'dylib', srcs = [ 'Dylib2Bin.m' ],",
+ " platform_type = 'ios',",
+ " deps = [':Dylib2Lib'])",
+ "apple_binary(name = 'alternate', srcs = [ 'alternate.m' ],",
+ " platform_type = 'ios',",
+ " deps = ['//package:ObjcLib'])");
+
+ Action lipobinAction = lipoBinAction("//x:x");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), "x/x_bin");
+
+ Action linkAction = getGeneratingAction(binArtifact);
+
+ assertThat(getFirstArtifactEndingWith(linkAction.getInputs(),
+ "package/libObjcLib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(linkAction.getInputs(),
+ "package/libDylib1Lib.a")).isNull();
+ assertThat(getFirstArtifactEndingWith(linkAction.getInputs(),
+ "package/libDylib2Lib.a")).isNull();
+
+ // Sanity check that the identical binary without dylibs would be fully linked.
+ Action alternateLipobinAction = lipoBinAction("//package:alternate");
+ Artifact alternateBinArtifact = getFirstArtifactEndingWith(alternateLipobinAction.getInputs(),
+ "package/alternate_bin");
+ Action alternateLinkAction = getGeneratingAction(alternateBinArtifact);
+
+ assertThat(getFirstArtifactEndingWith(alternateLinkAction.getInputs(),
+ "package/libObjcLib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(alternateLinkAction.getInputs(),
+ "package/libDylib1Lib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(alternateLinkAction.getInputs(),
+ "package/libDylib2Lib.a")).isNotNull();
+ }
+
+ /**
+ * Tests that direct cc_library dependencies of a dylib (and their dependencies) are correctly
+ * removed from the main binary.
+ */
+ // transitively avoided, even if it is not present in deps.
+ public void checkAvoidDepsObjects_avoidViaCcLibrary(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch,
+ "deps", "['//package:objcLib']",
+ "dylibs", "['//package:avoidLib']");
+ scratchFrameworkSkylarkStub("frameworkstub/framework_stub.bzl");
+ scratch.file("package/BUILD",
+ "load('//frameworkstub:framework_stub.bzl', 'framework_stub_rule')",
+ "framework_stub_rule(name = 'avoidLib', binary = ':avoidLibBinary')",
+ "apple_binary(name = 'avoidLibBinary', binary_type = 'dylib', srcs = [ 'c.m' ],",
+ " platform_type = 'ios',",
+ " deps = [':avoidCclib'])",
+ "cc_library(name = 'avoidCclib', srcs = ['cclib.c'], deps = [':avoidObjcLib'])",
+ "objc_library(name = 'objcLib', srcs = [ 'b.m' ], deps = [':avoidObjcLib'])",
+ "objc_library(name = 'avoidObjcLib', srcs = [ 'c.m' ])");
+
+ Action lipobinAction = actionProducingArtifact("//x:x", "_lipobin");
+ Artifact binArtifact = getFirstArtifactEndingWith(lipobinAction.getInputs(), "x/x_bin");
+
+ Action action = getGeneratingAction(binArtifact);
+
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libobjcLib.a")).isNotNull();
+ assertThat(getFirstArtifactEndingWith(action.getInputs(), "package/libavoidObjcLib.a"))
+ .isNull();
+ }
+
+ public void checkFilesToCompileOutputGroup(RuleType ruleType) throws Exception {
+ ruleType.scratchTarget(scratch, "srcs", "['a.m']");
+ ConfiguredTarget target = getConfiguredTarget("//x:x");
+ assertThat(
+ ActionsTestUtil.baseNamesOf(
+ getOutputGroup(target, OutputGroupProvider.FILES_TO_COMPILE)))
+ .isEqualTo("a.o");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcSkylarkTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcSkylarkTest.java
new file mode 100644
index 0000000000..4dea91f381
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcSkylarkTest.java
@@ -0,0 +1,1234 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.rules.objc.BundleableFile.BUNDLED_FIELD;
+import static com.google.devtools.build.lib.rules.objc.BundleableFile.BUNDLE_PATH_FIELD;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ObjectArrays;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.apple.DottedVersion;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import com.google.devtools.build.lib.syntax.SkylarkDict;
+import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for Skylark interaction with the objc_* rules.
+ */
+@RunWith(JUnit4.class)
+public class ObjcSkylarkTest extends ObjcRuleTestCase {
+
+ @Override
+ protected void useConfiguration(String... args) throws Exception {
+ // Do not test crosstool for skylark tests.
+ useConfiguration(ObjcCrosstoolMode.OFF, args);
+ }
+
+ @Test
+ public void testSkylarkRuleCanDependOnNativeAppleRule() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " return struct(",
+ " found_libs = dep.objc.library,",
+ " found_hdrs = dep.objc.header,",
+ " )",
+ "my_rule = rule(implementation = my_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False, providers = ['objc']),",
+ "})");
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'my_rule')",
+ "my_rule(",
+ " name = 'my_target',",
+ " deps = [':lib'],",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " hdrs = ['b.h']",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+ SkylarkNestedSet skylarkLibraries =
+ (SkylarkNestedSet) skylarkTarget.get("found_libs");
+ SkylarkNestedSet skylarkHdrs =
+ (SkylarkNestedSet) skylarkTarget.get("found_hdrs");
+
+ assertThat(ActionsTestUtil.baseArtifactNames(skylarkLibraries.getSet(Artifact.class)))
+ .contains("liblib.a");
+ assertThat(ActionsTestUtil.baseArtifactNames(skylarkHdrs.getSet(Artifact.class)))
+ .contains("b.h");
+ }
+
+ @Test
+ public void testSkylarkProviderRetrievalNoneIfNoProvider() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " objc_provider = dep.objc",
+ " return struct()",
+ "my_rule = rule(implementation = my_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False),",
+ "})");
+ scratch.file("examples/apple_skylark/a.cc");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'my_rule')",
+ "my_rule(",
+ " name = 'my_target',",
+ " deps = [':lib'],",
+ ")",
+ "cc_library(",
+ " name = 'lib',",
+ " srcs = ['a.cc'],",
+ " hdrs = ['b.h']",
+ ")");
+ try {
+ getConfiguredTarget("//examples/apple_skylark:my_target");
+ fail("Should throw assertion error");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains("File \"/workspace/examples/apple_skylark/BUILD\", line 3");
+ assertThat(e).hasMessageThat().contains("my_rule(name = 'my_target')");
+ assertThat(e)
+ .hasMessageThat()
+ .contains("File \"/workspace/examples/rule/apple_rules.bzl\", line 3, in my_rule_impl");
+ assertThat(e).hasMessageThat().contains("dep.objc");
+ assertThat(e)
+ .hasMessageThat()
+ .contains("target (rule class of 'cc_library') doesn't have provider 'objc'.");
+ }
+ }
+
+ @Test
+ public void testSkylarkProviderCanCheckForExistanceOfObjcProvider() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " cc_has_provider = hasattr(ctx.attr.deps[0], 'objc')",
+ " objc_has_provider = hasattr(ctx.attr.deps[1], 'objc')",
+ " return struct(cc_has_provider=cc_has_provider, objc_has_provider=objc_has_provider)",
+ "my_rule = rule(implementation = my_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False),",
+ "})");
+ scratch.file("examples/apple_skylark/a.cc");
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'my_rule')",
+ "my_rule(",
+ " name = 'my_target',",
+ " deps = [':cc_lib', ':objc_lib'],",
+ ")",
+ "objc_library(",
+ " name = 'objc_lib',",
+ " srcs = ['a.m'],",
+ ")",
+ "cc_library(",
+ " name = 'cc_lib',",
+ " srcs = ['a.cc'],",
+ ")");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+ boolean ccResult =
+ (boolean) skylarkTarget.get("cc_has_provider");
+ boolean objcResult =
+ (boolean) skylarkTarget.get("objc_has_provider");
+ assertThat(ccResult).isFalse();
+ assertThat(objcResult).isTrue();
+ }
+
+ @Test
+ public void testSkylarkExportsObjcProviderToNativeRule() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " objc_provider = dep.objc",
+ " return struct(objc=objc_provider)",
+ "swift_library = rule(implementation = my_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False, providers = ['objc'])",
+ "})");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'swift_library')",
+ "swift_library(",
+ " name='my_target',",
+ " deps=[':lib'],",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " defines = ['mock_define']",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " deps = [':my_target']",
+ ")");
+
+ ConfiguredTarget binaryTarget = getConfiguredTarget("//examples/apple_skylark:bin");
+ ObjcProvider objcProvider = binaryTarget.getProvider(ObjcProvider.class);
+
+ assertThat(Artifact.toRootRelativePaths(objcProvider.get(ObjcProvider.LIBRARY)))
+ .contains("examples/apple_skylark/liblib.a");
+ assertThat(objcProvider.get(ObjcProvider.DEFINE)).contains("mock_define");
+ }
+
+ @Test
+ public void testObjcRuleCanDependOnArbitrarySkylarkRuleThatProvidesObjc() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " objc_provider = apple_common.new_objc_provider(define=depset(['mock_define']))",
+ " return struct(objc=objc_provider)",
+ "my_rule = rule(implementation = my_rule_impl,",
+ " attrs = {})");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'my_rule')",
+ "my_rule(",
+ " name='my_target'",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " deps = [':my_target']",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " deps = [':lib']",
+ ")");
+
+ ConfiguredTarget binaryTarget = getConfiguredTarget("//examples/apple_skylark:bin");
+ ObjcProvider objcProvider = binaryTarget.getProvider(ObjcProvider.class);
+
+ assertThat(objcProvider.get(ObjcProvider.DEFINE)).contains("mock_define");
+ }
+
+ @Test
+ public void testSkylarkCanAccessAppleConfiguration() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_binary_impl(ctx):",
+ " cpu = ctx.fragments.apple.ios_cpu()",
+ " platform = ctx.fragments.apple.ios_cpu_platform()",
+ " env = ctx.fragments.apple.target_apple_env(platform)",
+ " xcode_version = ctx.fragments.apple.xcode_version()",
+ " sdk_version = ctx.fragments.apple.sdk_version_for_platform(platform)",
+ " single_arch_platform = ctx.fragments.apple.single_arch_platform",
+ " single_arch_cpu = ctx.fragments.apple.single_arch_cpu",
+ " platform_type = single_arch_platform.platform_type",
+ " bitcode_mode = ctx.fragments.apple.bitcode_mode",
+ " return struct(",
+ " cpu=cpu,",
+ " env=env,",
+ " xcode_version=str(xcode_version),",
+ " sdk_version=str(sdk_version),",
+ " single_arch_platform=str(single_arch_platform),",
+ " single_arch_cpu=str(single_arch_cpu),",
+ " platform_type=str(platform_type),",
+ " bitcode_mode=str(bitcode_mode)",
+ " )",
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "fragments = ['apple']",
+ ")");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--cpu=ios_i386", "--xcode_version=7.1");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+
+ Object iosCpu = skylarkTarget.get("cpu");
+ @SuppressWarnings("unchecked")
+ SkylarkDict<String, String> env =
+ (SkylarkDict<String, String>) skylarkTarget.get("env");
+ Object sdkVersion = skylarkTarget.get("sdk_version");
+
+ assertThat(iosCpu).isEqualTo("i386");
+ assertThat(env).containsEntry("APPLE_SDK_PLATFORM", "iPhoneSimulator");
+ assertThat(env).containsEntry("APPLE_SDK_VERSION_OVERRIDE", "8.4");
+ assertThat(sdkVersion).isEqualTo("8.4");
+ assertThat(skylarkTarget.get("xcode_version")).isEqualTo("7.1");
+ assertThat(skylarkTarget.get("single_arch_platform")).isEqualTo("IOS_SIMULATOR");
+ assertThat(skylarkTarget.get("single_arch_cpu")).isEqualTo("i386");
+ assertThat(skylarkTarget.get("platform_type")).isEqualTo("ios");
+ assertThat(skylarkTarget.get("bitcode_mode")).isEqualTo("none");
+ }
+
+ @Test
+ public void testSkylarkCanAccessApplePlatformNames() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " platform = ctx.fragments.apple.ios_cpu_platform()",
+ " return struct(",
+ " name=platform.name_in_plist,",
+ " )",
+ "test_rule = rule(",
+ "implementation = _test_rule_impl,",
+ "fragments = ['apple']",
+ ")");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--cpu=ios_i386");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ Object name = skylarkTarget.get("name");
+ assertThat(name).isEqualTo("iPhoneSimulator");
+ }
+
+ @Test
+ public void testSkylarkCanAccessAppleToolchain() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_binary_impl(ctx):",
+ " apple_toolchain = apple_common.apple_toolchain()",
+ " sdk_dir = apple_toolchain.sdk_dir()",
+ " platform_developer_framework_dir = \\",
+ " apple_toolchain.platform_developer_framework_dir(ctx.fragments.apple)",
+ " return struct(",
+ " platform_developer_framework_dir=platform_developer_framework_dir,",
+ " sdk_dir=sdk_dir,",
+ " )",
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "fragments = ['apple']",
+ ")");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--cpu=ios_i386");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ String platformDevFrameworksDir =
+ (String)
+ skylarkTarget.get("platform_developer_framework_dir");
+ String sdkDir = (String) skylarkTarget.get("sdk_dir");
+
+ assertThat(platformDevFrameworksDir)
+ .isEqualTo(
+ AppleToolchain.developerDir()
+ + "/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks");
+ assertThat(sdkDir).isEqualTo(AppleToolchain.sdkDir());
+ }
+
+ @Test
+ public void testSkylarkCanAccessSdkAndMinimumOs() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_binary_impl(ctx):",
+ " ios_sdk_version = ctx.fragments.apple.sdk_version_for_platform\\",
+ "(apple_common.platform.ios_device)",
+ " watchos_sdk_version = ctx.fragments.apple.sdk_version_for_platform\\",
+ "(apple_common.platform.watchos_device)",
+ " tvos_sdk_version = ctx.fragments.apple.sdk_version_for_platform\\",
+ "(apple_common.platform.tvos_device)",
+ " macos_sdk_version = ctx.fragments.apple.sdk_version_for_platform\\",
+ "(apple_common.platform.macos)",
+ " ios_minimum_os = ctx.fragments.apple.minimum_os_for_platform_type\\",
+ "(apple_common.platform_type.ios)",
+ " watchos_minimum_os = ctx.fragments.apple.minimum_os_for_platform_type\\",
+ "(apple_common.platform_type.watchos)",
+ " tvos_minimum_os = ctx.fragments.apple.minimum_os_for_platform_type\\",
+ "(apple_common.platform_type.tvos)",
+ " return struct(",
+ " ios_sdk_version=str(ios_sdk_version),",
+ " watchos_sdk_version=str(watchos_sdk_version),",
+ " tvos_sdk_version=str(tvos_sdk_version),",
+ " macos_sdk_version=str(macos_sdk_version),",
+ " ios_minimum_os=str(ios_minimum_os),",
+ " watchos_minimum_os=str(watchos_minimum_os),",
+ " tvos_minimum_os=str(tvos_minimum_os)",
+ " )",
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "fragments = ['apple']",
+ ")");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--ios_sdk_version=1.1", "--ios_minimum_os=1.0",
+ "--watchos_sdk_version=2.1", "--watchos_minimum_os=2.0",
+ "--tvos_sdk_version=3.1", "--tvos_minimum_os=3.0",
+ "--macos_sdk_version=4.1");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+
+ assertThat(skylarkTarget.get("ios_sdk_version")).isEqualTo("1.1");
+ assertThat(skylarkTarget.get("ios_minimum_os")).isEqualTo("1.0");
+ assertThat(skylarkTarget.get("watchos_sdk_version")).isEqualTo("2.1");
+ assertThat(skylarkTarget.get("watchos_minimum_os")).isEqualTo("2.0");
+ assertThat(skylarkTarget.get("tvos_sdk_version")).isEqualTo("3.1");
+ assertThat(skylarkTarget.get("tvos_minimum_os")).isEqualTo("3.0");
+ assertThat(skylarkTarget.get("macos_sdk_version")).isEqualTo("4.1");
+
+ useConfiguration("--ios_sdk_version=1.1",
+ "--watchos_sdk_version=2.1",
+ "--tvos_sdk_version=3.1",
+ "--macos_sdk_version=4.1");
+ skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ assertThat(skylarkTarget.get("ios_sdk_version")).isEqualTo("1.1");
+ assertThat(skylarkTarget.get("ios_minimum_os")).isEqualTo("1.1");
+ assertThat(skylarkTarget.get("watchos_sdk_version")).isEqualTo("2.1");
+ assertThat(skylarkTarget.get("watchos_minimum_os")).isEqualTo("2.1");
+ assertThat(skylarkTarget.get("tvos_sdk_version")).isEqualTo("3.1");
+ assertThat(skylarkTarget.get("tvos_minimum_os")).isEqualTo("3.1");
+ assertThat(skylarkTarget.get("macos_sdk_version")).isEqualTo("4.1");
+ }
+
+ @Test
+ public void testSkylarkCanAccessObjcConfiguration() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/objc_rules.bzl",
+ "def swift_binary_impl(ctx):",
+ " copts = ctx.fragments.objc.copts",
+ " compilation_mode_copts = ctx.fragments.objc.copts_for_current_compilation_mode",
+ " ios_simulator_device = ctx.fragments.objc.ios_simulator_device",
+ " ios_simulator_version = ctx.fragments.objc.ios_simulator_version",
+ " signing_certificate_name = ctx.fragments.objc.signing_certificate_name",
+ " generate_dsym = ctx.fragments.objc.generate_dsym",
+ " return struct(",
+ " copts=copts,",
+ " compilation_mode_copts=compilation_mode_copts,",
+ " ios_simulator_device=ios_simulator_device,",
+ " ios_simulator_version=str(ios_simulator_version),",
+ " signing_certificate_name=signing_certificate_name,",
+ " generate_dsym=generate_dsym,",
+ " )",
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "fragments = ['objc']",
+ ")");
+
+ scratch.file("examples/objc_skylark/a.m");
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration(
+ "--compilation_mode=opt",
+ "--objccopt=-DTestObjcCopt",
+ "--ios_simulator_device='iPhone 6'",
+ "--ios_simulator_version=8.4",
+ "--ios_signing_cert_name='Apple Developer'",
+ "--apple_generate_dsym");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/objc_skylark:my_target");
+
+ @SuppressWarnings("unchecked")
+ List<String> copts = (List<String>) skylarkTarget.get("copts");
+ @SuppressWarnings("unchecked")
+ List<String> compilationModeCopts = (List<String>) skylarkTarget.get("compilation_mode_copts");
+ Object iosSimulatorDevice = skylarkTarget.get("ios_simulator_device");
+ Object iosSimulatorVersion = skylarkTarget.get("ios_simulator_version");
+ Object signingCertificateName = skylarkTarget.get("signing_certificate_name");
+ Boolean generateDsym = (Boolean) skylarkTarget.get("generate_dsym");
+
+ assertThat(copts).contains("-DTestObjcCopt");
+ assertThat(compilationModeCopts).containsExactlyElementsIn(ObjcConfiguration.OPT_COPTS);
+ assertThat(iosSimulatorDevice).isEqualTo("'iPhone 6'");
+ assertThat(iosSimulatorVersion).isEqualTo("8.4");
+ assertThat(signingCertificateName).isEqualTo("'Apple Developer'");
+ assertThat(generateDsym).isTrue();
+ }
+
+ @Test
+ public void testSigningCertificateNameCanReturnNone() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/objc_rules.bzl",
+ "def my_rule_impl(ctx):",
+ " signing_certificate_name = ctx.fragments.objc.signing_certificate_name",
+ " return struct(",
+ " signing_certificate_name=str(signing_certificate_name),",
+ " )",
+ "my_rule = rule(",
+ "implementation = my_rule_impl,",
+ "fragments = ['objc']",
+ ")");
+
+ scratch.file("examples/objc_skylark/a.m");
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'my_rule')",
+ "my_rule(",
+ " name='my_target',",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/objc_skylark:my_target");
+
+ Object signingCertificateName = skylarkTarget.get("signing_certificate_name");
+ assertThat(signingCertificateName).isEqualTo("None");
+ }
+
+ @Test
+ public void testUsesDebugEntitlementsIsTrueIfCompilationModeIsNotOpt() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/objc_rules.bzl",
+ "def test_rule_impl(ctx):",
+ " uses_device_debug_entitlements = ctx.fragments.objc.uses_device_debug_entitlements",
+ " return struct(",
+ " uses_device_debug_entitlements=uses_device_debug_entitlements,",
+ " )",
+ "test_rule = rule(",
+ "implementation = test_rule_impl,",
+ "fragments = ['objc']",
+ ")");
+
+ scratch.file("examples/objc_skylark/a.m");
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'test_rule')",
+ "test_rule(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--compilation_mode=dbg");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/objc_skylark:my_target");
+
+ boolean usesDeviceDebugEntitlements = (boolean) skylarkTarget
+ .get("uses_device_debug_entitlements");
+ assertThat(usesDeviceDebugEntitlements).isTrue();
+ }
+
+ @Test
+ public void testUsesDebugEntitlementsIsFalseIfFlagIsExplicitlyFalse() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/objc_rules.bzl",
+ "def test_rule_impl(ctx):",
+ " uses_device_debug_entitlements = ctx.fragments.objc.uses_device_debug_entitlements",
+ " return struct(",
+ " uses_device_debug_entitlements=uses_device_debug_entitlements,",
+ " )",
+ "test_rule = rule(",
+ "implementation = test_rule_impl,",
+ "fragments = ['objc']",
+ ")");
+
+ scratch.file("examples/objc_skylark/a.m");
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'test_rule')",
+ "test_rule(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration(
+ "--compilation_mode=dbg",
+ "--nodevice_debug_entitlements");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/objc_skylark:my_target");
+
+ boolean usesDeviceDebugEntitlements = (boolean) skylarkTarget
+ .get("uses_device_debug_entitlements");
+ assertThat(usesDeviceDebugEntitlements).isFalse();
+ }
+
+ @Test
+ public void testUsesDebugEntitlementsIsFalseIfCompilationModeIsOpt() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/objc_rules.bzl",
+ "def test_rule_impl(ctx):",
+ " uses_device_debug_entitlements = ctx.fragments.objc.uses_device_debug_entitlements",
+ " return struct(",
+ " uses_device_debug_entitlements=uses_device_debug_entitlements,",
+ " )",
+ "test_rule = rule(",
+ "implementation = test_rule_impl,",
+ "fragments = ['objc']",
+ ")");
+
+ scratch.file("examples/objc_skylark/a.m");
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'test_rule')",
+ "test_rule(",
+ " name='my_target',",
+ ")");
+
+ useConfiguration("--compilation_mode=opt");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/objc_skylark:my_target");
+
+ boolean usesDeviceDebugEntitlements = (boolean) skylarkTarget
+ .get("uses_device_debug_entitlements");
+ assertThat(usesDeviceDebugEntitlements).isFalse();
+ }
+
+ private ConfiguredTarget createObjcProviderSkylarkTarget(String... implLines) throws Exception {
+ String[] impl =
+ ObjectArrays.concat(
+ ObjectArrays.concat("def swift_binary_impl(ctx):", implLines),
+ new String[] {
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "attrs = {",
+ " 'deps': attr.label_list(",
+ "allow_files = False, mandatory = False, providers = ['objc'])",
+ "})"
+ },
+ String.class);
+
+ scratch.file("examples/rule/BUILD");
+ scratch.file("examples/rule/objc_rules.bzl", impl);
+ scratch.file(
+ "examples/objc_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/objc_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ " deps=[':lib'],",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " defines = ['define_from_dep']",
+ ")");
+
+ return getConfiguredTarget("//examples/objc_skylark:my_target");
+ }
+
+ @Test
+ public void testSkylarkCanCreateObjcProviderFromScratch() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " defines = depset(['define1', 'define2'])",
+ " linkopts = depset(['somelinkopt'])",
+ " created_provider = apple_common.new_objc_provider\\",
+ "(define=defines, linkopt=linkopts)",
+ " return struct(objc=created_provider)");
+
+ Iterable<String> foundLinkopts =
+ skylarkTarget.getProvider(ObjcProvider.class).get(ObjcProvider.LINKOPT);
+ Iterable<String> foundDefines =
+ skylarkTarget.getProvider(ObjcProvider.class).get(ObjcProvider.DEFINE);
+ boolean usesSwift =
+ skylarkTarget.getProvider(ObjcProvider.class).is(ObjcProvider.Flag.USES_SWIFT);
+
+ assertThat(foundLinkopts).containsExactly("somelinkopt");
+ assertThat(foundDefines).containsExactly("define1", "define2");
+ assertThat(usesSwift).isFalse();
+ }
+
+ @Test
+ public void testSkylarkCanPassLinkInputsInObjcProvider() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " file = ctx.actions.declare_file('foo.ast')",
+ " ctx.actions.run_shell(outputs=[file], command='echo')",
+ " link_inputs = depset([file])",
+ " created_provider = apple_common.new_objc_provider\\",
+ "(link_inputs=link_inputs)",
+ " return struct(objc=created_provider)");
+
+ Iterable<Artifact> foundLinkInputs =
+ skylarkTarget.getProvider(ObjcProvider.class).get(ObjcProvider.LINK_INPUTS);
+ assertThat(ActionsTestUtil.baseArtifactNames(foundLinkInputs)).contains("foo.ast");
+ }
+
+ @Test
+ public void testSkylarkCanPassUsesSwiftFlag() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(uses_swift=True)",
+ " return struct(objc=created_provider)");
+
+ boolean usesSwift =
+ skylarkTarget.getProvider(ObjcProvider.class).is(ObjcProvider.Flag.USES_SWIFT);
+
+ assertThat(usesSwift).isTrue();
+ }
+
+ @Test
+ public void testSkylarkCanCreateObjcProviderWithPathFragments() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " includes = depset(['path1', 'path_dir/path2', 'path_dir1/path_dir2/path3'])",
+ " created_provider = apple_common.new_objc_provider\\",
+ "(include=includes)",
+ " return struct(objc=created_provider)");
+
+ Iterable<PathFragment> foundIncludes =
+ skylarkTarget.getProvider(ObjcProvider.class).get(ObjcProvider.INCLUDE);
+
+ assertThat(foundIncludes)
+ .containsExactly(
+ PathFragment.create("path1"),
+ PathFragment.create("path_dir/path2"),
+ PathFragment.create("path_dir1/path_dir2/path3"));
+ }
+
+ @Test
+ public void testSkylarkCanCreateObjcProviderWithStrictDeps() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " strict_includes = depset(['path1'])",
+ " propagated_includes = depset(['path2'])",
+ " strict_provider = apple_common.new_objc_provider\\",
+ "(include=strict_includes)",
+ " created_provider = apple_common.new_objc_provider\\",
+ "(include=propagated_includes, direct_dep_providers=[strict_provider])",
+ " return struct(objc=created_provider)");
+
+ ObjcProvider skylarkProvider = skylarkTarget.getProvider(ObjcProvider.class);
+ ObjcProvider skylarkProviderDirectDepender =
+ new ObjcProvider.Builder().addTransitiveAndPropagate(skylarkProvider).build();
+ ObjcProvider skylarkProviderIndirectDepender =
+ new ObjcProvider.Builder().addTransitiveAndPropagate(skylarkProviderDirectDepender).build();
+
+ assertThat(skylarkProvider.get(ObjcProvider.INCLUDE))
+ .containsExactly(PathFragment.create("path1"), PathFragment.create("path2"));
+ assertThat(skylarkProviderDirectDepender.get(ObjcProvider.INCLUDE))
+ .containsExactly(PathFragment.create("path1"), PathFragment.create("path2"));
+ assertThat(skylarkProviderIndirectDepender.get(ObjcProvider.INCLUDE))
+ .containsExactly(PathFragment.create("path2"));
+ }
+
+ @Test
+ public void testSkylarkCanCreateObjcProviderFromObjcProvider() throws Exception {
+ ConfiguredTarget skylarkTarget =
+ createObjcProviderSkylarkTarget(
+ " dep = ctx.attr.deps[0]",
+ " define = depset(['define_from_impl'])",
+ " created_provider = apple_common.new_objc_provider\\",
+ "(providers=[dep.objc], define=define)",
+ " return struct(objc=created_provider)");
+
+ Iterable<String> foundStrings =
+ skylarkTarget.getProvider(ObjcProvider.class).get(ObjcProvider.DEFINE);
+
+ assertThat(foundStrings).containsExactly("define_from_dep", "define_from_impl");
+ }
+
+ @Test
+ public void testSkylarkErrorOnBadObjcProviderInputKey() throws Exception {
+ try {
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(foo=depset(['bar']))",
+ " return struct(objc=created_provider)");
+ fail("Should throw AssertionError");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(String.format(AppleSkylarkCommon.BAD_KEY_ERROR, "foo"));
+ }
+ }
+
+ @Test
+ public void testSkylarkErrorOnNonSetObjcProviderInputValue() throws Exception {
+ try {
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(library='bar')",
+ " return struct(objc=created_provider)");
+ fail("Should throw AssertionError");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(String.format(AppleSkylarkCommon.NOT_SET_ERROR, "library", "string"));
+ }
+ }
+
+ @Test
+ public void testSkylarkErrorOnObjcProviderInputValueWrongSetType() throws Exception {
+ try {
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(library=depset(['bar']))",
+ " return struct(objc=created_provider)");
+ fail("Should throw AssertionError");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(
+ String.format(AppleSkylarkCommon.BAD_SET_TYPE_ERROR, "library", "File", "string"));
+ }
+ }
+
+ @Test
+ public void testSkylarkErrorOnNonIterableObjcProviderProviderValue() throws Exception {
+ try {
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(providers='bar')",
+ " return struct(objc=created_provider)");
+ fail("Should throw AssertionError");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(String.format(AppleSkylarkCommon.BAD_PROVIDERS_ITER_ERROR, "string"));
+ }
+ }
+
+ @Test
+ public void testSkylarkErrorOnBadIterableObjcProviderProviderValue() throws Exception {
+ try {
+ createObjcProviderSkylarkTarget(
+ " created_provider = apple_common.new_objc_provider(providers=['bar'])",
+ " return struct(objc=created_provider)");
+ fail("Should throw AssertionError");
+ } catch (AssertionError e) {
+ assertThat(e)
+ .hasMessageThat()
+ .contains(String.format(AppleSkylarkCommon.BAD_PROVIDERS_ELEM_ERROR, "string"));
+ }
+ }
+
+ @Test
+ public void testEmptyObjcProviderKeysArePresent() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def swift_binary_impl(ctx):",
+ " objc_provider = ctx.attr.deps[0].objc",
+ " return struct(",
+ " empty_value=objc_provider.include,",
+ " )",
+ "swift_binary = rule(",
+ "implementation = swift_binary_impl,",
+ "fragments = ['apple'],",
+ "attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False, providers = ['objc'])",
+ "})");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'swift_binary')",
+ "swift_binary(",
+ " name='my_target',",
+ " deps=[':lib'],",
+ ")",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ ")");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+ SkylarkNestedSet emptyValue =
+ (SkylarkNestedSet)
+ skylarkTarget.get("empty_value");
+ assertThat(emptyValue.toCollection()).isEmpty();
+ }
+
+ @Test
+ public void testSkylarkCanAccessProvidedBundleFiles() throws Exception {
+ // Since the collections of structs with Artifact values are extremely difficult to test with
+ // Truth, we fudge them in the Skylark side to return easily comparable dictionaries instead.
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _simplify_bundle_file(bf):",
+ " return {'file': bf.file.path, 'bundle_path': bf.bundle_path}",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " objc_provider = dep.objc",
+ " bundle_file = [_simplify_bundle_file(bf) for bf in list(objc_provider.bundle_file)]",
+ " return struct(",
+ " bundle_file=bundle_file,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False, providers = ['objc'])",
+ "})");
+
+ scratch.file("examples/apple_skylark/a.m");
+ scratch.file("examples/apple_skylark/flattened/a/a.txt");
+ scratch.file("examples/apple_skylark/flattened/b.lproj/b.txt");
+ scratch.file("examples/apple_skylark/structured/c/c.txt");
+ scratch.file("examples/apple_skylark/structured/d/d.txt");
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " resources = glob(['flattened/**']),",
+ " structured_resources = glob(['structured/**']),",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':lib'],",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ Iterable<?> bundleFiles = (Iterable<?>)
+ skylarkTarget.get("bundle_file");
+ assertThat(bundleFiles).containsAllOf(ImmutableMap.of(
+ BUNDLE_PATH_FIELD, "a.txt",
+ BUNDLED_FIELD, "examples/apple_skylark/flattened/a/a.txt"
+ ), ImmutableMap.of(
+ BUNDLE_PATH_FIELD, "b.lproj/b.txt",
+ BUNDLED_FIELD, "examples/apple_skylark/flattened/b.lproj/b.txt"
+ ), ImmutableMap.of(
+ BUNDLE_PATH_FIELD, "structured/c/c.txt",
+ BUNDLED_FIELD, "examples/apple_skylark/structured/c/c.txt"
+ ), ImmutableMap.of(
+ BUNDLE_PATH_FIELD, "structured/d/d.txt",
+ BUNDLED_FIELD, "examples/apple_skylark/structured/d/d.txt"
+ ));
+ }
+
+ @Test
+ public void testSkylarkCanAccessSdkFrameworks() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " dep = ctx.attr.deps[0]",
+ " objc_provider = dep.objc",
+ " return struct(",
+ " sdk_frameworks=objc_provider.sdk_framework,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'deps': attr.label_list(allow_files = False, mandatory = False, providers = ['objc'])",
+ "})");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['a.m'],",
+ " sdk_frameworks = ['Accelerate', 'GLKit'],",
+ ")",
+ "test_rule(",
+ " name = 'my_target',",
+ " deps = [':lib'],",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ SkylarkNestedSet sdkFrameworks = (SkylarkNestedSet)
+ skylarkTarget.get("sdk_frameworks");
+ assertThat(sdkFrameworks.toCollection()).containsAllOf("Accelerate", "GLKit");
+ }
+
+ @Test
+ public void testSkylarkCanAccessAndUseApplePlatformTypes() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " apple = ctx.fragments.apple",
+ " ios_platform = apple.multi_arch_platform(apple_common.platform_type.ios)",
+ " watchos_platform = apple.multi_arch_platform(apple_common.platform_type.watchos)",
+ " tvos_platform = apple.multi_arch_platform(apple_common.platform_type.tvos)",
+ " return struct(",
+ " ios_platform=str(ios_platform),",
+ " watchos_platform=str(watchos_platform),",
+ " tvos_platform=str(tvos_platform),",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " fragments = ['apple'])");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ useConfiguration(
+ "--ios_multi_cpus=arm64,armv7",
+ "--watchos_cpus=armv7k",
+ "--tvos_cpus=arm64");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ Object iosPlatform =
+ skylarkTarget.get("ios_platform");
+ Object watchosPlatform =
+ skylarkTarget.get("watchos_platform");
+ Object tvosPlatform =
+ skylarkTarget.get("tvos_platform");
+
+ assertThat(iosPlatform).isEqualTo("IOS_DEVICE");
+ assertThat(watchosPlatform).isEqualTo("WATCHOS_DEVICE");
+ assertThat(tvosPlatform).isEqualTo("TVOS_DEVICE");
+ }
+
+ @Test
+ public void testPlatformIsDeviceReturnsTrueForDevicePlatforms() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " apple = ctx.fragments.apple",
+ " platform = apple.multi_arch_platform(apple_common.platform_type.ios)",
+ " return struct(",
+ " is_device=platform.is_device,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " fragments = ['apple'])");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ useConfiguration(
+ "--ios_multi_cpus=arm64,armv7");
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ Boolean isDevice =
+ (Boolean) skylarkTarget.get("is_device");
+ assertThat(isDevice).isTrue();
+ }
+
+ @Test
+ public void testPlatformIsDeviceReturnsFalseForSimulatorPlatforms() throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " apple = ctx.fragments.apple",
+ " platform = apple.multi_arch_platform(apple_common.platform_type.ios)",
+ " return struct(",
+ " is_device=platform.is_device,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " fragments = ['apple'])");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ Boolean isDevice =
+ (Boolean) skylarkTarget.get("is_device");
+ assertThat(isDevice).isFalse();
+ }
+
+ @Test
+ public void testXcTestAppProviderCanBeCreated() throws Exception {
+ scratch.file("examples/rule/BUILD",
+ "exports_files(['test_artifact'])");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " artifact = list(ctx.attr.test_artifact.files)[0]",
+ " objc_provider = apple_common.new_objc_provider(define=depset(['TEST_DEFINE']))",
+ " xctest_app_provider = apple_common.new_xctest_app_provider(",
+ " bundle_loader=artifact, ipa=artifact, objc_provider=objc_provider)",
+ " return struct(",
+ " xctest_app=xctest_app_provider,",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " attrs = {",
+ " 'test_artifact': attr.label(",
+ " allow_single_file=True,",
+ " default=Label('//examples/rule:test_artifact')),",
+ " })");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ XcTestAppProvider xcTestAppProvider = skylarkTarget.getProvider(XcTestAppProvider.class);
+
+ assertThat(xcTestAppProvider.getBundleLoader().getRootRelativePathString())
+ .isEqualTo("examples/rule/test_artifact");
+ assertThat(xcTestAppProvider.getIpa().getRootRelativePathString())
+ .isEqualTo("examples/rule/test_artifact");
+ assertThat(xcTestAppProvider.getObjcProvider().get(ObjcProvider.DEFINE))
+ .containsExactly("TEST_DEFINE");
+ }
+
+ @Test
+ public void testSkylarkWithRunMemleaksEnabled() throws Exception {
+ useConfiguration("--ios_memleaks");
+ checkSkylarkRunMemleaksWithExpectedValue(true);
+ }
+
+ @Test
+ public void testSkylarkWithRunMemleaksDisabled() throws Exception {
+ checkSkylarkRunMemleaksWithExpectedValue(false);
+ }
+
+ @Test
+ public void testDottedVersion() throws Exception {
+ scratch.file("examples/rule/BUILD",
+ "exports_files(['test_artifact'])");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " version = apple_common.dotted_version('5.4')",
+ " return struct(",
+ " version=version",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl)");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ DottedVersion version = (DottedVersion) skylarkTarget.get("version");
+ assertThat(version).isEqualTo(DottedVersion.fromString("5.4"));
+ }
+
+ @Test
+ public void testDottedVersion_invalid() throws Exception {
+ scratch.file("examples/rule/BUILD",
+ "exports_files(['test_artifact'])");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " version = apple_common.dotted_version('hello')",
+ " return struct(",
+ " version=version",
+ " )",
+ "test_rule = rule(implementation = _test_rule_impl)");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ try {
+ getConfiguredTarget("//examples/apple_skylark:my_target");
+ fail("Expected an error to be thrown for invalid dotted version string");
+ } catch (AssertionError e) {
+ assertThat(e).hasMessageThat().contains("illegal argument in call to dotted_version");
+ assertThat(e).hasMessageThat().contains("Dotted version components must all be of the form");
+ }
+ }
+
+ private void checkSkylarkRunMemleaksWithExpectedValue(boolean expectedValue) throws Exception {
+ scratch.file("examples/rule/BUILD");
+ scratch.file(
+ "examples/rule/apple_rules.bzl",
+ "def _test_rule_impl(ctx):",
+ " return struct(run_memleaks = ctx.fragments.objc.run_memleaks)",
+ "test_rule = rule(implementation = _test_rule_impl,",
+ " fragments = ['objc'],",
+ " attrs = {},",
+ ")");
+
+ scratch.file(
+ "examples/apple_skylark/BUILD",
+ "package(default_visibility = ['//visibility:public'])",
+ "load('/examples/rule/apple_rules', 'test_rule')",
+ "test_rule(",
+ " name = 'my_target',",
+ ")");
+
+ ConfiguredTarget skylarkTarget = getConfiguredTarget("//examples/apple_skylark:my_target");
+
+ boolean runMemleaks = (boolean) skylarkTarget.get("run_memleaks");
+ assertThat(runMemleaks).isEqualTo(expectedValue);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/OnlyNeedsSourcesRuleType.java b/src/test/java/com/google/devtools/build/lib/rules/objc/OnlyNeedsSourcesRuleType.java
new file mode 100644
index 0000000000..043974d736
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/OnlyNeedsSourcesRuleType.java
@@ -0,0 +1,42 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.testutil.Scratch;
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * This exists for convenience for any rule type that requires only one file in {@code srcs} or
+ * {@code non_arc_srcs}, and no other attributes.
+ */
+final class OnlyNeedsSourcesRuleType extends RuleType {
+ OnlyNeedsSourcesRuleType(String ruleTypeName) {
+ super(ruleTypeName);
+ }
+
+ @Override
+ Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException {
+ ImmutableList.Builder<String> attributes = new ImmutableList.Builder<>();
+ if (!alreadyAdded.contains("srcs") && !alreadyAdded.contains("non_arc_srcs")) {
+ scratch.file(packageDir + "/a.m");
+ scratch.file(packageDir + "/private.h");
+ attributes.add("srcs = ['a.m', 'private.h']");
+ }
+ return attributes.build();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/README.md b/src/test/java/com/google/devtools/build/lib/rules/objc/README.md
new file mode 100644
index 0000000000..388dbc6e2b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/README.md
@@ -0,0 +1,13 @@
+# Objc rule tests
+This package contains subclasses of ObjcRuleTestCase. These test cases use
+--experimental_objc_crosstool=all by default, as per
+ObjcRuleTestCase#useConfiguration. This is meant to test the "crosstool"
+case.
+
+The "legacy" case (that is, --experimental_objc_crosstool=off) is also tested
+in subclasses prefixed with the word "Legacy". Tests in the superclass, then,
+are tested for both crosstool configurations, while tests in the subclass are
+only tested for --experimental_objc_crosstool=off.
+
+As the crosstool case is developed, tests will moved up to superclasses.
+Eventually, the legacy subclasses will be removed.
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/RuleType.java b/src/test/java/com/google/devtools/build/lib/rules/objc/RuleType.java
new file mode 100644
index 0000000000..18875c680d
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/RuleType.java
@@ -0,0 +1,145 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.util.Preconditions;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Provides utilities to help test a certain rule type without requiring the calling code to know
+ * exactly what kind of rule is being tested. Only one instance is needed per rule type (e.g. one
+ * instance for {@code objc_library}).
+ */
+public abstract class RuleType {
+ /**
+ * What to pass as the value of some attribute to indicate an attribute should not be added to the
+ * rule. This can either be to test an error condition, or to use an alternative attribute to
+ * supply the value.
+ */
+ public static final String OMIT_REQUIRED_ATTR = "<OMIT_REQUIRED_ATTR>";
+
+ private final String ruleTypeName;
+
+ RuleType(String ruleTypeName) {
+ this.ruleTypeName = ruleTypeName;
+ }
+
+ /**
+ * The name of this type as it appears in {@code BUILD} files, such as {@code objc_library}.
+ */
+ final String getRuleTypeName() {
+ return ruleTypeName;
+ }
+
+ /**
+ * Returns whether this type exports companion library target in Xcode.
+ */
+ final boolean exportsXcodeCompanionTarget() {
+ return ruleTypeName.equals("objc_binary");
+ }
+
+ /**
+ * Returns the bundle extension for the bundles generated by the rule.
+ */
+ final String bundleExtension() {
+ return ruleTypeName.equals("ios_test") ? "xctest" : "app";
+ }
+
+ /**
+ * Returns names and values, and otherwise prepares, extra attributes required for this rule type
+ * to be without error. For instance, if this rule type requires 'srcs' and 'infoplist'
+ * attributes, this method may be implemented as follows:
+ * <pre>
+ * {@code
+ * List<String> attributes = new ArrayList<>();
+ * if (!alreadyAdded.contains("srcs")) {
+ * scratch.file("/workspace_root/" + packageDir + "/a.m");
+ * attributes.add("srcs = ['a.m']");
+ * }
+ * if (!alreadyAdded.contains(INFOPLIST_ATTR)) {
+ * scratch.file("/workspace_root/" + packageDir + "Info.plist");
+ * attributes.add("infoplist = ['Info.plist']");
+ * }
+ * return attributes;
+ * </pre>
+ * }
+ *
+ * @throws IOException for whatever reason the implementator feels like, but mostly just when
+ * a scratch file couldn't be created
+ */
+ abstract Iterable<String> requiredAttributes(
+ Scratch scratch, String packageDir, Set<String> alreadyAdded) throws IOException;
+
+ private ImmutableMap<String, String> map(String... attrs) {
+ ImmutableMap.Builder<String, String> map = new ImmutableMap.Builder<>();
+ Preconditions.checkArgument((attrs.length & 1) == 0,
+ "attrs must have an even number of elements");
+ for (int i = 0; i < attrs.length; i += 2) {
+ map.put(attrs[i], attrs[i + 1]);
+ }
+ return map.build();
+ }
+
+ /**
+ * Generates the String necessary to define a target of this rule type.
+ *
+ * @param packageDir the package in which to create the target
+ * @param name the name of the target
+ * @param checkSpecificAttrs alternating name/values of attributes to add to the rule that are
+ * required for the check being performed to be defined a certain way. Pass
+ * {@link #OMIT_REQUIRED_ATTR} for a value to prevent an attribute from being automatically
+ * defined.
+ */
+ final String target(
+ Scratch scratch, String packageDir, String name, String... checkSpecificAttrs)
+ throws IOException {
+ ImmutableMap<String, String> checkSpecific = map(checkSpecificAttrs);
+ StringBuilder target = new StringBuilder(ruleTypeName)
+ .append("(name = '")
+ .append(name)
+ .append("',");
+ for (Map.Entry<String, String> entry : checkSpecific.entrySet()) {
+ if (entry.getValue().equals(OMIT_REQUIRED_ATTR)) {
+ continue;
+ }
+ target.append(entry.getKey())
+ .append("=")
+ .append(entry.getValue())
+ .append(",");
+ }
+ Joiner.on(",").appendTo(
+ target,
+ requiredAttributes(scratch, packageDir, checkSpecific.keySet()));
+ target.append(')');
+ return target.toString();
+
+ }
+
+ /**
+ * Creates a target at //x:x which is the only target in the BUILD file. Returns the string that
+ * is written to the scratch file as it is often useful for debugging purposes.
+ */
+ public final String scratchTarget(Scratch scratch, String... checkSpecificAttrs)
+ throws IOException {
+ String target = target(scratch, "x", "x", checkSpecificAttrs);
+ scratch.file("x/BUILD", target);
+ return target;
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/TargetDeviceFamilyTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/TargetDeviceFamilyTest.java
new file mode 100644
index 0000000000..7cc7b001e9
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/TargetDeviceFamilyTest.java
@@ -0,0 +1,87 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.InvalidFamilyNameException;
+import com.google.devtools.build.lib.rules.objc.TargetDeviceFamily.RepeatedFamilyNameException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for {@link TargetDeviceFamily}.
+ */
+@RunWith(JUnit4.class)
+public class TargetDeviceFamilyTest {
+ @Test
+ public void uiDeviceFamilyValuesUndefinedForEmpty() {
+ assertThat(TargetDeviceFamily.UI_DEVICE_FAMILY_VALUES.keySet())
+ .doesNotContain(ImmutableSet.<TargetDeviceFamily>of());
+ }
+
+ @Test
+ public void fromBuildSettings() {
+ assertThat(TargetDeviceFamily.fromBuildSetting("1,2"))
+ .isEqualTo(ImmutableSet.of(TargetDeviceFamily.IPAD, TargetDeviceFamily.IPHONE));
+ assertThat(TargetDeviceFamily.fromBuildSetting(" 1, 2"))
+ .isEqualTo(ImmutableSet.of(TargetDeviceFamily.IPAD, TargetDeviceFamily.IPHONE));
+ assertThat(TargetDeviceFamily.fromBuildSetting("1,2\n"))
+ .isEqualTo(ImmutableSet.of(TargetDeviceFamily.IPAD, TargetDeviceFamily.IPHONE));
+ assertThat(TargetDeviceFamily.fromBuildSetting("1"))
+ .isEqualTo(ImmutableSet.of(TargetDeviceFamily.IPHONE));
+ assertThat(TargetDeviceFamily.fromBuildSetting("2"))
+ .isEqualTo(ImmutableSet.of(TargetDeviceFamily.IPAD));
+ }
+
+ private void checkFromNamesInRuleThrows(
+ Class<? extends Exception> expectedClass, String... names) {
+ try {
+ TargetDeviceFamily.fromNamesInRule(ImmutableList.copyOf(names));
+ fail("should have thrown");
+ } catch (IllegalArgumentException expected) {
+ assertThat(expected.getClass()).isEqualTo(expectedClass);
+ }
+ }
+
+ @Test
+ public void fromNamesInRule_errors() {
+ checkFromNamesInRuleThrows(InvalidFamilyNameException.class, "foo");
+ checkFromNamesInRuleThrows(InvalidFamilyNameException.class, "foo", "bar");
+ checkFromNamesInRuleThrows(InvalidFamilyNameException.class, "iphone", "ipad", "bar");
+ checkFromNamesInRuleThrows(RepeatedFamilyNameException.class, "iphone", "iphone");
+ checkFromNamesInRuleThrows(RepeatedFamilyNameException.class, "ipad", "ipad");
+ }
+
+ @Test
+ public void fromNamesInRule() {
+ assertThat(TargetDeviceFamily.fromNamesInRule(ImmutableList.<String>of()))
+ .isEmpty();
+ assertThat(TargetDeviceFamily.fromNamesInRule(ImmutableList.of("iphone", "ipad")))
+ .containsExactly(TargetDeviceFamily.IPAD, TargetDeviceFamily.IPHONE)
+ .inOrder();
+ assertThat(TargetDeviceFamily.fromNamesInRule(ImmutableList.of("ipad", "iphone")))
+ .containsExactly(TargetDeviceFamily.IPAD, TargetDeviceFamily.IPHONE)
+ .inOrder();
+ assertThat(TargetDeviceFamily.fromNamesInRule(ImmutableList.of("iphone")))
+ .containsExactly(TargetDeviceFamily.IPHONE);
+ assertThat(TargetDeviceFamily.fromNamesInRule(ImmutableList.of("ipad")))
+ .containsExactly(TargetDeviceFamily.IPAD);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ValueTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ValueTest.java
new file mode 100644
index 0000000000..dbb72843cd
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ValueTest.java
@@ -0,0 +1,75 @@
+// Copyright 2017 The Bazel Authors. 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.
+
+package com.google.devtools.build.lib.rules.objc;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.fail;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit tests for {@class Value}.
+ */
+@RunWith(JUnit4.class)
+public class ValueTest {
+ private static final class PersonName extends Value<PersonName> {
+ public PersonName(String first, String last) {
+ super(first, last);
+ }
+ }
+
+ private enum NameData {
+ JOHN_DOE, JANE_DOE, JOHN_SMITH,
+ }
+
+ private PersonName make(NameData what) {
+ switch (what) {
+ case JOHN_DOE:
+ return new PersonName("John", "Doe");
+ case JANE_DOE:
+ return new PersonName("Jane", "Doe");
+ case JOHN_SMITH:
+ return new PersonName("John", "Smith");
+ default:
+ throw new IllegalArgumentException("unknown: " + what);
+ }
+ }
+
+ @Test
+ public void nullNotAllowedInMemberData() {
+ try {
+ new PersonName(null, "Doe");
+ fail("should have thrown");
+ } catch (NullPointerException expected) {}
+ }
+
+ @Test
+ public void equality() {
+ EqualsTester tester = new EqualsTester();
+ for (NameData what : NameData.values()) {
+ tester.addEqualityGroup(make(what), make(what));
+ }
+ tester.testEquals();
+ }
+
+ @Test
+ public void testToString() {
+ assertThat(make(NameData.JOHN_DOE).toString()).contains("John");
+ assertThat(make(NameData.JOHN_DOE).toString()).contains("Doe");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
index 480a5d3cac..2aacc9ea2a 100644
--- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
+++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java
@@ -67,6 +67,8 @@ public class TestConstants {
public static final ImmutableList<String> IGNORED_MESSAGE_PREFIXES = ImmutableList.<String>of();
+ public static final String WORKSPACE_CONTENT = "";
+
public static final String GCC_INCLUDE_PATH = "external/bazel_tools/tools/cpp/gcc3";
public static final String TOOLS_REPOSITORY = "@bazel_tools";