[Development] Qt 4.x and Qt 5 frameworks should use @rpath (QTBUG-31814)
Jake Petroules
jake.petroules at petroules.com
Mon Aug 4 04:30:06 CEST 2014
On 2014-08-03, at 08:17 PM, Adam Strzelecki <ono at java.pl> wrote:
>> 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.
>
> OMG, we were talking about two different Xcode versions. I am talking about Xcode 5 that does behave like I described, you are talking about Xcode 6 that indeed defaults to @rpath like you have described. But Xcode 6 is not final release, it is beta, so this may stay or not.
Don't hold your breath.
> It makes completely sense to bundle project libraries into project application bundles. Yet Qt isn't part of your project, it is an external dependency, your project does not build Qt, it just links to it.
As Qt is not a system library it's as much a part of your project as anything. For all you know, some project out there bundles Qt with its source and builds it along with everything else. Not a wrong thing to do, especially if that project relies on specific customizations. Whether a particular target is built within your source tree or not is rather irrelevant to whether it needs to be copied into your application bundle. Unless it's a system library that exists on all installations of the OS, it needs to be copied.
> Does Xcode 6 automatically bundle an external framework added as dependency to your project, NO it does not.
>
>> There is a very simple solution to this problem. I and the majority of developers do this:
>> QMAKE_EMBEDDED_FRAMEWORKS = QtCore QtGui QtWidgets
>
> "would" is more adequate here because we are talking about some possible setting not existing one.
>
>> 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.
>
> Sorry it doesn't make sense to me. Why would you like to specify which frameworks are to be copied if this is figured out by macdeployqt today automatically. Why someone would like to copy just some of the frameworks not all used by the application.
Because macdeployqt needs to go away. Once the Qt SDK is built correctly, it becomes a useless tool and can be deleted. That's not to say qmake can't automatically set the value of QMAKE_EMBEDDED_FRAMEWORKS. You can then add additional frameworks to it as necessary, i.e. QMAKE_EMBEDDED_FRAMEWORKS += /Library/Frameworks/Sparkle.framework /Library/Frameworks/Growl.framework
> Reasonable choice it just to bundle when building ("make") or manually ("make && make bundle").
>
>> For other users' sake we DO want to make it default. The workflows you want are foreign to every Mac developer out there.
>
> Because Xcode 6 which is beta (not stable, may change, etc. etc.) does bundle frameworks which are part of the project? Qt are not part of your project, these are external dependencies. Xcode 6 won't bundle them if you add them as dependencies.
Don't try to use its beta status as a way of trying to argue against the correct solution. The only reason I mentioned Xcode 6 functionality was to place additional emphasis on this is how OS X and iOS applications are built in the real world. Regardless of additional conveniences that Xcode 6 may or may not add, my argument is solid on its own.
>> New in Xcode 6.
>
> You should say that at the very beginning.
>
>> 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.
>
> Minimal GUI app's Qt frameworks weight around 20MB in release and 40MB in debug versions. This may be not much, but considering the fact app itself may be just few hundred KB this makes a difference. It won't have noticeable impact, unless you are working on network drives or whatever like that.
Then if you admit it won't have noticeable impact, why are you continuing to argue against it? Try this experiment on your machine:
mkdir -p /tmp/experiments/Frameworks
mkdir -p /tmp/experiments/SDK
cd /tmp/experiments/SDK
mkdir QtCore.framework QtGui.framework QtNetwork.framework QtSvg.framework QtXml.framework QtWidgets.framework Frameworks
dd if=/dev/zero of=QtCore.framework/A bs=1024 count=10240
dd if=/dev/zero of=QtGui.framework/A bs=1024 count=10240
dd if=/dev/zero of=QtNetwork.framework/A bs=1024 count=10240
dd if=/dev/zero of=QtSvg.framework/A bs=1024 count=10240
dd if=/dev/zero of=QtXml.framework/A bs=1024 count=10240
dd if=/dev/zero of=QtWidgets.framework/A bs=1024 count=10240
cd ..
time rsync -a SDK/ Frameworks/
time rsync -a SDK/ Frameworks/
time rsync -a SDK/ Frameworks/
time rsync -a SDK/ Frameworks/
No sane implementation of the proposed QMAKE_EMBEDDED_FRAMEWORKS would blindly run cp -R every single time you build; that is ridiculous and I'm guessing that's what you think I am advocating. There are ways to optimize copying large numbers of files as you can clearly see based on rsync's performance.
If you run this experiment, you'll notice that the first call to rsync completes in maybe a few seconds (mine was 4.6 seconds). Each subsequent call is less than 0.06 seconds (60ms). I even duplicated the source frameworks 9 more times, raising the payload from something like a typical 60 MB to 600 MB. No Qt application bundles even close to 600 MB worth of Qt frameworks. Wonder how long it takes rsync to copy on rebuild? Still 0.06 seconds. +0.06 seconds rebuild time increase to copy 600 MB worth of Qt frameworks.
I even rscyned to a slow external hard drive to test the copying speed. Still only 0.07 seconds on average (and only 39 seconds cold - for 600 MB). Ok, let's even copy to a remote server outside my LAN to further demonstrate the point. 7.5 minutes cold copy. Understandable. But still only 0.8 seconds on average to warm-copy 600 MB to a remote server outside LAN.
There is no conceivable real world scenario where you can argue that copying frameworks to bundles as part of the standard build process is a significant enough performance impediment to seek alternate solutions, especially when said solution is already in universal use by the platform vendor.
So my solution adds MAYBE 5-30 seconds on average to a cold build (which is going to take on the order of minutes to hours anyways), and 60 MILLISECONDS to a rebuild. Why are we even debating the addition of 60 milliseconds?! Especially when it solves several much more important problems.
So, let's end this discussion and start focusing efforts towards building the solution.
> Altogether we have just different opinions about single post-process step, but we both agree we need @rpath working, we agree that bundling should be mark of qmake. So I believe decision whether bundle by default or not should be taken by Qt project maintainers, that's it. But we should have both options supported.
>
> If we had BTRFS with COW this would be obvious choice, but we don't.
This would not make any difference to the argument whatsoever. As I mentioned before, you have not provided any benchmarks. I have. Prove me wrong and we'll talk.
> Regards,
> --
> Adam
>
--
Jake Petroules - jake.petroules at petroules.com
Chief Technology Officer - Petroules Corporation
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140803/8737ce71/attachment.html>
More information about the Development
mailing list