Opened 10 years ago

Last modified 9 years ago

#46029 new submission

port submission: qtchooser

Reported by: RJVB (René Bertin) Owned by: macports-tickets@…
Priority: Normal Milestone:
Component: ports Version: 2.3.3
Keywords: Cc: michaelld (Michael Dickens), pixilla (Bradley Giesbrecht), mkae (Marko Käning)
Port: qtchooser

Description (last modified by ryandesign (Ryan Carsten Schmidt))

Please find attached a portfile with an initial set-up for qtchooser, the utility that makes it possible/easy to have Qt4 and Qt5 (and soon enough probably Qt6) installed in parallel. It replaces certain of the standard Qt binaries (like qmake) with links to itself, and then uses configuration files and (optional) arguments to determine what version of the binary in question is called.

Thus, with qmake a symlink to qtchooser

> qmake --version              # prints the version of the default Qt installation
> qmake -qt=4 --version   # prints the version of the Qt4 installation
> qmake -qt=5 --version   # prints the version of the Qt5 installation

What's missing are the configuration files that will determine which Qt goes and is expected where, though I have given an upbeat by assuming that'd be ${prefix}/libexec/qtN .

I hope this helps and brings the possibility to have concurrent qt4-mac and qt5-mac installs a step closer.

Attachments (3)

patch-for-macports.diff (6.9 KB) - added by RJVB (René Bertin) 9 years ago.
patch-for-macports-linux.diff (6.9 KB) - added by RJVB (René Bertin) 9 years ago.
indeed, I've managed to install my own port:qt5-kde under Linux…
Portfile (4.4 KB) - added by RJVB (René Bertin) 9 years ago.
This brings qtchooser up to date and introduces support for all Qt port versions and flavours I am aware of currently. The binary is renamed to qtchooser-mp and generation of the actual configuration profiles ("environments") is now done in the post-activation phase so that they always correspond to what the user actually has installed.

Download all attachments as: .zip

Change History (23)

comment:1 Changed 10 years ago by ryandesign (Ryan Carsten Schmidt)

Description: modified (diff)
Keywords: qt4-mac qt5-mac removed
Port: qtchooser added
Priority: HighNormal

comment:2 Changed 10 years ago by ryandesign (Ryan Carsten Schmidt)

Since this is hosted at github. the github portgroup should be used.

comment:3 Changed 10 years ago by pixilla (Bradley Giesbrecht)

Cc: pixilla@… added

Cc Me!

comment:4 Changed 10 years ago by mkae (Marko Käning)

Cc: mk@… added

Cc Me!

comment:5 Changed 10 years ago by mkae (Marko Käning)

What is the status of this port, René?

Can you make the requested changes for the github PortGroup?

Would it already be commit-ready then?

comment:6 Changed 10 years ago by larryv (Lawrence Velázquez)

Forgive me if this is obvious to those knowledgeable about Qt, but what benefit does this port provide over the port select mechanism?

comment:7 Changed 10 years ago by RJVB (René Bertin)

@mk: I have been putting this on hold for a while, because without a possibility to have multiple Qt versions installed concurrently, qtchooser doesn't serve a lot of purpose...

@larry: I'm not sure what port select would offer, but I think qtchooser gives more flexibility, and of course it's been conceived from the ground up to work with different Qt versions. And of course it's not unlikely at all that it provides functionality that's expected e.g. by 3rd party build systems that can build for both versions (QtCurve would be one of those).

I'm currently working on a +concurrent variant for qt4-mac (since I got some frowns for proposing to use new ports). Once I have qt4-mac and qt5-mac living together happily I'll see where we can go with qtchooser, and if it's necessary. I'll do the github PortGroup edit at that point, too. (I just hope I won't have to redefine the installation locations by then...)

Last edited 10 years ago by RJVB (René Bertin) (previous) (diff)

comment:8 Changed 10 years ago by RJVB (René Bertin)

This works now, of course with Qt's binaries installed in its their own location.

comment:9 Changed 10 years ago by larryv (Lawrence Velázquez)

configure {
    reinplace "s|prefix = /usr|prefix = ${prefix}|g" ${worksrcpath}/Makefile ${worksrcpath}/src/qtchooser/Makefile
    reinplace "s|INSTALL_ROOT|DESTDIR|g" ${worksrcpath}/Makefile ${worksrcpath}/src/qtchooser/Makefile
    # correct the hardcoded path to the xdg "root" directory
    reinplace "s|\"/etc/xdg\"|\"${prefix}/etc/xdg\"|g" ${worksrcpath}/src/qtchooser/main.cpp
}

This is extremely unorthodox. This should be done with a patch that replaces the hard-coded paths with a placeholder, a post-patch phase that replaces the placeholder with the correct value, and use_configure no.

The DESTDIR / INSTALL_ROOT swap should be done with destroot.destdir-strsed, as I mentioned on macports-users.

comment:10 in reply to:  9 ; Changed 10 years ago by RJVB (René Bertin)

Replying to larryv@…:

This is extremely unorthodox. This should be done with a patch that replaces the hard-coded paths with a placeholder, a post-patch phase that replaces the placeholder with the correct value

While I can agree that it's less unorthodox to do the patching in a patch phase, I don't agree with the principle of using a patchfile and then re-patching on top of that. Not for simple changes like this. That'd be orthodox in the Russian/Romanian church kind of sense :)

comment:11 in reply to:  10 Changed 10 years ago by larryv (Lawrence Velázquez)

Replying to rjvbertin@…:

While I can agree that it's less unorthodox to do the patching in a patch phase, I don't agree with the principle of using a patchfile and then re-patching on top of that. Not for simple changes like this.

They’re simple until the files change out from under you and your substitutions mysteriously stop working or start doing the wrong thing. And you’ll be confident that this won’t ever happen to you, until it does.

This isn’t just dogma; we do it this way from experience. With a patch, it’s obvious when the file has changed — the patch applies with an offset or fuzz. If the file changes too much, the patch fails to apply. It’s a little more work but much better practice.

comment:12 Changed 10 years ago by RJVB (René Bertin)

If you know me by now you know where I put dogma if it isn't the movie of the same name ;)

There is no way you can guarantee that the same kind of sneaky change won't happen when using destroot.destdir. Contrary to the changes I'm doing with reinplace, a failing destroot setting has potentially disastrous results because it causes things to get installed somewhere before the actual install phase, and there'd be no warning. It's not (just) that I'm confident this won't happen in this particular case, I'm above all confident that I'll catch those changes when they happen.

The way I see it, this is a decision that's up to the port maintainer to decide what approach to use, but of course others can change things too. In any case I'll first contact the author to see if I'm even following the official way of building his tool, and if he'd be open to incorporating certain changes like the hardcoded prefix in source code.

BTW, the Makefile does use the keyword prefix to designate the final install location; isn't there a way comparable to destroot.destdir to have make called with the correct parameter(s)??

comment:13 in reply to:  12 ; Changed 10 years ago by larryv (Lawrence Velázquez)

Replying to rjvbertin@…:

There is no way you can guarantee that the same kind of sneaky change won't happen when using destroot.destdir.

And how exactly would that happen? As long as INSTALL_ROOT is used, the makefile will behave properly.

Contrary to the changes I'm doing with reinplace, a failing destroot setting has potentially disastrous results because it causes things to get installed somewhere before the actual install phase, and there'd be no warning.

No. The destroot phase is run without superuser privileges. If the makefile changes suddenly stops using INSTALL_ROOT, the destroot phase will try to install files outside of the destroot and will fail. (This is one of the reasons we discourage users from setting “macportsuser root” in their macports.conf.)

It's not (just) that I'm confident this won't happen in this particular case, I'm above all confident that I'll catch those changes when they happen.

Okay. I assume you’ll scour the destroot every single time you muck with the port to make sure all the files are always in exactly the right place, then.

The way I see it, this is a decision that's up to the port maintainer to decide what approach to use, but of course others can change things too.

At some level, yes, it is up to the maintainer. Maintainers should write portfiles in a way that makes sense to them.

But at another level, you share this project with many other people. When people see a very common task done in an odd way, they think that the normal way wasn’t sufficient for some reason, and that there must be a very good reason for not using it. I frankly don’t see a good reason here.

comment:14 in reply to:  12 ; Changed 10 years ago by larryv (Lawrence Velázquez)

Replying to rjvbertin@…:

In any case I'll first contact the author to see if I'm even following the official way of building his tool, and if he'd be open to incorporating certain changes like the hardcoded prefix in source code.

Didn’t you say that it uses INSTALL_ROOT? Or is that not used for staging installs, and I’m misunderstanding the whole thing? I don’t know anything about Qt.

BTW, the Makefile does use the keyword prefix to designate the final install location; isn't there a way comparable to destroot.destdir to have make called with the correct parameter(s)??

Yes. It’s destroot.destdir. I don’t think you are understanding how the destroot command is constructed.

Roughly speaking, the command that is executed for the destroot phase is “${destroot.cmd} ${destroot.pre_args} ${destroot.args} ${destroot.post_args}”. The default value of destroot.pre_args is “${destroot.destdir}”, which itself defaults to “DESTDIR=${destroot}”. So the correct way to provide the destroot command with an argument that changes the way it installs to the destroot is by using destroot.destdir.

As Daniel suggested on macports-users, you could outright set destroot.destdir to “INSTALL_ROOT=${destroot}”, in lieu of my suggestion. Unless INSTALL_ROOT doesn’t actually represent a staging area.

comment:15 in reply to:  13 Changed 10 years ago by RJVB (René Bertin)

And how exactly would that happen?

Exactly the same way as the other patches could no longer work.

No. The destroot phase is run without superuser privileges. If the makefile changes suddenly stops using INSTALL_ROOT, the destroot phase will try to install files outside of the destroot and will fail. (This is one of the reasons we discourage users from setting “macportsuser root” in their macports.conf.)

Admin users can also have permissions to write in places where they better know what they're doing. I for one have long used MacPorts as myself, and only started sudoing the install step when I realised that some things do have to be installed as root. That means that /opt/local is still admin-group-writable. That may not be a supported configuration, but it is one I keep in mind (I have a hunch I might not be the only one doing things that way).

Okay. I assume you’ll scour the destroot every single time you muck with the port to make sure all the files are always in exactly the right place, then.

Guess how I found the destdir thing?

With my own ports (the ones I tweak and/or develop), I always run up to the destroot step as myself, often also doing the configure or even patch step first, in order to move the srcdir to a place where it won't be removed by port if I don't pay attention. So yes, I have a habit of checking the destroot for pending changes before applying them.

I frankly don’t see a good reason here.

Same here - I don't see a good reason to make things more complex. But as said, I have contacted the developer to see what can be done with the buildsystem to streamline things, e.g. by passing parameters to make.

comment:16 in reply to:  14 ; Changed 10 years ago by RJVB (René Bertin)

Replying to larryv@…:

Didn’t you say that it uses INSTALL_ROOT? Or is that not used for staging installs, and I’m misunderstanding the whole thing? I don’t know anything about Qt.

I have little idea what that variable is usually used for. Here it is clearly used to prepend a path to the regular prefix, *probably* indeed for Linux packagers. I can't say off the top of my head if the parameter is passed on to the inferior makefile, though.

BTW, the Makefile does use the keyword prefix to designate the final install location; isn't there a way comparable to destroot.destdir to have make called with the correct parameter(s)??

I meant the build step. Invoking make with prefix=${prefix} ought to take care of the hard-coded '/usr' path.

As Daniel suggested on macports-users, you could outright set destroot.destdir to “INSTALL_ROOT=${destroot}”, in lieu of my suggestion. Unless INSTALL_ROOT doesn’t actually represent a staging area.

Yes, and that's probably what I'll do if that works out. That *is* simpler than what I was doing.

comment:17 in reply to:  16 Changed 10 years ago by larryv (Lawrence Velázquez)

Replying to rjvbertin@…:

BTW, the Makefile does use the keyword prefix to designate the final install location; isn't there a way comparable to destroot.destdir to have make called with the correct parameter(s)??

I meant the build step.

I don’t understand what you’re asking for.

Last edited 10 years ago by larryv (Lawrence Velázquez) (previous) (diff)

comment:18 in reply to:  7 ; Changed 10 years ago by larryv (Lawrence Velázquez)

Replying to rjvbertin@…:

@larry: I'm not sure what port select would offer

A way to create a bunch of symlinks to allow the end-user to select between two concurrently installed ports. Which sounds exactly like this.

but I think qtchooser gives more flexibility, and of course it's been conceived from the ground up to work with different Qt versions. And of course it's not unlikely at all that it provides functionality that's expected e.g. by 3rd party build systems that can build for both versions (QtCurve would be one of those).

Okay, except that this port sounds an awful lot like the perl5 one, and we very much want to avoid that type of mess again.

comment:19 Changed 10 years ago by RJVB (René Bertin)

https://github.com/RJVB/mp-port-repository/tree/master/devel/qtchooser

this version adds just a conflict with port:qt_select which will provide a "MacPorts-native alternative" (albeit a less flexible one O:-))

Changed 9 years ago by RJVB (René Bertin)

Attachment: patch-for-macports.diff added

Changed 9 years ago by RJVB (René Bertin)

indeed, I've managed to install my own port:qt5-kde under Linux...

comment:20 in reply to:  18 Changed 9 years ago by RJVB (René Bertin)

Replying to larryv@…:

Okay, except that this port sounds an awful lot like the perl5 one, and we very much want to avoid that type of mess again.

I don't know what perl5 mess you are referring to, but I imagine it must have to do with the potentially huge body of perl scripts delivered by ports which can be dependencies for other ports.

Qt is not an interpreter and while you can draw a parallel between a port providing a set of libraries that depend on Qt (and hence a specific Qt version) the potential mess is much smaller because Qt guarantees backward compatibility inside a major version. As long as MacPorts doesn't provide separate, coinstallable ports for minor Qt releases, port:qtchooser should not create any messes. At least not as long as Qt-dependents use the Qt Portgroups and either the specific qmake (or CMake modules) for which the Portgroups define variables. qtchooser just allows the user to fire up the appropriate, say, Designer application from a shell (designer -qt=<version>), or to configure a software project against a Qt install of choice (qmake -qt=<version>).

Users who really know what they're doing can even use the qtchooser command itself to define an environment for an official (e.g. a commercial) Qt install so that they can configure source to build against that using the same qmake proxy in ${prefix}/bin. The resulting binaries will of course depend on the external Qt libraries. It's a convenience utility that is very much intended for developers (but not as a potential dependency for other ports :)).

Changed 9 years ago by RJVB (René Bertin)

Attachment: Portfile added

This brings qtchooser up to date and introduces support for all Qt port versions and flavours I am aware of currently. The binary is renamed to qtchooser-mp and generation of the actual configuration profiles ("environments") is now done in the post-activation phase so that they always correspond to what the user actually has installed.

Note: See TracTickets for help on using tickets.