[Development] Qt 4.x and Qt 5 frameworks should use @rpath (QTBUG-31814)

Jake Petroules jake.petroules at petroules.com
Sun Aug 3 23:24:11 CEST 2014


On 2014-08-03, at 06:11 AM, Adam Strzelecki <ono at java.pl> wrote:

>> Your proposal to simply add @rpath and do nothing else has no benefits. What problem does it solve, other than deleting a bit of code from macdeployqt that currently works and will continue to work without maintenance? None.
> 
> My original intention was to stop rewriting headers of Qt modules on install and app deploy.
> 
> I am aware it opens new possibilities, like these you proposed, including making macdeployqt as part of Qmake build step optional or default (upon request).
> 
> I wish also we had pure drag&drop Mac way installation of Qt SDK instead of this fancy installer that does just copying.

Yes, that's the idea. The installer would probably remain anyways, but we'll see.

>> There is no point in doing it unless we go all the way and make the Qt SDK completely relocatable.
> 
> Agreed.
> 
>> I understand you want to start by completing one objective at a time, but keep in mind each of these objectives is part of a greater overall goal. Alone, they are pointless.
> 
> Agreed.
> 
>> Furthermore, if you simply copy frameworks into the bundle at build time like every other native OS X app on the planet, this becomes a non-issue and you don't even need DYLD_LIBRARY_PATH. With my QMAKE_EMBEDDED_FRAMEWORKS suggestion, too, there would be a choice between the two, and be closer to native tools behaviour at the same time.
> 
> It isn't about copying few KB or few MB, Qt frameworks weight much more. Are you telling me that each Qt SDK example should have its own copy of Qt frameworks BY DEFAULT which makes around ~100 copies of Qt frameworks !?

Demos within the SDK can just have an extra runpath search path added... like @executable_path/../../../../../../lib or something, no need to copy the frameworks for that. For user apps it's a whole different story.

>> Those are system libraries that are part of the operating system, present on every OS X installation in the world and not designed to be relocatable. Qt is not a system library and should be relocatable. Anything residing in /System has no bearing on this discussion.
> 
> I gave you an example with external framework whose install name is set BY DEFAULT by Xcode to /Library/Frameworks/FrameworkName.framework and it isn't /System.

I think you're a little confused about the meaning of default. There is a system level default in Xcode's configuration files (you can find this deep in the app bundle), which is /Library/Frameworks for frameworks. However, when creating a new framework target in Xcode 6, the user-level DYLIB_INSTALL_NAME_BASE is set to @rpath, which overrides the system-level /Library/Frameworks value. The system one cannot be changed for compatibility reasons.

>> This still breaks the rule of absolute paths appearing somewhere. We do not want absolute paths anywhere during development except in per-session environment variables.
> 
> I gave you a clean example that Xcode (still!?) defaults to /Library/Frameworks for new projects/targets.

See above.

>> Linux is not OS X (also did you forget about $ORIGIN?).
> 
> You are talking about Linux kernel vs XNU or GNU/Linux which was inspired by BSD and OSX which is again based on BSD. So we are much closer to Linux that Windows. This is especially visible in Qmake scripts and code that is mostly common on Linux & Mac.
> 
> It is very likely also that someone will pin newly create app to the dock, and once it is pinned it won't work. I do really see benefit to keep absolute rpath to Qt SDK during dev process, until deploy.

I still don't consider this an issue. If you really want it that badly, add the following (or something of the sort, I don't know qmake) in YOUR app target in qmake:

QMAKE_LFLAGS_DEBUG += -Wl,-rpath,$$QT_INSTALL_LIBS

>>> Which tools? AFAIK Xcode doesn't copy external frameworks into app bundle by default.
>> 
>> Yes it does.
> 
> Maybe I was not clear enough, but again not it doesn't BY DEFAULT, Xcode does not copy any frameworks BY DEFAULT into app bundle. Again I am talking about default behavior not behavior requested & not Xcode capabilities.

In Xcode 6, when you create a new framework target, the first application target in the project is automatically selected for "embed in bundle" which you'd have to EXPLICITLY change for it to NOT be copied. Xcode 6 simply adds new and convenient UI for a practice that's been standard for over a decade. So yes, it does copy frameworks BY DEFAULT.

>> Examples of how Xcode facilitates this:
> 
> 
> This example exhibits explicit setting in Xcode project to copy selected frameworks into the bundle. But please remember you want this behavior to be default for Qmake (qbs?) Qt based app build. All I am saying this shouldn't be default.

We might be debating the meaning of "default". The default workflow should absolutely be to copy frameworks; I'm not saying that by default qmake should copy every framework into every app bundle without being told. Hence why QMAKE_EMBEDDED_FRAMEWORKS would be a user-set property. Much like qmake doesn't automatically invent values for SOURCES but you still need to set it to create anything useful.

There is a very simple solution to this problem. I and the majority of developers do this:

QMAKE_EMBEDDED_FRAMEWORKS = QtCore QtGui QtWidgets

You do this:

CONFIG(release, debug|release):QMAKE_EMBEDDED_FRAMEWORKS = QtCore QtGui QtWidgets
QMAKE_LFLAGS_DEBUG += -Wl,-rpath,$$QT_INSTALL_LIBS

>> This is not a novel idea I just came up with. This has been the standard workflow on OS X for over a decade.
> 
> I am not arguing with that. I am just arguing with proposed default behavior.
> 
> I am perfectly okay with ability to copy frameworks on build if it is requested by developer via CONFIG += bundle_on_build or whatever. But I am against doing it by default. I am running SSD on my both iMac & MBP since a while, but not anyone does.

I'm not running on an SSD and I have the slowest MacBook Pro imaginable (2008). I can assure you there is no performance degradation whatsoever when copying frameworks as part of the standard workflow. Also, like I said before... QMAKE_EMBEDDED_FRAMEWORKS. A CONFIG option is not necessary because if you don't want to copy things, simply don't set QMAKE_EMBEDDED_FRAMEWORKS, or set it for release configuration only.

> Please note that there is also some reasoning behind Copy Files Xcode build step option "Copy only when installing".

Which is unchecked by default and no one seems to use it. Either way I can assure you the reason for this setting was NOT a performance optimization for copying frameworks, in part because older versions of Xcode might not have actually set DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH.

>> The whole point of @rpath is to enable this improvement in workflow. By itself there is no point in adding it other than *slightly* simplifying some macdeployqt code.
> 
> Again, I am not against having a switch to do what you tell during build time. But for other users sake I don't want to make it default.

For other users' sake we DO want to make it default. The workflows you want are foreign to every Mac developer out there.

>> Apologies for parroting, but... you are in fact wrong. I've JUST tested this and Xcode does in fact set many environment variables when running an application. I've added NSLog(@"%@", [[NSProcessInfo processInfo] environment]);
> 
> Apologies taken. Especially having that I was wrong. Indeed Xcode does that for sake of frameworks being part of project that are yet not installed. Yet DYLD_FRAMEWORK_PATH serves bit different purpose here, it makes the app work even there is no framework yet in /Library/Frameworks.
> 
>> I work with Xcode on a daily basis building native Cocoa apps. (…)
> 
> I am sorry, it wasn't my intention to negate your skills or whatsoever. I am really happy that you take part of this discussion.
> 
>> Point being? The system default DYLIB_INSTALL_NAME_BASE for frameworks in the Xcode build system happens to be /Library/Frameworks. For new projects it should be set to @rpath (and the IDE does this when creating a new target). Nothing to see here.
> 
> Can you please check this, because I checked it twice and neither creating new Cocoa framework project nor adding new Cocoa framework target resulted in having @rpath as install name.

New in Xcode 6.

> So altogether I think best solution is to symlink all needed frameworks on build. This removes need to make proper change in Qt Creator to use DYLD_FRAMEWORK_PATH, makes app work via Dock/Finder even it is not yet completely bundled.

I'm curious why you think this will have a noticeable impact on performance. It is an unnecessary over-complication that actually leads to more bugs. Because this suggestion is contrary to every standard of Mac development, I will not accept this as a valid argument until you can provide benchmarks proving that there is a significant performance degradation.

Secondly, you're forgetting about user frameworks. Unless you copy those to the bundle at build time as well, currently, with Qt 5, your application WILL NOT work when launched via Dock/Finder. The fact that it works now for *some* apps is, like I mentioned before, a side effect.

> Such symlink may be relative (if possible) so all Qt examples may be built but not "bundled", therefore their will use single copies of frameworks.
> 
> I am perfectly okay to have "bundle_on_build" config which makes "make" behave as "make" & "make deploy" so it will satisfy your needs.
> 
> WDYT?
> 
> Regards,
> -- 
> Adam

-- 
Jake Petroules - jake.petroules at petroules.com
Chief Technology Officer - Petroules Corporation


More information about the Development mailing list