johnno1962 / injectionforxcode

Runtime Code Injection for Objective-C & Swift
MIT License
6.55k stars 565 forks source link

Patching main.m fails on projects that uses swift AND ls -t (null)/../Logs/Build/*.xcactivitylog’
 Could not locate compile command #36

Open danydev opened 9 years ago

danydev commented 9 years ago

The file main.m doesn't exist anymore when using swift, so the plugin injector fails when trying to patch it (see error below) Note how in cocoa touch the entry point is directly the AppDelegate.swift that is marked with @UIApplicationMain, while in cocoa the entry point is the main.swift file.

Patching project contained in: myProject/ 
Could not match project’s main.(m|mm) at ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/InjectionPlugin.xcplugin/Contents/Resources/common.pm line 51.
 main::error(‘Could not match projectÉmain.(m|mm)’) called at ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/InjectionPlugin.xcplugin/Contents/Resources/patchProject.pl line 65
*** Bundle build failed ***
Check Bundle project.

johnno1962 commented 9 years ago

Create an empty main.m file in the project to patch for injection.

danydev commented 9 years ago

So the final main.m file should look like this, is it correct? (i.e no main() function since it isn't the real entry point)

//
//  main.m
//  myProject
//

#import <UIKit/UIKit.h>

// From here to end of file added by Injection Plugin //

#ifdef DEBUG
static char _inMainFilePath[] = __FILE__;
static const char *_inIPAddresses[] = {"127.0.0.1", "192.168.1.127", NULL};

#define INJECTION_ENABLED
#import "/Users/myUser/Library/Application Support/Developer/Shared/Xcode/Plug-ins/InjectionPlugin.xcplugin/Contents/Resources/BundleInjection.h"
#endif

ps: what about using relative paths instead of absolute paths? This would be valuable for teams that share the same codebase, we don't want to have user-specific things commited. Maybe the injection patch should not be even tracked, but since currently it doesn't seem to be possible, having a generic injection path would help.

ps2: In the future you may want to find another place for this code, since you can't assume the presence of main.m anymore, and creating it just for the injection code looks like a temporary workaround.

danydev commented 9 years ago

While trying to patch my code I receive the following error on the injection console, can you take a look?

Connection from: /Users/myUser/Library/Developer/CoreSimulator/Devices/BAC81E55-6CE6-4789-93DD-7400CF37891C/data/Containers/Data/Application/0BA0EDE3-E774-4353-84ED-0CE5E8EC3370 i386 (61)
sh: -c: line 0: syntax error near unexpected token `(‘
sh: -c: line 0: `ls -t (null)/../Logs/Build/*.xcactivitylog’
Could not locate compile command for /Users/myUser/Desktop/projects/myProject-ios/ViewControllers/MyViewController.swift at /Users/myUser/Library/Application Support/Developer/Shared/Xcode/Plug-ins/InjectionPlugin.xcplugin/Contents/Resources/common.pm line 51.
   main::error(‘Could not locate compile command for /Users/myUser/Deskt…’) called at /Users/myUser/Library/Application Support/Developer/Shared/Xcode/Plug-ins/InjectionPlugin.xcplugin/Contents/Resources/injectSource.pl line 189
*** Bundle build failed ***
Check Bundle project.
johnno1962 commented 9 years ago

It’s not finding your build logs directory. are you sure the plugin is built correctly? Did you build it from source from github directly? There can be problems using Alcatraz. Re main.m it seems easiest to continue the way things are as a means of demendancy management. Most people patch and unpatch before commiting to source control.

danydev commented 9 years ago

Yes I was using the plugin installed with alcatraz, so I uninstalled it using alcatraz, I verified that there wasn't anymore the plugin at ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/, restarted Xcode, built the project, restarted Xcode, but I have the same exact error while injecting...:( I even used another simple project created from scratch (just to be sure that it was not a problem that depends on the project where I tried it at first), but I don't see differences

johnno1962 commented 9 years ago

Hmm.. the only thing I can think of is that you need to have selected text in a .swift or .m file before trying to patch. The relevant code is:

- (void)selectionDidChange:(NSNotification *)notification {
    id object = [notification object];
    if ([object isKindOfClass:DVTSourceTextView] &&
        [object isKindOfClass:[NSTextView class]] &&
        [[object delegate] respondsToSelector:@selector(document)])
        self.lastTextView = object;
}

- (NSString *)buildDirectory {
    return [self.lastTextView valueForKeyPath:@"window.delegate.workspace.executionEnvironment.workspaceArena.buildFolderPath.pathString"];
}
danydev commented 9 years ago

no luck, thanks anyway.

johnno1962 commented 9 years ago

Sorry to hear that. I’ve just performed some basic checks on the github version with Swift and I can’t get it to fail. This problem occurs when the nib has failed to load which shouldn’t be the case if you built of github besides there would have been a message. Can you attach you test project?

danydev commented 9 years ago

Here the test project, but I strongly suppose that it will work for you, it must be some incompatibility on my system configuration at this point. btw I'm using Xcode 6.1.1 (6A2008a) and Yosemiti 10.10.1 (14B25) https://dl.dropboxusercontent.com/u/2175823/TestProject.zip

I even tried to delete the plugin again, reinstalling it building master on github.

johnno1962 commented 9 years ago

Your test project does of course work this end. I’m interested why it could possibly be failing for you but short of remote screening onto your machine there is not much more I can do.

danydev commented 9 years ago

Ok, I just sent you an email at support (at) injectionforxcode.com, so that we can try with remote control, let me know if you didn't receive it.

danydev commented 9 years ago

After a bit of pair debugging we found that the issue was in the default Xcode Derived Data location path. Currently injectionforxcode assumes the "Unique" settings mode (that's the default setting), so to solve the issue I needed to change back the derived data path back to Unique. To do that, just open Xcode \ Preferences \ Locations \ Advanced and select Unique I initially set it to "Custom" relative to Derived Data in the past (I remember to have changed it to solve a problem that I'm not experiencing anymore regarding Cocoapods), this caused the plugin to not work correctly since it is not able to find the path where the needed build activity log is located

We could even find a workaround to support that settings, but it would require a bit of research, so for me it's ok to go back to the Unique derived data path settings.

s4cha commented 9 years ago

Thank god I found your post, adding the fake main.m + reseting the Derived Data location to "Unique" solved it for me. Thank you so much :)