Xcode build phases: Use previous build warning output in "run script" phase - ios

I want to have a run script that looks at the number of previous warnings (probably during the compile phase), and generates an error which stops the run/buid if the number of warnings is too large.
I am working on an app that has a large amount of warnings that happen during compile. They do not stop the app from compiling, but I want to stop devs from adding more warnings as they add features.
I have looked everywhere, but so far have not found a way to use previous build output in the run script phase of the build. Is there any way of doing this? Some kind of env variable, or a way of monitoring the build output in a custom script as it happens?
I see a similar question here:
Is there a way to access Xcodes current build output from a build phase run script?
But it seems that the output is only available after the build is complete in that answer. Is there any other option that would allow the build to be failed before it finishes?
Any insight into the build system in Xcode would be appreciated! Cheers
Additional context:
All I need is for Xcode's default warnings to have a feature similar to SwiftLint's warning_threshold
https://stackoverflow.com/a/52256459/7623867

I have looked into that problem as well for quite some time (I wanted to use warnings for quality measurement). The only way I have found is to compile the whole project with xcodebuild, with a command similar to:
xcrun xcodebuild -project MyProject.xcodeproj/ -scheme MyScheme -destination "platform=iOS Simulator" build -quiet | tee xcodebuild.log
and then counting the warnings using AWK or some other tool.
Here is an example.

Related

Building iOS app using Xcode works, but building the same app with xcodebuild command fails

Both new flutter and new react-native projects fail to build because the xcodebuild tool fails. They, however, succeed when I build the projects manually inside Xcode.
Apparently, the reason is because xcodebuild adds additional flag during the build, that, is:
export OTHER_CPLUSPLUSFLAGS=" -fmodule-map-file="/Users/aa/code/WW2/ios/Pods/Headers/Public/SSZipArchive/SSZipArchive.modulemap""
The result is that the build is failing because it cannot find the said module map, with the following error:
<unknown>:0: error: module map file '/Users/aa/code/WW2/ios/Pods/Headers/Public/SSZipArchive/SSZipArchive.modulemap' not found
The said module map is from a previous project (called WW2) which I moved. But the problem is that even newly-created projects are affected.
I wasted two days to solve this, even reading through the documentation about xcode build settings, but to no avail. What I'm trying to do is to find the source of this additional flag or configuration. I even used grep to find a file containing the particular flag, but it's not yet finished scanning my system.
So the problem is somehow the $PODS_ROOT variable is set to /Users/aa/code/WW2/ios/Pods, probably due to a canceled npm build. I only needed to restart the terminal and the problem is solved.
As a side note, I should have used the search function in the finder as it's much faster because it uses an index unlike grep.

xcodebuild default build path

I'm trying to make a FAT framework following this guide
What I'd like to understand is the xcodebuild build path. Based on that tutorial, this is created at the beginning:
BUILD_PATH="${SRCROOT}/build"
Now when I make a build, the builds for Release-iphoneos and Release-iphonesimulator go into that build folder. Is this a predefined variable that can be set to tell Xcode where your builds can go? Because based on this other tutorial: BUILD_DIR gets passed to xcodebuild.
I was wondering what the difference is here and how Xcode handles these arguments.
How does setting this directory work with DerivedData?
Also on the topics of building, does Xcode cache builds? Sometimes after I build and do a ls -al on my frameworks, they don't have current timestamps. But once I delete the build directory, it seems to force Xcode to build again and then I get "fresh" frameworks created. Is Xcode caching the build and not replacing the build? Is there a way to force it?

How to list all test cases using xcodebuild without running?

Using xcodebuild I can run a specific test or group of tests. But is there a way to list all tests without running them, using xcodebuild or any other tool that comes with xcode? Facebook's xctool can do this but I hope to not take dependency on third party tools.
Better late than never - I also needed to do this and couldn't find a way using xcode, so I wrote a python script that parses the test files and gets the names of XCTest test functions:
import re
import os
all_tests = []
TEST_FILES = os.path.expanduser("~/git/ios-proj/Test")
test_case_pattern = re.compile(r"^\s*func\s(test\w*)\(\)[\s\w]*\{")
for test_file in os.listdir(TEST_FILES):
all_tests += [test_case_pattern.match(line)[1] for line in
open(os.path.join(TEST_FILES, test_file), "r").readlines() if test_case_pattern.match(line)]
print(all_tests)
You can get the test names by using "strings". it's not an xcode command, but is normally available on the mac. Run "strings" on the following file and grep whatever marks your tests. in my case, all tests start with "test_":
strings <Tests-Target>-Runner.app/PlugIns/<Tests-Target>.xctest/<Tests-Target>|grep "test_"
an easy way to find this file is by running:
grep -r <single test name> <derived data folder for your project>
I cannot think of any way to sort automatically... but
If you want to test one of the classes by one command So you can run your test one by one through this command :
xcodebuild test -destination 'platform=iOS Simulator,name=iPhone 7,OS=11.1' '-only-testing:APPNAME-TESTTARGET/NAMEOFTHECLASS'
also you can see your list of targets, builds configurations, and schemes by using this command :
xcodebuild -list

Running clang static checker at project level (iOS app) rather than file by file (xcodebuild)

After solving this Omitted code blocks from clang AST for ObjectiveC, I've tried it on a small Objective C .m file along with an appropriate compile_commands.json and it works properly and I get the entire syntax tree.
Now I'm trying to see if it's possible to run it on the entire xcodebuild
[
{
"directory" : "/Users/xx/Desktop/iOSApplication",
"command" : "xcodebuild clean build CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_REQUIRED=NO -project /Users/xx/Desktop/iOSApplication/iOSApplication.xcodeproj/",
"file" : "iOSApplication.xcodeproj"
}
]
When I tried to then run clang-check -ast-dump /Users/xx/Desktop/iOSApplication/iOSApplication.xcodeproj it gives me the errors error: unknown argument: '-project' and error: unable to handle compilation, expected exactly one compiler job in ''
Is it actually possible to run the AST based checker on the entire xcodeproject? Or how should I go about compiling the files 1 at a time?
I've managed to generate the compile_commands.json by following this guide here http://docs.oclint.org/en/stable/guide/xcodebuild.html
However, I'd still like to be able to run my RecursiveASTVisitor on the entire projects. Or alternatively, pass in the xcode project and enumerate all the source files would probably work too.
Anyone has ideas how to go about passing entire xcodebuild project as parameter for RecursiveASTVisitor?
Right now I'm running my ASTVisitor like this ./MyASTChecker ~/Desktop/directory/sample1.m but I'd like to make it do something like ./MyASTChecker ~/Desktop/directory/sampleproject.xcodeproj
The way I do it is at compile time using scan-build. This works for me with cmake/make based projects.
scan-build --use-analyzer=clang -enable-checker <checker_name> make
This will read the makefile and build everything in there while running the specified checker on each file as it's compiled. If you only want to build with some flags or a specific target, you can do this:
scan-build --use-analyzer=clang -enable-checker <checker_name> make <build_options>
If you instead have a cmake based project. You might first want to generate a makefile in a build directory. I do this for that:
cmake <path_to_cmakelists> -DCMAKE_CXX_COMPILER=c++-analyzer -DCMAKE_CC_COMPILER=ccc-analyzer
This followed by scan-build from above will compile and run checker on the source files while each file is being compiled.
I have only tried this with CMAKE / MAKE but should work with xcode like this:
scan-build --use-analyzer=clang -enable-checker <checker_name> xcodebuild
and with build options
scan-build --use-analyzer=clang -enable-checker <checker_name> xcodebuild <build_options>
You can read more about scan-build here

Teamcity Step tests (Command Line) failed when testing an iOS app

I am trying to run tests automatically using Teamcity, but it seems that when the agent is compiling the project, it is not done correctly because when I run the command like for running test, I am getting the following error:
fatal error: 'Pushwoosh/PushNotificationManager.h' file not found
#import <Pushwoosh/PushNotificationManager.h>
[16:48:51][Step 2/2] ^
[16:48:51][Step 2/2] 1 error generated.
However, when I run manually the same commands I get no errors, but my test running. The application that I want to run was written in objective-c, and the command lines I am using are the following:
$ git clone REPOSITORY_URL (runs sucessfully)
$ pod install (runs sucessfully)
$ xctool -workspace Supermaxi.xcworkspace -scheme Supermaxi test -only FunctionalTests:TestCase000_Registration/test00_WrongEmail -sdk iphonesimulator (fails and I get the previous described error)
After being helped by I friend of mine, we found the solution to this issue in this link.
It turns out that the main problem was, as the link states, that CocoaPods uses symbolic links in it’s directory structure, and TeamCity can have trouble copying symbolic links in the VCS checkout to build agent, so I had to set the Version Control Settings of Teamcity as it is explained in the previous link.
Therefore, I have just changed the VCS checkout mode from Automatically on server to Automatically on agent (if supported by VCS roots). After that I run the agent again, and it worked properly.

Resources