johnno1962 / HotReloading

Hot reloading as a Swift Package

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

HotReloading as a Carthage dependency

aakarsh-sasi opened this issue · comments

Hi @johnno1962
I wanted to use hot reloading in my app but since we are using SPM is there any way to make it available in debug mode only and avoid it being shipped in release.

If we have hotreloading as a carthage dependency, we can include it as a debug only framework. Just a suggestion

Hi, interesting idea but I don't have the energy to set it up again using another package manager. Is there a reason why you can't use both.? You always have the alternative of using the InjectionIII app if you don't wan't to use SPM.

Just wanted to have it on our debug app only without having to remove it everytime before shipping for release. I had tried InjectorIII before and was facing re-compilation issues because our project is a mix of objective-C and swift

What were the type of recompilation issues? HotReloading is the same code as InjectionIII.

error: could not build module 'xyz'
#import <xyz/xyz.h>
^
:0: error: failed to import bridging header '/project-Bridging-Header.h'
💉 ⚠️ Adjust the "Header Search Paths" in your project's Build Settings ***

Find the path to xyz/xyz.h relative to the project root and add it to your project's "Header Search Paths" as $SRCROOT/... if you can't work it out I can TeamView, github at johnholdsworth.com

Thanks for being so generous @johnno1962 , but due to company policies I won't be able to TeamView. As per your suggestion, I added the Header Search Path for xyz.h in the build settings(for other objective-c headers too), but re-compilation still fails when using InjectorIII. But when using HotReloading there is no issue in recompilation. I'm in sort of a dilemma about what to do. On one side I'm fine with using HotReloading but since release process is automated, someone will have to manually unlink the framework before archiving and SPM doesn't support conditional targets as of now. And on the other side, injectorIII won't work/recompilation issues.

I also went ahead and tried to generate a carthage framework by taking a fork of your repository but there are some compilation issues in HotReloading-Package. If you can help me with getting around that, I'll be happy to raise a pull request adding carthage support.

Strange that it should be specific to InjectionIII as its the same code. Have you tried one of the more recent releases from https://github.com/johnno1962/InjectionIII/releases/tag/2.6.6? Let me know how you get on, then we can look at Carthage.

Will try with this release and let you know!

One last thing to check which could be a difference between HotReloading and InjectionII (App Store) Are you sure the casing of the file paths is correct. Are you including xyz.h when it should be Xyz.h or suchlike. The App Store version recompiles in a case sensitive file system.

@johnno1962 I switched to 2.6.6 and it solved the issue. InjectionIII is working on changes on the main project now but when I'm making changes in containing projects it is showing me a error in the console.
The following is the error:

💉 ⚠️ Could not locate containing project or it's logs.
For a macOS app you need to turn off the App Sandbox.
Have you customised the DerivedData path?

It's not a macOS app though.
I can open a issue on injectionIII repository if its not relevant here

Good news. When you say "containing projects" are they under the same directory as the other file you were trying to inject?

No, they are not under the same directory. But when I change the project directory to make changes to the containing project , it throws the above error

Have you tried the "Add Directory" menu item instead of changing the project if it is not under the same directory. Do you have multiple targets or multiple project files?

I have multiple project files. Trying with the add directory option.

Facing a different issue now

Loading .dylib ...
💉 Loading .dylib has failed, This is likely because Swift code being injected refers to a function with a default argument. Consult the section in the README at https://github.com/johnno1962/InjectionIII about using "unhide".
💉 ⚠️ dlopen() error: dlopen(/Users/aakarshs/Library/Developer/CoreSimulator/Devices/5E362CED-6B6C-438F-B22D-A283E154E817/data/Containers/Data/Application/EBBD5C4B-057D-438B-A292-FC50F2A7F5B1/tmp/eval102.dylib, 2): Symbol not found:

Now I have to build the unhide project and add the unhide script to the build phase?

Yes I'm afraid so -- and build a second time.

It is working now!!! Thank you so much! This will save a lot of time.

Just one last query, does the unhide error occur only once, or it happens every once in a while?

You only need to do the extra build once after a clean build or after you make a change to the file which contains the default argument as it patches the object files. I'm thinking about integrating it into InjectionIII as it is for HotReloading.

That would be great!

@johnno1962 is the injector tool supposed to start automatically when I build my project? This is the code I have written in the appDelegate since it is in objective-C.

    NSBundle *bundle = [NSBundle bundleWithPath:@"/Applications/InjectionIII.app/Contents/Resources/iOSInjection.bundle"];
    [bundle load];

That should be correct but you need to run the InjectionIII application yourself well. Only HotReloading starts when you build your project if you add the "Run Script" build phase.

I've integrated "unhide" into the InjectionIII.app finally and a pre-release is available here: https://github.com/johnno1962/InjectionIII/releases/tag/2.7.0RC1. Can you give it a try?

Sure, so have to clean build and run injectorIII to test?

Yes, clean build is the test to provoke the error and then rebuild+run to make it go away.

Don't have to include unhide.sh in build phase right?

Yup, it is working without any issue on the second run! Have not included unhide.sh in build phase script.

Looks like there might is a problem with the release candidate. I need to look into the problem further. Can you wait for a bit?

Cool, so it works for you. I have an edge case that I need to sort out. I'll let you know if I can sort it out.

What's the problem with the release config? Does this problem exist even when using 2.6.6 and unhide seperately? Let me know if you want to test out anything further

The problem is InjectionIII doesn't have as much information about a project as HotReloading which gets a copy of all Xcode environment variables as it is run from a build phase. The edge case is the SwiftUI example peoject Fruita so I figure I have to get it working.

Oh okay. We don't use SwiftUI currently, so do we have to worry about any issue while archiving for release?

Not if you are using InjectionIII (the unhide script only operates on Debug builds)

Even on the Pre-release version?

Pre-release version only unhides when you load the bundle and inject which you wouldn't be doing during an archive.

Unhide isn't working in the pre-release version when I tried a clean build today. Deleted the unhide.sh copied in bin folder when we run the unhide project and it is not added back.

I've published a second release candidate if you want to give it a try here with the edge case resolved. It shouldn't need unhide so you can remove that build phase step and injecting a default argument should fail then work after a clean build. Thanks very much for bearing with me.

Third release candidate fixing problem where you needed to restart the InjectionIII app each time you built clean.
https://github.com/johnno1962/InjectionIII/releases/tag/2.7.0RC3

Will try this! Thank you very much for putting all this effort !

Your project file seems to be in the Desktop or Documents folder and may prevent InjectionIII working as it has special permissions.

Was working fine initially but now showing this, anyway to grant permission to Injector to access documents?

I haven't looked into that. I think there is a way to request access but it's a bit complicated for injection for various reasons. At the moment the app just points out this might be a problem and suggests the user moves their project.

Oh it seems to work anyway, even though this warning/error is displayed.

It might, I had a couple of issues where people were getting strange errors so I put the message in and used the word "may"

All good with the new RC3 version?

Haven't tried the RC3 version yet, but will definitely switch to it, if it allows getting rid of the unhide script in the build phase

I hope so. Thanks for the time you're putting into this and your quick turnaround.

@johnno1962 i'm unable to archive in debug configuration after the pbxproj changes( added linker flags and disabled bitcode).

Please see this comment johnno1962/InjectionIII#128 (comment) on how to filter the options for "Other Linker Flags" for only the simulator. InjectionIII only patches the project file once so you can check those changes in. I'm curious though, why would you archive in debug mode?

For enterprise builds we archive in debug mode so that it has debug settings and other tools included

I understand now. Please try to switch with 2.7.0RC3 if you have the time and let me know if you encounter any problems.
The changes RC2 -> RC3 were very minor. Then I will be able to release it. Thanks again for your help!

Sure, will let you know in a few hours!

Hey, sorry for the delay. Was caught up with some other work. 2.7 is working great without the unhide script. One great addition that will make it equivalent to HotReloading would be the option to launch it automatically before the simulator is launched and specifying the Add directory beforehand itself rather than having to manually select it. Launching can be done by adding the following to the build phase:
open ./InjectionIII.app
But to specifiy the directory it may be possible using command line arguments:-
open ./AppName.app --args -addDirectory $(SRCROOT)

Let me know what do you think!

It's not possible to start InjectionIII from inside the simulator but you could add it as a "Build Phase". I've just published https://github.com/johnno1962/InjectionIII/releases/tag/2.7.1 which allows you to have a build phase:

open /Applications/InjectionIII.app --args -projectFile "$PROJECT_FILE_PATH" -addDirectory <whatever>

This is exactly what I was looking for! Trying this out

Thanks for the "--args" tip. Don't forget the the arguments won't take effect if the app is already running.

Tried it out by adding it in the build phase. But it doesn't seem to work. When I run the project on the Simulator it launches injectorIII without any issues. But after that I get the finder window where it asks me to choose the project directory, followed by choose for add directory. Am i doing something wrong?

This is the command added by me in the build phase:
open /Applications/InjectionIII.app --args -projectFile "$PROJECT_FILE_PATH" -addDirectory "($SRCROOT)/../../"

$PROJECT_FILE_PATH will be the complete path to the .xcodeproj. For ex Desktop/abc/xyz/xyz.xcodeproj. Is that fine?

They need to be absolute paths as InjectionII has no "current directory". Try something like "$PWD/../.."

Still not working. Added the complete path to test it: "Users/aakarsh/Example/xyz.xcodeproj". It opens both these windows as soon as injector launches.

image

Did you open Users/aakarsh/Example/xyz.xcodeproj or /Users/aakarsh/Example/xyz.xcodeproj? Can you select the project directory once then quit. Then it might work (It was all a bit rushed. This problem may be to do with the app having to be able run in the sandbox.) Did it open the directory you specified to select?

I have added /Users/aakarsh/Example/xyz.xcodeproj. Checking if opening it once fixes it

No, it seems to be all broken. It have seen it work but the final release seems to have issues. Give me a while I'll push out the release again when it works and let you know. Apologies for this.

Hey, no issues. I tested it out anyway and observed that adding the command line arguments always opens the Finder window to select project directory. This didn't happen when I didn't pass the arguments. But good news is that the finder always opens in the directory that I had specified in the arguments.
For ex: If I specified /Users/aakarsh/xyz/xyz.xcodeproj. It will open in this directory by default, just have to click select project directory. Maybe you are passing this path received to the finder and not injection?

Strange problem. If I use the released version I get the Finder window. Yet, if I run that version from DerivedData it behaves the way I expect to. Just weird. It's a good idea though. I'd like to see it work.

Let me know if you want any additional information or need help with testing!

Thanks. One question, when it prompts you for the directory when you specify -project file you should only have to select it once and it shouldn't prompt you after that. Is that true or does it open the Finder panel always? It should store credentials to read the directory and avoid the prompt. I'd like to get this running but not if I break how it works in the sandbox (App Store version).

It opens the finder window regardless of the fact that I had selected the project directory previously

Thanks, I've published two new pre-releases which should resolve these issue if you want to kick the tyres:
Un-sandboxed: https://github.com/johnno1962/InjectionIII/releases/tag/2.7.1RC1
Sandboxed: https://github.com/johnno1962/InjectionIII/releases/tag/2.7.1RC2
Both should work for you though the sandboxed version will require you to open the project using the Finder panel before you can use it (once.) Let me know how you get on. Thanks.

Hey, tested the unsandboxed version and -projectFile arguement is working correctly but --addDirectory doesn't seem to work. Verified the path by doing open /Users/aakarsh/Desktop/xyz in terminal and its not an issue with the path.

This is the complete build phase script:

    if  [ -d "/Applications/InjectionIII.app" ]; then
    open /Applications/InjectionIII.app --args --projectFile "/Users/aakarshs/Desktop/My-Projects/ios/test/test.xcodeproj" --addDirectory "/Users/aakarshs/Desktop/My-Projects/"
    fi

Something wrong here?

Does Injection say it is watching the directory you added in the Xcode console? The problem could be you're using the Desktop folder which has special permissions. Can you move the directory you're trying to watch elsewhere?

Yeah it says watching directory, /Users/aakarshs/Desktop/My-Projects/ios/test/ (which is the project file directory)

Injection is able to watch changes in the projectFile directory which is on Desktop as well. Still that could be a problem with only -addDirectory? Should I try moving it to Downloads? Was it working when you tested it?

Odd, Downloads and Desktop are the same in terms of permissions though so that wouldn't be the problem. I've just tested -addDirectory on the both versions and it seems be working fine. Are you always quitting InjectionIII?

I will test it out again in a few hours and let you know! Yes, I'm quitting injection before every build to verify if its working currently.

Thanks! If you have the time to investigate what the problem is your end you can build the release candidate yourself using this branch (it builds sandboxed by default though you can change that in the entitlements.)

Hey @aakarsh-sasi, did you ever get the new command line options working for your app?

Hi @johnno1962 , I didn't try it again as of now but will definitely try it in a day or two. Will keep you posted!

Add directory is working now! I was doing --addDirectory instead of -addDirectory

One more doubt , is there any way to check target architecture in the build script phase? There are certain environment variables like CONFIGURATION, PROJECT_DIR. If I can get access to the target architecture, I can start injector only when building on simulator

I figure this variable is probably the one you want to use:

    export TARGET_DEVICE_PLATFORM_NAME=iphonesimulator

Yes, trying this

Moved the script to pre-run actions. It's working just like hot reload now!

# Type a script or drag a script file from your workspace to insert its path.
if [ "$CONFIGURATION" == "Debug" ]; then
    if [[ "$SDK_NAME" =~ ([A-Za-z]+) ]]; then
        SDK_PLATFORM=${BASH_REMATCH[1]}
        if  [ "$SDK_PLATFORM" = "iphonesimulator" ] && [ -d "/Applications/InjectionIII.app" ]; then
            open /Applications/InjectionIII.app --args -projectFile "${PROJECT_DIR}/MyProj.xcodeproj" -addDirectory "${PROJECT_DIR}/../.."
        fi
    fi
fi

Running into an issue when I tried to run it on a teammate's system
⚠️ Codesign failed. If you are using macOS 11 (Big Sur), Please download a new release from https://github.com/johnno1962/InjectionIII/releases
I had installed 2.7.2 on his system

Have a look on the Console.app when it happens or run InjectionIII.app from the command line to see more information. Does Hot Reloading work for him? It probably because the code signing identity is ambiguous.
You can force the code signing identity using a preference with the project path as the name:

defaults write com.johnholdsworth.InjectionIII "$PROJECT_FILE_PATH" $EXPANDED_CODE_SIGN_IDENTITY

https://github.com/johnno1962/InjectionIII#macos-injection

Haven't tried Hot reloading on his system but InjectionIII was working fine with the previous releases. This issue came up after I uninstalled the existing version and upgraded to 2.7.2 (also removed unhide from the build phase since it was not required anymore). It's not an M1 mac, so is forcing the code sign identity required?

Have your tried 2.7.1 on your friend's machine? The differences between them shouldn't be related to code signing.

Just tried 2.7.1, same issue. Even tried adding the codesign script from https://github.com/johnno1962/InjectionIII#macos-injection
But no luck

So both versions work on your machine/project and don't on your colleague's? Did you try running InjectionIII.app from the command line to be able to see the code signing error:

$ /Applications/InjectionIII.app/Contents/MacOS/InjectionIII

Didn't try this. Trying it right now.

It seems to work when it was running from the command line and opening the tool directly from Applications. But not if it gets launched due to the command added to build script
open /Applications/InjectionIII.app --args -projectFile "${PROJECT_DIR}/MyProj.xcodeproj" -addDirectory "${PROJECT_DIR}/../.."

Ha, some weird OS permissions constraint I guess. You say this is specific to Big Sur? It's a nuisance but I'm happy when Apple tries to tighten things up.

Both me and my friend are on Big Sur : 11.2 and 11.2.3 respectively.

But it works for you and not him. Seems like they changed something. The message is a little out of date. Originally it wasn't possible to code sign from inside the App Store version so I started doing the github release but this came right before 11.0. You could try the direct command (rather than using "open") in your build phase.

/Applications/InjectionIII.app/Contents/MacOS/InjectionIII -projectFile ... >/tmp/injection.log 2>&1 &

But this will run the app again and again do you'll end up with multiple injections unless you kill them each time.

Thanks @johnno1962! I'm updating to Big Sur 11.3 (latest version) to check if this might be the issue.

@johnno1962 I updated to 11.3 and I'm facing the same issue as well. what might be the reason for the codesign failing when launching from the bash script? And is there any possible workaround. tried to have a look on the console but it is flooded