diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml index 3df5fe8..b8209c4 100644 --- a/.bcr/presubmit.yml +++ b/.bcr/presubmit.yml @@ -13,7 +13,5 @@ tasks: test_targets: - '@apple_support//test/...' - '--' - - '-@apple_support//test/shell:apple_test' - - '-@apple_support//test/shell:objc_test' # Needs the new toolchain - '-@apple_support//test:linking_disable_objc_apple_link_test' diff --git a/test/binary_tests.bzl b/test/binary_tests.bzl index dd358d7..db44ee2 100644 --- a/test/binary_tests.bzl +++ b/test/binary_tests.bzl @@ -22,6 +22,17 @@ def binary_test_suite(name): target_under_test = "//test/test_data:macos_binary", ) + apple_verification_test( + name = "{}_macos_binary_with_spaces_test".format(name), + tags = [name], + build_type = "device", + cpus = {"macos_cpus": "x86_64"}, + expected_platform_type = "macos", + generate_dsym = True, + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:macos_binary_with_spaces", + ) + apple_verification_test( name = "{}_visionos_device_test".format(name), tags = [name], @@ -73,3 +84,62 @@ def binary_test_suite(name): target_under_test = "//test/test_data:ios_app_with_unused_symbol", tags = [name], ) + + apple_verification_test( + name = "{}_archive_timestamps".format(name), + build_type = "simulator", + cpus = {"ios_multi_cpus": "x86_64"}, + verifier_script = "//test:verify_archive_timestamps.sh", + target_under_test = "//test/test_data:static_lib", + tags = [name], + ) + + apple_verification_test( + name = "{}_fat_static_lib".format(name), + build_type = "simulator", + cpus = {"ios_multi_cpus": "x86_64,sim_arm64"}, + expected_platform_type = "ios", + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:static_lib", + tags = [name], + ) + + apple_verification_test( + name = "{}_watchos_device_test".format(name), + tags = [name], + build_type = "device", + cpus = {"watchos_cpus": "x86_64"}, + expected_platform_type = "watchos", + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:watch_binary", + ) + + apple_verification_test( + name = "{}_watchos_simulator_test".format(name), + tags = [name], + build_type = "device", + cpus = {"watchos_cpus": "arm64"}, + expected_platform_type = "watchos", + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:watch_binary", + ) + + apple_verification_test( + name = "{}_ios_device_test".format(name), + tags = [name], + build_type = "device", + cpus = {"ios_multi_cpus": "x86_64,sim_arm64"}, + expected_platform_type = "ios", + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:ios_binary", + ) + + apple_verification_test( + name = "{}_ios_simulator_test".format(name), + tags = [name], + build_type = "device", + cpus = {"ios_multi_cpus": "arm64,arm64e"}, + expected_platform_type = "ios", + verifier_script = "//test/shell:verify_binary.sh", + target_under_test = "//test/test_data:ios_binary", + ) diff --git a/test/linking_tests.bzl b/test/linking_tests.bzl index f879702..ed1032f 100644 --- a/test/linking_tests.bzl +++ b/test/linking_tests.bzl @@ -15,6 +15,12 @@ disable_objc_test = make_action_command_line_test_rule( }, ) +dsym_test = make_action_command_line_test_rule( + config_settings = { + "//command_line_option:apple_generate_dsym": True, + }, +) + def linking_test_suite(name): default_test( name = "{}_default_apple_link_test".format(name), @@ -26,6 +32,10 @@ def linking_test_suite(name): "2", "-ObjC", ], + not_expected_argv = [ + "-g", + "DSYM_HINT_LINKED_BINARY", + ], mnemonic = "ObjcLink", target_under_test = "//test/test_data:macos_binary", ) @@ -43,3 +53,14 @@ def linking_test_suite(name): mnemonic = "ObjcLink", target_under_test = "//test/test_data:macos_binary", ) + + dsym_test( + name = "{}_generate_dsym_test".format(name), + tags = [name], + expected_argv = [ + "-g", + "DSYM_HINT_LINKED_BINARY", + ], + mnemonic = "ObjcLink", + target_under_test = "//test/test_data:macos_binary", + ) diff --git a/test/rules/apple_verification_test.bzl b/test/rules/apple_verification_test.bzl index 0108f44..4735682 100644 --- a/test/rules/apple_verification_test.bzl +++ b/test/rules/apple_verification_test.bzl @@ -20,6 +20,7 @@ _supports_visionos = hasattr(apple_common.platform_type, "visionos") def _transition_impl(_, attr): output_dictionary = { + "//command_line_option:apple_generate_dsym": attr.generate_dsym, "//command_line_option:compilation_mode": attr.compilation_mode, "//command_line_option:cpu": "darwin_x86_64", "//command_line_option:ios_signing_cert_name": "-", @@ -56,6 +57,7 @@ _transition = transition( implementation = _transition_impl, inputs = [], outputs = [ + "//command_line_option:apple_generate_dsym", "//command_line_option:compilation_mode", "//command_line_option:cpu", "//command_line_option:ios_multi_cpus", @@ -110,6 +112,12 @@ def _apple_verification_test_impl(ctx): apple_verification_test = rule( implementation = _apple_verification_test_impl, attrs = { + "generate_dsym": attr.bool( + default = False, + doc = """ +Whether to generate a dSYM file for the binary under test. +""", + ), "build_type": attr.string( mandatory = True, values = ["simulator", "device"], diff --git a/test/shell/BUILD b/test/shell/BUILD index e856628..32a3f1c 100644 --- a/test/shell/BUILD +++ b/test/shell/BUILD @@ -23,26 +23,6 @@ sh_library( ], ) -sh_test( - name = "objc_test", - size = "large", - srcs = ["objc_test.sh"], - data = [":for_bazel_tests"], - deps = [ - ":bashunit", - ], -) - -sh_test( - name = "apple_test", - srcs = ["apple_test.sh"], - data = [":for_bazel_tests"], - shard_count = 3, - deps = [ - ":bashunit", - ], -) - sh_test( name = "wrapped_clang_test", size = "small", diff --git a/test/shell/apple_test.sh b/test/shell/apple_test.sh deleted file mode 100755 index 9c2db27..0000000 --- a/test/shell/apple_test.sh +++ /dev/null @@ -1,345 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 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. - -# --- begin runfiles.bash initialization v2 --- -# Copy-pasted from the Bazel Bash runfiles library v2. -set -uo pipefail; set +e; f=bazel_tools/tools/bash/runfiles/runfiles.bash -# shellcheck disable=SC1090 -source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ - source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ - source "$0.runfiles/$f" 2>/dev/null || \ - source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ - source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ - { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e -# --- end runfiles.bash initialization v2 --- - -source "$(rlocation build_bazel_apple_support/test/shell/integration_test_setup.sh)" \ - || { echo "integration_test_setup.sh not found!" >&2; exit 1; } - -function set_up() { - setup_objc_test_support -} - -function test_apple_binary_crosstool_watchos() { - rm -rf package - mkdir -p package - - cat > package/BUILD < \$(@)", - tags = ["requires-darwin"], -) - -starlark_apple_binary( - name = "main_binary", - deps = [":main_lib"], - platform_type = "watchos", - minimum_os_version = '8.0', -) -objc_library( - name = "main_lib", - srcs = ["main.m"], - deps = [":lib_a"], -) -cc_library( - name = "cc_lib", - srcs = ["cc_lib.cc"], -) -# By depending on a library which requires it is built for watchos, this test -# verifies that dependencies of starlark_apple_binary are compiled for the -# specified platform_type. -objc_library( - name = "lib_a", - srcs = ["a.m"], - deps = [":cc_lib"], -) -EOF - cat > package/main.m < - -// Note that WKExtensionDelegate is only available in Watch SDK. -@interface TestInterfaceMain : NSObject -@end - -int main() { - return 0; -} -EOF - cat > package/a.m < - -// Note that WKExtensionDelegate is only available in Watch SDK. -@interface TestInterfaceA : NSObject -@end - -int aFunction() { - return 0; -} -EOF - cat > package/cc_lib.cc << EOF -#include - -std::string GetString() { return "h3ll0"; } -EOF - - bazel build --verbose_failures //package:lipo_out \ - --noincompatible_enable_cc_toolchain_resolution \ - --watchos_cpus=armv7k \ - || fail "should build watch binary" - - grep "armv7k" bazel-bin/package/lipo_out \ - || fail "expected output binary to be for armv7k architecture" - - bazel build --verbose_failures //package:lipo_out \ - --noincompatible_enable_cc_toolchain_resolution \ - --watchos_cpus=x86_64 \ - || fail "should build watch binary" - - grep "x86_64" bazel-bin/package/lipo_out \ - || fail "expected output binary to be for x86_64 architecture" -} - -function test_apple_static_library() { - rm -rf package - mkdir -p package - - cat > package/BUILD < "package/dummy.m" < package/BUILD < package/main.m < package/BUILD < "package/the main.m" < package/BUILD < \$(@)", - tags = ["requires-darwin"], -) -EOF - touch package/a.m - touch package/b.m - cat > package/main.m < package/cc_lib.cc << EOF -#include - -std::string GetString() { return "h3ll0"; } -EOF - - bazel build --verbose_failures //package:lipo_out \ - --noincompatible_enable_cc_toolchain_resolution \ - --ios_multi_cpus=sim_arm64,x86_64 \ - || fail "should build starlark_apple_binary and obtain info via lipo" - - grep "x86_64 arm64" bazel-bin/package/lipo_out \ - || fail "expected output binary to be for x86_64 architecture" -} - -function test_apple_binary_dsym_builds() { - rm -rf package - mkdir -p package - - cat > package/BUILD < package/main.m < package/BUILD < \$(@)", - tags = ["requires-darwin"], -) -EOF - touch package/a.m - cat > package/b.m </dev/null || \ - source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ - source "$0.runfiles/$f" 2>/dev/null || \ - source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ - source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ - { echo>&2 "ERROR: cannot find $f"; exit 1; }; f=; set -e -# --- end runfiles.bash initialization v2 --- - -source "$(rlocation build_bazel_apple_support/test/shell/integration_test_setup.sh)" \ - || { echo "integration_test_setup.sh not found!" >&2; exit 1; } - -function make_lib() { - rm -rf ios - mkdir -p ios - - cat >ios/main.m < - -int main(int argc, char *argv[]) { - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - int retVal = UIApplicationMain(argc, argv, nil, nil); - [pool release]; - return retVal; -} -EOF - - cat >ios/BUILD <"$TEST_log" 2>&1 || fail "should pass" - ls bazel-out/*/bin/ios/liblib.a \ - || fail "should generate lib.a" -} - -# Verifies contents of .a files do not contain timestamps -- if they did, the -# results would not be hermetic. -function test_archive_timestamps() { - setup_objc_test_support - - mkdir -p objclib - cat > objclib/BUILD < objclib/mysrc.m <"$TEST_log" 2>&1 \ - || fail "Should build objc_library" - - # Based on timezones, ar -tv may show the timestamp of the contents as either - # Dec 31 1969 or Jan 1 1970 -- either is fine. - # We would use 'date' here, but the format is slightly different (Jan 1 vs. - # Jan 01). - ar -tv bazel-out/*/bin/objclib/libobjclib.a \ - | grep "mysrc" | grep "Dec 31" | grep "1969" \ - || ar -tv bazel-out/*/bin/objclib/libobjclib.a \ - | grep "mysrc" | grep "Jan 1" | grep "1970" || \ - fail "Timestamp of contents of archive file should be zero" -} - -run_suite "objc/ios test suite" diff --git a/test/shell/verify_binary.sh b/test/shell/verify_binary.sh index 1da7040..f73943a 100755 --- a/test/shell/verify_binary.sh +++ b/test/shell/verify_binary.sh @@ -1,27 +1,34 @@ #!/bin/bash set -euo pipefail +set -x readonly binary="%{binary}s" expected_platform="MACOS" if [[ "$PLATFORM_TYPE" == "ios" && "$BUILD_TYPE" == "device" ]]; then - expected_platform="IPHONEOS" + expected_platform="IOS" elif [[ "$PLATFORM_TYPE" == "ios" && "$BUILD_TYPE" == "simulator" ]]; then - expected_platform="IPHONESIMULATOR" + expected_platform="IOSSIMULATOR" elif [[ "$PLATFORM_TYPE" == "visionos" && "$BUILD_TYPE" == "device" ]]; then expected_platform="XROS" elif [[ "$PLATFORM_TYPE" == "visionos" && "$BUILD_TYPE" == "simulator" ]]; then expected_platform="XROSSIMULATOR" +elif [[ "$PLATFORM_TYPE" == "watchos" && "$BUILD_TYPE" == "device" ]]; then + expected_platform="WATCHOS" +elif [[ "$PLATFORM_TYPE" == "watchos" && "$BUILD_TYPE" == "simulator" ]]; then + expected_platform="WATCHSIMULATOR" fi -otool_output=$(otool -lv "$binary") -if ! echo "$otool_output" | grep -q "platform $expected_platform"; then - echo "error: binary $binary does not contain platform $expected_platform, got: '$(echo "$otool_output" | grep platform || true)'" +platforms=$(otool -lv "$binary" | grep "platform " | sort -u || true) +if ! echo "$platforms" | grep -q "platform $expected_platform"; then + echo "error: binary $binary does not contain platform $expected_platform, got: '$platforms'" >&2 exit 1 fi lipo_output=$(lipo -info "$binary") -if ! echo "$lipo_output" | grep -q "$CPU"; then +expected_cpus=${CPU//,/ } +expected_cpus=${expected_cpus//sim_/} +if ! echo "$lipo_output" | grep -q "$expected_cpus"; then echo "error: binary $binary does not contain CPU $CPU, got: '$lipo_output" exit 1 fi diff --git a/test/test_data/BUILD b/test/test_data/BUILD index 81f8e23..26b9bb4 100644 --- a/test/test_data/BUILD +++ b/test/test_data/BUILD @@ -1,8 +1,6 @@ -load( - "//rules:universal_binary.bzl", - "universal_binary", -) +load("//rules:universal_binary.bzl", "universal_binary") load("//test:starlark_apple_binary.bzl", "starlark_apple_binary") +load("//test:starlark_apple_static_library.bzl", "starlark_apple_static_library") package( default_testonly = 1, @@ -40,19 +38,40 @@ starlark_apple_binary( deps = [":cc_main"], ) +starlark_apple_binary( + name = "macos_binary_with_spaces", + minimum_os_version = "13.0", + platform_type = "macos", + tags = TARGETS_UNDER_TEST_TAGS, + deps = [":objc_lib_with_spaces"], +) + cc_library( name = "cc_lib", - srcs = ["lib.cc"], + srcs = ["cc_lib.cc"], tags = TARGETS_UNDER_TEST_TAGS, ) objc_library( name = "objc_lib", - srcs = ["lib.m"], + srcs = ["objc_lib.m"], tags = TARGETS_UNDER_TEST_TAGS, deps = ["cc_lib"], ) +objc_library( + name = "objc_lib_with_spaces", + srcs = ["objc lib with spaces.m"], + tags = TARGETS_UNDER_TEST_TAGS, +) + +starlark_apple_static_library( + name = "static_lib", + minimum_os_version = "15.0", + platform_type = "ios", + deps = [":objc_lib"], +) + objc_library( name = "objc_main", srcs = ["main.m"], @@ -90,3 +109,33 @@ starlark_apple_binary( }), deps = [":objc_main"], ) + +objc_library( + name = "watch_main", + srcs = ["watch_main.m"], + tags = TARGETS_UNDER_TEST_TAGS, + deps = [":cc_lib"], +) + +starlark_apple_binary( + name = "watch_binary", + minimum_os_version = "8.0", + platform_type = "watchos", + tags = TARGETS_UNDER_TEST_TAGS, + deps = [":watch_main"], +) + +objc_library( + name = "ios_main", + srcs = ["ios_main.m"], + tags = TARGETS_UNDER_TEST_TAGS, + deps = [":cc_lib"], +) + +starlark_apple_binary( + name = "ios_binary", + minimum_os_version = "15.0", + platform_type = "ios", + tags = TARGETS_UNDER_TEST_TAGS, + deps = [":ios_main"], +) diff --git a/test/test_data/lib.cc b/test/test_data/cc_lib.cc similarity index 100% rename from test/test_data/lib.cc rename to test/test_data/cc_lib.cc diff --git a/test/test_data/ios_main.m b/test/test_data/ios_main.m new file mode 100644 index 0000000..a3d2c3a --- /dev/null +++ b/test/test_data/ios_main.m @@ -0,0 +1,5 @@ +#import + +int main(int argc, char *argv[]) { + return UIApplicationMain(argc, argv, nil, nil); +} diff --git a/test/test_data/objc lib with spaces.m b/test/test_data/objc lib with spaces.m new file mode 100644 index 0000000..33c14ce --- /dev/null +++ b/test/test_data/objc lib with spaces.m @@ -0,0 +1,3 @@ +int main() { + return 0; +} diff --git a/test/test_data/lib.m b/test/test_data/objc_lib.m similarity index 100% rename from test/test_data/lib.m rename to test/test_data/objc_lib.m diff --git a/test/test_data/watch_main.m b/test/test_data/watch_main.m new file mode 100644 index 0000000..7477162 --- /dev/null +++ b/test/test_data/watch_main.m @@ -0,0 +1,9 @@ +#import + +// Note that WKExtensionDelegate is only available in Watch SDK. +@interface TestInterfaceMain : NSObject +@end + +int main() { + return 0; +} diff --git a/test/verify_archive_timestamps.sh b/test/verify_archive_timestamps.sh new file mode 100755 index 0000000..b6d26fa --- /dev/null +++ b/test/verify_archive_timestamps.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -euo pipefail +set -x + +readonly binary="%{binary}s" + +if [[ "$binary" != *_lipo.a ]]; then + echo "$binary: error: binary name does not end in _lipo.a" >&2 + exit 1 +fi + +ar -tv "$binary" + +# Based on timezones, ar -tv may show the timestamp of the contents as either +# Dec 31 1969 or Jan 1 1970 -- either is fine. +# We would use 'date' here, but the format is slightly different (Jan 1 vs. +# Jan 01). +if ! ar -tv "$binary" | grep "objc_lib" | grep "Dec 31" | grep "1969" \ + && ! ar -tv "$binary" | grep "objc_lib" | grep "Jan 1" | grep "1970" +then + echo "error: timestamp of contents of archive file should be zero" >&2 + exit 1 +fi