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

Ziller Eike Eike.Ziller at digia.com
Wed Aug 13 10:04:21 CEST 2014


On Aug 12, 2014, at 9:14 PM, Jake Petroules <jake.petroules at petroules.com> wrote:

> On 2014-08-12, at 12:36 PM, Adam Strzelecki <ono at java.pl> wrote:
> 
>>> Default behavior: I’m on favor of keeping it opt-in, either via "CONFIG += bundle_frameworks" or “make bundle”
>> 
>> Me too. However as I said previously stakeholders are to decide. I don't want start over this discussion with Jake.
> 
> Please stop saying that to fuel your argument just because I disagree with some of your points; it sounds kind of rude. Also, I am one of these "stakeholders", though I'm not sure what definition you're going off of, because the dictionary's definition "a person with an interest or concern in something" would include you as well, now, wouldn't it? ;)
> 
> Also, believe it or not, but I agree with not copying frameworks by default (see below)...
> 
> On 2014-08-12, at 10:25 AM, Adam Strzelecki <ono at java.pl> wrote:
> 
>> Okay, Phase II.
>> 
>> (1) Introduce "bundle_frameworks" CONFIG option, and set it default for "rpath" shared builds on iOS & OS X
> 
> This falls apart in the face of third party libraries. Who says a particular application is even using Qt with qmake?
> 
>> (2) Introduce "bundle" make target, when "bundle_frameworks" CONFIG is set, it is added to "all"
>> 
>> (3) Make's "bundle" will copy (update if not there) all used Qt frameworks to app's bundle Frameworks and used plugins to Plugins (currently implemented as separate macdeployqt)
>> 
>> NOTES:
>> 
>> * Since qmake knows which Qt libraries and plugins are used "bundle" target it will generate following Makefile entries
>> 
>> 	all: Sample.app bundle
>> 
>> 	bundle: Sample.app/Frameworks/QtCore.framework
>> 	  mkdir -p Sample.app/Frameworks && cp -r $$[QT_INSTALL_LIBS]/QtCore.framework Sample.app/Frameworks
>> 	  ...
>> Of course this example is simplification, since we don't need to copy headers and we need to take debug versions or release. So there will be more commands in practice.
> 
> Yes, cp is a very slow way of copying, and is especially intolerable for incremental builds. Using rsync is much better as you get instantaneous (< 70ms) incremental builds (and makes your speed argument about making copying non-default, totally pointless).
> 
>> 
>> * One can disable "bundle_frameworks" via CONFIG -= bundle_frameworks, so existing workflow where executable is given rpath pointing to Qt libraries
>> 
>> * If disabled, one can still do "make bundle" that is equivalent to current "macdeployqt" and "bundle" target will also add "install_name_tool" -rpath replacement steps
>> 
>> Regards,
>> -- 
>> Adam
>> _______________________________________________
>> Development mailing list
>> Development at qt-project.org
>> http://lists.qt-project.org/mailman/listinfo/development
> 
> 
> So, this is all wrong; the biggest problem is that it's too Qt centric. Also, it's extremely inflexible (as is macdeployqt). In the real world, people use more libraries than just Qt and may want to customize their bundle layout, the locations of embedded frameworks, etc. So let's summarize what must be done:
> 
> (1) Add qmake options QMAKE_EMBEDDED_FRAMEWORKS, QMAKE_EMBEDDED_LIBRARIES, QMAKE_EMBEDDED_PLUGINS, each taking a list of absolute paths and/or objects; applies to any qmake bundle target, app, framework, etc. Does nothing for non-bundle targets. Does nothing outside of OS X and iOS.
> (1a) "objects" (don't know what this is called in qmake but INSTALLS works similarly) meaning:
> 
> weirdlib.src = /Library/Frameworks/WeirdLib.framework
> weirdlib.dst = $$join($$QMAKE_EMBEDDED_FRAMEWORKS_LOCATION, SubFolderForSomeReason)
> weirdlib.headers = true
> weirdlib.variants = debug release
> QMAKE_EMBEDDED_FRAMEWORKS += weirdlib /Library/Frameworks/Sparkle.framework
> 
> qmake could set some default objects like embed_qtcore (translates to $$[QT_INSTALL_LIBS]/QtCore.framework + default options). That would be important for Qt plugins which would need to augment the default "dst" to place themselves in a subdirectory of Contents/PlugIns. Items specified as absolute paths simply take the default options for headers, variants or the target-level options specified in (3).
> 
> (2) These options can be populated with a default list containing Qt libraries, using qmake's dependency knowledge -- or not, I don't care.
> (3) Additional target-level control options: QMAKE_EMBEDDED_FRAMEWORKS_LOCATION, QMAKE_EMBEDDED_LIBRARIES_LOCATION (default to Contents/Frameworks for OS X, Frameworks for iOS, relative to bundle "wrapper path" aka the .app folder), QMAKE_EMBEDDED_PLUGINS_LOCATION (Contents/PlugIns & PlugIns), QMAKE_EMBEDDED_FRAMEWORKS_HEADERS (bool), QMAKE_EMBEDDED_FRAMEWORKS_VARIANTS (list: debug, release, debug+release).
> (4) User's OWN responsibility (NOT qmake's) to set QMAKE_RPATHDIR for their application/library/framework to whatever they like - @executable_path/../Frameworks, $$[QT_INSTALL_LIBS], /Library/Application Support/FooBar/Frameworks, etc.

> (5) Qt Creator (and `qbs run`) set DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to appropriate paths ($$[QT_INSTALL_LIBS] + possibly others) as an additional convenience for folks who don't (or forget to) set QMAKE_EMBEDDED_* or QMAKE_RPATHDIR (follows Xcode behaviour, and conceptually follows Qt Creator's behaviour on Windows). Don't want? Go to settings, delete.

I’m against setting any DYLD_... in Qt Creator. Better fail early than create confusion later. If application .pro files need some settings to create workable applications, so *be* it. If qmake && make fails on the command line, it should fail in Qt Creator too.
Qt Creator’s behavior on Windows matches the behavior of developing Qt applications on the command line, where you develop in a shell with the corresponding environment settings.

> My requirements:
> 
> (1) NO changes are made to USER targets by qmake, ever. That means qmake MUST NOT set any rpaths in user targets unless EXPLICITLY given by the user with QMAKE_RPATHDIR (currently you are doing this but only as a transitionary measure and it will be removed once support for copying frameworks is added).
> 
> Understand that some things belong at the system level (i.e. internal to qmake) and some things belong at the user level. That's just the way it is.
> 
> Now, if some people don't like the standard way of doing things... scenario: user doesn't want to copy frameworks (note that your no-default-copy idea falls apart for third party libraries so you'd need to end up adding additional rpaths to your app ANYWAYS):
> 
> <code>
> CONFIG(debug, debug|release) {
>    QMAKE_EMBEDDED_FRAMEWORKS =  # empty
>    QMAKE_RPATHDIR = $$[QT_INSTALL_LIBS]
> }
> <code>
> 
> Side benefits
> (1) No need for `install_name_tool -delete_rpath` when you want to release.
> (2) Doesn't bother anyone else or engineer qmake completely for one single non-standard use case (i.e. yours).
> 
> Discuss. Keep in mind that I am very much in favour of solutions that will serve all parties' use cases. Flexibility here is key.
> -- 
> Jake Petroules - jake.petroules at petroules.com
> Chief Technology Officer - Petroules Corporation
> _______________________________________________
> Development mailing list
> Development at qt-project.org
> http://lists.qt-project.org/mailman/listinfo/development

-- 
Eike Ziller, Senior Software Engineer - Digia, Qt
 
Digia Germany GmbH, Rudower Chaussee 13, D-12489 Berlin
Geschäftsführer: Mika Pälsi, Juha Varelius, Tuula Haataja
Sitz der Gesellschaft: Berlin, Registergericht: Amtsgericht Charlottenburg, HRB 144331 B




More information about the Development mailing list