diff --git a/.gitignore b/.gitignore index aa12fcc8..a78c04df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,17 @@ .clang_complete .ycm_extra_conf.py* compile_commands.json -/build* +/build/ +/buildtools/ /external/googletest /external/SPIRV-Headers /external/spirv-headers /external/effcee /external/re2 +/out /TAGS /third_party/llvm-build/ +/testing/libfuzzer/ /tools/clang/ /utils/clang-format-diff.py diff --git a/.gn b/.gn new file mode 100644 index 00000000..ee4734f7 --- /dev/null +++ b/.gn @@ -0,0 +1,20 @@ +# Copyright 2018 Google Inc. +# +# 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 +# +# https://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. + +buildconfig = "//build/config/BUILDCONFIG.gn" +secondary_source = "//build/secondary/" + +default_args = { + use_custom_libcxx = false +} diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 00000000..9765a889 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,776 @@ +# Copyright 2018 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//testing/test.gni") +import("//build_overrides/build.gni") + +if (build_with_chromium) { + spirv_headers = "//third_party/spirv-headers/src" +} else { + spirv_headers = "external/spirv-headers" +} + +template("spvtools_core_tables") { + assert(defined(invoker.version), "Need version in $target_name generation.") + + action("spvtools_core_tables_" + target_name) { + script = "utils/generate_grammar_tables.py" + + version = invoker.version + + core_json_file = + "${spirv_headers}/include/spirv/$version/spirv.core.grammar.json" + core_insts_file = "${target_gen_dir}/core.insts-$version.inc" + operand_kinds_file = "${target_gen_dir}/operand.kinds-$version.inc" + extinst_file = "source/extinst.debuginfo.grammar.json" + + sources = [ + core_json_file, + ] + outputs = [ + core_insts_file, + operand_kinds_file, + ] + args = [ + "--spirv-core-grammar", + rebase_path(core_json_file, root_build_dir), + "--core-insts-output", + rebase_path(core_insts_file, root_build_dir), + "--extinst-debuginfo-grammar", + rebase_path(extinst_file, root_build_dir), + "--operand-kinds-output", + rebase_path(operand_kinds_file, root_build_dir), + ] + } +} + +template("spvtools_core_enums") { + assert(defined(invoker.version), "Need version in $target_name generation.") + + action("spvtools_core_enums_" + target_name) { + script = "utils/generate_grammar_tables.py" + + version = invoker.version + + core_json_file = + "${spirv_headers}/include/spirv/$version/spirv.core.grammar.json" + debug_insts_file = "source/extinst.debuginfo.grammar.json" + extension_enum_file = "${target_gen_dir}/extension_enum.inc" + extension_map_file = "${target_gen_dir}/enum_string_mapping.inc" + + args = [ + "--spirv-core-grammar", + rebase_path(core_json_file, root_build_dir), + "--extinst-debuginfo-grammar", + rebase_path(debug_insts_file, root_build_dir), + "--extension-enum-output", + rebase_path(extension_enum_file, root_build_dir), + "--enum-string-mapping-output", + rebase_path(extension_map_file, root_build_dir), + ] + inputs = [ + core_json_file, + ] + outputs = [ + extension_enum_file, + extension_map_file, + ] + } +} + +template("spvtools_glsl_tables") { + assert(defined(invoker.version), "Need version in $target_name generation.") + + action("spvtools_glsl_tables_" + target_name) { + script = "utils/generate_grammar_tables.py" + + version = invoker.version + + core_json_file = + "${spirv_headers}/include/spirv/$version/spirv.core.grammar.json" + glsl_json_file = "${spirv_headers}/include/spirv/${version}/extinst.glsl.std.450.grammar.json" + glsl_insts_file = "${target_gen_dir}/glsl.std.450.insts.inc" + debug_insts_file = "source/extinst.debuginfo.grammar.json" + + args = [ + "--spirv-core-grammar", + rebase_path(core_json_file, root_build_dir), + "--extinst-glsl-grammar", + rebase_path(glsl_json_file, root_build_dir), + "--glsl-insts-output", + rebase_path(glsl_insts_file, root_build_dir), + "--extinst-debuginfo-grammar", + rebase_path(debug_insts_file, root_build_dir), + ] + inputs = [ + core_json_file, + glsl_json_file, + ] + outputs = [ + glsl_insts_file, + ] + } +} + +template("spvtools_opencl_tables") { + assert(defined(invoker.version), "Need version in $target_name generation.") + + action("spvtools_opencl_tables_" + target_name) { + script = "utils/generate_grammar_tables.py" + + version = invoker.version + + core_json_file = + "${spirv_headers}/include/spirv/$version/spirv.core.grammar.json" + opengl_json_file = "${spirv_headers}/include/spirv/${version}/extinst.opencl.std.100.grammar.json" + opencl_insts_file = "${target_gen_dir}/opencl.std.insts.inc" + debug_insts_file = "source/extinst.debuginfo.grammar.json" + + args = [ + "--spirv-core-grammar", + rebase_path(core_json_file, root_build_dir), + "--extinst-opencl-grammar", + rebase_path(opengl_json_file, root_build_dir), + "--opencl-insts-output", + rebase_path(opencl_insts_file, root_build_dir), + "--extinst-debuginfo-grammar", + rebase_path(debug_insts_file, root_build_dir), + ] + inputs = [ + core_json_file, + opengl_json_file, + ] + outputs = [ + opencl_insts_file, + ] + } +} + +template("spvtools_language_header") { + assert(defined(invoker.name), "Need name in $target_name generation.") + + action("spvtools_language_header_" + target_name) { + script = "utils/generate_language_headers.py" + + name = invoker.name + extinst_output_base = "${target_gen_dir}/${name}" + debug_insts_file = "source/extinst.debuginfo.grammar.json" + + args = [ + "--extinst-name", + "${name}", + "--extinst-grammar", + rebase_path(debug_insts_file, root_build_dir), + "--extinst-output-base", + rebase_path(extinst_output_base, root_build_dir), + ] + inputs = [ + debug_insts_file, + ] + outputs = [ + "${extinst_output_base}.h", + ] + } +} + +template("spvtools_vendor_table") { + assert(defined(invoker.name), "Need name in $target_name generation.") + + action("spvtools_vendor_tables_" + target_name) { + script = "utils/generate_grammar_tables.py" + + name = invoker.name + extinst_vendor_grammar = "source/extinst.${name}.grammar.json" + extinst_file = "${target_gen_dir}/${name}.insts.inc" + + args = [ + "--extinst-vendor-grammar", + rebase_path(extinst_vendor_grammar, root_build_dir), + "--vendor-insts-output", + rebase_path(extinst_file, root_build_dir), + ] + inputs = [ + extinst_vendor_grammar, + ] + outputs = [ + extinst_file, + ] + } +} + +action("spvtools_generators_inc") { + script = "utils/generate_registry_tables.py" + + # TODO(dsinclair): Make work for chrome + xml_file = "${spirv_headers}/include/spirv/spir-v.xml" + inc_file = "${target_gen_dir}/generators.inc" + + sources = [ + xml_file, + ] + outputs = [ + inc_file, + ] + args = [ + "--xml", + rebase_path(xml_file, root_build_dir), + "--generator", + rebase_path(inc_file, root_build_dir), + ] +} + +spvtools_core_tables("unified1") { + version = "unified1" +} +spvtools_core_enums("unified1") { + version = "unified1" +} +spvtools_glsl_tables("glsl1-0") { + version = "1.0" +} +spvtools_opencl_tables("opencl1-0") { + version = "1.0" +} +spvtools_language_header("unified1") { + name = "DebugInfo" +} + +spvtools_vendor_tables = [ + "spv-amd-shader-explicit-vertex-parameter", + "spv-amd-shader-trinary-minmax", + "spv-amd-gcn-shader", + "spv-amd-shader-ballot", + "debuginfo", +] + +foreach(table, spvtools_vendor_tables) { + spvtools_vendor_table(table) { + name = table + } +} + +config("spvtools_config") { + include_dirs = [ + ".", + "include", + "source", + "$target_gen_dir", + "${spirv_headers}/include", + ] + + if (is_clang) { + cflags = [ "-Wno-implicit-fallthrough" ] + } +} + +static_library("spvtools") { + deps = [ + ":spvtools_core_enums_unified1", + ":spvtools_core_tables_unified1", + ":spvtools_generators_inc", + ":spvtools_glsl_tables_glsl1-0", + ":spvtools_language_header_unified1", + ":spvtools_opencl_tables_opencl1-0", + ] + foreach(target_name, spvtools_vendor_tables) { + deps += [ ":spvtools_vendor_tables_$target_name" ] + } + + sources = [ + "source/assembly_grammar.cpp", + "source/assembly_grammar.h", + "source/binary.cpp", + "source/binary.h", + "source/diagnostic.cpp", + "source/diagnostic.h", + "source/disassemble.cpp", + "source/enum_set.h", + "source/enum_string_mapping.cpp", + "source/ext_inst.cpp", + "source/ext_inst.h", + "source/extensions.cpp", + "source/extensions.h", + "source/instruction.h", + "source/libspirv.cpp", + "source/macro.h", + "source/message.cpp", + "source/name_mapper.cpp", + "source/name_mapper.h", + "source/opcode.cpp", + "source/opcode.h", + "source/operand.cpp", + "source/operand.h", + "source/parsed_operand.cpp", + "source/parsed_operand.h", + "source/print.cpp", + "source/print.h", + "source/spirv_constant.h", + "source/spirv_definition.h", + "source/spirv_endian.cpp", + "source/spirv_endian.h", + "source/spirv_target_env.cpp", + "source/spirv_target_env.h", + "source/spirv_validator_options.cpp", + "source/spirv_validator_options.h", + "source/table.cpp", + "source/table.h", + "source/text.cpp", + "source/text.h", + "source/text_handler.cpp", + "source/text_handler.h", + "source/util/bit_stream.cpp", + "source/util/bit_stream.h", + "source/util/bit_vector.cpp", + "source/util/bit_vector.h", + "source/util/bitutils.h", + "source/util/hex_float.h", + "source/util/hufman_codec.h", + "source/util/ilist.h", + "source/util/ilist_node.h", + "source/util/move_to_front.h", + "source/util/parse_number.cpp", + "source/util/parse_number.h", + "source/util/small_vector.h", + "source/util/string_utils.cpp", + "source/util/string_utils.h", + "source/util/timer.cpp", + "source/util/timer.h", + ] + + public_configs = [ ":spvtools_config" ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} + +static_library("spvtools_val") { + sources = [ + "source/val/basic_block.cpp", + "source/val/construct.cpp", + "source/val/function.cpp", + "source/val/instruction.cpp", + "source/val/validate.cpp", + "source/val/validate.h", + "source/val/validate_adjacency.cpp", + "source/val/validate_arithmetics.cpp", + "source/val/validate_atomics.cpp", + "source/val/validate_barriers.cpp", + "source/val/validate_bitwise.cpp", + "source/val/validate_builtins.cpp", + "source/val/validate_capability.cpp", + "source/val/validate_cfg.cpp", + "source/val/validate_composites.cpp", + "source/val/validate_conversion.cpp", + "source/val/validate_datarules.cpp", + "source/val/validate_decorations.cpp", + "source/val/validate_derivatives.cpp", + "source/val/validate_ext_inst.cpp", + "source/val/validate_id.cpp", + "source/val/validate_image.cpp", + "source/val/validate_instruction.cpp", + "source/val/validate_interfaces.cpp", + "source/val/validate_layout.cpp", + "source/val/validate_literals.cpp", + "source/val/validate_logicals.cpp", + "source/val/validate_non_uniform.cpp", + "source/val/validate_primitives.cpp", + "source/val/validate_type_unique.cpp", + "source/val/validation_state.cpp", + ] + + deps = [ + ":spvtools", + ] + + public_configs = [ ":spvtools_config" ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} + +static_library("spvtools_opt") { + sources = [ + "source/opt/aggressive_dead_code_elim_pass.cpp", + "source/opt/aggressive_dead_code_elim_pass.h", + "source/opt/basic_block.cpp", + "source/opt/basic_block.h", + "source/opt/block_merge_pass.cpp", + "source/opt/block_merge_pass.h", + "source/opt/build_module.cpp", + "source/opt/build_module.h", + "source/opt/ccp_pass.cpp", + "source/opt/ccp_pass.h", + "source/opt/cfg.cpp", + "source/opt/cfg.h", + "source/opt/cfg_cleanup_pass.cpp", + "source/opt/cfg_cleanup_pass.h", + "source/opt/common_uniform_elim_pass.cpp", + "source/opt/common_uniform_elim_pass.h", + "source/opt/compact_ids_pass.cpp", + "source/opt/compact_ids_pass.h", + "source/opt/composite.cpp", + "source/opt/composite.h", + "source/opt/const_folding_rules.cpp", + "source/opt/const_folding_rules.h", + "source/opt/constants.cpp", + "source/opt/constants.h", + "source/opt/copy_prop_arrays.cpp", + "source/opt/copy_prop_arrays.h", + "source/opt/dead_branch_elim_pass.cpp", + "source/opt/dead_branch_elim_pass.h", + "source/opt/dead_insert_elim_pass.cpp", + "source/opt/dead_insert_elim_pass.h", + "source/opt/dead_variable_elimination.cpp", + "source/opt/dead_variable_elimination.h", + "source/opt/decoration_manager.cpp", + "source/opt/decoration_manager.h", + "source/opt/def_use_manager.cpp", + "source/opt/def_use_manager.h", + "source/opt/dominator_analysis.cpp", + "source/opt/dominator_analysis.h", + "source/opt/dominator_tree.cpp", + "source/opt/dominator_tree.h", + "source/opt/eliminate_dead_constant_pass.cpp", + "source/opt/eliminate_dead_constant_pass.h", + "source/opt/eliminate_dead_functions_pass.cpp", + "source/opt/eliminate_dead_functions_pass.h", + "source/opt/feature_manager.cpp", + "source/opt/feature_manager.h", + "source/opt/flatten_decoration_pass.cpp", + "source/opt/flatten_decoration_pass.h", + "source/opt/fold.cpp", + "source/opt/fold.h", + "source/opt/fold_spec_constant_op_and_composite_pass.cpp", + "source/opt/fold_spec_constant_op_and_composite_pass.h", + "source/opt/folding_rules.cpp", + "source/opt/folding_rules.h", + "source/opt/freeze_spec_constant_value_pass.cpp", + "source/opt/freeze_spec_constant_value_pass.h", + "source/opt/function.cpp", + "source/opt/function.h", + "source/opt/if_conversion.cpp", + "source/opt/if_conversion.h", + "source/opt/inline_exhaustive_pass.cpp", + "source/opt/inline_exhaustive_pass.h", + "source/opt/inline_opaque_pass.cpp", + "source/opt/inline_opaque_pass.h", + "source/opt/inline_pass.cpp", + "source/opt/inline_pass.h", + "source/opt/instruction.cpp", + "source/opt/instruction.h", + "source/opt/instruction_list.cpp", + "source/opt/instruction_list.h", + "source/opt/ir_builder.h", + "source/opt/ir_context.cpp", + "source/opt/ir_context.h", + "source/opt/ir_loader.cpp", + "source/opt/ir_loader.h", + "source/opt/iterator.h", + "source/opt/licm_pass.cpp", + "source/opt/licm_pass.h", + "source/opt/local_access_chain_convert_pass.cpp", + "source/opt/local_access_chain_convert_pass.h", + "source/opt/local_redundancy_elimination.cpp", + "source/opt/local_redundancy_elimination.h", + "source/opt/local_single_block_elim_pass.cpp", + "source/opt/local_single_block_elim_pass.h", + "source/opt/local_single_store_elim_pass.cpp", + "source/opt/local_single_store_elim_pass.h", + "source/opt/local_ssa_elim_pass.cpp", + "source/opt/local_ssa_elim_pass.h", + "source/opt/log.h", + "source/opt/loop_dependence.cpp", + "source/opt/loop_dependence.h", + "source/opt/loop_dependence_helpers.cpp", + "source/opt/loop_descriptor.cpp", + "source/opt/loop_descriptor.h", + "source/opt/loop_fission.cpp", + "source/opt/loop_fission.h", + "source/opt/loop_fusion.cpp", + "source/opt/loop_fusion.h", + "source/opt/loop_fusion_pass.cpp", + "source/opt/loop_fusion_pass.h", + "source/opt/loop_peeling.cpp", + "source/opt/loop_peeling.h", + "source/opt/loop_unroller.cpp", + "source/opt/loop_unroller.h", + "source/opt/loop_unswitch_pass.cpp", + "source/opt/loop_unswitch_pass.h", + "source/opt/loop_utils.cpp", + "source/opt/loop_utils.h", + "source/opt/make_unique.h", + "source/opt/mem_pass.cpp", + "source/opt/mem_pass.h", + "source/opt/merge_return_pass.cpp", + "source/opt/merge_return_pass.h", + "source/opt/module.cpp", + "source/opt/module.h", + "source/opt/null_pass.h", + "source/opt/optimizer.cpp", + "source/opt/pass.cpp", + "source/opt/pass.h", + "source/opt/pass_manager.cpp", + "source/opt/pass_manager.h", + "source/opt/passes.h", + "source/opt/private_to_local_pass.cpp", + "source/opt/private_to_local_pass.h", + "source/opt/propagator.cpp", + "source/opt/propagator.h", + "source/opt/reduce_load_size.cpp", + "source/opt/reduce_load_size.h", + "source/opt/redundancy_elimination.cpp", + "source/opt/redundancy_elimination.h", + "source/opt/reflect.h", + "source/opt/register_pressure.cpp", + "source/opt/register_pressure.h", + "source/opt/remove_duplicates_pass.cpp", + "source/opt/remove_duplicates_pass.h", + "source/opt/replace_invalid_opc.cpp", + "source/opt/replace_invalid_opc.h", + "source/opt/scalar_analysis.cpp", + "source/opt/scalar_analysis.h", + "source/opt/scalar_analysis_nodes.h", + "source/opt/scalar_analysis_simplification.cpp", + "source/opt/scalar_replacement_pass.cpp", + "source/opt/scalar_replacement_pass.h", + "source/opt/set_spec_constant_default_value_pass.cpp", + "source/opt/set_spec_constant_default_value_pass.h", + "source/opt/simplification_pass.cpp", + "source/opt/simplification_pass.h", + "source/opt/ssa_rewrite_pass.cpp", + "source/opt/ssa_rewrite_pass.h", + "source/opt/strength_reduction_pass.cpp", + "source/opt/strength_reduction_pass.h", + "source/opt/strip_debug_info_pass.cpp", + "source/opt/strip_debug_info_pass.h", + "source/opt/strip_reflect_info_pass.cpp", + "source/opt/strip_reflect_info_pass.h", + "source/opt/tree_iterator.h", + "source/opt/type_manager.cpp", + "source/opt/type_manager.h", + "source/opt/types.cpp", + "source/opt/types.h", + "source/opt/unify_const_pass.cpp", + "source/opt/unify_const_pass.h", + "source/opt/value_number_table.cpp", + "source/opt/value_number_table.h", + "source/opt/vector_dce.cpp", + "source/opt/vector_dce.h", + "source/opt/workaround1209.cpp", + "source/opt/workaround1209.h", + ] + deps = [ + ":spvtools", + ] + + public_configs = [ ":spvtools_config" ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] +} + +static_library("SPIRV-Tools") { + deps = [ + ":spvtools", + ":spvtools_opt", + ":spvtools_val", + ] +} + +if (!build_with_chromium) { + static_library("gtest") { + testonly = true + + defines = [ + # In order to allow regex matches in gtest to be shared between Windows + # and other systems, we tell gtest to always use its internal engine. + "GTEST_HAS_POSIX_RE=0", + + # Enables C++11 features. + "GTEST_LANG_CXX11=1", + + # Prevents gtest from including both and . + "GTEST_HAS_TR1_TUPLE=0", + ] + + sources = [ + "external/googletest/googletest/include/gtest/gtest-death-test.h", + "external/googletest/googletest/include/gtest/gtest-message.h", + "external/googletest/googletest/include/gtest/gtest-param-test.h", + "external/googletest/googletest/include/gtest/gtest-printers.h", + "external/googletest/googletest/include/gtest/gtest-spi.h", + "external/googletest/googletest/include/gtest/gtest-test-part.h", + "external/googletest/googletest/include/gtest/gtest-typed-test.h", + "external/googletest/googletest/include/gtest/gtest.h", + "external/googletest/googletest/include/gtest/gtest_pred_impl.h", + "external/googletest/googletest/include/gtest/internal/gtest-death-test-internal.h", + "external/googletest/googletest/include/gtest/internal/gtest-filepath.h", + "external/googletest/googletest/include/gtest/internal/gtest-internal.h", + "external/googletest/googletest/include/gtest/internal/gtest-linked_ptr.h", + "external/googletest/googletest/include/gtest/internal/gtest-param-util-generated.h", + "external/googletest/googletest/include/gtest/internal/gtest-param-util.h", + "external/googletest/googletest/include/gtest/internal/gtest-port.h", + "external/googletest/googletest/include/gtest/internal/gtest-string.h", + "external/googletest/googletest/include/gtest/internal/gtest-tuple.h", + "external/googletest/googletest/include/gtest/internal/gtest-type-util.h", + "external/googletest/googletest/src/gtest-death-test.cc", + "external/googletest/googletest/src/gtest-filepath.cc", + "external/googletest/googletest/src/gtest-internal-inl.h", + "external/googletest/googletest/src/gtest-port.cc", + "external/googletest/googletest/src/gtest-printers.cc", + "external/googletest/googletest/src/gtest-test-part.cc", + "external/googletest/googletest/src/gtest-typed-test.cc", + "external/googletest/googletest/src/gtest.cc", + ] + + include_dirs = [ + "external/googletest/googletest/include", + "external/googletest/googletest/", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + } + + static_library("gmock") { + testonly = true + sources = [ + "external/googletest/googlemock/include/gmock/gmock-actions.h", + "external/googletest/googlemock/include/gmock/gmock-cardinalities.h", + "external/googletest/googlemock/include/gmock/gmock-generated-actions.h", + "external/googletest/googlemock/include/gmock/gmock-generated-function-mockers.h", + "external/googletest/googlemock/include/gmock/gmock-generated-matchers.h", + "external/googletest/googlemock/include/gmock/gmock-generated-nice-strict.h", + "external/googletest/googlemock/include/gmock/gmock-matchers.h", + "external/googletest/googlemock/include/gmock/gmock-spec-builders.h", + "external/googletest/googlemock/include/gmock/gmock.h", + "external/googletest/googlemock/include/gmock/internal/gmock-generated-internal-utils.h", + "external/googletest/googlemock/include/gmock/internal/gmock-internal-utils.h", + "external/googletest/googlemock/include/gmock/internal/gmock-port.h", + "external/googletest/googlemock/src/gmock-cardinalities.cc", + "external/googletest/googlemock/src/gmock-internal-utils.cc", + "external/googletest/googlemock/src/gmock-matchers.cc", + "external/googletest/googlemock/src/gmock-spec-builders.cc", + "external/googletest/googlemock/src/gmock.cc", + ] + + include_dirs = [ + "external/googletest/googletest/include", + "external/googletest/googlemock/include", + ] + } +} + +config("spvtools_test_config") { + if (is_clang) { + cflags = [ "-Wno-self-assign" ] + } +} + +test("spvtools_test") { + sources = [ + "test/assembly_context_test.cpp", + "test/assembly_format_test.cpp", + "test/binary_destroy_test.cpp", + "test/binary_endianness_test.cpp", + "test/binary_header_get_test.cpp", + "test/binary_parse_test.cpp", + "test/binary_strnlen_s_test.cpp", + "test/binary_to_text.literal_test.cpp", + "test/binary_to_text_test.cpp", + "test/comment_test.cpp", + "test/enum_set_test.cpp", + "test/enum_string_mapping_test.cpp", + "test/ext_inst.debuginfo_test.cpp", + "test/ext_inst.glsl_test.cpp", + "test/ext_inst.opencl_test.cpp", + "test/fix_word_test.cpp", + "test/generator_magic_number_test.cpp", + "test/hex_float_test.cpp", + "test/immediate_int_test.cpp", + "test/libspirv_macros_test.cpp", + "test/name_mapper_test.cpp", + "test/named_id_test.cpp", + "test/opcode_make_test.cpp", + "test/opcode_require_capabilities_test.cpp", + "test/opcode_split_test.cpp", + "test/opcode_table_get_test.cpp", + "test/operand_capabilities_test.cpp", + "test/operand_pattern_test.cpp", + "test/operand_test.cpp", + "test/target_env_test.cpp", + "test/test_fixture.h", + "test/text_advance_test.cpp", + "test/text_destroy_test.cpp", + "test/text_literal_test.cpp", + "test/text_start_new_inst_test.cpp", + "test/text_to_binary.annotation_test.cpp", + "test/text_to_binary.barrier_test.cpp", + "test/text_to_binary.constant_test.cpp", + "test/text_to_binary.control_flow_test.cpp", + "test/text_to_binary.debug_test.cpp", + "test/text_to_binary.device_side_enqueue_test.cpp", + "test/text_to_binary.extension_test.cpp", + "test/text_to_binary.function_test.cpp", + "test/text_to_binary.group_test.cpp", + "test/text_to_binary.image_test.cpp", + "test/text_to_binary.literal_test.cpp", + "test/text_to_binary.memory_test.cpp", + "test/text_to_binary.misc_test.cpp", + "test/text_to_binary.mode_setting_test.cpp", + "test/text_to_binary.pipe_storage_test.cpp", + "test/text_to_binary.reserved_sampling_test.cpp", + "test/text_to_binary.subgroup_dispatch_test.cpp", + "test/text_to_binary.type_declaration_test.cpp", + "test/text_to_binary_test.cpp", + "test/text_word_get_test.cpp", + "test/unit_spirv.cpp", + "test/unit_spirv.h", + ] + + deps = [ + ":spvtools", + ] + + if (build_with_chromium) { + deps += [ + "//testing/gmock", + "//testing/gtest", + "//testing/gtest:gtest_main", + ] + } else { + deps += [ + ":gmock", + ":gtest", + ] + + sources += [ "external/googletest/googletest/src/gtest_main.cc" ] + + include_dirs = [ + "external/googletest/googletest/include", + "external/googletest/googlemock/include", + ] + } + + configs += [ + ":spvtools_config", + ":spvtools_test_config", + ] +} + +if (!build_with_chromium) { + group("fuzzers") { + testonly = true + deps = [ + "//testing/fuzzers", + ] + } +} diff --git a/DEPS b/DEPS index 4ce20c87..a1f24fce 100644 --- a/DEPS +++ b/DEPS @@ -4,15 +4,20 @@ vars = { 'chromium_git': 'https://chromium.googlesource.com', 'github': 'https://github.com', + 'build_revision': '037f38ae0fe5e11b4f7c33b750fd7a1e9634a606', 'buildtools_revision': 'ab7b6a7b350dd15804c87c20ce78982811fdd76f', 'clang_revision': 'abe5e4f9dc0f1df848c7a0efa05256253e77a7b7', 'effcee_revision': '04b624799f5a9dbaf3fa1dbed2ba9dce2fc8dcf2', 'googletest_revision': '98a0d007d7092b72eea0e501bb9ad17908a1a036', + 'libfuzzer_revision': 'c24c2cd3f4d6130e815b6baff8165e4df440d442', 're2_revision': '6cf8ccd82dbaab2668e9b13596c68183c9ecd13f', 'spirv_headers_revision': 'ff684ffc6a35d2a58f0f63108877d0064ea33feb', } deps = { + "build": + Var('chromium_git') + "/chromium/src/build.git@" + Var('build_revision'), + 'buildtools': Var('chromium_git') + '/chromium/buildtools.git@' + Var('buildtools_revision'), @@ -30,6 +35,10 @@ deps = { 'external/re2': Var('github') + '/google/re2.git@' + Var('re2_revision'), + 'testing/libfuzzer': + Var('chromium_git') + '/chromium/src/testing/libfuzzer@' + + Var('libfuzzer_revision'), + 'tools/clang': Var('chromium_git') + '/chromium/src/tools/clang@' + Var('clang_revision') } @@ -40,6 +49,38 @@ recursedeps = [ ] hooks = [ + { + 'name': 'gn_win', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=win32', + '--no_auth', + '--bucket', 'chromium-gn', + '-s', 'SPIRV-Tools/buildtools/win/gn.exe.sha1', + ], + }, + { + 'name': 'gn_mac', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=darwin', + '--no_auth', + '--bucket', 'chromium-gn', + '-s', 'SPIRV-Tools/buildtools/mac/gn.sha1', + ], + }, + { + 'name': 'gn_linux64', + 'pattern': '.', + 'action': [ 'download_from_google_storage', + '--no_resume', + '--platform=linux*', + '--no_auth', + '--bucket', 'chromium-gn', + '-s', 'SPIRV-Tools/buildtools/linux64/gn.sha1', + ], + }, # Pull clang-format binaries using checked-in hashes. { 'name': 'clang_format_win', @@ -82,4 +123,52 @@ hooks = [ 'SPIRV-Tools/tools/clang/scripts/update.py' ], }, + { + 'name': 'sysroot_arm', + 'pattern': '.', + 'condition': 'checkout_linux and checkout_arm', + 'action': ['python', 'SPIRV-Tools/build/linux/sysroot_scripts/install-sysroot.py', + '--arch=arm'], + }, + { + 'name': 'sysroot_arm64', + 'pattern': '.', + 'condition': 'checkout_linux and checkout_arm64', + 'action': ['python', 'SPIRV-Tools/build/linux/sysroot_scripts/install-sysroot.py', + '--arch=arm64'], + }, + { + 'name': 'sysroot_x86', + 'pattern': '.', + 'condition': 'checkout_linux and (checkout_x86 or checkout_x64)', + 'action': ['python', 'SPIRV-Tools/build/linux/sysroot_scripts/install-sysroot.py', + '--arch=x86'], + }, + { + 'name': 'sysroot_mips', + 'pattern': '.', + 'condition': 'checkout_linux and checkout_mips', + 'action': ['python', 'SPIRV-Tools/build/linux/sysroot_scripts/install-sysroot.py', + '--arch=mips'], + }, + { + 'name': 'sysroot_x64', + 'pattern': '.', + 'condition': 'checkout_linux and checkout_x64', + 'action': ['python', 'SPIRV-Tools/build/linux/sysroot_scripts/install-sysroot.py', + '--arch=x64'], + }, + { + # Update the Windows toolchain if necessary. + 'name': 'win_toolchain', + 'pattern': '.', + 'condition': 'checkout_win', + 'action': ['python', 'SPIRV-Tools/build/vs_toolchain.py', 'update', '--force'], + }, + { + # Update the Mac toolchain if necessary. + 'name': 'mac_toolchain', + 'pattern': '.', + 'action': ['python', 'SPIRV-Tools/build/mac_toolchain.py'], + }, ] diff --git a/build_overrides/build.gni b/build_overrides/build.gni new file mode 100644 index 00000000..833fcd34 --- /dev/null +++ b/build_overrides/build.gni @@ -0,0 +1,46 @@ +# Copyright 2018 Google Inc. +# +# 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 +# +# https://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. + +# Variable that can be used to support multiple build scenarios, like having +# Chromium specific targets in a client project's GN file etc. +build_with_chromium = false + +# Don't use Chromium's third_party/binutils. +linux_use_bundled_binutils_override = false + +declare_args() { + # Android 32-bit non-component, non-clang builds cannot have symbol_level=2 + # due to 4GiB file size limit, see https://crbug.com/648948. + # Set this flag to true to skip the assertion. + ignore_elf32_limitations = false + + # Use the system install of Xcode for tools like ibtool, libtool, etc. + # This does not affect the compiler. When this variable is false, targets will + # instead use a hermetic install of Xcode. [The hermetic install can be + # obtained with gclient sync after setting the environment variable + # FORCE_MAC_TOOLCHAIN]. + use_system_xcode = "" +} + +if (use_system_xcode == "") { + if (target_os == "mac") { + _result = exec_script("//build/mac/should_use_hermetic_xcode.py", + [ target_os ], + "value") + use_system_xcode = _result == 0 + } + if (target_os == "ios") { + use_system_xcode = true + } +} diff --git a/build_overrides/gtest.gni b/build_overrides/gtest.gni new file mode 100644 index 00000000..c8b1bae4 --- /dev/null +++ b/build_overrides/gtest.gni @@ -0,0 +1,25 @@ +# Copyright 2018 Google Inc. +# +# 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 +# +# https://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. + +# Exclude support for registering main function in multi-process tests. +gtest_include_multiprocess = false + +# Exclude support for platform-specific operations across unit tests. +gtest_include_platform_test = false + +# Exclude support for testing Objective C code on OS X and iOS. +gtest_include_objc_support = false + +# Exclude support for flushing coverage files on iOS. +gtest_include_ios_coverage = false diff --git a/testing/fuzzers/BUILD.gn b/testing/fuzzers/BUILD.gn new file mode 100644 index 00000000..b8777ecd --- /dev/null +++ b/testing/fuzzers/BUILD.gn @@ -0,0 +1,89 @@ +# Copyright 2018 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//testing/libfuzzer/fuzzer_test.gni") +import("//testing/test.gni") + +config("fuzzer_config") { + configs = [ "../..:spvtools_config" ] +} + +group("fuzzers") { + testonly = true + deps = [] + + if (!build_with_chromium || use_fuzzing_engine) { + deps += [ ":fuzzers_bin" ] + } +} + +group("fuzzers_bin") { + testonly = true + + deps = [ + ":spvtools_opt_fuzzer", + ":spvtools_val_fuzzer", + ] +} + +template("spvtools_fuzzer") { + source_set(target_name) { + testonly = true + sources = invoker.sources + deps = [ + "../..:spvtools", + "../..:spvtools_opt", + "../..:spvtools_val", + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + ":fuzzer_config", + ] + } +} + +spvtools_fuzzer("spvtools_opt_fuzzer_src") { + sources = [ + "spvtools_opt_fuzzer.cpp", + ] +} + +spvtools_fuzzer("spvtools_val_fuzzer_src") { + sources = [ + "spvtools_val_fuzzer.cpp", + ] +} + +if (!build_with_chromium || use_fuzzing_engine) { + fuzzer_test("spvtools_opt_fuzzer") { + sources = [] + deps = [ + ":spvtools_opt_fuzzer_src", + ] + seed_corpus = "corpora/spv" + } + + fuzzer_test("spvtools_val_fuzzer") { + sources = [] + deps = [ + ":spvtools_val_fuzzer_src", + ] + seed_corpus = "corpora/spv" + } +} diff --git a/testing/fuzzers/corpora/spv/simple.spv b/testing/fuzzers/corpora/spv/simple.spv new file mode 100644 index 00000000..f972a56f Binary files /dev/null and b/testing/fuzzers/corpora/spv/simple.spv differ diff --git a/testing/fuzzers/spvtools_opt_fuzzer.cpp b/testing/fuzzers/spvtools_opt_fuzzer.cpp new file mode 100644 index 00000000..20ded9a0 --- /dev/null +++ b/testing/fuzzers/spvtools_opt_fuzzer.cpp @@ -0,0 +1,36 @@ +// Copyright (c) 2018 Google Inc. +// +// 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. + +#include + +#include "spirv-tools/optimizer.hpp" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_3); + optimizer.SetMessageConsumer([](spv_message_level_t, const char*, + const spv_position_t&, const char*) {}); + + std::vector input; + input.resize(size >> 2); + + size_t count = 0; + for (size_t i = 0; (i + 3) < size; i += 4) { + input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | + (data[i + 3]) << 24; + } + + optimizer.Run(input.data(), input.size(), &input); + + return 0; +} diff --git a/testing/fuzzers/spvtools_val_fuzzer.cpp b/testing/fuzzers/spvtools_val_fuzzer.cpp new file mode 100644 index 00000000..9b06a1f6 --- /dev/null +++ b/testing/fuzzers/spvtools_val_fuzzer.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2018 Google Inc. +// +// 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. + +#include + +#include "spirv-tools/libspirv.hpp" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + spvtools::SpirvTools tools(SPV_ENV_UNIVERSAL_1_3); + tools.SetMessageConsumer([](spv_message_level_t, const char*, + const spv_position_t&, const char*) {}); + + std::vector input; + input.resize(size >> 2); + + size_t count = 0; + for (size_t i = 0; (i + 3) < size; i += 4) { + input[count++] = data[i] | (data[i + 1] << 8) | (data[i + 2] << 16) | + (data[i + 3]) << 24; + } + + tools.Validate(input); + return 0; +} diff --git a/testing/test.gni b/testing/test.gni new file mode 100644 index 00000000..d42fe52c --- /dev/null +++ b/testing/test.gni @@ -0,0 +1,413 @@ +# Copyright 2018 The Chromium Authors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# ============================================================================== +# TEST SETUP +# ============================================================================== + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") + import("//build/config/sanitizers/sanitizers.gni") + import("//build/config/android/extract_unwind_tables.gni") +} + +if (is_fuchsia) { + import("//build/config/chromecast_build.gni") + import("//build/config/fuchsia/rules.gni") + import("//build/config/fuchsia/package.gni") +} + +if (is_chromeos) { + import("//build/config/chromeos/rules.gni") +} + +# Define a test as an executable (or apk on Android) with the "testonly" flag +# set. +# Variable: +# use_raw_android_executable: Use executable() rather than android_apk(). +# use_native_activity: Test implements ANativeActivity_onCreate(). +template("test") { + if (is_android) { + _use_raw_android_executable = defined(invoker.use_raw_android_executable) && + invoker.use_raw_android_executable + + # output_name is used to allow targets with the same name but in different + # packages to still produce unique runner scripts. + _output_name = invoker.target_name + if (defined(invoker.output_name)) { + _output_name = invoker.output_name + } + + _test_runner_target = "${_output_name}__test_runner_script" + _wrapper_script_vars = [ + "ignore_all_data_deps", + "shard_timeout", + ] + + assert(_use_raw_android_executable || enable_java_templates) + + _incremental_apk_only = + incremental_apk_by_default && !_use_raw_android_executable + + if (_use_raw_android_executable) { + _exec_target = "${target_name}__exec" + _dist_target = "${target_name}__dist" + _exec_output = + "$target_out_dir/${invoker.target_name}/${invoker.target_name}" + + executable(_exec_target) { + # Configs will always be defined since we set_defaults in BUILDCONFIG.gn. + configs = [] + data_deps = [] + forward_variables_from(invoker, + "*", + _wrapper_script_vars + [ "extra_dist_files" ]) + testonly = true + + # Thanks to the set_defaults() for test(), configs are initialized with + # the default shared_library configs rather than executable configs. + configs -= [ + "//build/config:shared_library_config", + "//build/config/android:hide_all_but_jni", + ] + configs += [ "//build/config:executable_config" ] + + # Don't output to the root or else conflict with the group() below. + output_name = rebase_path(_exec_output, root_out_dir) + if (is_component_build || is_asan) { + data_deps += [ "//build/android:cpplib_stripped" ] + } + } + + create_native_executable_dist(_dist_target) { + testonly = true + dist_dir = "$root_out_dir/$target_name" + binary = _exec_output + deps = [ + ":$_exec_target", + ] + if (defined(invoker.extra_dist_files)) { + extra_files = invoker.extra_dist_files + } + } + } else { + _library_target = "_${target_name}__library" + _apk_target = "${target_name}_apk" + _apk_specific_vars = [ + "android_manifest", + "android_manifest_dep", + "enable_multidex", + "proguard_configs", + "proguard_enabled", + "use_default_launcher", + "write_asset_list", + "use_native_activity", + ] + + # Adds the unwind tables from unstripped binary as an asset file in the + # apk, if |add_unwind_tables_in_apk| is specified by the test. + if (defined(invoker.add_unwind_tables_in_apk) && + invoker.add_unwind_tables_in_apk) { + _unwind_table_asset_name = "${target_name}_unwind_assets" + unwind_table_asset(_unwind_table_asset_name) { + testonly = true + library_target = _library_target + deps = [ + ":$_library_target", + ] + } + } + + shared_library(_library_target) { + # Configs will always be defined since we set_defaults in BUILDCONFIG.gn. + configs = [] # Prevent list overwriting warning. + configs = invoker.configs + testonly = true + + deps = [] + forward_variables_from( + invoker, + "*", + _apk_specific_vars + _wrapper_script_vars + [ "visibility" ]) + + if (!defined(invoker.use_default_launcher) || + invoker.use_default_launcher) { + deps += [ "//testing/android/native_test:native_test_native_code" ] + } + } + unittest_apk(_apk_target) { + forward_variables_from(invoker, _apk_specific_vars + [ "deps" ]) + shared_library = ":$_library_target" + apk_name = invoker.target_name + if (defined(invoker.output_name)) { + apk_name = invoker.output_name + install_script_name = "install_${invoker.output_name}" + } + + # Add the Java classes so that each target does not have to do it. + deps += [ "//base/test:test_support_java" ] + + if (defined(_unwind_table_asset_name)) { + deps += [ ":${_unwind_table_asset_name}" ] + } + + # TODO(agrieve): Remove this data_dep once bots don't build the _apk + # target (post-GYP). + # It's a bit backwards for the apk to depend on the runner script, since + # the apk is conceptually a runtime_dep of the script. However, it is + # currently necessary because the bots build this _apk target directly + # rather than the group() below. + data_deps = [ + ":$_test_runner_target", + ] + } + + _test_runner_target = "${_output_name}__test_runner_script" + _incremental_test_name = "${_output_name}_incremental" + _incremental_test_runner_target = + "${_output_name}_incremental__test_runner_script" + if (_incremental_apk_only) { + _incremental_test_name = _output_name + _incremental_test_runner_target = _test_runner_target + } + + # Incremental test targets work only for .apks. + test_runner_script(_incremental_test_runner_target) { + forward_variables_from(invoker, + _wrapper_script_vars + [ + "data", + "data_deps", + "deps", + "public_deps", + ]) + apk_target = ":$_apk_target" + test_name = _incremental_test_name + test_type = "gtest" + test_suite = _output_name + incremental_install = true + } + group("${target_name}_incremental") { + testonly = true + data_deps = [ + ":$_incremental_test_runner_target", + ] + deps = [ + ":${_apk_target}_incremental", + ] + } + } + + if (!_incremental_apk_only) { + test_runner_script(_test_runner_target) { + forward_variables_from(invoker, + _wrapper_script_vars + [ + "data", + "data_deps", + "deps", + "public_deps", + ]) + + if (_use_raw_android_executable) { + executable_dist_dir = "$root_out_dir/$_dist_target" + } else { + apk_target = ":$_apk_target" + } + test_name = _output_name + test_type = "gtest" + test_suite = _output_name + } + } + + test_runner_script(target_name) { + forward_variables_from(invoker, + _wrapper_script_vars + [ + "data", + "data_deps", + "deps", + "public_deps", + ]) + + if (_use_raw_android_executable) { + executable_dist_dir = "$root_out_dir/$_dist_target" + deps += [ + ":$_dist_target", + ":$_test_runner_target", + ] + } else { + apk_target = ":$_apk_target" + deps += [ ":$_apk_target" ] + if (_incremental_apk_only) { + deps += [ ":${target_name}_incremental" ] + } else { + deps += [ ":$_test_runner_target" ] + } + } + generated_script = "$root_build_dir/$_output_name" + incremental_install = _incremental_apk_only + test_name = _output_name + test_suite = _output_name + test_type = "gtest" + } + } else if (is_fuchsia) { + _output_name = invoker.target_name + _pkg_target = "${_output_name}_pkg" + _gen_runner_target = "${_output_name}_runner" + _exec_target = "${_output_name}__exec" + + group(target_name) { + testonly = true + deps = [ + ":$_gen_runner_target", + ":$_pkg_target", + ] + } + + # Makes the script which invokes the executable. + test_runner_script(_gen_runner_target) { + forward_variables_from(invoker, [ "use_test_server" ]) + test_name = _output_name + package_name = _output_name + } + + executable(_exec_target) { + testonly = true + forward_variables_from(invoker, "*") + output_name = _exec_target + } + + package(_pkg_target) { + testonly = true + package_name = _output_name + sandbox_policy = "//build/config/fuchsia/testing_sandbox_policy" + binary = get_label_info(_exec_target, "name") + deps = [ + ":$_exec_target", + ] + } + } else if (is_ios) { + import("//build/config/ios/ios_sdk.gni") + import("//build/config/ios/rules.gni") + + _test_target = target_name + _resources_bundle_data = target_name + "_resources_bundle_data" + + bundle_data(_resources_bundle_data) { + visibility = [ ":$_test_target" ] + sources = [ + "//testing/gtest_ios/Default.png", + ] + outputs = [ + "{{bundle_resources_dir}}/{{source_file_part}}", + ] + } + + ios_app_bundle(_test_target) { + testonly = true + + # See above call. + set_sources_assignment_filter([]) + forward_variables_from(invoker, "*", [ "testonly" ]) + + # Provide sensible defaults in case invoker did not define any of those + # required variables. + if (!defined(info_plist) && !defined(info_plist_target)) { + info_plist = "//testing/gtest_ios/unittest-Info.plist" + } + + _bundle_id_suffix = ios_generic_test_bundle_id_suffix + if (!ios_automatically_manage_certs) { + _bundle_id_suffix = "${target_name}" + } + if (!defined(extra_substitutions)) { + extra_substitutions = [] + } + extra_substitutions += [ "GTEST_BUNDLE_ID_SUFFIX=$_bundle_id_suffix" ] + + if (!defined(bundle_deps)) { + bundle_deps = [] + } + bundle_deps += [ ":$_resources_bundle_data" ] + } + } else if (is_chromeos && cros_board != "") { + # When the arg cros_board is set, assume we're in the cros chrome-sdk + # building simplechrome. + + _gen_runner_target = "${target_name}__runner" + _runtime_deps_file = + "$root_out_dir/gen.runtime/" + get_label_info(target_name, "dir") + + "/" + get_label_info(target_name, "name") + ".runtime_deps" + + generate_vm_runner_script(_gen_runner_target) { + testonly = true + generated_script = "$root_build_dir/bin/run_" + invoker.target_name + test_exe = "$root_out_dir/" + get_label_info(invoker.target_name, "name") + runtime_deps_file = _runtime_deps_file + } + + executable(target_name) { + forward_variables_from(invoker, "*") + if (!defined(deps)) { + deps = [] + } + if (!defined(data)) { + data = [] + } + + testonly = true + output_name = target_name + write_runtime_deps = _runtime_deps_file + data += [ _runtime_deps_file ] + deps += [ ":$_gen_runner_target" ] + } + } else { + executable(target_name) { + forward_variables_from(invoker, "*") + if (!defined(deps)) { + deps = [] + } + + testonly = true + deps += [ + # Give tests the default manifest on Windows (a no-op elsewhere). + "//build/win:default_exe_manifest", + ] + } + } +} + +# Test defaults. +set_defaults("test") { + if (is_android) { + configs = default_shared_library_configs + configs -= [ "//build/config/android:hide_all_but_jni_onload" ] + configs += [ "//build/config/android:hide_all_but_jni" ] + } else { + configs = default_executable_configs + } +}