Periphery doesn't work as expected when `skip_build: true` and `index_store_path` specified
Hello.
I want to run Periphery on CI after the unit-tests passed. Right now I run Periphery with skip_build: false and index_store_path: null. This works as expected. But I want to increase speed of periphery scan by setting skip_build: true and specify index_store_path. When I'm doing this Periphery doesn't work. It outputs a lot of false positives.
When index_store_path is null I see a lot of [index:swift] PATH_TO_SWIFT_FILE lines in the output. This is good.
When index_store_path is not null I see a lot of the following lines in the output.
[index:swift] Failed to identify property declaration at PATH_TO_SWIFT_FILE
[index:swift] Failed to identify conformable declaration at PATH_TO_SWIFT_FILE
[index:swift] Failed to identify function declaration at at PATH_TO_SWIFT_FILE
Before running periphery scan I press CMD+B in the Xcode to build my app and wait until it finishes.
Why Periphery perform an indexing phase with a lot of errors when skip_build: true and index_store_path specified?
I've removed Derived Data directory and now everything works as expected. When running xcodebuild ... clean it doesn't remove contents of the Index directory. I noticed that Index directory may contains "bad" files that seems to breaks Periphery.
Example:
In the .../Index/DataStore/v5/units/ directory I have MainScreen.o-3Q052XDC7WQ3W file.
Sometimes I see several Main.screen.o-HASH files with different HASH. It is an LLVM Hash of the absolute path of the output file.
When a file is moved to the different location LLVM Hash recalculated and we have several files in the units directory.
When I remove any file, *.o-Hash file is still exists.
Right now I have two unit files:
I've add a breakpoint to the SwiftIndexer:51 with condition = unit.name?.contains("TransferRouter") == true
Both of the files links to the same file:
(lldb) po unit.name
▿ Optional<String>
- some : "TransferRouter.o-RKWE3OGIRH93"
(lldb) po filePath
".../Transfer/TransferRouter.swift"
(lldb) po unit.name
▿ Optional<String>
- some : "TransferRouter.o-BDYR936CXPMC"
(lldb) po filePath
".../Transfer/TransferRouter.swift"
Periphery uses incorrect unit file which causes a false positives.
How Periphery can decide which unit file to use:
- Compare by modified date and use newest file.
- Check
targetof unit file.targetcan bearmorx86_64. I am on the M1 Mac so Periphery must use unit file witharmtarget.
Hey @subdan, sorry for such a late reply on this. Did you manage to get any further? Is the issue that the index store path to the source file is incorrect for the old unit, or that the arch is different?
Hi, @ileitch. We run Periphery on a CI machine. We noticed that sometimes Periphery doesn't work as expected and shows some false positives. We happened to discover that when we keep open Xcode on CI machine it breaks Index/DataStore. Unit and record files gets duplicated as I mention earlier. Periphery uses wrong unit and record files and shows false positives.
We cleaned up Index directory and decided to never open Xcode on CI machine. This fixed the issue.
Now, we have the following flow that works as expected with Periphery:
- Run build for testing — Faslane
scanaction withbuild_for_testing: true - Run tests — Faslane
scanaction withtest_without_building: true - Run Periphery with
skip_build: trueand--index-store-pathflags
Thanks for investigating the root cause. I've added a check to detect these conflicting units.