How can I make sure that builds are using v14.x iOS/tvOS simulators? - fastlane

Some of the builds in our environment are failing because the builds are using a 13.X iOS/tvOS simulator and for some reason that causes issues. I made changes to our Fastfile so that the builds use a 14.2 simulator instead and now the builds are succeeding.
Here are the changes I made to the fast file.
First, I declared a dict:
XCODE_DESTINATION = {
iphoneos: "generic/platform=iOS",
iphonesimulator: "platform=iOS Simulator,OS=14.2,name=iPhone 11 Pro Max",
appletvos: "generic/platform=tvOS",
appletvsimulator: "platform=tvOS Simulator,OS=14.2,name=Apple TV 4K"
}
Then, in the run_tests lane for both iOS and tvOS, I reference the iphonesimulator and the appletvsimulator:
run_tests(
destination: XCODE_DESTINATION[:iphonesimulator],
workspace: WORKSPACE_NAME,
scheme: options[:scheme_tests]
)
run_tests(
destination: XCODE_DESTINATION[:appletvsimulator],
workspace: WORKSPACE_NAME,
scheme: options[:scheme_tests]
)
Even though this solution solves the problem, I don't really want the XCODE_DESTINATION dict to have to specifically reference an OS version and a specific device.
Is there a way I can configure this Fastfile so that it runs the tests only if a 14.X simulator is present within XCode without having to specifically indicate that in the dict?
Thank you!

Currently fastlane does not support this, so feel free to create an issue ->
https://github.com/fastlane/fastlane/issues
But you can specify the simulators and versions in the run_tests:
run_tests(
devices: ['iPhone 11 Pro Max (14.2)'],
workspace: WORKSPACE_NAME,
scheme: options[:scheme_tests],
ensure_devices_found: true
)
Additionally you can set ensure_devices_found to true, so if the specified simulator(s) not found, tests will fail.

Related

Very Strange Errors From IB During Build With Swift Package, Using IBDesignable

I have developed this shared package. It works fine.
In the package test harnesses (3 iOS apps), it works great, and also, the IB storyboard renders the control (It's an IBDesignable).
However, when I include it as a package in another app (I can't share the source), I get these really weird render failure messages:
Error: 'UIPickerView' is unavailable in tvOS
And so on. There's a bunch of "not available in tvOS" errors.
Here's what the log looks like:
The build happens, and the app runs fine. However, I'm wondering if this could cause problems in the App Store release process.
Well...DUH. It's an iOS package and utility, and leverages a lot of things like haptics.
The package explicitly states that it is iOS(12), and I can't see any indication of why my storyboard is insisting on trying to render as tvOS.
What am I missing? I think that I must be missing something from the Package.swift file, but it's pretty straightforward:
import PackageDescription
let package = Package(
name: "RVS_Spinner",
platforms: [
.iOS(.v12)
],
products: [
.library(
name: "RVS-Spinner",
targets: ["RVS_Spinner"])
],
targets: [
.target(name: "RVS_Spinner")
]
)
You need to wrap each of these problematic files in
#if os(iOS)
#endif
so that they don't get compiled for other platforms, as things you are referring are only available on iOS.
As far as i know, you can't stop a package from building on all platforms, but you can select which file to be compiled on which platform with the #if os() trick
I think you got confused by the platforms parameter in the Package.swift file. It is not saying where this package is available, it is saying the minimum version required for each platform.
Take a look at Apple's doc for the platforms parameter:
platforms - The list of minimum deployment targets per platform.

XCTestManifests in generated swift package

I am currently creating a Swift Package. By default, the package generated by Xcode contains the XCTestManifests file with the following code:
#if !canImport(ObjectiveC)
public func allTests() -> [XCTestCaseEntry] {
return [
testCase(TestPkgTests.allTests),
]
}
#endif
As you can see, this is the function that returns all test cases. However, I am curious when it will be called and in what case the condition !CanImport (ObjectiveC) will be satisfied.
This is needed for running tests on platforms other than macOS.
On macOS the test runner relies on the ObjectiveC runtime which is absent on other platforms, hence canImport(ObjectiveC) is false. The allTests() function is called from LinuxMain.swift file, you can generate it on macOS by running swift test --generate-linuxmain.
In newer SwiftPM releases there is an alternative option for running tests on those platforms: swift test --enable-test-discovery. You can read more about it here: https://forums.swift.org/t/pitch-enable-test-discovery-by-default/36619
Swift 5.4: Automatic Test Discovery Included
Swift 5.4 (April 26, 2021 release) includes test discovery by default.
Automatic test discovery is now the default on all platforms
swift test --enable-test-discovery is no longer needed.
The Swift 5.4+ swift package init template does not generate allTests and XCTestManifests.swift.

"Module was not compiled for testing" error when using Swift Package Manager

I created a Swift library with swift package init --type library and generated an Xcode project with swift package generate-xcodeproj.
Now I'm trying to run the Test scheme in Xcode. It prints following error:
Module '<title>' was not compiled for testing
However when I run swift build and swift test in terminal, it works fine.
I have ENABLE_TESTABILITY set to YES in all of the targets. I didn't change anything in the project except this. How can I make Xcode perform unit testing?
You need to set the "Enable Testability" to Yes in build setting over your "Main Target"
I was having this issue today, it seems like #testable cannot be used with projects generated by Swift Package Manager.
Removing #testable from my import statements solved this issue. Of course, this means we can only test the public interface of our modules.
Xcode -> Product -> Scheme -> Edit Scheme
Select the Info tab.
Set the following -
Build Configuration: Debug
Add a check mark to Debug executable
Tested with Xcode 12.4(12D4e) and iOS 14.1 deployment target.

MacOS Swift Framework testing fail

I have a framework written in obj-c and swift.
Now i try to run a related unit test target, but I get this error:
2014-07-10 07:45:54.064 xctest[4908:303] The test bundle at /Users/steve/Temporary/Build/Products/Debug/SOGraphDB-Mac Tests.xctest could not be loaded because an unanticipated error occurred: Error Domain=NSCocoaErrorDomain Code=3587 "The bundle “SOGraphDB-Mac Tests” couldn’t be loaded because it is damaged or missing necessary resources." (dlopen_preflight(/Users/steve/Temporary/Build/Products/Debug/SOGraphDB-Mac Tests.xctest/Contents/MacOS/SOGraphDB-Mac Tests): Library not loaded: #rpath/libswiftAppKit.dylib
Referenced from: /Users/steve/Temporary/Build/Products/Debug/SOGraphDB.framework/Versions/A/SOGraphDB
Reason: image not found) UserInfo=0x10011c640 {NSLocalizedFailureReason=The bundle is damaged or missing necessary resources., NSLocalizedRecoverySuggestion=Try reinstalling the bundle., NSFilePath=/Users/steve/Temporary/Build/Products/Debug/SOGraphDB-Mac Tests.xctest/Contents/MacOS/SOGraphDB-Mac Tests, NSDebugDescription=dlopen_preflight(/Users/steve/Temporary/Build/Products/Debug/SOGraphDB-Mac Tests.xctest/Contents/MacOS/SOGraphDB-Mac Tests): Library not loaded: #rpath/libswiftAppKit.dylib
Referenced from: /Users/steve/Temporary/Build/Products/Debug/SOGraphDB.framework/Versions/A/SOGraphDB
Reason: image not found, NSBundlePath=/Users/steve/Temporary/Build/Products/Debug/SOGraphDB-Mac Tests.xctest, NSLocalizedDescription=The bundle “SOGraphDB-Mac Tests” couldn’t be loaded because it is damaged or missing necessary resources.}
Any idea what the root cause can be?
The error seems realated to "Library not loaded: #rpath/libswiftAppKit.dylib"
Both (framework and test bundle) compile without any error or warning (in Beta2)
I had a similar problem, though mine was an iOS test target, linking to a Swift framework, that failed to run on Xcode 6 GM. The test target had run successfully on an early beta of Xcode 6, but the final version reported the runtime error: Library not loaded: #rpath/libswiftCore.dylib
I noticed that a newer project did not have the failure, so I compared the build settings and test code. I was able to resolve the problem with three steps:
The test target needs the "Embedded Target Contains Swift Code" setting to be YES. This tells the linker to add the Swift runtime libraries to the executable.
The test target needs an explicit value for the "Runpath Search Paths" build setting. This tells the loader where to find the Swift runtime libaries. I copied the following setting from a fresh new test target:
LD_RUNPATH_SEARCH_PATHS = $(inherited) #executable_path/../Frameworks #loader_path/../Frameworks
The test cases need to explicitly import any modules that are used by the linked framework. In my project, the framework used UIKit but the test cases only used my framework. When I added an explicit import UIKit to the test cases, the link problem went away.
Since I keep running into this issue whenever I mess with build settings, here's the cleanest answer I can provide as of Xcode 8b5:
If unit tests don't run on iOS, make sure you have:
Runpath Search Paths: #loader_path/Frameworks
If unit tests don't run on macOS, make sure you have:
Runpath Search Paths: #loader_path/../Frameworks
This will show up as LD_RUNPATH_SEARCH_PATHS in your pbxproj file. You can also add $(inherited) to make sure project-wide paths are added as well, but those are probably empty.
Lastly, I didn't need the executable_path/... settings, doesn't make a difference for me whether they're there or not for unit tests.
I had the same problem.
Ended up copying libswiftAppKit.dylib out of the Xcode application directory (I am using beta 3), into a directory that I could reference (not part of an application bundle), then adding the library to the "Link binary with libraries" setting for the test bundle. My tests then started working.
FYI, the path for the dylib was at '/Applications/Xcode6-Beta3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx/libswiftAppKit.dylib'
Probably not a good final solution, but it works for the interim.
My solution was to add a single file to my test target, AppKitTests.swift (or AppKitSpec.swift in my case), and all the file contains is:
// While I don't know why, The.framework is built linked to libswiftAppKit.
// Frameworks do not embed the Swift libraries themselves, it's up to the host
// app to include the necessary libraries. So here we are, including AppKit on
// behalf of The.framework so that the tests can run.
import AppKit
Oh, I also added AppKit to the test target's set of frameworks.
I had this occur to me in Beta 4 and it turned out that I had done it to myself without realizing it.
I had a Framework project called Fnord. My FnordTests target contained a couple of unit test classes that had import Fnord at the top of each file. For some reason Xcode was complaining about those imports and so I commented them out. This is when I started getting the same symptoms while trying to run my unit tests.
I noticed that the settings for my FnordTests target were such that the target would be linked with Fnord.framework, and I realized that it might not be able to do that with the aforementioned import Fnord statements diked-out.
So I put them back in, and everything went back to normal. Curiously, Xcode no longer showed those import statements as being problematic, but this is beta so I can forgive that.
I hope this helps someone.
I ran into the same issue, adding
import AppKit
in the Swift file fixed it

Xcode iOS deployment target check?

On more than one occasion, I have accidentally changed the deployment target of my Xcode project to something I don't want. The latest time, I found out because a customer wasn't seeing my app. Is there a way to put something into my code somewhere to assert the value of the deployment target? I think I would be much less likely to change that by mistake.
You can check your deployment target version via __IPHONE_OS_VERSION_MIN_REQUIRED macro and compare it to some sdk version, e.g. to make sure that your deployment target is 4.0 put the following lines somewhere:
#if __IPHONE_OS_VERSION_MIN_REQUIRED != __IPHONE_4_0
#error wrong deployment target - should be 4.0
#endif
Add a New Run Script Build Phase to your target and put this script inside:
DEPLOYMENT_TARGET_VALID=`expr ${IPHONEOS_DEPLOYMENT_TARGET} \>= "4.0"`;
if [ $DEPLOYMENT_TARGET_VALID = 1 ]; then
echo "Deployment target ($IPHONEOS_DEPLOYMENT_TARGET) is too high."
exit 1
fi;
Here, build will fail if the deployment target is set to 4.0 or higher.