ofxCef
ofxCef copied to clipboard
Get it working with OF 0.9.8 (macOS)
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:
-
Download the latest Mac OS X 64-bit Build from the Spotify Automated Builds site. (I downloaded the Standard Distribution
3.2987.1601.gf035232
) -
cmake -G "Xcode"
in the root of the downloaded folder. -
Open the Xcode project and compile the
cefclient
- I switched in
Product
->Scheme
->Edit Scheme…
the Build Configuration toRelease
.
- I switched in
-
Copy
Chromium Embedded Framework.framework
andcefclient Helper.app
fromtests/cefclient/Release/cefclient.app/Contents/Frameworks
into the ofxCEF folder inlibs/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.
-
Also copy
libcef_dll_wrapper/Release/libcef_dll_wrapper.a
into the same folderlibs/CEF/lib/osx
. -
And copy the contents of the
include
folder intolibs/CEF/include
-
Now open the project generator and create a new project with ofxCef as addon selected.
-
Open the Xcode project and drag and drop the
cefclient Helper.app
intoaddons/ofxCef/libs/CEF/lib/osx
-
In the project settings got to Build Phases and add a Copy Files Phase. This is for
Chromium Embedded Framework.framework
andcefclient Helper.app
, the Destination should be set toFrameworks
. There might already be aCopy Files
Phase to Frameworks in withChromium Embedded Framework.framework
, in that case just add thecefclient Helper.app
. -
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?!
-
Also remove
process_helper_mac.cc
from theCompile Sources
phase. -
Now select each .cpp file in
addons/ofxCef/src
and set the type in the file inspector toObjective-C++ Source
. Do the same forofApp.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) -
Copy the contents from my cef-test project
main.cpp
,ofApp.cpp
, andofApp.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:fSleepMillis(10); // Seems to help a bit eshape(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 ;)
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)...
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
My colleague has got things running under windows pretty well - see the other issue - https://github.com/ofZach/ofxCef/issues/32
I'll get him to update it with some more recent things he had fixed up
@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 👍
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
@razvanilin @sheridanis, yes, just post the details in issue #32 and I will try and help
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.
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?
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.
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.
@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?
@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
@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?
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.
hi, toooo hard to me! ;) I am trying to make it work, but I am getting this errors:
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:
On the step 11 the process_helper_mac.cc file was not there.. just a .cpp one...
cefclient.app is working btw...
@moebiussurfing First off all, sorry for the late reply.
-
yeah the
CefWindowInfo
changed a little since I wrote the steps. I've changed the first line towindowInfo.SetAsWindowless(view);
and deleted the second line with
transparent_painting_enabled
. -
You probably want to create a separate
Run Script Phase
after theCopy Files Phase
of Step 9. This way the files you are referring to are actually there. -
You're right, it's
.cpp
, not sure why I wrote.cc
.
Hope you're getting it to compile now!