Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get it working with OF 0.9.8 (macOS) #34

Open
michaelbaisch opened this issue May 1, 2017 · 16 comments
Open

Get it working with OF 0.9.8 (macOS) #34

michaelbaisch opened this issue May 1, 2017 · 16 comments

Comments

@michaelbaisch
Copy link

michaelbaisch commented May 1, 2017

I would like to see this working on at least macOS and Windows. I started with macOS and I couldn't get the example working. After a while I decided to started from scratch with OF 0.9.8, Xcode 8.3.2, and macOS Sierra 10.12.4.

I tried to make this process a bit more automatic by using the ProjectGenerator as much as possible. This is why the folder structure is a bit different and the building phases are much simpler.

Here is my fork with a cef-test example (To get this working you need to do the first 6 steps anyway).


This is what I did to get it working:
  1. Download the latest Mac OS X 64-bit Build from the Spotify Automated Builds site. (I downloaded the Standard Distribution 3.2987.1601.gf035232)

  2. cmake -G "Xcode" in the root of the downloaded folder.

  3. Open the Xcode project and compile the cefclient

    • I switched in Product -> Scheme -> Edit Scheme… the Build Configuration to Release.
  4. Copy Chromium Embedded Framework.framework and cefclient Helper.app from tests/cefclient/Release/cefclient.app/Contents/Frameworks into the ofxCEF folder in libs/CEF/lib/osx

    • The Helper app might be a separate target in the future again but I wanted to eliminate any potential source of failure, so I simply copied this one.
  5. Also copy libcef_dll_wrapper/Release/libcef_dll_wrapper.a into the same folder libs/CEF/lib/osx.

  6. And copy the contents of the include folder into libs/CEF/include

  7. Now open the project generator and create a new project with ofxCef as addon selected.

  8. Open the Xcode project and drag and drop the cefclient Helper.app into addons/ofxCef/libs/CEF/lib/osx

  9. In the project settings got to Build Phases and add a Copy Files Phase. This is for Chromium Embedded Framework.framework and cefclient Helper.app, the Destination should be set to Frameworks. There might already be a Copy FilesPhase to Frameworks in with Chromium Embedded Framework.framework, in that case just add the cefclient Helper.app.

  10. We need another build phase this time a script phase. In there goes:

    install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"
    rm -rf "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app"
    mv "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/cefclient Helper.app" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app"
    mv "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app/Contents/MacOS/cefclient Helper" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app/Contents/MacOS/$PRODUCT_NAME Helper"
    

    With that I think I replaced all the other script phases and the additional script.
    As far as I understand only the Helper app and executable name needs to be changed to *appName* + Helper. For some reason we also need to change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" of the app executable, which I don't understand because it already seems to point to the right place?!

  11. Also remove process_helper_mac.cc from the Compile Sourcesphase.

  12. Now select each .cpp file in addons/ofxCef/src and set the type in the file inspector to Objective-C++ Source. Do the same for ofApp.cpp. (If we have separate source files for macOS and windows we could change the extension for the macOS sources to .mm to skip this step)

  13. Copy the contents from my cef-test project main.cpp, ofApp.cpp, and ofApp.h

Now your project should be in the same state as my cef-test project in my fork and it should hopefully compile and show a website.


Well, sometimes at least. I'm running into a few problems:
  • The web content only showed up when resizing the window. OnPaint isn't called when the the browser initially loads the website, which I don't understand. A dirty workaround was to add this:

     ofSleepMillis(10);	// Seems to help a bit
     reshape(ofGetWidth(), ofGetHeight());
    

    at the end of void ofxCEF::setup()

  • Sometimes the site doesn't seem to show at all. Even after I resize the window a few times. Although I see through Little Snitch that the app makes a connection.

  • Sometimes the memory skyrockets to ~3GB at the start and after a few laggy seconds it goes back to ~1GB. I wasn't able to find out what is using the memory. Looking at the app and the Helper app with Instruments only shows few MB. Normally the Debugging Navigator in Xcode shows around 40MB.

  • The menu bar isn't useable. I also can't cmd+q the app which is annoying.

I looked at cef and the ofxCef code and tried a few things. For example when calling void ofxCEF::setup() in ofApp::setup() NSView * view = [ cocoaWindow contentView]; isn't available. I guess OF hasn't created the window yet. So I moved that into offApp::update() but it didn't really improve a lot.

Is there anyone else who wants to see this production ready? I would appreciate some feedback on the steps I took to get it working and the problems I run into. Maybe I missed something.
And I'm sorry to put all this in one Issue, it's pretty general and everything might be connected after all ;)

@ofZach
Copy link
Owner

ofZach commented May 1, 2017

i haven't looked at this in a few years -- will take a look! thanks for detailed notes.

PRs always welcome if you feel there are useful changes...

I don't think this project will work well with project generator because there's alot of weird stuff like this:

https://github.com/ofZach/ofxCef/blob/master/example_ofxCEF/src/main.cpp

that an empty project created using the PG won't have (but if you update a project with this kind of main it will be fine)...

@razvanilin
Copy link

I'm currently working on getting it up and running on Windows 10 - Visual Studio 2015. Will update once I succeed. Thanks for the MacOS instructions @michaelbaisch, will give that a go later in the week too

@sheridanis
Copy link

My colleague has got things running under windows pretty well - see the other issue - #32

I'll get him to update it with some more recent things he had fixed up

@razvanilin
Copy link

@sheridanis I was checking up the steps in that issue but unfortunately it's not working that well for me. Will be great if we can hear back from him 👍

@sheridanis
Copy link

I've asked him to update the issue when he's working next (should be today or tomorrow) - could you please detail on the other thread where you got up to in his steps and what problems your still seeing

@rjx-ray
Copy link

rjx-ray commented May 3, 2017

@razvanilin @sheridanis, yes, just post the details in issue #32 and I will try and help

@michaelbaisch
Copy link
Author

Glad to see some interest in this!

I looked into stuff a bit more. I created a new issue #36 for the main problem I think I'm having.

@ofZach concerning the PG. I'm aware that this addon probably will never be completely useable with PG, without some some additional work (As long as the PG doesn't get more powerful). But then for every addon you have to do a bit of work, even if it's just including and calling some methods on an instance from a class from the addon. And normally this is explained in the Readme. For this addon there are a few more steps. I think making it as compatible as possible plus explaining the missing steps has quite a few advantages. For instance it makes it possible to add it to an existing project. Then we have to think about which steps are really necessary, which makes it more maintainable and easier to understand. Having said that, I don't think you disagree, I just wanted to throw it in there.

About the changes in main.cpp. I'm not sure why you guys decided to create this ofxCEF object and having a pointer in ofApp pointing to it. I tried to dynamically add browsers and I completely removed that pointer. I'm just creating new instances of ofxCEF in ofApp and throwing them into a vector. Works like a charm (except the problem from #36). So I guess my question is can we remove this? Or is this needed on Windows for some weird reason?
This way we could have only one call before running ofApp to init CEF and one after for shutting down CEF.

@razvanilin
Copy link

Hi @michaelbaisch , I tried to get it up and running on MacOS following your instructions. Unfortunately I get some linker errors, most likely because of the way the Helper and Chromium frameworks are referenced in the project.

Undefined symbols for architecture x86_64:
  "CefV8Context::GetCurrentContext()", referenced from:
      ofxCEFV8ExtensionHandler::Execute(CefStringBase<CefStringTraitsUTF16> const&, scoped_refptr<CefV8Value>, std::__1::vector<scoped_refptr<CefV8Value>, std::__1::allocator<scoped_refptr<CefV8Value> > > const&, scoped_refptr<CefV8Value>&, CefStringBase<CefStringTraitsUTF16>&) in ofxCEFV8ExtensionHandler.o
  "CefRegisterExtension(CefStringBase<CefStringTraitsUTF16> const&, CefStringBase<CefStringTraitsUTF16> const&, scoped_refptr<CefV8Handler>)", referenced from:
      ofxCEFClientApp::OnWebKitInitialized() in ofxCEFClientApp.o
  "cef::logging::LogMessage::LogMessage(char const*, int, int)", referenced from:
      scoped_refptr<CefBrowser>::operator->() const in ofxCEF.o
      scoped_refptr<CefBrowserHost>::operator->() const in ofxCEF.o
      scoped_refptr<CefFrame>::operator->() const in ofxCEF.o
      scoped_refptr<CefProcessMessage>::operator->() const in ofxCEFBrowserClient.o
      scoped_refptr<CefListValue>::operator->() const in ofxCEFBrowserClient.o
      scoped_refptr<CefV8Value>::operator->() const in ofxCEFV8ExtensionHandler.o
      scoped_refptr<CefV8Context>::operator->() const in ofxCEFV8ExtensionHandler.o
      ...
  "cef::logging::LogMessage::~LogMessage()", referenced from:
      scoped_refptr<CefBrowser>::operator->() const in ofxCEF.o
      scoped_refptr<CefBrowserHost>::operator->() const in ofxCEF.o
      scoped_refptr<CefFrame>::operator->() const in ofxCEF.o
      scoped_refptr<CefProcessMessage>::operator->() const in ofxCEFBrowserClient.o
      scoped_refptr<CefListValue>::operator->() const in ofxCEFBrowserClient.o
      scoped_refptr<CefV8Value>::operator->() const in ofxCEFV8ExtensionHandler.o
      scoped_refptr<CefV8Context>::operator->() const in ofxCEFV8ExtensionHandler.o
      ...
  "CefShutdown()", referenced from:
      _main in main.o
  "CefDoMessageLoopWork()", referenced from:
      ofxCEF::update() in ofxCEF.o
  "CefExecuteProcess(CefMainArgs const&, scoped_refptr<CefApp>, void*)", referenced from:
      initofxCEF(int, char**) in ofxCEF.o
  "CefBrowserHost::CreateBrowserSync(CefWindowInfo const&, scoped_refptr<CefClient>, CefStringBase<CefStringTraitsUTF16> const&, CefStructBase<CefBrowserSettingsTraits> const&, scoped_refptr<CefRequestContext>)", referenced from:
      ofxCEF::setup() in ofxCEF.o
  "CefProcessMessage::Create(CefStringBase<CefStringTraitsUTF16> const&)", referenced from:
      ofxCEFV8ExtensionHandler::Execute(CefStringBase<CefStringTraitsUTF16> const&, scoped_refptr<CefV8Value>, std::__1::vector<scoped_refptr<CefV8Value>, std::__1::allocator<scoped_refptr<CefV8Value> > > const&, scoped_refptr<CefV8Value>&, CefStringBase<CefStringTraitsUTF16>&) in ofxCEFV8ExtensionHandler.o
  "CefInitialize(CefMainArgs const&, CefStructBase<CefSettingsTraits> const&, scoped_refptr<CefApp>, void*)", referenced from:
      initofxCEF(int, char**) in ofxCEF.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I tried this on a new project generated with the OF project generator with ofxCef as an addon. Did you come across this issue at any point when setting up the project?

@michaelbaisch
Copy link
Author

Hey @razvanilin could it be that you missed step 5. ?
If you didn't copy the libcef_dll_wrapper.a before using the PG, it won't add it to Other linker Flags. If that was the case you can add ../../../addons/ofxCef/libs/CEF/lib/osx/libcef_dll_wrapper.a to Other linker Flags without rerunning the PG.

@razvanilin
Copy link

Thanks for pointing that out, @michaelbaisch
I managed to get it running on my end. Unfortunately, I couldn't make your cef-test example to work for some reason (I didn't try a lot). It doesn't display anything so I assume something must go wrong in the ofApp::setup() or ofApp::draw().
The good news is that I integrated this in my own project where I have a separate class handling the ofxCEF instance and it's working like a charm. The performance seems a bit lower than Windows but I'll try to tweak that a bit later.

Regarding the memory usage, I can't see any spikes on my end. The helper and the OF app both stay under 100mb usage. (~60-80MB)

I'll try and set up an example in my fork later today.

@michaelbaisch
Copy link
Author

@razvanilin My first guess is that you maybe didn't copy the data folder with the html file that is loaded there. It would interest me if it was only that or if there is something more going on.

Concerning the memory, did you try running it a few times? Because it doesn't always happen. Maybe try the my other branch + example from the issue #36. There are also a few notes where I explained in which case it always happens on the first ofxCEF instance. It could be maybe some kind of weird timing issue where different machines react differently. I'm on a MacBook Pro Mid 2015, 2.8Ghz i7, 16GB.

Lastly how do you measure the performance? Or is it just a feeling how smooth it runs?

@razvanilin
Copy link

@michaelbaisch you were right, I figured that afterwards haha
I measured the performance using the Xcode performance tool and the activity monitor. I tried it like dozens of times and I'm sure there were no spikes in memory usage. I did change some stuff in my project though so I will try to give it a go with your fork. I don't have my mac with me though so I will try it next time I'm in the office.
My Macbook Pro is from late 2011 (right out of the ice-age). I can't remember the exact specs but my guess is that it's a 2nd get i7 2.6-2.8Ghz, 8GB RAM

@michaelbaisch
Copy link
Author

@razvanilin did you have time to test my example project in the other branch in my fork?

When you say you "have a separate class handling the ofxCEF instance" does that really mean that you call in that class the methods of an ofxCEF instance, or did you actually replace the ofxCEF class and implemented your own setup and draw methods? In the first case I guess you simply do something similar like me in the ofApp but the second case would be interesting, and I would love to see some sample code.
Then I wanted to ask which specific CEF version did you use for your macOS tests?

@razvanilin
Copy link

Hi @michaelbaisch , sorry for the late reply. Things are busy at work at the moment and I'm having a hard time getting on this. I still don't have my mac with me and will give you more details when I get to it.

Regarding the separate class, it's the first case you are describing so it should be similar to your setup.

@moebiussurfing
Copy link

hi, toooo hard to me! ;) I am trying to make it work, but I am getting this errors:
screen shot 2017-12-02 at 10 03 19 pm
In some steps I don't know if doing bad...

On the step 10. I don't know if the script must be place there, after the previous one:
screen shot 2017-12-02 at 10 04 39 pm

On the step 11 the process_helper_mac.cc file was not there.. just a .cpp one...
screen shot 2017-12-02 at 10 05 51 pm

cefclient.app is working btw...

@michaelbaisch
Copy link
Author

@moebiussurfing First off all, sorry for the late reply.

  1. yeah the CefWindowInfo changed a little since I wrote the steps. I've changed the first line to

    windowInfo.SetAsWindowless(view);
    

    and deleted the second line with transparent_painting_enabled.

  2. You probably want to create a separate Run Script Phase after the Copy Files Phase of Step 9. This way the files you are referring to are actually there.

  3. You're right, it's .cpp, not sure why I wrote .cc.

Hope you're getting it to compile now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants