Как я могу построить SBTUITestTunnel для приложения Swift, используя Buck? - PullRequest
2 голосов
/ 10 апреля 2020

Я пытаюсь использовать Buck для включения библиотеки SBTUITestTunnel в пару iOS приложений, над которыми я работаю. Эта библиотека расширяет стандартную среду тестирования пользовательского интерфейса Xcode, предлагая дополнительные функции, такие как мониторинг сетевых вызовов. Хотя SBTUITestTunnel написан в основном на Objective- C, приложения, в которые я надеюсь включить эту библиотеку, написаны на Swift и используют Buck в качестве инструмента для сборки. Я также хотел бы иметь возможность использовать как Buck, так и Xcode для выполнения тестов, как только я их напишу.

К сожалению, SBTUITestTunnel Установка / Настройка / Использование Документы, по-видимому, не дают никаких рекомендаций по их созданию с помощью Buck. Репо включает в себя файлы конфигурации CocoaPods, которые я пытался преобразовать в файл BUCK. Тем не менее, я не смог заставить это работать должным образом после нескольких попыток. Я даже пытался извлечь предварительно скомпилированные .framework s из результатов сборки предоставленного SBTUITestTunnel Пример приложения , но все еще не повезло.

Вот попытки, которые я сделал до сих пор при создании рабочего файла BUCK:

Попытка 1 - Построение как библиотеки из источника:

Код:

apple_library(
  name = 'SBTUITestTunnelCommon',
  visibility = ['PUBLIC'],
  swift_version = '5',
  exported_headers = glob([
    'Pod/Common/**/*.h',
  ]),
  srcs = glob([
    'Pod/Common/**/*.swift',
    'Pod/Common/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
  ]
)

apple_library(
  name = 'SBTUITestTunnelClient',
  visibility = ['PUBLIC'],
  swift_version = '5',
  exported_headers = glob([
    'Pod/Client/**/*.h',
  ]),
  srcs = glob([
    'Pod/Client/**/*.swift',
    'Pod/Client/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:SBTUITestTunnelCommon',
  ]
)

apple_library(
  name = 'SBTUITestTunnelServer',
  visibility = ['PUBLIC'],
  swift_version = '5',
  exported_headers = glob([
    'Pod/Server/**/*.h',
  ]),
  srcs = glob([
    'Pod/Server/**/*.swift',
    'Pod/Server/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:SBTUITestTunnelCommon',
  ]
)

Результат:

Сборка Buck завершена успешно, но выполнение тестов в Buck и попытка встраивания в XCode оба терпят неудачу из-за ошибок, подобных этой (при попытке запустить @import SBTUITestTunnelCommon; из файла в классе SBTUITestTunnelServer):

Module 'SBTUITestTunnelCommon' not found

Попытка 2 - Построение как фреймворк из источника:

Код:

sbt_ui_test_tunnel_common_bundle_name = 'SBTUITestTunnelCommon'
sbt_ui_test_tunnel_common_binary_name = sbt_ui_test_tunnel_common_bundle_name + 'Binary'
sbt_ui_test_tunnel_common_module_name = sbt_ui_test_tunnel_common_bundle_name
sbt_ui_test_tunnel_common_product_name = sbt_ui_test_tunnel_common_bundle_name
# Copied `Info.plist` from the Example app to this Pod folder:
sbt_ui_test_tunnel_common_info_plist = 'Pod/Common/' + sbt_ui_test_tunnel_common_bundle_name + '-Info.plist'

sbt_ui_test_tunnel_client_bundle_name = 'SBTUITestTunnelClient'
sbt_ui_test_tunnel_client_binary_name = sbt_ui_test_tunnel_client_bundle_name + 'Binary'
sbt_ui_test_tunnel_client_module_name = sbt_ui_test_tunnel_client_bundle_name
sbt_ui_test_tunnel_client_product_name = sbt_ui_test_tunnel_client_bundle_name
# Copied `Info.plist` from the Example app to this Pod folder:
sbt_ui_test_tunnel_client_info_plist = 'Pod/Client/' + sbt_ui_test_tunnel_client_bundle_name + '-Info.plist'

sbt_ui_test_tunnel_server_bundle_name = 'SBTUITestTunnelServer'
sbt_ui_test_tunnel_server_binary_name = sbt_ui_test_tunnel_server_bundle_name + 'Binary'
sbt_ui_test_tunnel_server_module_name = sbt_ui_test_tunnel_server_bundle_name
sbt_ui_test_tunnel_server_product_name = sbt_ui_test_tunnel_server_bundle_name
# Copied `Info.plist` from the Example app to this Pod folder:
sbt_ui_test_tunnel_server_info_plist = 'Pod/Server/' + sbt_ui_test_tunnel_server_bundle_name + '-Info.plist'

apple_binary(
  name = sbt_ui_test_tunnel_common_binary_name,
  visibility = ['PUBLIC'],
  module_name = sbt_ui_test_tunnel_common_module_name,
  swift_version = '5',
  linker_flags = [
    '-ObjC', # Have tried with and without this
  ],
  link_style = 'shared',
  exported_headers = glob([
    'Pod/Common/**/*.h',
  ]),
  srcs = glob([
    'Pod/Common/**/*.swift',
    'Pod/Common/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
  ]
)

apple_bundle(
  name = sbt_ui_test_tunnel_common_bundle_name,
  visibility = ['PUBLIC'],
  product_name = sbt_ui_test_tunnel_common_product_name,
  binary = ':' + sbt_ui_test_tunnel_common_binary_name,
  extension = 'framework',
  xcode_product_type = 'com.apple.product-type.framework',
  info_plist = sbt_ui_test_tunnel_common_info_plist,
)

apple_binary(
  name = sbt_ui_test_tunnel_client_binary_name,
  visibility = ['PUBLIC'],
  module_name = sbt_ui_test_tunnel_client_module_name,
  swift_version = '5',
  linker_flags = [
    '-ObjC', # Have tried with and without this
  ],
  link_style = 'shared',
  exported_headers = glob([
    'Pod/Client/**/*.h',
  ]),
  srcs = glob([
    'Pod/Client/**/*.swift',
    'Pod/Client/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:' + sbt_ui_test_tunnel_common_binary_name,
  ]
)

apple_bundle(
  name = sbt_ui_test_tunnel_client_bundle_name,
  visibility = ['PUBLIC'],
  product_name = sbt_ui_test_tunnel_client_product_name,
  binary = ':' + sbt_ui_test_tunnel_client_binary_name,
  extension = 'framework',
  xcode_product_type = 'com.apple.product-type.framework',
  info_plist = sbt_ui_test_tunnel_client_info_plist,
)

apple_binary(
  name = sbt_ui_test_tunnel_server_binary_name,
  visibility = ['PUBLIC'],
  module_name = sbt_ui_test_tunnel_server_module_name,
  swift_version = '5',
enter code here
  linker_flags = [
    '-ObjC', # Have tried with and without this
  ],
  link_style = 'shared',
  exported_headers = glob([
    'Pod/Server/**/*.h',
  ]),
  srcs = glob([
    'Pod/Server/**/*.swift',
    'Pod/Server/**/*.m',
  ]),
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:' + sbt_ui_test_tunnel_common_binary_name,
  ]
)

apple_bundle(
  name = sbt_ui_test_tunnel_server_bundle_name,
  visibility = ['PUBLIC'],
  product_name = sbt_ui_test_tunnel_server_product_name,
  binary = ':' + sbt_ui_test_tunnel_server_binary_name,
  extension = 'framework',
  xcode_product_type = 'com.apple.product-type.framework',
  info_plist = sbt_ui_test_tunnel_server_info_plist,
)

Результат:

Сбой сборки Buck с этим сообщением об ошибке:

Command failed with exit code 1.
stderr: ld: warning: -sdk_version and -platform_version are not compatible, ignoring - 
sdk_version
Undefined symbols for architecture x86_64:
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Попытка 3 - Построение как prebuilt_apple_framework s:

Код:

sbt_ui_test_tunnel_common_framework_name = 'SBTUITestTunnelCommon'
# Copied .framework file from build output of the Example app to this Frameworks folder:
sbt_ui_test_tunnel_common_framework_path = 'Frameworks/' + sbt_ui_test_tunnel_common_framework_name + '/' + sbt_ui_test_tunnel_common_framework_name + '.framework'

sbt_ui_test_tunnel_client_framework_name = 'SBTUITestTunnelClient'
# Copied .framework file from build output of the Example app to this Frameworks folder:
sbt_ui_test_tunnel_client_framework_path = 'Frameworks/' + sbt_ui_test_tunnel_common_framework_name + '/' + sbt_ui_test_tunnel_common_framework_name + '.framework'

sbt_ui_test_tunnel_server_framework_name = 'SBTUITestTunnelServer'
# Copied .framework file from build output of the Example app to this Frameworks folder:
sbt_ui_test_tunnel_server_framework_path = 'Frameworks/' + sbt_ui_test_tunnel_common_framework_name + '/' + sbt_ui_test_tunnel_common_framework_name + '.framework'

prebuilt_apple_framework(
  name = sbt_ui_test_tunnel_common_framework_name,
  framework = sbt_ui_test_tunnel_common_framework_path,
  preferred_linkage = 'stat',
  visibility = [
    'PUBLIC'
  ],
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
  ],
)

prebuilt_apple_framework(
  name = sbt_ui_test_tunnel_client_framework_name,
  framework = sbt_ui_test_tunnel_client_framework_path,
  preferred_linkage = 'shared',
  visibility = [
    'PUBLIC'
  ],
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:' + sbt_ui_test_tunnel_common_framework_name,
  ],
)

prebuilt_apple_framework(
  name = sbt_ui_test_tunnel_server_framework_name,
  framework = sbt_ui_test_tunnel_server_framework_path,
  preferred_linkage = 'shared',
  visibility = [
    'PUBLIC'
  ],
  deps = [
    '//Path/GCDWebServer:GCDWebServer',
    '//Path/SBTUITestTunnel:' + sbt_ui_test_tunnel_common_framework_name,
  ],
)

Результат:

Сборка Buck завершается с этим сообщением об ошибке:

Command failed with exit code 1.
stderr: /Users/me/path/BridgingHeader.h:12:9: error: 'SBTUITestTunnelServer/SBTUITestTunnelServer.h' file not found
#import <SBTUITestTunnelServer/SBTUITestTunnelServer.h>
        ^
<unknown>:0: error: failed to import bridging header 'path/BridgingHeader.h'

Дополнительные примечания:

  • Я выполнил все шаги в документации, включая установку параметров DEBUG / DEBUG=1 и добавление необходимых зависимостей в файлы BridgingHeaders.h, например:

    • В файле заголовка моста для библиотеки, которая должна быть протестирована:

      #import <SBTUITestTunnelCommon/SBTUITestTunnelCommon.h>
      #import <SBTUITestTunnelServer/SBTUITestTunnelServer.h>
      
    • И в файле заголовка моста для библиотеки, в которой есть тесты:

      #import <SBTUITestTunnelClient/SBTUITunneledApplication.h>
      #import <SBTUITestTunnelClient/XCTestCase+AppExtension.h>
      #import <SBTUITestTunnelCommon/SBTUITestTunnelCommon.h> // Have tried with and without this line
      
  • Я включил библиотеки / фреймворки SBTUITestTunnel как зависимости в моем Файл BUCK основного приложения выглядит следующим образом:

        apple_library(
          ...
          bridging_header = 'BridgingHeader.h',
          deps = [
            '//Path/SBTUITestTunnel:SBTUITestTunnelCommon',
            '//Path/SBTUITestTunnel:SBTUITestTunnelServer',
            '//Path/GCDWebServer:GCDWebServer',
          ]
        )
    
        apple_test(
          ...
          bridging_header = 'UITests/BridgingHeader.h',
          deps = [
            '//Path/SBTUITestTunnel:SBTUITestTunnelClient',
          ]
        )
    
  • SBTUITestTunnel зависит от другой библиотеки, GCDWebServer , которая также не предоставляет файл BUCK. Тем не менее, я смог заставить его работать с этим:

    apple_library(
      name = 'GCDWebServer',
      visibility = ['PUBLIC'],
      swift_version = '5',
      exported_headers = glob([
        'GCDWebServer/**/*.h',
      ]),
      srcs = glob([
        'GCDWebServer/**/*.swift',
        'GCDWebServer/**/*.m',
      ])
    )
    
    apple_library(
      name = 'GCDWebDAVServer',
      visibility = ['PUBLIC'],
      swift_version = '5',
      exported_headers = glob([
        'GCDWebDAVServer/**/*.h',
      ]),
      srcs = glob([
        'GCDWebDAVServer/*.swift',
        'GCDWebDAVServer/*.m',
      ]),
      deps = [
        '//Path/GCDWebServer:GCDWebServer',
      ]
    )
    
    apple_library(
      name = 'GCDWebUploader',
      visibility = ['PUBLIC'],
      swift_version = '5',
      exported_headers = glob([
        'GCDWebUploader/**/*.h',
      ]),
      srcs = glob([
        'GCDWebUploader/**/*.swift',
        'GCDWebUploader/**/*.m',
      ]),
      deps = [
        '//Path/GCDWebServer:GCDWebServer',
      ]
    )
    

Есть идеи, что я делаю неправильно? Или, по крайней мере, может быть, какой-нибудь совет, какой из этих вариантов, скорее всего, лучший путь?

...